├── .gitignore ├── LICENSE ├── README.md ├── bitstreams ├── HTG-VKUS-V095 │ ├── example_top.bit │ └── example_top.ltx └── README.md ├── doc └── README.md ├── implementation ├── README.md └── syn │ ├── axi_dram_if │ └── axi_dram_if.sv │ ├── bankfsm_cmdmux_if │ └── bankfsm_cmdmux_if.sv │ ├── bus_shuffler_4 │ └── bus_shuffler_4.sv │ ├── ch_ctrl │ └── ch_ctrl.sv │ ├── ch_ctrl_bank_fsm │ └── ch_ctrl_bank_fsm.sv │ ├── ch_ctrl_rank_fsm │ ├── ch_ctrl_rank_fsm.sv │ ├── ch_ctrl_rank_fsm_unit_test.sv │ └── ch_ctrl_rank_fsm_wrapper.sv │ ├── cmd_mux │ └── cmd_mux.sv │ ├── config_bus_slave │ ├── config_bus_slave.sv │ ├── reg_bus_if.sv │ └── reg_bus_pkg.sv │ ├── congen │ └── congen.v │ ├── ddr4_mem_ch_top │ └── ddr4_mem_ch_top.sv │ ├── mem_ctrl │ ├── mem_ctrl.sv │ └── mem_ctrl_if.sv │ ├── mem_ctrl_top │ └── mem_ctrl_top.sv │ └── xiphy_if │ ├── bit_packing_xiphy_ultrascale.sv │ └── xiphy_ultrascale_if.sv ├── ips ├── README.md ├── Xi_BRAM │ ├── BRAM_512x64.tcl │ ├── BRAM_528x64.tcl │ ├── BRAM_528x8.tcl │ ├── BRAM_52x4.tcl │ └── ip_setup.tcl ├── Xi_Phy │ ├── Mig_phy_only_ip.tcl │ ├── Sim_CompileLib.tcl │ └── ip_setup.tcl ├── axi_slice │ ├── LICENSE │ ├── README.md │ ├── axi_ar_buffer.sv │ ├── axi_aw_buffer.sv │ ├── axi_b_buffer.sv │ ├── axi_r_buffer.sv │ ├── axi_w_buffer.sv │ └── src_files.yml └── ems_lib │ ├── axi_tgen │ ├── TGEN_AXI_GENERIC.sv │ ├── TGEN_TASK_GENERIC.sv │ ├── params_tgen_axi.sv │ └── verif_utils.sv │ ├── comp_sel_grt │ └── comp_sel_grt.sv │ ├── demux_1_4 │ └── demux_1_4.sv │ ├── dual_clock_fifo │ └── dual_clock_fifo.sv │ ├── generic_fifo │ ├── bram_fifo_512x64.sv │ ├── bram_fifo_528x64.sv │ ├── bram_fifo_528x8.sv │ ├── bram_fifo_52x4.sv │ └── generic_fifo.sv │ ├── lfsr │ └── lfsr_gen.sv │ ├── mem_tgen_checker │ └── mem_tgen_checker.sv │ ├── min_8 │ └── lowest_nr_identifier.sv │ ├── min_generic │ └── lowest_nr_identifier.sv │ ├── mux_8_1 │ └── mux_8_1.sv │ ├── mux_generic │ └── mux_generic.sv │ ├── priority_arbiter_8 │ └── priority_arbiter_8.sv │ ├── priority_arbiter_generic │ ├── priority_arbiter_generic.sv │ ├── priority_encoder.sv │ └── priority_mux.sv │ └── pulp_clock_gating │ └── pulp_clock_gating.sv ├── runs └── FPGA │ ├── CONST │ ├── example_design.xdc │ └── example_design_ADM_9V3.xdc │ ├── example_bit.tcl │ ├── example_impl.tcl │ └── example_synth.tcl └── validation ├── README.md ├── tb_ddr4_ch_ctrl ├── glbl.v ├── light_phy.svh ├── run.tcl ├── tb_ddr4_ch_ctrl.sv └── wave.do └── tb_ddr4_mem_ch_top ├── glbl.v ├── light_phy.svh ├── run.tcl ├── tb_ddr4_mem_ch_top.sv └── wave.do /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SYSTEM-VERILOG CODE for DDR4 Memory Controller with XILINX Phy 2 | 3 | Designed by: TU Kaiserslatern (https://ems.eit.uni-kl.de/) 4 | 5 | This is the first FPGA version of a DDR4 memory controller for Transprecision Computing. This DDR4 controller is migrated from our DDR3 memory controller that was originally desined as an ASIC IP. In the future, we will optimize the design for different FPGA platforms. 6 | 7 | ## Folder Organization 8 | * bitstreams <-- FPGA bit files and debug files for various boards 9 | * doc <-- Documentation of the DRAM-Controller 10 | * implementation/syn <-- RTL-Models 11 | * ips <-- contains submodules, shared design libraries and proprietary test modules 12 | * validation <-- Holds all Testbenchs (each Testbench has its own folder) 13 | 14 | ## Xilinx Phy IP generation, BRAM IP generation and setting up libraries for simulation 15 | ### Requirements: 16 | * Vivado 2019.1 17 | * Modelsim 2019.1 64-bit 18 | 19 | ### Configuration: 20 | * Open file ips/Xi_Phy/ip_setup.tcl 21 | * Open file ips/Xi_BRAM/ip_setup.tcl 22 | * Configure MEMCTRL_DIR : Path where our DDR4 controller (dram.ctrl.verilog) is cloned. Enter the full path including "DDR4_controller" 23 | * Configure SIM_LIB_PATH (optional) : Path where you would like to store the Xilinx specific simulation library for Modelsim. Default config is correct. 24 | * If you have the pre-compiled library for Modelsim, then set SIM_LIB_PATH to that path. Also copy modelsim.ini file to validation/tb_ddr4_mem_ch_top folder and validation/tb_ddr4_ch_ctrl folder 25 | * Configure MODELSIM_EXE_PATH : Folder where the modelsim execution is located. Eg. "C:/modeltech64_2019.1/win64" 26 | * Configure VIVADO_FOLDER_PATH : Vivado source directory. Eg. "C:/Xilinx/Vivado/2019.1" 27 | * Configure PART to used FPGA device number. 28 | * Configure IP_NAME (optional) 29 | * Open ips/Xi_Phy/Mig_Phy_only_ip.tcl 30 | * Configure Mig Phy reference clock and DRAM timings. Current configuration corresponds to Reference clk = 200MHz (i.e. HTG-VKUS-V095 Board clk), DRAM clk = 800MHz, DQ = 64, CL = 11 and CWL = 11. For more details refer PG150. 31 | 32 | ### IP Generation and Sim Lib Setup: 33 | * Open Command prompt or terminal 34 | * Change directory to ips/Xi_Phy: cd 35 | * Execute: vivado -mode batch -source Sim_CompileLib.tcl 36 | * Execute: vivado -mode batch -source Mig_phy_only_ip.tcl 37 | * Change directory to ips/Xi_Phy: cd 38 | * Execute: vivado -mode batch -source BRAM_512x64.tcl 39 | * Execute: vivado -mode batch -source BRAM_52x4.tcl 40 | * Execute: vivado -mode batch -source BRAM_528x64.tcl 41 | * Execute: vivado -mode batch -source BRAM_528x8.tcl 42 | * Note that the tcl scripts are tested only on Windows 10 - For linux, please contact Chirag Sudarshan (Sudarshan@eit.uni-kl.de). 43 | * Note: please wait for IP synthesis to be complete. Before proceeding to further steps please wait until the file "\__synthesis_is_complete__" is generated for all the Xilinx IPs. E.g. "ips/Xi_Phy/IP/mig_phy/mig_phy.runs/ddr4_0_synth_1/\__synthesis_is_complete__" , "ips/Xi_BRAM/IP/bram_528x64/bram_528x64.runs/blk_mem_gen_528x64_synth_1/\__synthesis_is_complete__" 44 | 45 | ## For Integration 46 | * Refer example Simulation Top of the complete Memory Controller Channel (i.e. TG <-> AXI <-> MEM_CNTRL <-> Xi-PHY <-> DRAM Model) in folder "validation/tb_ddr4_mem_ch_top/tb_ddr4_mem_ch_top.sv" 47 | 48 | ## Simulation and Testbench 49 | * This version has 2 testbenches a)"validation/tb_ddr4_mem_ch_top/tb_ddr4_mem_ch_top.sv b) "validation/tb_ddr4_ch_ctrl/tb_ddr4_ch_ctrl.sv" 50 | * sys_clk_i frequency (see clock generation in testbench) should be same as the configured CONFIG.C0.DDR4_InputClockPeriod in ips/Xi_Phy/Mig_Phy_only_ip.tcl file. 51 | * Synthesisable testbench (including top) : "validation/tb_ddr4_ch_ctrl/tb_ddr4_ch_ctrl.sv". NEW_TGEN has to be defined in the synthesis tcl scripts. 52 | 53 | ## Synthesis, Implementation and Bit file generation. 54 | * XDC File: Store the xdc file in the folder "runs/FPGA/CONST". The example xdc files for FPGA xcvu095-ffvb2104-2-e (i.e. example_design.xdc) and xcvu3p-ffvc1517-2-e (i.e. example_design_ADM_9V3.xdc) can be found in the folder "runs/FPGA/CONST". 55 | * example_synth.tcl, example_impl.tcl and example_bit.tcl are the example tcl files for Synthesis, Implementation and Bit file generation, respectively. 56 | * Set the xdc file path in example_synth.tcl (line 128 to line 133) and example_impl.tcl file (line 19 to line 22) 57 | * Synthesis: vivado -mode batch -source example_synth.tcl -> Output files and Logs can be found in folder "SYNTH" 58 | * Implementation: vivado -mode batch -source example_impl.tcl -> Output files and Logs can be found in folder "IMPL" 59 | * Bit File: vivado -mode batch -source example_bit.tcl -> Output files and Logs can be found in folder "BIT" 60 | * This DDR4 controller is tested on FPGA xcvu095-ffvb2104-2-e , HTG-VKUS-V095 board, CT4GSFS824A.C8FBD2 DDR4 DIMM. 61 | 62 | 63 | ## Limitations for this Release 64 | * AXI interface only supports burst-length of one at this moment (AXI slave was taken from one of the previous projects - AXI slave require update and improvements) 65 | * Tested at this moment only with parameters specified in tb_ddr4_ch_ctrl.sv. Change of these parameters require generation of appropriate BRAM IPs and Xi_Phy. 66 | 67 | ## TODO 68 | * Enable Power Down 69 | * AXI with variable burst-length 70 | * Latency optimizations. 71 | -------------------------------------------------------------------------------- /bitstreams/HTG-VKUS-V095/example_top.bit: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oprecomp/DDR4_controller/35c1900e13662404658ab2c87d08a19477e92e04/bitstreams/HTG-VKUS-V095/example_top.bit -------------------------------------------------------------------------------- /bitstreams/HTG-VKUS-V095/example_top.ltx: -------------------------------------------------------------------------------- 1 | { 2 | "ltx_root": { 3 | "version": 4, 4 | "minor": 0, 5 | "ltx_data": [ 6 | { 7 | "name": "EDA_PROBESET", 8 | "active": true, 9 | "debug_cores": [ 10 | { 11 | "type": "XSDB_V3", 12 | "name": "dbg_hub", 13 | "spec": "labtools_xsdbm_v3", 14 | "clk_input_freq_hz": "200000001" 15 | }, 16 | { 17 | "type": "ILA_V3", 18 | "name": "u_ila_0", 19 | "spec": "labtools_ila_v6", 20 | "core_location": { 21 | "user_chain": 1, 22 | "slave_index": 0, 23 | "bscan_switch_index": 0 24 | }, 25 | "uuid": "23E7D65A79BC59F7BC47406C1714DFAE", 26 | "pins": [ 27 | { 28 | "name": "probe0", 29 | "id": 0, 30 | "type": "DATA_TRIGGER", 31 | "direction": "IN", 32 | "isVector": false, 33 | "leftIndex": 0, 34 | "rightIndex": 0, 35 | "portIndex": 0, 36 | "nets": [ 37 | { 38 | "name": "c0_data_compare_error_OBUF", 39 | "isBus": false 40 | } 41 | ] 42 | }, 43 | { 44 | "name": "probe1", 45 | "id": 1, 46 | "type": "DATA_TRIGGER", 47 | "direction": "IN", 48 | "isVector": false, 49 | "leftIndex": 0, 50 | "rightIndex": 0, 51 | "portIndex": 1, 52 | "nets": [ 53 | { 54 | "name": "c0_init_calib_complete_OBUF", 55 | "isBus": false 56 | } 57 | ] 58 | }, 59 | { 60 | "name": "probe2", 61 | "id": 2, 62 | "type": "DATA_TRIGGER", 63 | "direction": "IN", 64 | "isVector": false, 65 | "leftIndex": 0, 66 | "rightIndex": 0, 67 | "portIndex": 2, 68 | "nets": [ 69 | { 70 | "name": "fe_cmd", 71 | "isBus": false 72 | } 73 | ] 74 | }, 75 | { 76 | "name": "probe3", 77 | "id": 3, 78 | "type": "DATA_TRIGGER", 79 | "direction": "IN", 80 | "isVector": false, 81 | "leftIndex": 0, 82 | "rightIndex": 0, 83 | "portIndex": 3, 84 | "nets": [ 85 | { 86 | "name": "fe_req", 87 | "isBus": false 88 | } 89 | ] 90 | }, 91 | { 92 | "name": "probe4", 93 | "id": 4, 94 | "type": "DATA_TRIGGER", 95 | "direction": "IN", 96 | "isVector": false, 97 | "leftIndex": 0, 98 | "rightIndex": 0, 99 | "portIndex": 4, 100 | "nets": [ 101 | { 102 | "name": "fe_stall", 103 | "isBus": false 104 | } 105 | ] 106 | }, 107 | { 108 | "name": "probe5", 109 | "id": 5, 110 | "type": "DATA_TRIGGER", 111 | "direction": "IN", 112 | "isVector": false, 113 | "leftIndex": 0, 114 | "rightIndex": 0, 115 | "portIndex": 5, 116 | "nets": [ 117 | { 118 | "name": "rdDataEn", 119 | "isBus": false 120 | } 121 | ] 122 | } 123 | ] 124 | }, 125 | { 126 | "type": "XSDBS_V2", 127 | "name": "ddr4_phy", 128 | "spec": "labtools_xsdbslavelib_v2", 129 | "ipName": "DDR4_SDRAM", 130 | "core_location": { 131 | "user_chain": 1, 132 | "slave_index": 1, 133 | "bscan_switch_index": 0 134 | }, 135 | "uuid": "1F4CDFA740BF5493880E6464362B2E5A" 136 | } 137 | ] 138 | } 139 | ] 140 | } 141 | } -------------------------------------------------------------------------------- /bitstreams/README.md: -------------------------------------------------------------------------------- 1 | # Bitstreams -------------------------------------------------------------------------------- /doc/README.md: -------------------------------------------------------------------------------- 1 | # Documentation -------------------------------------------------------------------------------- /implementation/README.md: -------------------------------------------------------------------------------- 1 | # Implementation Folder 2 | 3 | * implementation <-- Holds RTL-Models -------------------------------------------------------------------------------- /implementation/syn/bankfsm_cmdmux_if/bankfsm_cmdmux_if.sv: -------------------------------------------------------------------------------- 1 | module bankfsm_cmdmux_if 2 | #( 3 | parameter DRAM_ADDR_WIDTH = 15, 4 | parameter DRAM_BANKS = 8, 5 | parameter DRAM_CMD_WIDTH = 5, 6 | parameter CLK_RATIO = 4, 7 | parameter PRIORITY_WIDTH = 6, 8 | parameter FE_ID_WIDTH = 8 9 | ) 10 | ( 11 | input clk, 12 | input rst_n, 13 | input [DRAM_BANKS-1:0][DRAM_ADDR_WIDTH-1:0] bm_addr, 14 | input [DRAM_BANKS-1:0][$clog2(CLK_RATIO)-1:0] bm_slot, 15 | input [DRAM_BANKS-1:0][PRIORITY_WIDTH-1:0] bm_priority, 16 | input [DRAM_BANKS-1:0][FE_ID_WIDTH-1:0] bm_id, 17 | input [DRAM_BANKS-1:0] bm_act, 18 | input [DRAM_BANKS-1:0] bm_cas, 19 | input [DRAM_BANKS-1:0] bm_r_w, // 1=read, 0=write 20 | input [DRAM_BANKS-1:0] bm_pre, 21 | input [DRAM_BANKS-1:0][$clog2(DRAM_BANKS)-1:0] bm_bank, 22 | input rm_stall, 23 | /*input cmd_mux_act_ack, 24 | input [$clog2(DRAM_BANKS)-1:0] cmd_mux_act_grant, 25 | input [$clog2(CLK_RATIO)-1:0] cmd_mux_act_slot, 26 | input cmd_mux_cas_ack, 27 | input [$clog2(DRAM_BANKS)-1:0] cmd_mux_cas_grant, 28 | input [$clog2(CLK_RATIO)-1:0] cmd_mux_cas_slot, 29 | input cmd_mux_pre_ack, 30 | input [$clog2(DRAM_BANKS)-1:0] cmd_mux_pre_grant, 31 | input [$clog2(CLK_RATIO)-1:0] cmd_mux_pre_slot,*/ 32 | output logic [DRAM_BANKS-1:0][DRAM_ADDR_WIDTH-1:0] bm_addr_o, 33 | output logic [DRAM_BANKS-1:0][$clog2(CLK_RATIO)-1:0] bm_slot_o, 34 | output logic [DRAM_BANKS-1:0][PRIORITY_WIDTH-1:0] bm_priority_o, 35 | output logic [DRAM_BANKS-1:0][FE_ID_WIDTH-1:0] bm_id_o, 36 | output logic [DRAM_BANKS-1:0] bm_act_o, 37 | output logic [DRAM_BANKS-1:0] bm_cas_o, 38 | output logic [DRAM_BANKS-1:0] bm_r_w_o, // 1=read, 0=write 39 | output logic [DRAM_BANKS-1:0] bm_pre_o, 40 | output logic [DRAM_BANKS-1:0][$clog2(DRAM_BANKS)-1:0] bm_bank_o 41 | ); 42 | 43 | /*logic [DRAM_BANKS-1:0][DRAM_ADDR_WIDTH-1:0] bm_addr_q; 44 | logic [DRAM_BANKS-1:0][$clog2(CLK_RATIO)-1:0] bm_slot_q; 45 | logic [DRAM_BANKS-1:0][PRIORITY_WIDTH-1:0] bm_priority_q; 46 | logic [DRAM_BANKS-1:0][FE_ID_WIDTH-1:0] bm_id_q; 47 | logic [DRAM_BANKS-1:0][$clog2(DRAM_BANKS)-1:0] bm_bank_q; 48 | logic [DRAM_BANKS-1:0] bm_cas_q; 49 | logic [DRAM_BANKS-1:0] bm_r_w_q; // 1=read, 0=write 50 | logic [DRAM_BANKS-1:0] bm_pre_q; 51 | logic [DRAM_BANKS-1:0][$clog2(DRAM_BANKS)-1:0] bm_bank_q;*/ 52 | 53 | 54 | always_ff @(posedge clk, negedge rst_n) 55 | begin 56 | if(rst_n == 1'b0) 57 | begin 58 | bm_addr_o <='0; 59 | bm_slot_o <='0; 60 | bm_priority_o <='0; 61 | bm_id_o <='0; 62 | bm_act_o <='0; 63 | bm_cas_o <='0; 64 | bm_r_w_o <='0; // 1=read, 0=write 65 | bm_pre_o <='0; 66 | bm_bank_o <='0; 67 | end // if (rst_n == 1'b0) 68 | else 69 | begin 70 | bm_addr_o <=bm_addr; 71 | bm_slot_o <=bm_slot; 72 | bm_priority_o <=bm_priority; 73 | bm_id_o <=bm_id; 74 | bm_act_o <=bm_act & {DRAM_BANKS{!rm_stall}}; 75 | bm_cas_o <=bm_cas & {DRAM_BANKS{!rm_stall}}; 76 | bm_r_w_o <=bm_r_w; // 1=read, 0=write 77 | bm_pre_o <=bm_pre & {DRAM_BANKS{!rm_stall}}; 78 | bm_bank_o <= bm_bank; 79 | end // else: !if(rst_n == 1'b0) 80 | end // always_ff @ (posedge clk, negedge rst_n) 81 | 82 | endmodule // bankfsm_cmdmux_if 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /implementation/syn/bus_shuffler_4/bus_shuffler_4.sv: -------------------------------------------------------------------------------- 1 | module bus_shuffler_4 2 | #( 3 | parameter BUS_SIZE = 16//Bus size of each slot in bits 4 | ) 5 | ( 6 | input [3:0][BUS_SIZE-1:0] bus_i, 7 | input [3:0] req_slot, 8 | input [3:0][1:0] req_slot_nr, 9 | 10 | output [3:0][BUS_SIZE-1:0] bus_o, 11 | output [3:0] bus_valid_o 12 | ); 13 | 14 | // This module has four input bus of width BUS_SIZE each. Data on each bus is 15 | // channelized to the respective slot requested by req_slot signal. 16 | // This operation is performed by a 1:4 demux. There are as many demux as 17 | // bus, the output of all demux is later OR'ed to combine it into one single 18 | // bus with four slots. 19 | // This mudule assumes that there are no two input request from different bus 20 | // to a same slot. 21 | 22 | logic [3:0][BUS_SIZE-1:0] demux_out [3:0]; 23 | logic [3:0] demux_valid [3:0]; 24 | 25 | assign bus_o = demux_out[0] | demux_out[1] | demux_out[2] | demux_out[3]; 26 | assign bus_valid_o = demux_valid[0] | demux_valid[1] | demux_valid[2] | 27 | demux_valid[3]; 28 | //always_comb $display("v %b", demux_valid[1]); 29 | 30 | generate 31 | for(genvar i=0; i<=3; i++) 32 | begin 33 | demux_1_4 34 | #( 35 | .WIDTH (BUS_SIZE) 36 | )demux_inst_data 37 | ( 38 | .in (bus_i[i] & {BUS_SIZE{req_slot[i]}}), 39 | .sel (req_slot_nr[i]), 40 | .out (demux_out[i]) 41 | ); 42 | demux_1_4 43 | #( 44 | .WIDTH (1) 45 | )demux_inst_valid 46 | ( 47 | .in (req_slot[i]), 48 | .sel (req_slot_nr[i]), 49 | .out (demux_valid[i]) 50 | ); 51 | end // for (genvar i=0;i<=3;i++) 52 | endgenerate 53 | endmodule // bus_shuffler_four 54 | 55 | -------------------------------------------------------------------------------- /implementation/syn/ch_ctrl_rank_fsm/ch_ctrl_rank_fsm_wrapper.sv: -------------------------------------------------------------------------------- 1 | module ch_ctrl_rank_fsm_wrapper 2 | #( 3 | parameter BANK_FIFO_DEPTH = 8, 4 | parameter ROW_ADDR_WIDTH = 15, 5 | parameter COL_ADDR_WIDTH = 10, 6 | parameter DRAM_ADDR_WIDTH = 15, 7 | parameter DRAM_CMD_WIDTH = 5, 8 | parameter DRAM_BANKS = 8, 9 | parameter DRAM_BUS_WIDTH = 8, 10 | parameter FE_ADDR_WIDTH = 28, 11 | parameter FE_CMD_WIDTH = 1, 12 | parameter FE_ID_WIDTH = 8, 13 | parameter FE_WRITE = 0, 14 | parameter CLK_RATIO = 4, 15 | parameter AREF_CNT_WIDTH = 16, 16 | parameter RFC_DRAM_CYCLES_LOG2 = 9, 17 | parameter RC_DRAM_CYCLES_LOG2 = 6, 18 | parameter RAS_DRAM_CYCLES_LOG2 = 6, 19 | parameter RP_DRAM_CYCLES_LOG2 = 4, 20 | parameter WR2PRE_DRAM_CYCLES_LOG2 = 8, 21 | parameter RD2PRE_DRAM_CYCLES_LOG2 = 8, 22 | parameter RCD_DRAM_CYCLES_LOG2 = 4, 23 | parameter RRD_DRAM_CYCLES_LOG2 = 4, 24 | parameter WR2RD_DRAM_CYCLES_LOG2 = 8, 25 | parameter RD2WR_DRAM_CYCLES_LOG2 = 8, 26 | parameter ZQS_DRAM_CYCLES_LOG2 = 7, 27 | parameter ZQSI_TREFI_CYCLES = 128 //1ms=128*tREFI. assumption:tREFI = 7.8 28 | /*parameter RRD_DRAM_CYCLES = 4, 29 | parameter WTR_DRAM_CYCLES = 4, 30 | parameter CCD_DRAM_CYCLES = 4, 31 | parameter RP_DRAM_CYCLES = 6, 32 | parameter RTP_DRAM_CYCLES = 4, 33 | parameter WR_DRAM_CYCLES = 6, 34 | parameter RCD_DRAM_CYCLES = 6, 35 | parameter RAS_DRAM_CYCLES = 15, 36 | parameter AREF_DRAM_CYCLES = 3120,//7.8us 37 | parameter RFC_DRAM_CYCLES = 44,//1Gb 110ns 38 | parameter ZQS_DRAM_CYCLES = 64, // max(64nCK, 80ns) 39 | parameter CL = 6, 40 | parameter CWL = 5, 41 | parameter TFAW_NS = 40, 42 | parameter BL = 8*/ 43 | ) 44 | ( 45 | //********* SIGNALS FROM THE FRONT END *********************** 46 | input rst_n, // Reset 47 | input clk,// System Clock 48 | input fe_req, 49 | input [FE_CMD_WIDTH-1:0] fe_cmd, 50 | input [FE_ADDR_WIDTH-1:0] fe_addr, 51 | input [FE_ID_WIDTH-1:0] fe_id, 52 | output fe_stall, 53 | // from wrapper 54 | input read_stall, 55 | input init_done, 56 | output logic init_en, 57 | //****************** SIGNALS TO THE PHY *********************** 58 | output [CLK_RATIO-1:0][DRAM_ADDR_WIDTH-1:0] rm_addr, 59 | output [CLK_RATIO-1:0][$clog2(DRAM_BANKS)-1:0] rm_bank, 60 | output [CLK_RATIO-1:0][DRAM_CMD_WIDTH-1:0] rm_cmd, 61 | output rm_valid, 62 | output [FE_ID_WIDTH-1:0] rm_cas_cmd_id, 63 | output rm_cas_cmd_id_valid,//not req 64 | output rm_write, 65 | output rm_read, 66 | output [$clog2(CLK_RATIO)-1:0] rm_cas_slot, 67 | //**************** CONFIG & TIMING INPUTS *********************** 68 | input decoder_type, 69 | input rg_en, 70 | input [3:0] RP_DRAM_CYCLES, 71 | input [3:0] RTP_DRAM_CYCLES, 72 | input [4:0] WR_DRAM_CYCLES, 73 | input [3:0] RCD_DRAM_CYCLES, 74 | input [5:0] RAS_DRAM_CYCLES, 75 | 76 | input [2:0] CCD_DRAM_CYCLES, // ccd always 4 for DDR3, Required for DDR4 77 | input [3:0] WTR_DRAM_CYCLES, // wr max 7.5 ns for DDR3 78 | input [3:0] RRD_DRAM_CYCLES, //same as WTR 79 | input [15:0] AREF_DRAM_CYCLES, 80 | input [8:0] RFC_DRAM_CYCLES, 81 | input [5:0] FAW_DRAM_CYCLES, 82 | input [6:0] ZQS_DRAM_CYCLES, 83 | input [3:0] BL, 84 | input [3:0] CWL, 85 | input [3:0] CL 86 | ); 87 | 88 | dram_global_timing_if dram_t_rm(); 89 | dram_bank_timing_if dram_t_bm(); 90 | 91 | assign dram_t_bm.RP_DRAM_CYCLES = RP_DRAM_CYCLES; 92 | assign dram_t_bm.RTP_DRAM_CYCLES = RTP_DRAM_CYCLES; 93 | assign dram_t_bm.WR_DRAM_CYCLES = WR_DRAM_CYCLES; 94 | assign dram_t_bm.RCD_DRAM_CYCLES = RCD_DRAM_CYCLES; 95 | assign dram_t_bm.RAS_DRAM_CYCLES = RAS_DRAM_CYCLES; 96 | assign dram_t_rm.CCD_DRAM_CYCLES = CCD_DRAM_CYCLES; 97 | assign dram_t_rm.WTR_DRAM_CYCLES = WTR_DRAM_CYCLES; 98 | assign dram_t_rm.RRD_DRAM_CYCLES = RRD_DRAM_CYCLES; 99 | assign dram_t_rm.AREF_DRAM_CYCLES = AREF_DRAM_CYCLES; 100 | assign dram_t_rm.RFC_DRAM_CYCLES = RFC_DRAM_CYCLES; 101 | assign dram_t_rm.FAW_DRAM_CYCLES = FAW_DRAM_CYCLES; 102 | assign dram_t_rm.ZQS_DRAM_CYCLES = ZQS_DRAM_CYCLES; 103 | assign dram_t_rm.BL = BL; 104 | assign dram_t_rm.CWL = CWL; 105 | assign dram_t_rm.CL = CL; 106 | 107 | ch_ctrl_rank_fsm 108 | #( 109 | .BANK_FIFO_DEPTH(BANK_FIFO_DEPTH), 110 | .ROW_ADDR_WIDTH(ROW_ADDR_WIDTH), 111 | .COL_ADDR_WIDTH(COL_ADDR_WIDTH), 112 | .DRAM_ADDR_WIDTH(DRAM_ADDR_WIDTH), 113 | .DRAM_CMD_WIDTH(DRAM_CMD_WIDTH), 114 | .DRAM_BANKS(DRAM_BANKS), 115 | .DRAM_BUS_WIDTH(DRAM_BUS_WIDTH), 116 | .FE_ADDR_WIDTH(FE_ADDR_WIDTH), 117 | .FE_CMD_WIDTH(FE_CMD_WIDTH), 118 | .FE_ID_WIDTH(FE_ID_WIDTH), 119 | .FE_WRITE(FE_WRITE), 120 | .CLK_RATIO(CLK_RATIO), 121 | .AREF_CNT_WIDTH(AREF_CNT_WIDTH), 122 | .RFC_DRAM_CYCLES_LOG2(RFC_DRAM_CYCLES_LOG2), 123 | .RC_DRAM_CYCLES_LOG2(RC_DRAM_CYCLES_LOG2), 124 | .RAS_DRAM_CYCLES_LOG2(RAS_DRAM_CYCLES_LOG2), 125 | .RP_DRAM_CYCLES_LOG2(RP_DRAM_CYCLES_LOG2), 126 | .WR2PRE_DRAM_CYCLES_LOG2(WR2PRE_DRAM_CYCLES_LOG2), 127 | .RD2PRE_DRAM_CYCLES_LOG2(RD2PRE_DRAM_CYCLES_LOG2), 128 | .RCD_DRAM_CYCLES_LOG2(RCD_DRAM_CYCLES_LOG2), 129 | .RRD_DRAM_CYCLES_LOG2(RRD_DRAM_CYCLES_LOG2), 130 | .WR2RD_DRAM_CYCLES_LOG2(WR2RD_DRAM_CYCLES_LOG2), 131 | .RD2WR_DRAM_CYCLES_LOG2(RD2WR_DRAM_CYCLES_LOG2), 132 | .ZQS_DRAM_CYCLES_LOG2(ZQS_DRAM_CYCLES_LOG2), 133 | .ZQSI_TREFI_CYCLES(ZQSI_TREFI_CYCLES)// ZQ short interval 134 | /*.RRD_DRAM_CYCLES(RRD_DRAM_CYCLES), 135 | .WTR_DRAM_CYCLES(WTR_DRAM_CYCLES), 136 | .CCD_DRAM_CYCLES(CCD_DRAM_CYCLES), 137 | .RP_DRAM_CYCLES(RP_DRAM_CYCLES), 138 | .RTP_DRAM_CYCLES(RTP_DRAM_CYCLES), 139 | .WR_DRAM_CYCLES(WR_DRAM_CYCLES), 140 | .RCD_DRAM_CYCLES(RCD_DRAM_CYCLES), 141 | .RAS_DRAM_CYCLES(RAS_DRAM_CYCLES), 142 | .ZQS_DRAM_CYCLES(ZQS_DRAM_CYCLES), 143 | .AREF_DRAM_CYCLES(AREF_DRAM_CYCLES), 144 | .RFC_DRAM_CYCLES(RFC_DRAM_CYCLES), 145 | .CL(CL), 146 | .CWL(CWL), 147 | .TFAW_NS(TFAW_NS), 148 | .BL(BL)*/ 149 | ) RM 150 | ( 151 | .rst_n(rst_n), 152 | .clk(clk), 153 | .fe_req(fe_req), 154 | .fe_cmd(fe_cmd), 155 | .fe_addr(fe_addr), 156 | .fe_id(fe_id), 157 | .fe_stall(fe_stall), 158 | .read_stall(read_stall), 159 | .init_done(init_done), 160 | .init_en(init_en), 161 | .rm_addr(rm_addr), 162 | .rm_bank(rm_bank), 163 | .rm_cmd(rm_cmd), 164 | .rm_valid(rm_valid), 165 | .rm_cas_cmd_id(rm_cas_cmd_id), 166 | .rm_cas_cmd_id_valid(rm_cas_cmd_id_valid), 167 | .rm_write(rm_write), 168 | .rm_read(rm_read), 169 | .rm_cas_slot(rm_cas_slot), 170 | .decoder_type(decoder_type), 171 | .rg_en(rg_en), 172 | .dram_t_rm(dram_t_rm), 173 | .dram_t_bm(dram_t_bm) 174 | ); 175 | endmodule 176 | -------------------------------------------------------------------------------- /implementation/syn/config_bus_slave/reg_bus_if.sv: -------------------------------------------------------------------------------- 1 | interface reg_bus_if 2 | #( 3 | //parameter type atype = logic, 4 | parameter ADDR_WIDTH = 8, 5 | parameter DATA_WIDTH = 8 6 | ) 7 | ( 8 | input logic clk 9 | ); 10 | logic [ADDR_WIDTH-1:0] addr; 11 | logic write;//0 = read , 1= write 12 | logic error; // 0=ok, 1= transaction error 13 | logic valid; 14 | logic ready; 15 | logic [DATA_WIDTH-1:0] wdata; 16 | logic [DATA_WIDTH/8-1:0] wstrb; // byte-wise strobe 17 | logic [DATA_WIDTH-1:0] rdata; 18 | 19 | modport slave (input clk, addr, write, wdata, wstrb, valid, 20 | output error, ready, rdata); 21 | modport master (output addr, wdata, write, wstrb, valid, 22 | input clk, error, ready, rdata); 23 | endinterface // REG_BUS 24 | -------------------------------------------------------------------------------- /implementation/syn/config_bus_slave/reg_bus_pkg.sv: -------------------------------------------------------------------------------- 1 | package reg_bus_pkg; 2 | typedef enum logic [7:0] {IDLE = 0,WTR_RRD=1,CWL_CL=2,RP_RTP=3,WR=4, 3 | BL_RCD=5,RAS=6,FAW=7,ZQS=8,AREF=9,AREF_1=10, 4 | AREF_2=11,RFC=12,RFC_1=13,DRV_IMP_RON_DATA=14, 5 | DRV_IMP_RON_ADDR=15,DRV_IMP_RTT_DATA=16,DRV_SLEW=17, 6 | MR0=18,MR0_1=19,MR1=20,MR1_1=21,MR2=22, 7 | MR2_1=23,MR3=24,MR3_1=25,RG_REF_START_ADDR=26, 8 | RG_REF_START_ADDR_1=27,RG_REF_END_ADDR=28, 9 | RG_REF_END_ADDR_1=29,RG_REF_NUM_ROW_PER_REF=30, 10 | RG_REF_EN_RASMIN=31,RG_REF_RP_RRD=32, 11 | DRV_OCD_CAL_PU=33,DRV_OCD_CAL_PD=34, 12 | DRV_OCD_CAL_DIS=35,DQS_OFFSET=36,DQS_OFFSET_1=37, 13 | CLK_OFFSET=38,CLK_OFFSET_1=39,DISABLE_REF=40, 14 | TREG_END=41,DRV_END=42,MODE_END=43,RG_REF_END=44, 15 | RD_STATUS_MC=45,RD_STATUS_PHY_10=46, 16 | RD_STATUS_PHY_11=47,RD_STATUS_PHY_12=48, 17 | RD_STATUS_PHY_13=49,RD_STATUS_PHY_20=50, 18 | RD_STATUS_PHY_21=51,RD_STATUS_PHY_22=52, 19 | RD_STATUS_PHY_23=53,RD_STATUS_INIT_1=54, 20 | RD_STATUS_INIT_2=55,BYPASS_BUS_RDY=56, 21 | DRV_DLL_CAL_DIS=57,CONGEN_C3=58, 22 | CONGEN_C4=59,CONGEN_C5=60, 23 | CONGEN_C6=61,CONGEN_C7=62,CONGEN_C8=63, 24 | CONGEN_C9=64,CONGEN_C10=65,CONGEN_R0=66, 25 | CONGEN_R1=67,CONGEN_R2=68,CONGEN_R3=69, 26 | CONGEN_R4=70,CONGEN_R5=71,CONGEN_R6=72, 27 | CONGEN_R7=73,CONGEN_R8=74,CONGEN_R9=75, 28 | CONGEN_R10=76,CONGEN_R11=77,CONGEN_R12=78, 29 | CONGEN_R13=79,CONGEN_R14=80,CONGEN_R15=81, 30 | CONGEN_B0=82,CONGEN_B1=83,CONGEN_B2=84, 31 | CONGEN_XOR_SEL=85,CONGEN_END=86} REG_BUS_FRAMES; 32 | endpackage: reg_bus_pkg 33 | -------------------------------------------------------------------------------- /implementation/syn/congen/congen.v: -------------------------------------------------------------------------------- 1 | // Authors: Matthias Jung (2017) and Chirag Sudarshan 2 | 3 | module mux (input [31:0] in, input [4:0] addr, output logic out); 4 | 5 | always @(in) 6 | case (addr) 7 | 5'd0 : out = in[ 0]; 8 | 5'd1 : out = in[ 1]; 9 | 5'd2 : out = in[ 2]; 10 | 5'd3 : out = in[ 3]; 11 | 5'd4 : out = in[ 4]; 12 | 5'd5 : out = in[ 5]; 13 | 5'd6 : out = in[ 6]; 14 | 5'd7 : out = in[ 7]; 15 | 5'd8 : out = in[ 8]; 16 | 5'd9 : out = in[ 9]; 17 | 5'd10 : out = in[10]; 18 | 5'd11 : out = in[11]; 19 | 5'd12 : out = in[12]; 20 | 5'd13 : out = in[13]; 21 | 5'd14 : out = in[14]; 22 | 5'd15 : out = in[15]; 23 | 5'd16 : out = in[16]; 24 | 5'd17 : out = in[17]; 25 | 5'd18 : out = in[18]; 26 | 5'd19 : out = in[19]; 27 | 5'd20 : out = in[20]; 28 | 5'd21 : out = in[21]; 29 | 5'd22 : out = in[22]; 30 | 5'd23 : out = in[23]; 31 | 5'd24 : out = in[24]; 32 | 5'd25 : out = in[25]; 33 | 5'd26 : out = in[26]; 34 | 5'd27 : out = in[27]; 35 | 5'd28 : out = in[28]; 36 | 5'd29 : out = in[29]; 37 | 5'd30 : out = in[30]; 38 | 5'd31 : out = in[31]; 39 | endcase 40 | endmodule 41 | 42 | /*module congen 43 | ( 44 | input [32-1:0] in, 45 | input [5*ADDR_WIDTH-1:0] conf, 46 | output reg [32-1:0] out 47 | ); 48 | 49 | assign out[0] = in[0]; // C0 50 | assign out[1] = in[1]; // C1 51 | assign out[2] = in[2]; // C2 52 | 53 | genvar i; 54 | 55 | generate 56 | for (i=3;i<32;i++) 57 | begin 58 | mux mux (in, conf[(i-3)*5 +: 5], out[i]); 59 | end 60 | endgenerate 61 | */ 62 | module congen (input [31:0] in, input [144:0] conf, output reg [31:0] out); 63 | 64 | assign out[0] = in[0]; // C0 65 | assign out[1] = in[1]; // C1 66 | assign out[2] = in[2]; // C2 67 | mux mux0 ({3'd0,in[31:3]}, conf[ 4:0], out[ 3]); 68 | mux mux1 ({3'd0,in[31:3]}, conf[ 9:5], out[ 4]); 69 | mux mux2 ({3'd0,in[31:3]}, conf[ 14:10], out[ 5]); 70 | mux mux3 ({3'd0,in[31:3]}, conf[ 19:15], out[ 6]); 71 | mux mux4 ({3'd0,in[31:3]}, conf[ 24:20], out[ 7]); 72 | mux mux5 ({3'd0,in[31:3]}, conf[ 29:25], out[ 8]); 73 | mux mux6 ({3'd0,in[31:3]}, conf[ 34:30], out[ 9]); 74 | mux mux7 ({3'd0,in[31:3]}, conf[ 39:35], out[10]); 75 | mux mux8 ({3'd0,in[31:3]}, conf[ 44:40], out[11]); 76 | mux mux9 ({3'd0,in[31:3]}, conf[ 49:45], out[12]); 77 | mux mux10 ({3'd0,in[31:3]}, conf[ 54:50], out[13]); 78 | mux mux11 ({3'd0,in[31:3]}, conf[ 59:55], out[14]); 79 | mux mux12 ({3'd0,in[31:3]}, conf[ 64:60], out[15]); 80 | mux mux13 ({3'd0,in[31:3]}, conf[ 69:65], out[16]); 81 | mux mux14 ({3'd0,in[31:3]}, conf[ 74:70], out[17]); 82 | mux mux15 ({3'd0,in[31:3]}, conf[ 79:75], out[18]); 83 | mux mux16 ({3'd0,in[31:3]}, conf[ 84:80], out[19]); 84 | mux mux17 ({3'd0,in[31:3]}, conf[ 89:85], out[20]); 85 | mux mux18 ({3'd0,in[31:3]}, conf[ 94:90], out[21]); 86 | mux mux19 ({3'd0,in[31:3]}, conf[ 99:95], out[22]); 87 | mux mux20 ({3'd0,in[31:3]}, conf[104:100], out[23]); 88 | mux mux21 ({3'd0,in[31:3]}, conf[109:105], out[24]); 89 | mux mux22 ({3'd0,in[31:3]}, conf[114:110], out[25]); 90 | mux mux23 ({3'd0,in[31:3]}, conf[119:115], out[26]); 91 | mux mux24 ({3'd0,in[31:3]}, conf[124:120], out[27]); 92 | mux mux25 ({3'd0,in[31:3]}, conf[129:125], out[28]); 93 | mux mux26 ({3'd0,in[31:3]}, conf[134:130], out[29]); 94 | mux mux27 ({3'd0,in[31:3]}, conf[139:135], out[30]); 95 | mux mux28 ({3'd0,in[31:3]}, conf[144:140], out[31]); 96 | 97 | endmodule 98 | -------------------------------------------------------------------------------- /implementation/syn/mem_ctrl/mem_ctrl_if.sv: -------------------------------------------------------------------------------- 1 | // bank independent timing DDR3 specific 2 | interface dram_global_timing_if; 3 | logic [2:0] CCD_DRAM_CYCLES; // ccd always 4 for DDR3, Required for DDR4 4 | logic [3:0] WTR_DRAM_CYCLES; // wr max 7.5 ns for DDR3 5 | logic [3:0] RRD_DRAM_CYCLES; //same as WTR 6 | `ifdef DDR4 7 | logic [2:0] CCD_DRAM_CYCLES_L; 8 | logic [3:0] WTR_DRAM_CYCLES_L; 9 | logic [3:0] RRD_DRAM_CYCLES_L; 10 | `endif 11 | //logic [15:0] AREF_DRAM_CYCLES; 12 | //logic [8:0] RFC_DRAM_CYCLES; 13 | logic [5:0] FAW_DRAM_CYCLES; 14 | //logic [6:0] ZQS_DRAM_CYCLES; 15 | logic [3:0] BL; 16 | logic [3:0] CWL; 17 | logic [3:0] CL; 18 | 19 | modport wp (input CCD_DRAM_CYCLES,WTR_DRAM_CYCLES, 20 | RRD_DRAM_CYCLES, 21 | `ifdef DDR4 22 | input CCD_DRAM_CYCLES_L,WTR_DRAM_CYCLES_L, 23 | RRD_DRAM_CYCLES_L, 24 | `endif 25 | /*AREF_DRAM_CYCLES, 26 | RFC_DRAM_CYCLES,*/input FAW_DRAM_CYCLES,/*ZQS_DRAM_CYCLES,*/ 27 | BL,CWL,CL); 28 | modport rp (output CCD_DRAM_CYCLES,WTR_DRAM_CYCLES, 29 | RRD_DRAM_CYCLES, 30 | `ifdef DDR4 31 | output CCD_DRAM_CYCLES_L,WTR_DRAM_CYCLES_L, 32 | RRD_DRAM_CYCLES_L, 33 | `endif 34 | /*RFC_DRAM_CYCLES,AREF_DRAM_CYCLES,*/ 35 | output FAW_DRAM_CYCLES,/*ZQS_DRAM_CYCLES,*/BL,CWL,CL); 36 | //modport mc_port (input CCD_DRAM_CYCLES,WTR_DRAM_CYCLES,RRD_DRAM_CYCLES, 37 | // AREF_DRAM_CYCLES,RFC_DRAM_CYCLES,FAW_DRAM_CYCLES,BL,CWL,CL); 38 | endinterface // dram_timing_global 39 | 40 | // bank specific timing 41 | interface dram_bank_timing_if; 42 | logic [3:0] RP_DRAM_CYCLES; 43 | logic [3:0] RTP_DRAM_CYCLES; 44 | logic [4:0] WR_DRAM_CYCLES; 45 | logic [3:0] RCD_DRAM_CYCLES; 46 | logic [5:0] RAS_DRAM_CYCLES; 47 | 48 | modport wp (input RP_DRAM_CYCLES,RTP_DRAM_CYCLES, 49 | WR_DRAM_CYCLES,RCD_DRAM_CYCLES,RAS_DRAM_CYCLES); 50 | modport rp (output RP_DRAM_CYCLES,RTP_DRAM_CYCLES, 51 | WR_DRAM_CYCLES,RCD_DRAM_CYCLES,RAS_DRAM_CYCLES); 52 | //modport mc_port (input RP_DRAM_CYCLES,RTP_DRAM_CYCLES,WR_DRAM_CYCLES, 53 | // RCD_DRAM_CYCLES,RAS_DRAM_CYCLES); 54 | endinterface // dram_timing_bank 55 | 56 | interface dram_aref_zq_timing_if; 57 | logic [19:0] AREFI_DRAM_CYCLES; 58 | logic [8:0] RFC_DRAM_CYCLES; 59 | logic [6:0] ZQS_DRAM_CYCLES; 60 | logic ZQS_DISABLE; 61 | logic DISABLE_REF; 62 | 63 | modport wp (input AREFI_DRAM_CYCLES,RFC_DRAM_CYCLES,ZQS_DRAM_CYCLES,ZQS_DISABLE,DISABLE_REF); 64 | modport rp (output AREFI_DRAM_CYCLES,RFC_DRAM_CYCLES,ZQS_DRAM_CYCLES,ZQS_DISABLE,DISABLE_REF); 65 | 66 | endinterface // dram_ref_zq_timing_if 67 | 68 | interface dram_rg_ref_if 69 | #( 70 | parameter DRAM_ADDR_WIDTH = 15 71 | ) 72 | (); 73 | logic [DRAM_ADDR_WIDTH-1:0] start_addr; 74 | logic [DRAM_ADDR_WIDTH-1:0] end_addr; 75 | logic [5:0] num_row_per_ref; // per bank 76 | logic [3:0] rrd_dram_clk_cycle; 77 | logic [5:0] ras_dram_clk_cycle; 78 | logic [3:0] rp_dram_clk_cycle; 79 | logic en; 80 | 81 | modport wp (input start_addr,end_addr,num_row_per_ref, 82 | rrd_dram_clk_cycle,ras_dram_clk_cycle, 83 | rp_dram_clk_cycle,en); 84 | modport rp (output start_addr,end_addr,num_row_per_ref, 85 | rrd_dram_clk_cycle,ras_dram_clk_cycle, 86 | rp_dram_clk_cycle,en); 87 | 88 | endinterface // dram_rg_ref_if 89 | 90 | 91 | 92 | interface mode_reg_config_if; // mode reg 93 | logic [15:0] mr0; 94 | logic [15:0] mr1; 95 | logic [15:0] mr2; 96 | logic [15:0] mr3; 97 | 98 | 99 | modport wp (input mr0,mr1,mr2,mr3); 100 | modport rp (output mr0,mr1,mr2,mr3); 101 | endinterface 102 | 103 | interface phy_config_if; 104 | // IMPEDANCE SELECTION 105 | logic [4:0] ron_data; 106 | logic [4:0] rtt_data; 107 | logic [4:0] ron_adr_cmd; 108 | // IMPEDANCE CALIBRATION OVERRIGHT DEBUG 109 | logic [4:0] pu_en_ocd_cal; 110 | logic [4:0] pd_en_ocd_cal; 111 | logic disable_ocd_cal; 112 | // SLEW RATE CONFIG 113 | logic [1:0] td_ctrl_n_data; 114 | logic tdqs_trim_n_data; 115 | logic [1:0] td_ctrl_n_adr_cmd; 116 | logic tdqs_trim_n_adr_cmd; 117 | 118 | // PHY Side 119 | //*************************************** 120 | modport phy 121 | ( 122 | input ron_data, input rtt_data, input ron_adr_cmd, 123 | input pu_en_ocd_cal, input pd_en_ocd_cal, input disable_ocd_cal, 124 | input td_ctrl_n_data, input tdqs_trim_n_data, input td_ctrl_n_adr_cmd, 125 | input tdqs_trim_n_adr_cmd); 126 | // DRAM INIT UNIT Side 127 | //*************************************** 128 | modport mem_cntrl 129 | ( 130 | output ron_data, output rtt_data, output ron_adr_cmd, 131 | output pu_en_ocd_cal, output pd_en_ocd_cal, output disable_ocd_cal, 132 | output td_ctrl_n_data, output tdqs_trim_n_data, output td_ctrl_n_adr_cmd, 133 | output tdqs_trim_n_adr_cmd); 134 | endinterface // if_dram_init 135 | 136 | interface congen_if; 137 | logic [4:0] c3; 138 | logic [4:0] c4; 139 | logic [4:0] c5; 140 | logic [4:0] c6; 141 | logic [4:0] c7; 142 | logic [4:0] c8; 143 | logic [4:0] c9; 144 | logic [4:0] c10; 145 | logic [4:0] r0; 146 | logic [4:0] r1; 147 | logic [4:0] r2; 148 | logic [4:0] r3; 149 | logic [4:0] r4; 150 | logic [4:0] r5; 151 | logic [4:0] r6; 152 | logic [4:0] r7; 153 | logic [4:0] r8; 154 | logic [4:0] r9; 155 | logic [4:0] r10; 156 | logic [4:0] r11; 157 | logic [4:0] r12; 158 | logic [4:0] r13; 159 | logic [4:0] r14; 160 | logic [4:0] r15; 161 | logic [4:0] b0; 162 | logic [4:0] b1; 163 | logic [4:0] b2; 164 | `ifdef DDR4 165 | logic [4:0] b3; 166 | logic [4:0] r16; 167 | `endif 168 | logic [2:0] xor_sel; 169 | 170 | modport wp (input c3,c4,c5,c6,c7,c8,c9,c10, 171 | r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14,r15, 172 | b0,b1,b2, 173 | `ifdef DDR4 174 | input b3, r16, 175 | `endif 176 | input xor_sel 177 | ); 178 | modport rp (output c3,c4,c5,c6,c7,c8,c9,c10, 179 | r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14,r15, 180 | b0,b1,b2, 181 | `ifdef DDR4 182 | output b3, r16, 183 | `endif 184 | input xor_sel); 185 | endinterface // congen_if 186 | 187 | -------------------------------------------------------------------------------- /implementation/syn/xiphy_if/bit_packing_xiphy_ultrascale.sv: -------------------------------------------------------------------------------- 1 | // This module packs the bits as specified in Xilinx PG150 (October 30, 2019) page 167. 2 | // Xilinx ultrascale phy requires the bits to be packed in a certain pattern. 3 | // for more details refer the following link 4 | // https://www.xilinx.com/support/documentation/ip_documentation/ultrascale_memory_ip/v1_4/pg150-ultrascale-memory-ip.pdf#page=167 5 | 6 | module bit_packing_xiphy_ultrascale 7 | #( 8 | parameter DATA_WIDTH = 8, 9 | parameter CLK_RATIO = 4, 10 | parameter DUPLICATES = 2 11 | ) 12 | ( 13 | input [CLK_RATIO-1:0][DATA_WIDTH-1:0] data_i, 14 | output [DATA_WIDTH-1:0][CLK_RATIO-1:0][DUPLICATES-1:0] data_o 15 | ); 16 | 17 | genvar i,j; 18 | 19 | generate 20 | for(i=0; i 0) ? int' (A/B) +1 : int' (A/B))) 85 | 86 | // Min Function 87 | `define EVAL_MIN(A,B) ((A>B)? B : A) 88 | 89 | // Max Function 90 | `define EVAL_MAX(A,B) ((A>B)? A : B) 91 | 92 | // Address Offset based on the width of the data bus (W:bits), and the number of words to fetch (N) 93 | `define ADDRESS_OFFSET(N,W) (`EVAL_LOG2(N)+`EVAL_LOG2(W/8)) 94 | 95 | //////////////////////////////////////////////////////////////////////////// 96 | 97 | // This is the system fast clock, and can be different from DRAM Clock (CLK_PERIOD_DRAM) 98 | //`define CLK_PERIOD_SYS 1.0 99 | 100 | // Colors (Only usable in linux shell) 101 | `define COLOR_NONE "\033[0m" 102 | `define COLOR_RED "\033[1;31m" 103 | `define COLOR_GREEN "\033[1;32m" 104 | `define COLOR_YELLOW "\033[1;33m" 105 | `define COLOR_BLUE "\033[1;34m" 106 | `define COLOR_VIOLET "\033[1;35m" 107 | 108 | // Errors defined in the Generic TGEN 109 | 110 | `define NAN 2000000000 111 | 112 | `ifndef SYNTHESIS 113 | // Generate a random number up to the limit 114 | //****************************** 115 | function longint RANDOM; 116 | input longint LIMIT; 117 | begin 118 | if ( LIMIT == 0 || LIMIT == 1 ) 119 | return 0; 120 | return {$random} % LIMIT; 121 | end 122 | endfunction; 123 | 124 | // Cleanup a string to convert it to a file name 125 | //****************************** 126 | function string cleanup_string; 127 | input string s; 128 | integer k; 129 | begin 130 | for ( k=0; k < s.len(); k++ ) 131 | begin 132 | if ( 133 | s.getc(k) == "[" || 134 | s.getc(k) == "]" || 135 | s.getc(k) == "/" || 136 | s.getc(k) == "\\" 137 | ) s.putc(k,"_"); 138 | end 139 | return s; 140 | end 141 | endfunction; 142 | `endif 143 | 144 | `ifdef SYNTHESIS 145 | `define DONT_CARE '0 146 | `else 147 | `define DONT_CARE 'X 148 | `endif 149 | 150 | 151 | `define nbits_ch (byte'(`EVAL_LOG2(`N_INIT_PORT))) // Channel bits 152 | `define nbits_lb (byte'(`EVAL_LOG2(`BANKS_PER_VAULT))) // Layer + Bank bits 153 | `define nbits_of (byte'(`EVAL_LOG2(`CH_BURST_LENGTH * `DRAM_BUS_WIDTH / 8))) // Offset bits 154 | `define nbits_rc (byte'(`row_size+`column_size-`EVAL_LOG2(`CH_BURST_LENGTH))) // Row+Col bits 155 | 156 | /******************************************************/ 157 | ///////params_axi//////////////// 158 | /******************************************************/ 159 | `ifndef PARAMS_AXI_HEADER 160 | `define PARAMS_AXI_HEADER 161 | 162 | `define OKAY 2'b00 163 | `define EXOKAY 2'b01 164 | `define SLVERR 2'b10 165 | `define DECERR 2'b11 166 | 167 | // `define N_INIT_PORT 8 168 | // `define N_TARG_PORT 5 169 | // `define N_REGION 4 170 | // `define AXI_ID_IN 8 // ID Before the AXI Interconnect 171 | // `define AXI_DATA_W 32 172 | // `define AXI_BURST_LENGTH 8 173 | `define AXI_USER_W 10 174 | `define AXI_ADDRESS_W 32 175 | 176 | `define AXI_NUMBYTES `AXI_DATA_W/8 177 | //`define AXI_ID_OUT `AXI_ID_IN + `EVAL_LOG2(`N_TARG_PORT) // ID After the AXI Interconnect 178 | `define AXI_OFFSET_BITS (`EVAL_LOG2(`AXI_DATA_W) - 3) // Lowest bits of address which should be ignored 179 | `define AXI_BURST_LENGTH_LOG2 (`EVAL_LOG2(`AXI_BURST_LENGTH)) 180 | `define CONV_TO_AXI_BURST(BURST) ((BURST+1)/`DATA_WIDTH_RATIO-1) 181 | 182 | `endif 183 | -------------------------------------------------------------------------------- /ips/ems_lib/axi_tgen/verif_utils.sv: -------------------------------------------------------------------------------- 1 | 2 | // AXI Command 3 | //******************************* 4 | typedef struct { 5 | logic [AXI4_ID_WIDTH-1:0] id; 6 | logic [AXI4_ADDRESS_WIDTH-1:0] address; 7 | logic [ AXI4_USER_WIDTH-1:0] user; 8 | integer length; 9 | time issue_time; 10 | `ifdef GEM5_CLOSEDLOOP_MODELSIM 11 | logic RWB; // R=1, W=0 12 | longint unsigned original_address; 13 | `endif 14 | } COMMAND; 15 | 16 | // AXI Data 17 | //******************************* 18 | typedef struct { 19 | logic [AXI4_ID_WIDTH-1:0] id; 20 | logic [`AXI_BURST_LENGTH-1:0][AXI4_RDATA_WIDTH-1:0] rdata; 21 | logic [`AXI_BURST_LENGTH-1:0][AXI_NUMBYTES-1:0] be; 22 | integer length; 23 | } DATA; 24 | 25 | // Pending transactions which have not been injected yet 26 | // This way we can decouple generation of transactions from their 27 | // injection, and MAT will become more natural 28 | COMMAND pending_AWLIST[$]; 29 | DATA pending_WLIST[$]; 30 | COMMAND pending_ARLIST[$]; 31 | 32 | // Keep track of the transaction which are already injected 33 | COMMAND AWLIST[$]; 34 | COMMAND ARLIST[$]; 35 | DATA RLIST[$]; 36 | 37 | // New command 38 | //******************************* 39 | function COMMAND new_command; 40 | input logic [AXI4_ID_WIDTH-1:0] id; 41 | input logic [AXI4_ADDRESS_WIDTH-1:0] address; 42 | input integer length; 43 | COMMAND cmd; 44 | begin 45 | cmd.id = id; 46 | cmd.address = address; 47 | cmd.length = length; 48 | cmd.issue_time = $time; 49 | return cmd; 50 | end 51 | endfunction 52 | 53 | // New data 54 | //******************************* 55 | function DATA new_data; 56 | input logic [AXI4_ID_WIDTH-1:0] id; 57 | input logic [AXI4_WDATA_WIDTH-1:0] rdata; 58 | input integer length; 59 | input [`AXI_BURST_LENGTH-1:0][AXI_NUMBYTES-1:0] be; 60 | DATA dta; 61 | begin 62 | dta.id = id; 63 | dta.rdata = rdata; 64 | dta.length = length; 65 | dta.be = be; 66 | return dta; 67 | end 68 | endfunction 69 | 70 | // Print command 71 | //******************************* 72 | task print_command; 73 | input COMMAND CMD; 74 | input string NAME; 75 | begin 76 | $write(, "... COMMAND:%s|ID:%d|A:%h|L:%d|@%d(ns)\n", NAME, CMD.id, CMD.address, CMD.length, $time); 77 | end 78 | endtask 79 | 80 | // Print data 81 | //******************************* 82 | task print_data; 83 | input DATA DTA; 84 | input string NAME; 85 | begin 86 | $write(, "... DATA:%s|ID:%d|D:%h|L:%d|@%d(ns)\n", NAME, DTA.id, DTA.rdata, DTA.length, $time); 87 | end 88 | endtask 89 | 90 | // Print command list 91 | //******************************* 92 | task print_command_list; 93 | input COMMAND LIST[$]; 94 | input string NAME; 95 | begin 96 | $write("........................................\n"); 97 | $write("COMMAND_LIST:%s @%d(ns)\n", NAME, $time); 98 | for (i=0; i < LIST.size();i++) 99 | begin 100 | $write(" %d)ID:%d|A:%h|L:%d\n", i, LIST[i].id, LIST[i].address, LIST[i].length); 101 | end 102 | $write("........................................\n"); 103 | end 104 | endtask 105 | 106 | // Print data list 107 | //******************************* 108 | task print_data_list; 109 | input DATA LIST[$]; 110 | input string NAME; 111 | begin 112 | $write("........................................\n"); 113 | $write("DATA_LIST:%s @%d(ns)\n", NAME, $time); 114 | for (i=0; i < LIST.size();i++) 115 | begin 116 | $write(" %d)ID:%d|D:%h|L:%h\n", i, LIST[i].id, LIST[i].rdata, LIST[i].length); 117 | end 118 | $write("........................................\n"); 119 | end 120 | endtask 121 | 122 | // Search command list (Associative) 123 | //******************************* 124 | function COMMAND search_command_list; 125 | input COMMAND LIST[$]; 126 | input logic [AXI4_ID_WIDTH-1:0] id; 127 | output integer search_index; 128 | COMMAND obj; 129 | logic found; 130 | begin 131 | found = '0; 132 | for (i=0; i < LIST.size();i++) 133 | if ( LIST[i].id == id ) 134 | begin 135 | if ( !found ) 136 | begin 137 | obj = LIST[i]; 138 | found = '1; 139 | search_index = i; 140 | end 141 | else 142 | $error("Two command with the same ID were found in the list! (ID=%h(h))", id); 143 | end 144 | if ( !found ) 145 | $error("Command not found in the list! (ID=%h(h))", id ); 146 | 147 | return obj; 148 | end 149 | endfunction 150 | 151 | // Search data list (Associative) 152 | //******************************* 153 | function DATA search_data_list; 154 | input DATA LIST[$]; 155 | input logic [AXI4_ID_WIDTH-1:0] id; 156 | output integer search_index; 157 | DATA obj; 158 | logic found; 159 | begin 160 | found = '0; 161 | for (i=0; i < LIST.size();i++) 162 | if ( LIST[i].id == id ) 163 | begin 164 | if ( !found ) 165 | begin 166 | obj = LIST[i]; 167 | found = '1; 168 | search_index = i; 169 | end 170 | else 171 | $error("Two data with the same ID were found in the list! (ID=%d)", id); 172 | end 173 | if ( !found ) 174 | $error("Data not found in the list! (ID=%d)", id); 175 | 176 | return obj; 177 | end 178 | endfunction 179 | 180 | // Pop AWLIST 181 | //******************************* 182 | function COMMAND pop_AWLIST; 183 | input logic [AXI4_ID_WIDTH-1:0] id; 184 | COMMAND obj; 185 | integer search_index; 186 | begin 187 | obj = search_command_list(AWLIST, id, search_index); // Just to check for errors 188 | AWLIST.delete(search_index); 189 | return obj; 190 | end 191 | endfunction 192 | 193 | // Pop ARLIST 194 | //******************************* 195 | function COMMAND pop_ARLIST; 196 | input logic [AXI4_ID_WIDTH-1:0] id; 197 | COMMAND obj; 198 | integer search_index; 199 | begin 200 | obj = search_command_list(ARLIST, id, search_index); // Just to check for errors 201 | ARLIST.delete(search_index); 202 | return obj; 203 | end 204 | endfunction 205 | 206 | // Pop RLIST 207 | //******************************* 208 | function DATA pop_RLIST; 209 | input logic [AXI4_ID_WIDTH-1:0] id; 210 | DATA obj; 211 | integer search_index; 212 | begin 213 | obj = search_data_list(RLIST, id, search_index); // Just to check for errors 214 | RLIST.delete(search_index); 215 | return obj; 216 | end 217 | endfunction 218 | -------------------------------------------------------------------------------- /ips/ems_lib/comp_sel_grt/comp_sel_grt.sv: -------------------------------------------------------------------------------- 1 | module comp_sel_grt 2 | #( 3 | parameter DATA_WIDTH = 16 4 | ) 5 | ( 6 | input [DATA_WIDTH-1:0] in_a, 7 | input [DATA_WIDTH-1:0] in_b, 8 | output [DATA_WIDTH -1:0] out 9 | ); 10 | 11 | // This module ouputs the greater value signal among 2 input signals. 12 | 13 | assign out=(in_a > in_b)?in_a:in_b; 14 | endmodule // comp_sel_grt 15 | -------------------------------------------------------------------------------- /ips/ems_lib/demux_1_4/demux_1_4.sv: -------------------------------------------------------------------------------- 1 | module demux_1_4 2 | #( 3 | parameter WIDTH = 16, 4 | parameter INVERTED_OUTPUT = 0 5 | ) 6 | ( 7 | input [WIDTH-1:0] in, 8 | input [1:0] sel, 9 | output logic [3:0][WIDTH-1:0] out 10 | ); 11 | 12 | logic [WIDTH-1:0] in_lcl; 13 | 14 | assign in_lcl = (INVERTED_OUTPUT==0)?in:~in; 15 | 16 | always_comb 17 | begin 18 | out = 0; 19 | if(INVERTED_OUTPUT!=0) 20 | out = '1; 21 | case(sel) 22 | 0: begin 23 | out[0] = in_lcl; 24 | end 25 | 1: begin 26 | out[1] = in_lcl; 27 | end 28 | 2: begin 29 | out[2] = in_lcl; 30 | end 31 | 3: begin 32 | out[3] = in_lcl; 33 | end 34 | default: begin 35 | out[0] = in_lcl; 36 | end 37 | endcase // case (sel) 38 | end // always_comb 39 | endmodule // demux_1_4 40 | -------------------------------------------------------------------------------- /ips/ems_lib/dual_clock_fifo/dual_clock_fifo.sv: -------------------------------------------------------------------------------- 1 | // Copyright 2018 ETH Zurich and TU Kaiserslautern. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 0.51 (the “License”); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | module dual_clock_fifo 12 | #( 13 | parameter DATA_WIDTH = 64, 14 | parameter DATA_DEPTH = 8 15 | ) 16 | ( 17 | input logic clk, 18 | input logic rst_n, 19 | //PUSH SIDE input 20 | input logic [DATA_WIDTH-1:0] data_i, 21 | input logic clk_valid_i, // incr. iptr 22 | output logic grant_o, // not_full 23 | //POP SIDE output 24 | output logic [DATA_WIDTH-1:0] data_o, 25 | output logic valid_o, // not_empty 26 | input logic grant_i // incr. optr 27 | ); 28 | 29 | 30 | // Local Parameter 31 | localparam ADDR_DEPTH = $clog2(DATA_DEPTH); 32 | 33 | 34 | // Internal Signals 35 | 36 | 37 | logic [ADDR_DEPTH-1:0] opntr; 38 | logic [ADDR_DEPTH-1:0] ipntr, ipntr_neg; // ipntr_syc; 39 | logic [DATA_WIDTH-1:0] fifo_latches[DATA_DEPTH-1:0]; 40 | integer i; 41 | 42 | assign grant_o = 1'b1; //Not used! 43 | 44 | 45 | 46 | // ocntr - 47 | always_ff @(negedge clk, negedge rst_n) 48 | begin 49 | if(rst_n == 1'b0) 50 | begin 51 | opntr <= {ADDR_DEPTH {1'b0}}; 52 | // ipntr_syc <= {ADDR_DEPTH {1'b0}}; 53 | end 54 | else 55 | begin 56 | // ipntr_syc <= ipntr_neg; 57 | opntr <= opntr; 58 | if(grant_i && valid_o) 59 | begin 60 | if (opntr == DATA_DEPTH-1) 61 | opntr <= {ADDR_DEPTH {1'b0}}; 62 | else 63 | opntr <= opntr + 1'b1; 64 | end 65 | end 66 | end 67 | 68 | always_ff @(negedge clk, negedge rst_n) 69 | begin 70 | if(rst_n == 1'b0) 71 | begin 72 | ipntr_neg <= {ADDR_DEPTH {1'b0}}; 73 | end 74 | else 75 | begin 76 | ipntr_neg <= ipntr; 77 | end 78 | end 79 | 80 | 81 | // opntr equal ipntr 82 | always_comb 83 | begin 84 | if (opntr == ipntr_neg) begin 85 | valid_o = 1'b0; 86 | end 87 | else begin 88 | valid_o = 1'b1; 89 | end 90 | end // always_comb 91 | 92 | // icntr - 93 | always_ff @(negedge clk_valid_i, negedge rst_n) 94 | begin 95 | if(rst_n == 1'b0) 96 | begin 97 | ipntr <= {ADDR_DEPTH {1'b0}}; 98 | end 99 | else 100 | begin 101 | if (ipntr == DATA_DEPTH-1) 102 | ipntr <= {ADDR_DEPTH {1'b0}}; 103 | else 104 | ipntr <= ipntr + 1'b1; 105 | end 106 | end 107 | 108 | 109 | // Fifo Latches 110 | 111 | always_ff @(negedge clk_valid_i, negedge rst_n) 112 | begin 113 | if(rst_n == 1'b0) 114 | begin 115 | for (i=0; i< DATA_DEPTH; i++) 116 | fifo_latches[i] <= {DATA_WIDTH {1'b0}}; 117 | end 118 | else 119 | begin 120 | fifo_latches[ipntr] <= data_i; 121 | end 122 | end 123 | 124 | assign data_o = fifo_latches[opntr]; 125 | 126 | endmodule // dual_clock_fifo 127 | -------------------------------------------------------------------------------- /ips/ems_lib/generic_fifo/bram_fifo_512x64.sv: -------------------------------------------------------------------------------- 1 | module bram_fifo_512x64 2 | #( 3 | //Don't change 4 | parameter DATA_WIDTH = 512, 5 | parameter DATA_DEPTH = 64 6 | ) 7 | ( 8 | input logic clk, 9 | input logic rst_n, 10 | //PUSH SIDE 11 | input logic [DATA_WIDTH-1:0] data_i, 12 | input logic valid_i, 13 | output logic grant_o, 14 | //POP SIDE 15 | output logic [DATA_WIDTH-1:0] data_o, 16 | output logic valid_o, 17 | input logic grant_i, 18 | 19 | input logic test_mode_i 20 | ); 21 | 22 | 23 | // Local Parameter 24 | localparam ADDR_DEPTH = $clog2(DATA_DEPTH); 25 | enum logic [1:0] { EMPTY, FULL, MIDDLE } CS, NS; 26 | // Internal Signals 27 | 28 | logic gate_clock; 29 | logic clk_gated; 30 | 31 | logic [ADDR_DEPTH-1:0] Pop_Pointer_CS, Pop_Pointer_NS; 32 | logic [ADDR_DEPTH-1:0] Push_Pointer_CS, Push_Pointer_NS; 33 | logic [ADDR_DEPTH-1:0] Pop_Pointer_BRAM; 34 | logic [DATA_WIDTH-1:0] FIFO_REGISTERS[DATA_DEPTH-1:0]; 35 | integer i; 36 | logic [DATA_WIDTH-1:0] data_i_q, data_o_BRAM; 37 | logic BRAM_overlap_d,BRAM_overlap_q; 38 | 39 | assign data_o = BRAM_overlap_q?data_i_q:data_o_BRAM; 40 | 41 | 42 | 43 | // Parameter Check 44 | // synopsys translate_off 45 | initial 46 | begin : parameter_check 47 | integer param_err_flg; 48 | param_err_flg = 0; 49 | 50 | if (DATA_WIDTH < 1) 51 | begin 52 | param_err_flg = 1; 53 | $display("ERROR: %m :\n Invalid value (%d) for parameter DATA_WIDTH \ 54 | (legal range: greater than 1)", DATA_WIDTH ); 55 | end 56 | 57 | if (DATA_DEPTH < 1) 58 | begin 59 | param_err_flg = 1; 60 | $display("ERROR: %m :\n Invalid value (%d) for parameter DATA_DEPTH \ 61 | (legal range: greater than 1)", DATA_DEPTH ); 62 | end 63 | end 64 | // synopsys translate_on 65 | 66 | 67 | assign clk_gated = clk; 68 | 69 | // UPDATE THE STATE 70 | always_ff @(posedge clk, negedge rst_n) 71 | begin 72 | if(rst_n == 1'b0) 73 | begin 74 | CS <= EMPTY; 75 | BRAM_overlap_q <= '0; 76 | Pop_Pointer_CS <= {ADDR_DEPTH {1'b0}}; 77 | Push_Pointer_CS <= {ADDR_DEPTH {1'b0}}; 78 | data_i_q <= '0; 79 | Pop_Pointer_BRAM <= '1; 80 | end 81 | else 82 | begin 83 | CS <= NS; 84 | Pop_Pointer_CS <= Pop_Pointer_NS; 85 | Push_Pointer_CS <= Push_Pointer_NS; 86 | data_i_q <= data_i; 87 | BRAM_overlap_q <= BRAM_overlap_d; 88 | if(NS != EMPTY) 89 | Pop_Pointer_BRAM <= Pop_Pointer_NS; 90 | end 91 | end 92 | 93 | assign BRAM_overlap_d = (CS==EMPTY)||(valid_i && 94 | ((Pop_Pointer_NS == Push_Pointer_NS -1)|| 95 | ((Pop_Pointer_NS == DATA_DEPTH-1) && 96 | (Push_Pointer_NS == 0)))); 97 | 98 | // Compute Next State 99 | always_comb 100 | begin 101 | gate_clock = 1'b0; 102 | 103 | case(CS) 104 | 105 | EMPTY: 106 | begin 107 | grant_o = 1'b1; 108 | valid_o = 1'b0; 109 | 110 | case(valid_i) 111 | 1'b0 : 112 | begin 113 | NS = EMPTY; 114 | Push_Pointer_NS = Push_Pointer_CS; 115 | Pop_Pointer_NS = Pop_Pointer_CS; 116 | gate_clock = 1'b1; 117 | end 118 | 119 | 1'b1: 120 | begin 121 | NS = MIDDLE; 122 | Push_Pointer_NS = Push_Pointer_CS + 1'b1; 123 | Pop_Pointer_NS = Pop_Pointer_CS; 124 | end 125 | 126 | endcase 127 | end//~EMPTY 128 | 129 | MIDDLE: 130 | begin 131 | grant_o = 1'b1; 132 | valid_o = 1'b1; 133 | 134 | case({valid_i,grant_i}) 135 | 136 | 2'b01: 137 | begin 138 | gate_clock = 1'b1; 139 | 140 | if((Pop_Pointer_CS == Push_Pointer_CS -1 ) || 141 | ((Pop_Pointer_CS == DATA_DEPTH-1) && (Push_Pointer_CS == 0))) 142 | NS = EMPTY; 143 | else 144 | NS = MIDDLE; 145 | 146 | Push_Pointer_NS = Push_Pointer_CS; 147 | 148 | if(Pop_Pointer_CS == DATA_DEPTH-1) 149 | Pop_Pointer_NS = 0; 150 | else 151 | Pop_Pointer_NS = Pop_Pointer_CS + 1'b1; 152 | end 153 | 154 | 2'b00 : 155 | begin 156 | gate_clock = 1'b1; 157 | NS = MIDDLE; 158 | Push_Pointer_NS = Push_Pointer_CS; 159 | Pop_Pointer_NS = Pop_Pointer_CS; 160 | end 161 | 162 | 2'b11: 163 | begin 164 | NS = MIDDLE; 165 | 166 | if(Push_Pointer_CS == DATA_DEPTH-1) 167 | Push_Pointer_NS = 0; 168 | else 169 | Push_Pointer_NS = Push_Pointer_CS + 1'b1; 170 | 171 | if(Pop_Pointer_CS == DATA_DEPTH-1) 172 | Pop_Pointer_NS = 0; 173 | else 174 | Pop_Pointer_NS = Pop_Pointer_CS + 1'b1; 175 | end 176 | 177 | 2'b10: 178 | begin 179 | if(( Push_Pointer_CS == Pop_Pointer_CS - 1) || 180 | ((Push_Pointer_CS == DATA_DEPTH-1) && (Pop_Pointer_CS == 0))) 181 | NS = FULL; 182 | else 183 | NS = MIDDLE; 184 | 185 | if(Push_Pointer_CS == DATA_DEPTH - 1) 186 | Push_Pointer_NS = 0; 187 | else 188 | Push_Pointer_NS = Push_Pointer_CS + 1'b1; 189 | 190 | Pop_Pointer_NS = Pop_Pointer_CS; 191 | end 192 | 193 | endcase 194 | end 195 | 196 | FULL: 197 | begin 198 | grant_o = 1'b0; 199 | valid_o = 1'b1; 200 | gate_clock = 1'b1; 201 | 202 | case(grant_i) 203 | 1'b1: 204 | begin 205 | NS = MIDDLE; 206 | 207 | Push_Pointer_NS = Push_Pointer_CS; 208 | 209 | if(Pop_Pointer_CS == DATA_DEPTH-1) 210 | Pop_Pointer_NS = 0; 211 | else 212 | Pop_Pointer_NS = Pop_Pointer_CS + 1'b1; 213 | end 214 | 215 | 1'b0: 216 | begin 217 | NS = FULL; 218 | Push_Pointer_NS = Push_Pointer_CS; 219 | Pop_Pointer_NS = Pop_Pointer_CS; 220 | end 221 | endcase 222 | 223 | end // end of FULL 224 | 225 | default : 226 | begin 227 | gate_clock = 1'b1; 228 | grant_o = 1'b0; 229 | valid_o = 1'b0; 230 | NS = EMPTY; 231 | Pop_Pointer_NS = 0; 232 | Push_Pointer_NS = 0; 233 | end 234 | 235 | endcase 236 | end 237 | 238 | /*always_ff @(posedge clk_gated, negedge rst_n) 239 | begin 240 | if(rst_n == 1'b0) 241 | begin 242 | for (i=0; i< DATA_DEPTH; i++) 243 | FIFO_REGISTERS[i] <= {DATA_WIDTH {1'b0}}; 244 | end 245 | else 246 | begin 247 | if((grant_o == 1'b1) && (valid_i == 1'b1)) 248 | FIFO_REGISTERS[Push_Pointer_CS] <= data_i; 249 | end 250 | end // always_ff @ (posedge clk_gated, negedge rst_n)*/ 251 | 252 | blk_mem_gen_0 bram_512x64 ( 253 | .clka(clk_gated), // input wire clka 254 | .wea((grant_o == 1'b1) && (valid_i == 1'b1)), // input wire [0 : 0] wea 255 | .addra(Push_Pointer_CS), // input wire [5 : 0] addra 256 | .dina(data_i), // input wire [511 : 0] dina 257 | .clkb(clk), // input wire clkb 258 | .addrb(BRAM_overlap_d?Pop_Pointer_BRAM: 259 | Pop_Pointer_NS), // input wire [5 : 0] addrb 260 | .doutb(data_o_BRAM) // output wire [511 : 0] doutb 261 | ); 262 | 263 | //assign data_o = FIFO_REGISTERS[Pop_Pointer_CS]; 264 | 265 | endmodule // generic_fifo 266 | -------------------------------------------------------------------------------- /ips/ems_lib/generic_fifo/bram_fifo_528x64.sv: -------------------------------------------------------------------------------- 1 | module bram_fifo_528x64 2 | #( 3 | //Don't change 4 | parameter DATA_WIDTH = 528, 5 | parameter DATA_DEPTH = 64 6 | ) 7 | ( 8 | input logic clk, 9 | input logic rst_n, 10 | //PUSH SIDE 11 | input logic [DATA_WIDTH-1:0] data_i, 12 | input logic valid_i, 13 | output logic grant_o, 14 | //POP SIDE 15 | output logic [DATA_WIDTH-1:0] data_o, 16 | output logic valid_o, 17 | input logic grant_i, 18 | 19 | input logic test_mode_i 20 | ); 21 | 22 | 23 | // Local Parameter 24 | localparam ADDR_DEPTH = $clog2(DATA_DEPTH); 25 | enum logic [1:0] { EMPTY, FULL, MIDDLE } CS, NS; 26 | // Internal Signals 27 | 28 | logic gate_clock; 29 | logic clk_gated; 30 | 31 | logic [ADDR_DEPTH-1:0] Pop_Pointer_CS, Pop_Pointer_NS; 32 | logic [ADDR_DEPTH-1:0] Push_Pointer_CS, Push_Pointer_NS; 33 | logic [ADDR_DEPTH-1:0] Pop_Pointer_BRAM; 34 | logic [DATA_WIDTH-1:0] FIFO_REGISTERS[DATA_DEPTH-1:0]; 35 | integer i; 36 | logic [DATA_WIDTH-1:0] data_i_q, data_o_BRAM; 37 | logic BRAM_overlap_d,BRAM_overlap_q; 38 | 39 | assign data_o = BRAM_overlap_q?data_i_q:data_o_BRAM; 40 | 41 | 42 | // Parameter Check 43 | // synopsys translate_off 44 | initial 45 | begin : parameter_check 46 | integer param_err_flg; 47 | param_err_flg = 0; 48 | 49 | if (DATA_WIDTH < 1) 50 | begin 51 | param_err_flg = 1; 52 | $display("ERROR: %m :\n Invalid value (%d) for parameter DATA_WIDTH \ 53 | (legal range: greater than 1)", DATA_WIDTH ); 54 | end 55 | 56 | if (DATA_DEPTH < 1) 57 | begin 58 | param_err_flg = 1; 59 | $display("ERROR: %m :\n Invalid value (%d) for parameter DATA_DEPTH \ 60 | (legal range: greater than 1)", DATA_DEPTH ); 61 | end 62 | end 63 | // synopsys translate_on 64 | 65 | 66 | assign clk_gated = clk; 67 | 68 | // UPDATE THE STATE 69 | always_ff @(posedge clk, negedge rst_n) 70 | begin 71 | if(rst_n == 1'b0) 72 | begin 73 | CS <= EMPTY; 74 | BRAM_overlap_q <= '0; 75 | Pop_Pointer_CS <= {ADDR_DEPTH {1'b0}}; 76 | Push_Pointer_CS <= {ADDR_DEPTH {1'b0}}; 77 | data_i_q <= '0; 78 | Pop_Pointer_BRAM <= '1; 79 | end 80 | else 81 | begin 82 | CS <= NS; 83 | Pop_Pointer_CS <= Pop_Pointer_NS; 84 | Push_Pointer_CS <= Push_Pointer_NS; 85 | data_i_q <= data_i; 86 | BRAM_overlap_q <= BRAM_overlap_d; 87 | if(NS != EMPTY) 88 | Pop_Pointer_BRAM <= Pop_Pointer_NS; 89 | end 90 | end 91 | 92 | 93 | assign BRAM_overlap_d = (CS==EMPTY)||(valid_i && 94 | ((Pop_Pointer_NS == Push_Pointer_NS -1)|| 95 | ((Pop_Pointer_NS == DATA_DEPTH-1) && 96 | (Push_Pointer_NS == 0)))); 97 | 98 | // Compute Next State 99 | always_comb 100 | begin 101 | gate_clock = 1'b0; 102 | case(CS) 103 | 104 | EMPTY: 105 | begin 106 | grant_o = 1'b1; 107 | valid_o = 1'b0; 108 | 109 | case(valid_i) 110 | 1'b0 : 111 | begin 112 | NS = EMPTY; 113 | Push_Pointer_NS = Push_Pointer_CS; 114 | Pop_Pointer_NS = Pop_Pointer_CS; 115 | gate_clock = 1'b1; 116 | end 117 | 118 | 1'b1: 119 | begin 120 | NS = MIDDLE; 121 | Push_Pointer_NS = Push_Pointer_CS + 1'b1; 122 | Pop_Pointer_NS = Pop_Pointer_CS; 123 | end 124 | 125 | endcase 126 | end//~EMPTY 127 | 128 | MIDDLE: 129 | begin 130 | grant_o = 1'b1; 131 | valid_o = 1'b1; 132 | 133 | case({valid_i,grant_i}) 134 | 135 | 2'b01: 136 | begin 137 | gate_clock = 1'b1; 138 | 139 | if((Pop_Pointer_CS == Push_Pointer_CS -1 ) || 140 | ((Pop_Pointer_CS == DATA_DEPTH-1) && (Push_Pointer_CS == 0))) 141 | NS = EMPTY; 142 | else 143 | NS = MIDDLE; 144 | 145 | Push_Pointer_NS = Push_Pointer_CS; 146 | 147 | if(Pop_Pointer_CS == DATA_DEPTH-1) 148 | Pop_Pointer_NS = 0; 149 | else 150 | Pop_Pointer_NS = Pop_Pointer_CS + 1'b1; 151 | end 152 | 153 | 2'b00 : 154 | begin 155 | gate_clock = 1'b1; 156 | NS = MIDDLE; 157 | Push_Pointer_NS = Push_Pointer_CS; 158 | Pop_Pointer_NS = Pop_Pointer_CS; 159 | end 160 | 161 | 2'b11: 162 | begin 163 | NS = MIDDLE; 164 | 165 | if(Push_Pointer_CS == DATA_DEPTH-1) 166 | Push_Pointer_NS = 0; 167 | else 168 | Push_Pointer_NS = Push_Pointer_CS + 1'b1; 169 | 170 | if(Pop_Pointer_CS == DATA_DEPTH-1) 171 | Pop_Pointer_NS = 0; 172 | else 173 | Pop_Pointer_NS = Pop_Pointer_CS + 1'b1; 174 | end 175 | 176 | 2'b10: 177 | begin 178 | if(( Push_Pointer_CS == Pop_Pointer_CS - 1) || 179 | ((Push_Pointer_CS == DATA_DEPTH-1) && (Pop_Pointer_CS == 0))) 180 | NS = FULL; 181 | else 182 | NS = MIDDLE; 183 | 184 | if(Push_Pointer_CS == DATA_DEPTH - 1) 185 | Push_Pointer_NS = 0; 186 | else 187 | Push_Pointer_NS = Push_Pointer_CS + 1'b1; 188 | 189 | Pop_Pointer_NS = Pop_Pointer_CS; 190 | end 191 | 192 | endcase 193 | end 194 | 195 | FULL: 196 | begin 197 | grant_o = 1'b0; 198 | valid_o = 1'b1; 199 | gate_clock = 1'b1; 200 | 201 | case(grant_i) 202 | 1'b1: 203 | begin 204 | NS = MIDDLE; 205 | 206 | Push_Pointer_NS = Push_Pointer_CS; 207 | 208 | if(Pop_Pointer_CS == DATA_DEPTH-1) 209 | Pop_Pointer_NS = 0; 210 | else 211 | Pop_Pointer_NS = Pop_Pointer_CS + 1'b1; 212 | end 213 | 214 | 1'b0: 215 | begin 216 | NS = FULL; 217 | Push_Pointer_NS = Push_Pointer_CS; 218 | Pop_Pointer_NS = Pop_Pointer_CS; 219 | end 220 | endcase 221 | 222 | end // end of FULL 223 | 224 | default : 225 | begin 226 | gate_clock = 1'b1; 227 | grant_o = 1'b0; 228 | valid_o = 1'b0; 229 | NS = EMPTY; 230 | Pop_Pointer_NS = 0; 231 | Push_Pointer_NS = 0; 232 | end 233 | 234 | endcase 235 | end 236 | 237 | /*always_ff @(posedge clk_gated, negedge rst_n) 238 | begin 239 | if(rst_n == 1'b0) 240 | begin 241 | for (i=0; i< DATA_DEPTH; i++) 242 | FIFO_REGISTERS[i] <= {DATA_WIDTH {1'b0}}; 243 | end 244 | else 245 | begin 246 | if((grant_o == 1'b1) && (valid_i == 1'b1)) 247 | FIFO_REGISTERS[Push_Pointer_CS] <= data_i; 248 | end 249 | end // always_ff @ (posedge clk_gated, negedge rst_n)*/ 250 | 251 | blk_mem_gen_528x64 bram_528x64 ( 252 | .clka(clk_gated), // input wire clka 253 | .wea((grant_o == 1'b1) && (valid_i == 1'b1)), // input wire [0 : 0] wea 254 | .addra(Push_Pointer_CS), // input wire [5 : 0] addra 255 | .dina(data_i), // input wire [511 : 0] dina 256 | .clkb(clk), // input wire clkb 257 | .addrb(BRAM_overlap_d?Pop_Pointer_BRAM: 258 | Pop_Pointer_NS),// input wire [5 : 0] addrb 259 | .doutb(data_o_BRAM) // output wire [511 : 0] doutb 260 | ); 261 | 262 | //assign data_o = FIFO_REGISTERS[Pop_Pointer_CS]; 263 | 264 | endmodule // generic_fifo 265 | -------------------------------------------------------------------------------- /ips/ems_lib/generic_fifo/bram_fifo_528x8.sv: -------------------------------------------------------------------------------- 1 | module bram_fifo_528x8 2 | #( 3 | //Don't change 4 | parameter DATA_WIDTH = 528, 5 | parameter DATA_DEPTH = 8 6 | ) 7 | ( 8 | input logic clk, 9 | input logic rst_n, 10 | //PUSH SIDE 11 | input logic [DATA_WIDTH-1:0] data_i, 12 | input logic valid_i, 13 | output logic grant_o, 14 | //POP SIDE 15 | output logic [DATA_WIDTH-1:0] data_o, 16 | output logic valid_o, 17 | input logic grant_i, 18 | 19 | input logic test_mode_i 20 | ); 21 | 22 | 23 | // Local Parameter 24 | localparam ADDR_DEPTH = $clog2(DATA_DEPTH); 25 | enum logic [1:0] { EMPTY, FULL, MIDDLE } CS, NS; 26 | // Internal Signals 27 | 28 | logic gate_clock; 29 | logic clk_gated; 30 | 31 | logic [ADDR_DEPTH-1:0] Pop_Pointer_CS, Pop_Pointer_NS; 32 | logic [ADDR_DEPTH-1:0] Push_Pointer_CS, Push_Pointer_NS; 33 | logic [ADDR_DEPTH-1:0] Pop_Pointer_BRAM; 34 | logic [DATA_WIDTH-1:0] FIFO_REGISTERS[DATA_DEPTH-1:0]; 35 | integer i; 36 | logic [DATA_WIDTH-1:0] data_i_q, data_o_BRAM; 37 | logic BRAM_overlap_d,BRAM_overlap_q; 38 | 39 | assign data_o = BRAM_overlap_q?data_i_q:data_o_BRAM; 40 | 41 | 42 | // Parameter Check 43 | // synopsys translate_off 44 | initial 45 | begin : parameter_check 46 | integer param_err_flg; 47 | param_err_flg = 0; 48 | 49 | if (DATA_WIDTH < 1) 50 | begin 51 | param_err_flg = 1; 52 | $display("ERROR: %m :\n Invalid value (%d) for parameter DATA_WIDTH \ 53 | (legal range: greater than 1)", DATA_WIDTH ); 54 | end 55 | 56 | if (DATA_DEPTH < 1) 57 | begin 58 | param_err_flg = 1; 59 | $display("ERROR: %m :\n Invalid value (%d) for parameter DATA_DEPTH \ 60 | (legal range: greater than 1)", DATA_DEPTH ); 61 | end 62 | end 63 | // synopsys translate_on 64 | 65 | 66 | assign clk_gated = clk; 67 | 68 | // UPDATE THE STATE 69 | always_ff @(posedge clk, negedge rst_n) 70 | begin 71 | if(rst_n == 1'b0) 72 | begin 73 | CS <= EMPTY; 74 | BRAM_overlap_q <= '0; 75 | Pop_Pointer_CS <= {ADDR_DEPTH {1'b0}}; 76 | Push_Pointer_CS <= {ADDR_DEPTH {1'b0}}; 77 | data_i_q <= '0; 78 | Pop_Pointer_BRAM <= '1; 79 | end 80 | else 81 | begin 82 | CS <= NS; 83 | Pop_Pointer_CS <= Pop_Pointer_NS; 84 | Push_Pointer_CS <= Push_Pointer_NS; 85 | data_i_q <= data_i; 86 | BRAM_overlap_q <= BRAM_overlap_d; 87 | if(NS != EMPTY) 88 | Pop_Pointer_BRAM <= Pop_Pointer_NS; 89 | end 90 | end 91 | 92 | assign BRAM_overlap_d = (CS==EMPTY)||(valid_i && 93 | ((Pop_Pointer_NS == Push_Pointer_NS -1)|| 94 | ((Pop_Pointer_NS == DATA_DEPTH-1) && 95 | (Push_Pointer_NS == 0)))); 96 | // Compute Next State 97 | always_comb 98 | begin 99 | gate_clock = 1'b0; 100 | case(CS) 101 | 102 | EMPTY: 103 | begin 104 | grant_o = 1'b1; 105 | valid_o = 1'b0; 106 | case(valid_i) 107 | 1'b0 : 108 | begin 109 | NS = EMPTY; 110 | Push_Pointer_NS = Push_Pointer_CS; 111 | Pop_Pointer_NS = Pop_Pointer_CS; 112 | gate_clock = 1'b1; 113 | end 114 | 115 | 1'b1: 116 | begin 117 | NS = MIDDLE; 118 | Push_Pointer_NS = Push_Pointer_CS + 1'b1; 119 | Pop_Pointer_NS = Pop_Pointer_CS; 120 | end 121 | 122 | endcase 123 | end//~EMPTY 124 | 125 | MIDDLE: 126 | begin 127 | grant_o = 1'b1; 128 | valid_o = 1'b1; 129 | 130 | case({valid_i,grant_i}) 131 | 132 | 2'b01: 133 | begin 134 | gate_clock = 1'b1; 135 | 136 | if((Pop_Pointer_CS == Push_Pointer_CS -1 ) || 137 | ((Pop_Pointer_CS == DATA_DEPTH-1) && (Push_Pointer_CS == 0))) 138 | NS = EMPTY; 139 | else 140 | NS = MIDDLE; 141 | 142 | Push_Pointer_NS = Push_Pointer_CS; 143 | 144 | if(Pop_Pointer_CS == DATA_DEPTH-1) 145 | Pop_Pointer_NS = 0; 146 | else 147 | Pop_Pointer_NS = Pop_Pointer_CS + 1'b1; 148 | end 149 | 150 | 2'b00 : 151 | begin 152 | gate_clock = 1'b1; 153 | NS = MIDDLE; 154 | Push_Pointer_NS = Push_Pointer_CS; 155 | Pop_Pointer_NS = Pop_Pointer_CS; 156 | end 157 | 158 | 2'b11: 159 | begin 160 | NS = MIDDLE; 161 | 162 | if(Push_Pointer_CS == DATA_DEPTH-1) 163 | Push_Pointer_NS = 0; 164 | else 165 | Push_Pointer_NS = Push_Pointer_CS + 1'b1; 166 | 167 | if(Pop_Pointer_CS == DATA_DEPTH-1) 168 | Pop_Pointer_NS = 0; 169 | else 170 | Pop_Pointer_NS = Pop_Pointer_CS + 1'b1; 171 | end 172 | 173 | 2'b10: 174 | begin 175 | if(( Push_Pointer_CS == Pop_Pointer_CS - 1) || 176 | ((Push_Pointer_CS == DATA_DEPTH-1) && (Pop_Pointer_CS == 0))) 177 | NS = FULL; 178 | else 179 | NS = MIDDLE; 180 | 181 | if(Push_Pointer_CS == DATA_DEPTH - 1) 182 | Push_Pointer_NS = 0; 183 | else 184 | Push_Pointer_NS = Push_Pointer_CS + 1'b1; 185 | 186 | Pop_Pointer_NS = Pop_Pointer_CS; 187 | end 188 | 189 | endcase 190 | end 191 | 192 | FULL: 193 | begin 194 | grant_o = 1'b0; 195 | valid_o = 1'b1; 196 | gate_clock = 1'b1; 197 | 198 | case(grant_i) 199 | 1'b1: 200 | begin 201 | NS = MIDDLE; 202 | 203 | Push_Pointer_NS = Push_Pointer_CS; 204 | 205 | if(Pop_Pointer_CS == DATA_DEPTH-1) 206 | Pop_Pointer_NS = 0; 207 | else 208 | Pop_Pointer_NS = Pop_Pointer_CS + 1'b1; 209 | end 210 | 211 | 1'b0: 212 | begin 213 | NS = FULL; 214 | Push_Pointer_NS = Push_Pointer_CS; 215 | Pop_Pointer_NS = Pop_Pointer_CS; 216 | end 217 | endcase 218 | 219 | end // end of FULL 220 | 221 | default : 222 | begin 223 | gate_clock = 1'b1; 224 | grant_o = 1'b0; 225 | valid_o = 1'b0; 226 | NS = EMPTY; 227 | Pop_Pointer_NS = 0; 228 | Push_Pointer_NS = 0; 229 | end 230 | 231 | endcase 232 | end 233 | 234 | /*always_ff @(posedge clk_gated, negedge rst_n) 235 | begin 236 | if(rst_n == 1'b0) 237 | begin 238 | for (i=0; i< DATA_DEPTH; i++) 239 | FIFO_REGISTERS[i] <= {DATA_WIDTH {1'b0}}; 240 | end 241 | else 242 | begin 243 | if((grant_o == 1'b1) && (valid_i == 1'b1)) 244 | FIFO_REGISTERS[Push_Pointer_CS] <= data_i; 245 | end 246 | end // always_ff @ (posedge clk_gated, negedge rst_n)*/ 247 | 248 | blk_mem_gen_528x8 bram_528x8 ( 249 | .clka(clk_gated), // input wire clka 250 | .wea((grant_o == 1'b1) && (valid_i == 1'b1)), // input wire [0 : 0] wea 251 | .addra(Push_Pointer_CS), // input wire [5 : 0] addra 252 | .dina(data_i), // input wire [511 : 0] dina 253 | .clkb(clk), // input wire clkb 254 | .addrb(BRAM_overlap_d?Pop_Pointer_BRAM: 255 | Pop_Pointer_NS), // input wire [5 : 0] addrb 256 | .doutb(data_o_BRAM) // output wire [511 : 0] doutb 257 | ); 258 | 259 | //assign data_o = FIFO_REGISTERS[Pop_Pointer_CS]; 260 | 261 | endmodule // generic_fifo 262 | -------------------------------------------------------------------------------- /ips/ems_lib/generic_fifo/bram_fifo_52x4.sv: -------------------------------------------------------------------------------- 1 | module bram_fifo_52x4 2 | #( 3 | //Don't change 4 | parameter DATA_WIDTH = 52, 5 | parameter DATA_DEPTH = 4 6 | ) 7 | ( 8 | input logic clk, 9 | input logic rst_n, 10 | //PUSH SIDE 11 | input logic [DATA_WIDTH-1:0] data_i, 12 | input logic valid_i, 13 | output logic grant_o, 14 | //POP SIDE 15 | output logic [DATA_WIDTH-1:0] data_o, 16 | output logic valid_o, 17 | input logic grant_i, 18 | 19 | input logic test_mode_i 20 | ); 21 | 22 | 23 | // Local Parameter 24 | localparam ADDR_DEPTH = $clog2(DATA_DEPTH); 25 | enum logic [1:0] { EMPTY, FULL, MIDDLE } CS, NS; 26 | // Internal Signals 27 | 28 | logic gate_clock; 29 | logic clk_gated; 30 | 31 | logic [ADDR_DEPTH-1:0] Pop_Pointer_CS, Pop_Pointer_NS; 32 | logic [ADDR_DEPTH-1:0] Push_Pointer_CS, Push_Pointer_NS; 33 | logic [ADDR_DEPTH-1:0] Pop_Pointer_BRAM; 34 | logic [DATA_WIDTH-1:0] FIFO_REGISTERS[DATA_DEPTH-1:0]; 35 | integer i; 36 | logic [DATA_WIDTH-1:0] data_i_q, data_o_BRAM; 37 | logic BRAM_overlap_d,BRAM_overlap_q; 38 | 39 | assign data_o = BRAM_overlap_q?data_i_q:data_o_BRAM; 40 | 41 | 42 | // Parameter Check 43 | // synopsys translate_off 44 | initial 45 | begin : parameter_check 46 | integer param_err_flg; 47 | param_err_flg = 0; 48 | 49 | if (DATA_WIDTH < 1) 50 | begin 51 | param_err_flg = 1; 52 | $display("ERROR: %m :\n Invalid value (%d) for parameter DATA_WIDTH \ 53 | (legal range: greater than 1)", DATA_WIDTH ); 54 | end 55 | 56 | if (DATA_DEPTH < 1) 57 | begin 58 | param_err_flg = 1; 59 | $display("ERROR: %m :\n Invalid value (%d) for parameter DATA_DEPTH \ 60 | (legal range: greater than 1)", DATA_DEPTH ); 61 | end 62 | end 63 | // synopsys translate_on 64 | 65 | 66 | assign clk_gated = clk; 67 | 68 | // UPDATE THE STATE 69 | always_ff @(posedge clk, negedge rst_n) 70 | begin 71 | if(rst_n == 1'b0) 72 | begin 73 | CS <= EMPTY; 74 | BRAM_overlap_q <= EMPTY; 75 | Pop_Pointer_CS <= {ADDR_DEPTH {1'b0}}; 76 | Push_Pointer_CS <= {ADDR_DEPTH {1'b0}}; 77 | data_i_q <= '0; 78 | Pop_Pointer_BRAM <= '1; 79 | end 80 | else 81 | begin 82 | CS <= NS; 83 | Pop_Pointer_CS <= Pop_Pointer_NS; 84 | Push_Pointer_CS <= Push_Pointer_NS; 85 | data_i_q <= data_i; 86 | BRAM_overlap_q <= BRAM_overlap_d; 87 | if(NS != EMPTY) 88 | Pop_Pointer_BRAM <= Pop_Pointer_NS; 89 | end 90 | end 91 | 92 | assign BRAM_overlap_d = (CS==EMPTY)||(valid_i && 93 | ((Pop_Pointer_NS == Push_Pointer_NS -1)|| 94 | ((Pop_Pointer_NS == DATA_DEPTH-1) && 95 | (Push_Pointer_NS == 0)))); 96 | 97 | // Compute Next State 98 | always_comb 99 | begin 100 | gate_clock = 1'b0; 101 | case(CS) 102 | 103 | EMPTY: 104 | begin 105 | grant_o = 1'b1; 106 | valid_o = 1'b0; 107 | case(valid_i) 108 | 1'b0 : 109 | begin 110 | NS = EMPTY; 111 | Push_Pointer_NS = Push_Pointer_CS; 112 | Pop_Pointer_NS = Pop_Pointer_CS; 113 | gate_clock = 1'b1; 114 | end 115 | 116 | 1'b1: 117 | begin 118 | NS = MIDDLE; 119 | Push_Pointer_NS = Push_Pointer_CS + 1'b1; 120 | Pop_Pointer_NS = Pop_Pointer_CS; 121 | end 122 | 123 | endcase 124 | end//~EMPTY 125 | 126 | MIDDLE: 127 | begin 128 | grant_o = 1'b1; 129 | valid_o = 1'b1; 130 | 131 | case({valid_i,grant_i}) 132 | 133 | 2'b01: 134 | begin 135 | gate_clock = 1'b1; 136 | 137 | if((Pop_Pointer_CS == Push_Pointer_CS -1 ) || 138 | ((Pop_Pointer_CS == DATA_DEPTH-1) && (Push_Pointer_CS == 0))) 139 | NS = EMPTY; 140 | else 141 | NS = MIDDLE; 142 | 143 | Push_Pointer_NS = Push_Pointer_CS; 144 | 145 | if(Pop_Pointer_CS == DATA_DEPTH-1) 146 | Pop_Pointer_NS = 0; 147 | else 148 | Pop_Pointer_NS = Pop_Pointer_CS + 1'b1; 149 | end 150 | 151 | 2'b00 : 152 | begin 153 | gate_clock = 1'b1; 154 | NS = MIDDLE; 155 | Push_Pointer_NS = Push_Pointer_CS; 156 | Pop_Pointer_NS = Pop_Pointer_CS; 157 | end 158 | 159 | 2'b11: 160 | begin 161 | NS = MIDDLE; 162 | 163 | if(Push_Pointer_CS == DATA_DEPTH-1) 164 | Push_Pointer_NS = 0; 165 | else 166 | Push_Pointer_NS = Push_Pointer_CS + 1'b1; 167 | 168 | if(Pop_Pointer_CS == DATA_DEPTH-1) 169 | Pop_Pointer_NS = 0; 170 | else 171 | Pop_Pointer_NS = Pop_Pointer_CS + 1'b1; 172 | end 173 | 174 | 2'b10: 175 | begin 176 | if(( Push_Pointer_CS == Pop_Pointer_CS - 1) || 177 | ((Push_Pointer_CS == DATA_DEPTH-1) && (Pop_Pointer_CS == 0))) 178 | NS = FULL; 179 | else 180 | NS = MIDDLE; 181 | 182 | if(Push_Pointer_CS == DATA_DEPTH - 1) 183 | Push_Pointer_NS = 0; 184 | else 185 | Push_Pointer_NS = Push_Pointer_CS + 1'b1; 186 | 187 | Pop_Pointer_NS = Pop_Pointer_CS; 188 | end 189 | 190 | endcase 191 | end 192 | 193 | FULL: 194 | begin 195 | grant_o = 1'b0; 196 | valid_o = 1'b1; 197 | gate_clock = 1'b1; 198 | 199 | case(grant_i) 200 | 1'b1: 201 | begin 202 | NS = MIDDLE; 203 | 204 | Push_Pointer_NS = Push_Pointer_CS; 205 | 206 | if(Pop_Pointer_CS == DATA_DEPTH-1) 207 | Pop_Pointer_NS = 0; 208 | else 209 | Pop_Pointer_NS = Pop_Pointer_CS + 1'b1; 210 | end 211 | 212 | 1'b0: 213 | begin 214 | NS = FULL; 215 | Push_Pointer_NS = Push_Pointer_CS; 216 | Pop_Pointer_NS = Pop_Pointer_CS; 217 | end 218 | endcase 219 | 220 | end // end of FULL 221 | 222 | default : 223 | begin 224 | gate_clock = 1'b1; 225 | grant_o = 1'b0; 226 | valid_o = 1'b0; 227 | NS = EMPTY; 228 | Pop_Pointer_NS = 0; 229 | Push_Pointer_NS = 0; 230 | end 231 | 232 | endcase 233 | end 234 | 235 | /*always_ff @(posedge clk_gated, negedge rst_n) 236 | begin 237 | if(rst_n == 1'b0) 238 | begin 239 | for (i=0; i< DATA_DEPTH; i++) 240 | FIFO_REGISTERS[i] <= {DATA_WIDTH {1'b0}}; 241 | end 242 | else 243 | begin 244 | if((grant_o == 1'b1) && (valid_i == 1'b1)) 245 | FIFO_REGISTERS[Push_Pointer_CS] <= data_i; 246 | end 247 | end // always_ff @ (posedge clk_gated, negedge rst_n)*/ 248 | 249 | blk_mem_gen_52x4 bram_52x4 ( 250 | .clka(clk_gated), // input wire clka 251 | .wea((grant_o == 1'b1) && (valid_i == 1'b1)), // input wire [0 : 0] wea 252 | .addra(Push_Pointer_CS), // input wire [5 : 0] addra 253 | .dina(data_i), // input wire [511 : 0] dina 254 | .clkb(clk), // input wire clkb 255 | .addrb(BRAM_overlap_d?Pop_Pointer_BRAM: 256 | Pop_Pointer_NS), // input wire [5 : 0] addrb 257 | .doutb(data_o_BRAM) // output wire [511 : 0] doutb 258 | ); 259 | 260 | //assign data_o = FIFO_REGISTERS[Pop_Pointer_CS]; 261 | 262 | endmodule // generic_fifo 263 | -------------------------------------------------------------------------------- /ips/ems_lib/generic_fifo/generic_fifo.sv: -------------------------------------------------------------------------------- 1 | // Copyright 2017 ETH Zurich and University of Bologna. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 0.51 (the “License”); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | module generic_fifo 12 | #( 13 | parameter DATA_WIDTH = 32, 14 | parameter DATA_DEPTH = 8 15 | ) 16 | ( 17 | input logic clk, 18 | input logic rst_n, 19 | //PUSH SIDE 20 | input logic [DATA_WIDTH-1:0] data_i, 21 | input logic valid_i, 22 | output logic grant_o, 23 | //POP SIDE 24 | output logic [DATA_WIDTH-1:0] data_o, 25 | output logic valid_o, 26 | input logic grant_i, 27 | 28 | input logic test_mode_i 29 | ); 30 | 31 | 32 | // Local Parameter 33 | localparam ADDR_DEPTH = $clog2(DATA_DEPTH); 34 | enum logic [1:0] { EMPTY, FULL, MIDDLE } CS, NS; 35 | // Internal Signals 36 | 37 | logic gate_clock; 38 | logic clk_gated; 39 | 40 | logic [ADDR_DEPTH-1:0] Pop_Pointer_CS, Pop_Pointer_NS; 41 | logic [ADDR_DEPTH-1:0] Push_Pointer_CS, Push_Pointer_NS; 42 | logic [DATA_WIDTH-1:0] FIFO_REGISTERS[DATA_DEPTH-1:0]; 43 | integer i; 44 | 45 | 46 | 47 | // Parameter Check 48 | // synopsys translate_off 49 | initial 50 | begin : parameter_check 51 | integer param_err_flg; 52 | param_err_flg = 0; 53 | 54 | if (DATA_WIDTH < 1) 55 | begin 56 | param_err_flg = 1; 57 | $display("ERROR: %m :\n Invalid value (%d) for parameter DATA_WIDTH \ 58 | (legal range: greater than 1)", DATA_WIDTH ); 59 | end 60 | 61 | if (DATA_DEPTH < 1) 62 | begin 63 | param_err_flg = 1; 64 | $display("ERROR: %m :\n Invalid value (%d) for parameter DATA_DEPTH \ 65 | (legal range: greater than 1)", DATA_DEPTH ); 66 | end 67 | end 68 | // synopsys translate_on 69 | 70 | `ifndef PULP_FPGA_EMUL 71 | pulp_clock_gating cg_cell 72 | ( 73 | .clk_i ( clk ), 74 | .en_i (~gate_clock ), 75 | .test_en_i ( test_mode_i ), 76 | .clk_o ( clk_gated ) 77 | ); 78 | `else 79 | assign clk_gated = clk; 80 | `endif 81 | 82 | // UPDATE THE STATE 83 | always_ff @(posedge clk, negedge rst_n) 84 | begin 85 | if(rst_n == 1'b0) 86 | begin 87 | CS <= EMPTY; 88 | Pop_Pointer_CS <= {ADDR_DEPTH {1'b0}}; 89 | Push_Pointer_CS <= {ADDR_DEPTH {1'b0}}; 90 | end 91 | else 92 | begin 93 | CS <= NS; 94 | Pop_Pointer_CS <= Pop_Pointer_NS; 95 | Push_Pointer_CS <= Push_Pointer_NS; 96 | end 97 | end 98 | 99 | 100 | // Compute Next State 101 | always_comb 102 | begin 103 | gate_clock = 1'b0; 104 | 105 | case(CS) 106 | 107 | EMPTY: 108 | begin 109 | grant_o = 1'b1; 110 | valid_o = 1'b0; 111 | 112 | case(valid_i) 113 | 1'b0 : 114 | begin 115 | NS = EMPTY; 116 | Push_Pointer_NS = Push_Pointer_CS; 117 | Pop_Pointer_NS = Pop_Pointer_CS; 118 | gate_clock = 1'b1; 119 | end 120 | 121 | 1'b1: 122 | begin 123 | NS = MIDDLE; 124 | Push_Pointer_NS = Push_Pointer_CS + 1'b1; 125 | Pop_Pointer_NS = Pop_Pointer_CS; 126 | end 127 | 128 | endcase 129 | end//~EMPTY 130 | 131 | MIDDLE: 132 | begin 133 | grant_o = 1'b1; 134 | valid_o = 1'b1; 135 | 136 | case({valid_i,grant_i}) 137 | 138 | 2'b01: 139 | begin 140 | gate_clock = 1'b1; 141 | 142 | if((Pop_Pointer_CS == Push_Pointer_CS -1 ) || 143 | ((Pop_Pointer_CS == DATA_DEPTH-1) && (Push_Pointer_CS == 0))) 144 | NS = EMPTY; 145 | else 146 | NS = MIDDLE; 147 | 148 | Push_Pointer_NS = Push_Pointer_CS; 149 | 150 | if(Pop_Pointer_CS == DATA_DEPTH-1) 151 | Pop_Pointer_NS = 0; 152 | else 153 | Pop_Pointer_NS = Pop_Pointer_CS + 1'b1; 154 | end 155 | 156 | 2'b00 : 157 | begin 158 | gate_clock = 1'b1; 159 | NS = MIDDLE; 160 | Push_Pointer_NS = Push_Pointer_CS; 161 | Pop_Pointer_NS = Pop_Pointer_CS; 162 | end 163 | 164 | 2'b11: 165 | begin 166 | NS = MIDDLE; 167 | 168 | if(Push_Pointer_CS == DATA_DEPTH-1) 169 | Push_Pointer_NS = 0; 170 | else 171 | Push_Pointer_NS = Push_Pointer_CS + 1'b1; 172 | 173 | if(Pop_Pointer_CS == DATA_DEPTH-1) 174 | Pop_Pointer_NS = 0; 175 | else 176 | Pop_Pointer_NS = Pop_Pointer_CS + 1'b1; 177 | end 178 | 179 | 2'b10: 180 | begin 181 | if(( Push_Pointer_CS == Pop_Pointer_CS - 1) || 182 | ((Push_Pointer_CS == DATA_DEPTH-1) && (Pop_Pointer_CS == 0))) 183 | NS = FULL; 184 | else 185 | NS = MIDDLE; 186 | 187 | if(Push_Pointer_CS == DATA_DEPTH - 1) 188 | Push_Pointer_NS = 0; 189 | else 190 | Push_Pointer_NS = Push_Pointer_CS + 1'b1; 191 | 192 | Pop_Pointer_NS = Pop_Pointer_CS; 193 | end 194 | 195 | endcase 196 | end 197 | 198 | FULL: 199 | begin 200 | grant_o = 1'b0; 201 | valid_o = 1'b1; 202 | gate_clock = 1'b1; 203 | 204 | case(grant_i) 205 | 1'b1: 206 | begin 207 | NS = MIDDLE; 208 | 209 | Push_Pointer_NS = Push_Pointer_CS; 210 | 211 | if(Pop_Pointer_CS == DATA_DEPTH-1) 212 | Pop_Pointer_NS = 0; 213 | else 214 | Pop_Pointer_NS = Pop_Pointer_CS + 1'b1; 215 | end 216 | 217 | 1'b0: 218 | begin 219 | NS = FULL; 220 | Push_Pointer_NS = Push_Pointer_CS; 221 | Pop_Pointer_NS = Pop_Pointer_CS; 222 | end 223 | endcase 224 | 225 | end // end of FULL 226 | 227 | default : 228 | begin 229 | gate_clock = 1'b1; 230 | grant_o = 1'b0; 231 | valid_o = 1'b0; 232 | NS = EMPTY; 233 | Pop_Pointer_NS = 0; 234 | Push_Pointer_NS = 0; 235 | end 236 | 237 | endcase 238 | end 239 | 240 | always_ff @(posedge clk_gated, negedge rst_n) 241 | begin 242 | if(rst_n == 1'b0) 243 | begin 244 | for (i=0; i< DATA_DEPTH; i++) 245 | FIFO_REGISTERS[i] <= {DATA_WIDTH {1'b0}}; 246 | end 247 | else 248 | begin 249 | if((grant_o == 1'b1) && (valid_i == 1'b1)) 250 | FIFO_REGISTERS[Push_Pointer_CS] <= data_i; 251 | end 252 | end 253 | 254 | assign data_o = FIFO_REGISTERS[Pop_Pointer_CS]; 255 | 256 | endmodule // generic_fifo 257 | -------------------------------------------------------------------------------- /ips/ems_lib/lfsr/lfsr_gen.sv: -------------------------------------------------------------------------------- 1 | // Uses load pattern as reset to reset the pseudo random number generator 2 | // Input pattern is used as seed 3 | // need another reset to restart for the comparison 4 | //Author: Deepak M. Mathew, EMS, TUKL 5 | 6 | 7 | module lfsr_gen 8 | #( 9 | parameter lfsr_width = 64 10 | ) 11 | ( 12 | input logic clk, 13 | input logic new_seed, // works as a reset 14 | input logic [lfsr_width-1:0] seed, // will be reseted to this seed 15 | input logic readyMig, // check if Mig is ready for write 16 | input logic regen, // check if gen or regen 17 | input logic rd_valid, // check if valid data to read 18 | 19 | output logic [lfsr_width-1:0] gen_pattern 20 | ); 21 | 22 | logic [lfsr_width-1:0] pattern_aux; // feedback reg 23 | 24 | always_ff@(posedge clk) 25 | begin 26 | integer i; 27 | if(new_seed) begin 28 | for (i = 0; i < lfsr_width; i = i + 1) begin 29 | if ((i !=lfsr_width-1)) begin 30 | pattern_aux[i] <= seed[i+1]; 31 | end 32 | end 33 | pattern_aux[lfsr_width-1] <= (seed[0]~^seed[1]~^seed[3]~^seed[4]); //maximum length lfsr tap for n=64 34 | 35 | end 36 | else begin 37 | if (!regen) begin // If write check readyMig 38 | if (readyMig) begin 39 | for (i = 0; i < lfsr_width; i = i + 1) begin 40 | if ((i != lfsr_width-1)) begin 41 | pattern_aux[i] <= pattern_aux[i+1]; 42 | end 43 | end 44 | pattern_aux[lfsr_width-1] <= (pattern_aux[0]~^pattern_aux[1]~^pattern_aux[3]~^pattern_aux[4]); 45 | end 46 | else begin 47 | pattern_aux <= pattern_aux; 48 | end 49 | end 50 | else begin // If Read, check rd_valid 51 | if (rd_valid) begin 52 | for (i = 0; i < lfsr_width; i = i + 1) begin 53 | if ((i != lfsr_width-1)) begin 54 | pattern_aux[i] <= pattern_aux[i+1]; 55 | end 56 | end 57 | pattern_aux[lfsr_width-1] <= (pattern_aux[0]~^pattern_aux[1]~^pattern_aux[3]~^pattern_aux[4]); 58 | end 59 | else begin 60 | pattern_aux <= pattern_aux; 61 | end 62 | end 63 | end 64 | end 65 | 66 | always_comb 67 | begin 68 | if(new_seed) begin 69 | gen_pattern = seed; 70 | end 71 | else begin 72 | gen_pattern = pattern_aux; 73 | end 74 | end 75 | 76 | endmodule 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /ips/ems_lib/mem_tgen_checker/mem_tgen_checker.sv: -------------------------------------------------------------------------------- 1 | module mem_tgen_checker 2 | #( 3 | parameter DRAM_BUS_WIDTH = 8, 4 | parameter FE_CMD_WIDTH = 1, 5 | parameter FE_WRITE = 0, 6 | parameter FE_ADDR_WIDTH = 32, 7 | parameter FE_ID_WIDTH = 16, 8 | parameter NUM_TRANSACTIONS = 10000000, 9 | parameter BL = 8 10 | ) 11 | ( 12 | 13 | input ui_clk, 14 | input ui_rst_n, 15 | 16 | input logic fe_stall, 17 | 18 | output logic fe_req, 19 | output logic [FE_CMD_WIDTH-1:0] fe_cmd, 20 | output logic [FE_ADDR_WIDTH-6-1:0] fe_addr, 21 | output logic [FE_ID_WIDTH-1:0] fe_id, 22 | output logic [DRAM_BUS_WIDTH*BL-1:0] fe_data, 23 | 24 | input logic [DRAM_BUS_WIDTH*BL-1:0] fe_read_data, 25 | input logic [FE_ID_WIDTH-1:0] fe_read_id, 26 | input logic fe_read_valid, 27 | 28 | output logic data_cmp_err 29 | ); 30 | 31 | 32 | logic fe_req_wr; 33 | logic fe_wr_stall; 34 | logic [FE_CMD_WIDTH-1:0] fe_cmd_wr; 35 | logic [FE_ADDR_WIDTH-6-1:0] fe_addr_wr;// -6 = -3-1-2. -3 for lower three bits to be set to zero, -1 because c10 doesnt exsists in DDR4 so it has to be set to zero, -2 because the DDR4 model is for 4gb i.e. one Row0 to Row14, Row15,16 has to be set to zero. 36 | logic fe_req_rd; 37 | logic [FE_CMD_WIDTH-1:0] fe_cmd_rd; 38 | logic fe_cmd_sel; 39 | logic [FE_ADDR_WIDTH-6-1:0] fe_addr_rd; 40 | logic fe_stall_q; 41 | logic fe_req_regen; 42 | logic [FE_CMD_WIDTH-1:0] fe_cmd_regen; 43 | logic [FE_ADDR_WIDTH-6-1:0] fe_addr_regen; 44 | logic [FE_ID_WIDTH-1:0] fe_id_regen; 45 | logic [DRAM_BUS_WIDTH*BL-1:0] fe_data_regen; 46 | logic [DRAM_BUS_WIDTH*BL-1:0] fe_read_data_q; 47 | logic [FE_ID_WIDTH-1:0] fe_read_id_q; 48 | logic fe_read_valid_q; 49 | logic [63:0] fe_write_cnt; 50 | logic [$clog2(NUM_TRANSACTIONS)-1:0] write_cnt; 51 | logic stop_lfsr; 52 | 53 | 54 | 55 | lfsr_gen 56 | #( 57 | .lfsr_width(FE_ADDR_WIDTH-6+1+1) // -3 for lower three bit set to zero, -1 because c10 doesnt exsists in DDR4 so it has to be set to zero, -2 because the DDR4 model is for 4gb i.e. one Row0 to Row14, Row15,16 has to be set to zero 58 | )lfsr_generate_addr_wr 59 | ( 60 | .clk(ui_clk), 61 | .new_seed(~ui_rst_n || stop_lfsr), // works as a reset 62 | .seed(66'h2734c673a47f2345a), // will be reseted to this seed 63 | .readyMig((~fe_stall) && !(fe_wr_stall||(fe_cmd_sel && (fe_write_cnt>0)))), // check if Mig is ready for write 64 | .regen(1'b0), // check if gen or regen 65 | .rd_valid(1'b0), // check if valid data to read 66 | 67 | .gen_pattern({fe_addr_wr,fe_cmd_wr,fe_req_wr}) 68 | ); 69 | 70 | lfsr_gen 71 | #( 72 | .lfsr_width(FE_ADDR_WIDTH-6+1+1) 73 | )lfsr_generate_addr_rd 74 | ( 75 | .clk(ui_clk), 76 | .new_seed(~ui_rst_n || stop_lfsr), // works as a reset 77 | .seed(66'h2734c673a47f2345a), // will be reseted to this seed 78 | .readyMig((~fe_stall) && (fe_wr_stall||(fe_cmd_sel && (fe_write_cnt>0)))), // check if Mig is ready for write 79 | .regen(1'b0), // check if gen or regen 80 | .rd_valid(1'b0), // check if valid data to read 81 | 82 | .gen_pattern({fe_addr_rd,fe_cmd_rd,fe_req_rd}) 83 | ); 84 | 85 | lfsr_gen 86 | #( 87 | .lfsr_width(DRAM_BUS_WIDTH*BL) 88 | )lfsr_generate_data 89 | ( 90 | .clk(ui_clk), 91 | .new_seed(~ui_rst_n || stop_lfsr), // works as a reset 92 | .seed(512'h7cb7467189af4346_fcabbfa445676870_4125234647787889_afc444334bb34245_85768a424fc4256_453667ab678f6909_018783ab3645ac39_343cffb342c5645f), // will be reseted to this seed 93 | //.readyMig((~fe_stall_q) && (fe_req_wr) && !fe_cmd), 94 | .readyMig((~fe_stall)&& (fe_req_wr) && !(fe_wr_stall||(fe_cmd_sel && (fe_write_cnt>0)))), 95 | .regen(1'b0), // check if gen or regen 96 | .rd_valid(1'b0), // check if valid data to read 97 | 98 | .gen_pattern(fe_data) 99 | ); 100 | 101 | lfsr_gen 102 | #( 103 | .lfsr_width(16) 104 | )lfsr_generate_cmd_sel 105 | ( 106 | .clk(ui_clk), 107 | .new_seed(~ui_rst_n || stop_lfsr), // works as a reset 108 | .seed(16'h8dc3), // will be reseted to this seed 109 | .readyMig(1'b1), // check if Mig is ready for write 110 | .regen(1'b0), // check if gen or regen 111 | .rd_valid(1'b0), // check if valid data to read 112 | 113 | .gen_pattern(fe_cmd_sel) 114 | ); 115 | 116 | 117 | assign fe_addr = (fe_wr_stall||(fe_cmd_sel && (fe_write_cnt>0)))?fe_addr_rd:fe_addr_wr; 118 | assign fe_cmd = (fe_wr_stall||(fe_cmd_sel && (fe_write_cnt>0)))?1'b1:1'b0; 119 | assign fe_req = ((fe_wr_stall||(fe_cmd_sel && (fe_write_cnt>0)))?fe_req_rd:fe_req_wr) && !fe_stall; 120 | 121 | //sync FF 122 | //assumption fe_cmd_rd is initially zero, this happens if the seed is zero 123 | always_ff@(posedge ui_clk, negedge ui_rst_n) 124 | begin 125 | if(ui_rst_n == 1'b0) 126 | begin 127 | //fe_addr <= '0; 128 | //fe_cmd <= '0; 129 | //fe_req <= '0; 130 | fe_stall_q <= '1; 131 | fe_write_cnt <= '0; 132 | fe_wr_stall <= '0; 133 | write_cnt <= NUM_TRANSACTIONS-1; 134 | stop_lfsr <= 1'b0; 135 | end 136 | else 137 | begin 138 | fe_stall_q <= fe_stall; 139 | if((fe_cmd == FE_WRITE) && fe_req) 140 | write_cnt <= write_cnt - 1; 141 | 142 | if(write_cnt == '0) 143 | stop_lfsr <= 1'b1; 144 | 145 | if(!fe_stall) begin 146 | if((fe_wr_stall||(fe_cmd_sel && (fe_write_cnt>0)))) 147 | fe_write_cnt <= fe_write_cnt - 1; 148 | else 149 | fe_write_cnt <= fe_write_cnt + 1; 150 | 151 | if(fe_write_cnt>15) 152 | fe_wr_stall <= 1; 153 | else 154 | if(fe_wr_stall && (fe_write_cnt<8)) 155 | fe_wr_stall <= 0; 156 | end 157 | end // else: !if(ui_rst_n == 1'b0) 158 | end // always_ff@ (posedge ui_clk, negedge ui_rst_n) 159 | 160 | 161 | lfsr_gen 162 | #( 163 | .lfsr_width(DRAM_BUS_WIDTH*BL) 164 | )lfsr_regenerate_data 165 | ( 166 | .clk(ui_clk), 167 | .new_seed(~ui_rst_n), // works as a reset 168 | .seed(512'h7cb7467189af4346_fcabbfa445676870_4125234647787889_afc444334bb34245_85768a424fc4256_453667ab678f6909_018783ab3645ac39_343cffb342c5645f), // will be reseted to this seed 169 | .readyMig('0), // check if Mig is ready for write 170 | .regen(1'b1), // check if gen or regen 171 | .rd_valid(fe_read_valid), // check if valid data to read 172 | 173 | .gen_pattern(fe_data_regen) 174 | ); 175 | 176 | 177 | /*lfsr_gen 178 | #( 179 | .lfsr_width(FE_ADDR_WIDTH-6+1+1) 180 | )lfsr_regenerate_addr 181 | ( 182 | .clk(ui_clk), 183 | .new_seed(~ui_rst_n), // works as a reset 184 | .seed(66'h2734c673a47f2345a), // will be reseted to this seed 185 | .readyMig(), // check if Mig is ready for write 186 | .regen(1'b1), // check if gen or regen 187 | .rd_valid((fe_req_regen)?fe_read_valid:1'b1), // if previous cmd was write then skip, if read then wait for read valid 188 | 189 | .gen_pattern({fe_addr_regen,fe_cmd_regen,fe_req_regen}) 190 | );*/ 191 | 192 | always_ff@(posedge ui_clk, negedge ui_rst_n) 193 | begin 194 | if(ui_rst_n == 1'b0) 195 | begin 196 | fe_read_valid_q <= '0; 197 | fe_read_data_q <= '0; 198 | fe_read_id_q <= '0; 199 | end 200 | else 201 | begin 202 | fe_read_valid_q <= fe_read_valid; 203 | fe_read_data_q <= fe_read_data; 204 | fe_read_id_q <= fe_read_id; 205 | end 206 | end // always_ff@ (posedge ui_clk, negedge ui_rst_n) 207 | 208 | always_ff@(posedge ui_clk, negedge ui_rst_n) 209 | begin 210 | if(ui_rst_n == 1'b0) 211 | begin 212 | data_cmp_err <= 1'b0; 213 | end 214 | else 215 | begin 216 | if(fe_read_valid) 217 | begin 218 | if(fe_read_data != fe_data_regen) 219 | begin 220 | data_cmp_err <= 1'b1; 221 | `ifndef SYNTHESIS 222 | $display("ERROR"); 223 | $display("Written Data = %h",fe_data_regen); 224 | $display("Read Data = %h",fe_read_data); 225 | //$display("Addr = %h",fe_addr_regen); 226 | //$display("Read CMD ID = %h, Read Data ID = %h",fe_id_regen,fe_read_id_q); 227 | $stop; 228 | `endif 229 | end 230 | else 231 | begin 232 | `ifndef SYNTHESIS 233 | $display("GOOD"); 234 | $display("Written Data = %h",fe_data_regen); 235 | $display("Read Data = %h",fe_read_data); 236 | //$display("Addr = %h",fe_addr_regen); 237 | // $display("Read CMD ID = %h, Read Data ID = %h",fe_id_regen,fe_read_id_q); 238 | `endif 239 | data_cmp_err <= data_cmp_err; 240 | end 241 | end 242 | end // else: !if(ui_rst_n == 1'b0) 243 | end // always_ff@ (posedge ui_clk, negedge ui_rst_n) 244 | 245 | 246 | always_ff @(posedge ui_clk, negedge ui_rst_n) 247 | begin 248 | if(ui_rst_n == 1'b0) 249 | begin 250 | fe_id <= '0; 251 | fe_id_regen <= '0; 252 | end 253 | else 254 | begin 255 | if((~fe_stall_q)&&((fe_cmd_sel && (fe_write_cnt>0))?fe_req_rd:fe_req_wr)) 256 | fe_id <= fe_id + 1; 257 | if(((fe_cmd_regen==FE_WRITE) && fe_req_regen)?1'b1:fe_read_valid) 258 | fe_id_regen <= fe_id_regen + 1; 259 | end 260 | end // always_ff @ (posedge ui_clk, negedge ui_rst_n) 261 | 262 | endmodule 263 | -------------------------------------------------------------------------------- /ips/ems_lib/min_8/lowest_nr_identifier.sv: -------------------------------------------------------------------------------- 1 | module lowest_nr_identifier_8 2 | #( 3 | parameter NR_WIDTH = 8 4 | ) 5 | ( 6 | input [7:0][NR_WIDTH-1:0] nr, 7 | input [7:0] req, 8 | 9 | output [NR_WIDTH-1:0] lowest_nr, 10 | output logic [2:0] lowest_line, 11 | output logic lowest_valid 12 | ); 13 | 14 | // This module will select and output the lowest number among the eight 15 | // input numbers. It also will indicate on which input line the lowest number 16 | // was signaled. 17 | // This for same nr req, lowest line is the id of highest 18 | 19 | //To find lowest number among all reqs, we need 7 compare unit in 3 stages 20 | logic [3:0][NR_WIDTH-1:0] comp1_lowest; 21 | logic [1:0][NR_WIDTH-1:0] comp2_lowest; 22 | logic [3:0][0:0] comp1_res_v, comp1_low_line; 23 | logic [1:0] comp2_res_v, comp2_low_line; 24 | logic comp3_low_line; 25 | 26 | generate 27 | for(genvar i=0; i<=3; i++) begin 28 | assign comp1_low_line[i]=({!req[i*2],nr[i*2]}<{!req[i*2+1],nr[(i*2)+1]}); 29 | assign comp1_lowest[i]=(comp1_low_line[i])?nr[i*2]:nr[i*2+1]; 30 | assign comp1_res_v[i] = req[i*2] | req[i*2+1]; 31 | end 32 | 33 | for(genvar j=0; j<=1; j++) 34 | begin 35 | assign comp2_low_line[j]=({!comp1_res_v[j*2],comp1_lowest[j*2]}< 36 | {!comp1_res_v[j*2+1],comp1_lowest[j*2+1]}); 37 | assign comp2_lowest[j]=(comp2_low_line[j])?comp1_lowest[j*2]: 38 | comp1_lowest[j*2+1]; 39 | assign comp2_res_v[j] = comp1_res_v[j*2] | comp1_res_v[j*2+1]; 40 | end 41 | endgenerate 42 | 43 | assign comp3_low_line = ({!comp2_res_v[0],comp2_lowest[0]}< 44 | {!comp2_res_v[1],comp2_lowest[1]}); 45 | assign lowest_nr = (comp3_low_line)? comp2_lowest[0]: comp2_lowest[1]; 46 | assign lowest_valid = comp2_res_v[0] | comp2_res_v[1]; 47 | 48 | always_comb 49 | begin 50 | lowest_line[2] = !comp3_low_line; 51 | lowest_line[1] = comp3_low_line? !comp2_low_line[0]:!comp2_low_line[1]; 52 | case({lowest_line[2],lowest_line[1]}) 53 | 2'b00: lowest_line[0] = !comp1_low_line[0]; 54 | 2'b01: lowest_line[0] = !comp1_low_line[1]; 55 | 2'b10: lowest_line[0] = !comp1_low_line[2]; 56 | 2'b11: lowest_line[0] = !comp1_low_line[3]; 57 | endcase // case ({comp3_low_line,comp2_low_line}) 58 | end // always_comb 59 | endmodule // lowest_nr_identifier_8 60 | -------------------------------------------------------------------------------- /ips/ems_lib/min_generic/lowest_nr_identifier.sv: -------------------------------------------------------------------------------- 1 | module lowest_nr_identifier 2 | #( 3 | parameter NR_WIDTH = 8, 4 | parameter NR_INPUTS = 8 5 | ) 6 | ( 7 | input [NR_INPUTS-1:0][NR_WIDTH-1:0] nr, 8 | input [NR_INPUTS-1:0] req, 9 | 10 | output [NR_WIDTH-1:0] lowest_nr, 11 | output logic [$clog2(NR_INPUTS)-1:0] lowest_line, 12 | output logic lowest_valid 13 | ); 14 | 15 | // This module will select and output the lowest number among the eight 16 | // input numbers. It also will indicate on which input line the lowest number 17 | // was signaled. 18 | // This for same nr req, lowest line is the id of highest 19 | 20 | //To find lowest number among all reqs, we need 7 compare unit in 3 stages for 8 input device 21 | logic [$clog2(NR_INPUTS):0][NR_INPUTS-1:0][NR_WIDTH-1:0] comp_lowest; 22 | logic [$clog2(NR_INPUTS):0][NR_INPUTS-1:0] comp_res_v; 23 | logic [$clog2(NR_INPUTS):1][(NR_INPUTS/2)-1:0] comp_low_line; 24 | logic [$clog2(NR_INPUTS):0][NR_INPUTS-1:0][$clog2(NR_INPUTS)-1:0] lowest_line_tmp; 25 | logic [$clog2(NR_INPUTS)-1:0][(NR_INPUTS/2)-1:0] sign; 26 | logic [$clog2(NR_INPUTS)-1:0][(NR_INPUTS/2)-1:0][NR_WIDTH+1:0] sub; 27 | 28 | assign comp_lowest[0] = nr; 29 | assign comp_res_v[0] = req; 30 | 31 | generate 32 | for(genvar j=0; j 0; k--) begin 57 | for(integer i = 0; i < NR_INPUTS/(2**(k)); i++) begin 58 | if((lowest_line_tmp >> (k-1)) == i) 59 | lowest_line_tmp[k-1] = !comp_low_line[k][i]; 60 | end 61 | end 62 | end*/ 63 | endmodule 64 | -------------------------------------------------------------------------------- /ips/ems_lib/mux_8_1/mux_8_1.sv: -------------------------------------------------------------------------------- 1 | module mux_8_1 2 | #( 3 | parameter WIDTH = 16 4 | ) 5 | ( 6 | input [7:0][WIDTH-1:0] in, 7 | input [2:0] sel, 8 | output logic [WIDTH-1:0] out 9 | ); 10 | always_comb 11 | begin 12 | out = 0; 13 | case(sel) 14 | 0: begin 15 | out = in[0]; 16 | end 17 | 1: begin 18 | out = in[1]; 19 | end 20 | 2: begin 21 | out = in[2]; 22 | end 23 | 3: begin 24 | out = in[3]; 25 | end 26 | 4: begin 27 | out = in[4]; 28 | end 29 | 5: begin 30 | out = in[5]; 31 | end 32 | 6: begin 33 | out = in[6]; 34 | end 35 | 7: begin 36 | out = in[7]; 37 | end 38 | default: begin 39 | out = in[0]; 40 | end 41 | endcase // case (sel) 42 | end // always_comb 43 | endmodule // mux_8_1 44 | -------------------------------------------------------------------------------- /ips/ems_lib/mux_generic/mux_generic.sv: -------------------------------------------------------------------------------- 1 | module mux_1 2 | #( 3 | parameter WIDTH = 16, 4 | parameter NR_INPUTS = 8 5 | ) 6 | ( 7 | input [NR_INPUTS-1:0][WIDTH-1:0] in, 8 | input [$clog2(NR_INPUTS)-1:0] sel, 9 | output logic [WIDTH-1:0] out 10 | ); 11 | 12 | integer i; 13 | 14 | always_comb 15 | begin 16 | out = '0; 17 | for(i = 0; i < NR_INPUTS; i++) 18 | begin 19 | if(sel == i) 20 | out = in[i]; 21 | end 22 | end 23 | endmodule 24 | 25 | -------------------------------------------------------------------------------- /ips/ems_lib/priority_arbiter_8/priority_arbiter_8.sv: -------------------------------------------------------------------------------- 1 | module priority_arbiter_8 2 | #( 3 | parameter PRIORITY_WIDTH = 8, 4 | parameter DATA_WIDTH = 2 5 | ) 6 | ( 7 | input [7:0][PRIORITY_WIDTH-1:0] priority_i, 8 | input [7:0][DATA_WIDTH-1:0] data_i, 9 | input [7:0] req, 10 | input [PRIORITY_WIDTH-1:0] highest_priority, 11 | output [DATA_WIDTH-1:0] data_o, 12 | output valid, 13 | output [2:0] grant 14 | ); 15 | 16 | // This module accepts 8 input reqs, each req is associated with priority. 17 | // The data request with highest priority is passed to output. 18 | // Priority order: highest priority i/p value to highest priority-1(lowest). 19 | // It is in wrap around fashion. 20 | 21 | logic [2:0] select_lcl; 22 | logic [7:0][PRIORITY_WIDTH-1:0] priority_lcl; 23 | 24 | 25 | // for(genvar i = 0; i<=7; i++) 26 | // assign priority_lcl[i] = priority_i[i] - highest_priority; 27 | // endgenerate 28 | 29 | assign priority_lcl[0] = priority_i[0] - highest_priority; 30 | assign priority_lcl[1] = priority_i[1] - highest_priority; 31 | assign priority_lcl[2] = priority_i[2] - highest_priority; 32 | assign priority_lcl[3] = priority_i[3] - highest_priority; 33 | assign priority_lcl[4] = priority_i[4] - highest_priority; 34 | assign priority_lcl[5] = priority_i[5] - highest_priority; 35 | assign priority_lcl[6] = priority_i[6] - highest_priority; 36 | assign priority_lcl[7] = priority_i[7] - highest_priority; 37 | 38 | lowest_nr_identifier_8 39 | #( 40 | .NR_WIDTH(PRIORITY_WIDTH) 41 | )highest_priority_selector 42 | ( 43 | .nr(priority_lcl), 44 | .req(req), 45 | .lowest_nr(), 46 | .lowest_line(select_lcl), 47 | .lowest_valid(valid) 48 | ); 49 | assign grant = select_lcl; 50 | 51 | mux_8_1 52 | #( 53 | .WIDTH (DATA_WIDTH) 54 | )mux 55 | ( 56 | .in(data_i), 57 | .sel(select_lcl), 58 | .out(data_o) 59 | ); 60 | endmodule // priority_arbiter_8 61 | -------------------------------------------------------------------------------- /ips/ems_lib/priority_arbiter_generic/priority_arbiter_generic.sv: -------------------------------------------------------------------------------- 1 | module priority_arbiter 2 | #( 3 | parameter PRIORITY_WIDTH = 8, 4 | parameter DATA_WIDTH = 2, 5 | parameter NR_INPUTS = 8 6 | ) 7 | ( 8 | input [NR_INPUTS-1:0][PRIORITY_WIDTH-1:0] priority_i, 9 | input [NR_INPUTS-1:0][DATA_WIDTH-1:0] data_i, 10 | input [NR_INPUTS-1:0] req, 11 | input [PRIORITY_WIDTH-1:0] highest_priority, 12 | output [DATA_WIDTH-1:0] data_o, 13 | output valid, 14 | output [$clog2(NR_INPUTS)-1:0] grant 15 | ); 16 | 17 | // This module accepts 8 input reqs, each req is associated with priority. 18 | // The data request with highest priority is passed to output. 19 | // Priority order: highest priority i/p value to highest priority-1(lowest). 20 | // It is in wrap around fashion. 21 | 22 | logic [$clog2(NR_INPUTS)-1:0] select_lcl; 23 | logic [NR_INPUTS-1:0][PRIORITY_WIDTH-1:0] priority_lcl; 24 | 25 | generate 26 | for(genvar i = 0; i 0; k--) begin 64 | for(integer i = 0; i < NR_INPUTS/(2**(k)); i++) begin 65 | if((lowest_line_tmp >> (k-1)) == i) 66 | lowest_line_tmp[k-1] = !comp_low_line[k][i]; 67 | end 68 | end 69 | end*/ 70 | endmodule 71 | -------------------------------------------------------------------------------- /ips/ems_lib/pulp_clock_gating/pulp_clock_gating.sv: -------------------------------------------------------------------------------- 1 | // Copyright 2017 ETH Zurich and University of Bologna. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 0.51 (the “License”); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | module pulp_clock_gating 12 | ( 13 | input logic clk_i, 14 | input logic en_i, 15 | input logic test_en_i, 16 | output logic clk_o 17 | ); 18 | 19 | `ifdef PULP_FPGA_EMUL 20 | // no clock gates in FPGA flow 21 | assign clk_o = clk_i; 22 | `else 23 | logic clk_en; 24 | 25 | always_latch 26 | begin 27 | if (clk_i == 1'b0) 28 | clk_en <= en_i | test_en_i; 29 | end 30 | 31 | assign clk_o = clk_i & clk_en; 32 | `endif 33 | 34 | endmodule 35 | -------------------------------------------------------------------------------- /runs/FPGA/example_bit.tcl: -------------------------------------------------------------------------------- 1 | source ./../../ips/Xi_Phy/ip_setup.tcl 2 | 3 | file mkdir BIT 4 | set_part $PART 5 | 6 | #set IP_PATH c:/MyFiles/chirag/projects/FPGA_ctrl/try/mig_phy_only_ip_ex/IP/mig_phy 7 | #set IMPL_RES_PATH c:/MyFiles/chirag/projects/FPGA_ctrl/try/mig_phy_only_ip_ex/IMPL 8 | #set BIT_RES_PATH c:/MyFiles/chirag/projects/FPGA_ctrl/try/mig_phy_only_ip_ex/BIT 9 | 10 | cd $IMPL_RES_PATH 11 | open_checkpoint example_top_routed.dcp 12 | 13 | cd $IP_PATH 14 | add_file ./mig_phy.srcs/sources_1/ip/ddr4_0/sw/calibration_0/Debug/calibration_ddr.elf 15 | set_property SCOPED_TO_REF ddr4_0 [get_files -all ./mig_phy.srcs/sources_1/ip/ddr4_0/sw/calibration_0/Debug/calibration_ddr.elf] 16 | 17 | set_property SCOPED_TO_CELLS inst/u_ddr_cal_riu/mcs0/inst/microblaze_I [get_files -all ./mig_phy.srcs/sources_1/ip/ddr4_0/sw/calibration_0/Debug/calibration_ddr.elf] 18 | 19 | cd $BIT_RES_PATH 20 | catch { write_mem_info -force example_top.mmi } 21 | write_bitstream -force example_top.bit 22 | catch { write_sysdef -hwdef example_top.hwdef -bitfile example_top.bit -meminfo example_top.mmi -file example_top.sysdef } 23 | catch {write_debug_probes -quiet -force example_top} 24 | catch {file copy -force example_top.ltx debug_nets.ltx} 25 | -------------------------------------------------------------------------------- /runs/FPGA/example_impl.tcl: -------------------------------------------------------------------------------- 1 | source ./../../ips/Xi_Phy/ip_setup.tcl 2 | 3 | file mkdir IMPL 4 | 5 | create_project -in_memory 6 | set_part $PART 7 | 8 | #set IP_PATH c:/MyFiles/chirag/projects/FPGA_ctrl/try/mig_phy_only_ip_ex/IP/mig_phy 9 | #set IMPL_RES_PATH c:/MyFiles/chirag/projects/FPGA_ctrl/try/mig_phy_only_ip_ex/IMPL 10 | #set SYNTH_RES_PATH c:/MyFiles/chirag/projects/FPGA_ctrl/try/mig_phy_only_ip_ex/SYNTH 11 | #set CONST_PATH c:/MyFiles/chirag/projects/FPGA_ctrl/try/mig_phy_only_ip_ex/CONST 12 | 13 | cd $IP_PATH 14 | set_property ip_output_repo ./mig_phy.cache/ip [current_project] 15 | set_property ip_cache_permissions {read write} [current_project] 16 | set_property XPM_LIBRARIES XPM_MEMORY [current_project] 17 | 18 | cd $CONST_PATH 19 | #read_xdc example_design_ADM_9V3.xdc 20 | #set_property processing_order LATE [get_files example_design_ADM_9V3.xdc] 21 | read_xdc example_design.xdc 22 | set_property processing_order LATE [get_files example_design.xdc] 23 | 24 | 25 | cd $SYNTH_RES_PATH 26 | add_file ./example_top_synth.dcp 27 | 28 | cd $IP_PATH 29 | read_ip -quiet ./mig_phy.srcs/sources_1/ip/ddr4_0/ddr4_0.xci 30 | read_ip -quiet ./../../../Xi_BRAM/IP/bram_512x64/bram.srcs/sources_1/ip/blk_mem_gen_0/blk_mem_gen_0.xci 31 | read_ip -quiet ./../../../Xi_BRAM/IP/bram_528x64/bram_528x64.srcs/sources_1/ip/blk_mem_gen_528x64/blk_mem_gen_528x64.xci 32 | read_ip -quiet ./../../../Xi_BRAM/IP/bram_528x8/bram_528x8.srcs/sources_1/ip/blk_mem_gen_528x8/blk_mem_gen_528x8.xci 33 | read_ip -quiet ./../../../Xi_BRAM/IP/bram_52x4/bram_52x4.srcs/sources_1/ip/blk_mem_gen_52x4/blk_mem_gen_52x4.xci 34 | # disabling auto generated example_design.xdc file 35 | set ex_xdc [get_files -all -of_objects [get_files ./mig_phy.srcs/sources_1/ip/ddr4_0/ddr4_0.xci] -filter {name =~ "*example_design.xdc"}] 36 | set_property is_enabled false [get_files $ex_xdc] 37 | 38 | 39 | 40 | link_design -top tb_ddr4_ch_ctrl 41 | 42 | cd $IMPL_RES_PATH 43 | write_hwdef -force -file example_top.hwdef 44 | 45 | opt_design -aggressive_remap -bufg_opt > impl.log 46 | write_checkpoint -force example_top_opt.dcp 47 | report_drc -file example_top_drc_opted.rpt -pb example_top_drc_opted.pb -rpx example_top_drc_opted.rpx 48 | 49 | place_design -directive ExtraNetDelay_high >> impl.log 50 | #place_design >> impl.log 51 | place_design -post_place_opt >> impl.log 52 | phys_opt_design -directive AggressiveExplore 53 | write_checkpoint -force example_top_placed.dcp 54 | report_io -file example_top_io_placed.rpt 55 | report_utilization -file example_top_utilization_placed.rpt -pb example_top_utilization_placed.pb 56 | report_control_sets -verbose -file example_top_control_sets_placed.rpt 57 | 58 | route_design >> impl.log 59 | write_checkpoint -force example_top_routed.dcp 60 | write_verilog example_top_impl.v -force -mode design 61 | report_drc -file example_top_drc_routed.rpt -pb example_top_drc_routed.pb -rpx example_top_drc_routed.rpx 62 | report_methodology -file example_top_methodology_drc_routed.rpt -pb example_top_methodology_drc_routed.pb -rpx example_top_methodology_drc_routed.rpx 63 | report_power -file example_top_power_routed.rpt -pb example_top_power_summary_routed.pb -rpx example_top_power_routed.rpx 64 | report_route_status -file example_top_route_status.rpt -pb example_top_route_status.pb 65 | report_timing_summary -max_paths 10 -file example_top_timing_summary_routed.rpt -pb example_top_timing_summary_routed.pb -rpx example_top_timing_summary_routed.rpx -warn_on_violation 66 | report_incremental_reuse -file example_top_incremental_reuse_routed.rpt 67 | report_clock_utilization -file example_top_clock_utilization_routed.rpt 68 | report_bus_skew -warn_on_violation -file example_top_bus_skew_routed.rpt -pb example_top_bus_skew_routed.pb -rpx example_top_bus_skew_routed.rpx 69 | -------------------------------------------------------------------------------- /runs/FPGA/example_synth.tcl: -------------------------------------------------------------------------------- 1 | source ./../../ips/Xi_Phy/ip_setup.tcl 2 | 3 | file mkdir SYNTH 4 | 5 | create_project -in_memory 6 | set_part $PART 7 | 8 | #set_property XPM_LIBRARIES {XPM_CDC XPM_MEMORY} [current_project] 9 | 10 | #set IP_PATH c:/MyFiles/chirag/projects/FPGA_ctrl/try/mig_phy_only_ip_ex/IP/mig_phy 11 | #set SYNTH_RES_PATH c:/MyFiles/chirag/projects/FPGA_ctrl/try/mig_phy_only_ip_ex/SYNTH 12 | #set CONST_PATH c:/MyFiles/chirag/projects/FPGA_ctrl/try/mig_phy_only_ip_ex/CONST 13 | 14 | 15 | cd $IP_PATH 16 | set_property ip_output_repo ./mig_phy.cache/ip [current_project] 17 | set_property ip_cache_permissions {read write} [current_project] 18 | 19 | read_verilog -sv { 20 | ../../../axi_slice/axi_ar_buffer.sv 21 | ../../../axi_slice/axi_aw_buffer.sv 22 | ../../../axi_slice/axi_b_buffer.sv 23 | ../../../axi_slice/axi_r_buffer.sv 24 | ../../../axi_slice/axi_w_buffer.sv 25 | ../../../ems_lib/comp_sel_grt/comp_sel_grt.sv 26 | ../../../ems_lib/demux_1_4/demux_1_4.sv 27 | ../../../ems_lib/generic_fifo/generic_fifo.sv 28 | ../../../ems_lib/generic_fifo/bram_fifo_528x64.sv 29 | ../../../ems_lib/generic_fifo/bram_fifo_512x64.sv 30 | ../../../ems_lib/generic_fifo/bram_fifo_528x8.sv 31 | ../../../ems_lib/generic_fifo/bram_fifo_52x4.sv 32 | ../../../ems_lib/dual_clock_fifo/dual_clock_fifo.sv 33 | ../../../ems_lib/mux_generic/mux_generic.sv 34 | ../../../ems_lib/min_generic/lowest_nr_identifier.sv 35 | ../../../ems_lib/priority_arbiter_generic/priority_arbiter_generic.sv 36 | ../../../ems_lib/priority_arbiter_generic/priority_mux.sv 37 | ../../../ems_lib/priority_arbiter_generic/priority_encoder.sv 38 | ../../../ems_lib/pulp_clock_gating/pulp_clock_gating.sv 39 | ../../../ems_lib/lfsr/lfsr_gen.sv 40 | ../../../ems_lib/mem_tgen_checker/mem_tgen_checker.sv 41 | ../../../../implementation/syn/bankfsm_cmdmux_if/bankfsm_cmdmux_if.sv 42 | ../../../../implementation/syn/config_bus_slave/reg_bus_pkg.sv 43 | ../../../../implementation/syn/config_bus_slave/reg_bus_if.sv 44 | ../../../../implementation/syn/config_bus_slave/config_bus_slave.sv 45 | ../../../../implementation/syn/mem_ctrl/mem_ctrl_if.sv 46 | ../../../../implementation/syn/congen/congen.v 47 | ../../../../implementation/syn/axi_dram_if/axi_dram_if.sv 48 | ../../../../implementation/syn/ch_ctrl/ch_ctrl.sv 49 | ../../../../implementation/syn/ch_ctrl_bank_fsm/ch_ctrl_bank_fsm.sv 50 | ../../../../implementation/syn/bus_shuffler_4/bus_shuffler_4.sv 51 | ../../../../implementation/syn/cmd_mux/cmd_mux.sv 52 | ../../../../implementation/syn/ch_ctrl_rank_fsm/ch_ctrl_rank_fsm.sv 53 | ../../../../implementation/syn/ch_ctrl_rank_fsm/ch_ctrl_rank_fsm_wrapper.sv 54 | ../../../../implementation/syn/xiphy_if/bit_packing_xiphy_ultrascale.sv 55 | ../../../../implementation/syn/xiphy_if/xiphy_ultrascale_if.sv 56 | ../../../../validation/tb_ddr4_ch_ctrl/tb_ddr4_ch_ctrl.sv 57 | } 58 | 59 | read_ip -quiet ./mig_phy.srcs/sources_1/ip/ddr4_0/ddr4_0.xci 60 | 61 | # get all constraints files of the IP and do not include it in the resulting dcp file of this sysnthesis run output as its is already included in the dcp of the IP. When the dcp of IP is stiched to the design during implementation so does the IP contraints. 62 | set xdc [get_files -all -of_objects [get_files ./mig_phy.srcs/sources_1/ip/ddr4_0/ddr4_0.xci] -filter {name =~ "*.xdc"}] 63 | puts $xdc 64 | set_property used_in_implementation false [get_files $xdc] 65 | 66 | # disabling auto generated example_design.xdc file 67 | set ex_xdc [get_files -all -of_objects [get_files ./mig_phy.srcs/sources_1/ip/ddr4_0/ddr4_0.xci] -filter {name =~ "*example_design.xdc"}] 68 | set_property is_enabled false [get_files $ex_xdc] 69 | 70 | # get all dcp files of the IP (balck box) and do not stictch it to the resulting dcp file of this sysnthesis run output (i.e OOC(Out of context) flow). These dcp's are considered during the implemetation. This is a typical for OOC flow, also practiced in mig. 71 | set dcp [get_files -all -of_objects [get_files ./mig_phy.srcs/sources_1/ip/ddr4_0/ddr4_0.xci] -filter {name =~ "*.dcp"}] 72 | puts $dcp 73 | set_property used_in_implementation false [get_files $dcp] 74 | 75 | #foreach dcpn [get_files -quiet -all -filter file_type=="Design\ Checkpoint"] { 76 | # puts $dcpn 77 | # set_property used_in_implementation false $dcpn 78 | #} 79 | 80 | #### BRAM IP##### 81 | read_ip -quiet ./../../../Xi_BRAM/IP/bram_512x64/bram.srcs/sources_1/ip/blk_mem_gen_0/blk_mem_gen_0.xci 82 | 83 | set_property used_in_implementation false [get_files -all ./../../../Xi_BRAM/IP/bram_512x64/bram.srcs/sources_1/ip/blk_mem_gen_0/blk_mem_gen_0_ooc.xdc] 84 | 85 | read_ip -quiet ./../../../Xi_BRAM/IP/bram_528x64/bram_528x64.srcs/sources_1/ip/blk_mem_gen_528x64/blk_mem_gen_528x64.xci 86 | 87 | set_property used_in_implementation false [get_files -all ./../../../Xi_BRAM/IP/bram_528x64/bram_528x64.srcs/sources_1/ip/blk_mem_gen_528x64/blk_mem_gen_528x64_ooc.xdc] 88 | 89 | read_ip -quiet ./../../../Xi_BRAM/IP/bram_528x8/bram_528x8.srcs/sources_1/ip/blk_mem_gen_528x8/blk_mem_gen_528x8.xci 90 | 91 | set_property used_in_implementation false [get_files -all ./../../../Xi_BRAM/IP/bram_528x8/bram_528x8.srcs/sources_1/ip/blk_mem_gen_528x8/blk_mem_gen_528x8_ooc.xdc] 92 | 93 | read_ip -quiet ./../../../Xi_BRAM/IP/bram_52x4/bram_52x4.srcs/sources_1/ip/blk_mem_gen_52x4/blk_mem_gen_52x4.xci 94 | 95 | set_property used_in_implementation false [get_files -all ./../../../Xi_BRAM/IP/bram_52x4/bram_52x4.srcs/sources_1/ip/blk_mem_gen_52x4/blk_mem_gen_52x4_ooc.xdc] 96 | 97 | # Mark all dcp files as not used in implementation to prevent them from being 98 | # stitched into the results of this synthesis run. Any black boxes in the 99 | # design are intentionally left as such for best results. Dcp files will be 100 | # stitched into the design at a later time, either when this synthesis run is 101 | # opened, or when it is stitched into a dependent implementation run. 102 | 103 | set dcp [get_files -all -of_objects [get_files ./../../../Xi_BRAM/IP/bram_512x64/bram.srcs/sources_1/ip/blk_mem_gen_0/blk_mem_gen_0.xci] -filter {name =~ "*.dcp"}] 104 | puts $dcp 105 | set_property used_in_implementation false [get_files $dcp] 106 | 107 | set dcp [get_files -all -of_objects [get_files ./../../../Xi_BRAM/IP/bram_528x64/bram_528x64.srcs/sources_1/ip/blk_mem_gen_528x64/blk_mem_gen_528x64.xci] -filter {name =~ "*.dcp"}] 108 | puts $dcp 109 | set_property used_in_implementation false [get_files $dcp] 110 | 111 | set dcp [get_files -all -of_objects [get_files ./../../../Xi_BRAM/IP/bram_528x8/bram_528x8.srcs/sources_1/ip/blk_mem_gen_528x8/blk_mem_gen_528x8.xci] -filter {name =~ "*.dcp"}] 112 | puts $dcp 113 | set_property used_in_implementation false [get_files $dcp] 114 | 115 | set dcp [get_files -all -of_objects [get_files ./../../../Xi_BRAM/IP/bram_52x4/bram_52x4.srcs/sources_1/ip/blk_mem_gen_52x4/blk_mem_gen_52x4.xci] -filter {name =~ "*.dcp"}] 116 | puts $dcp 117 | set_property used_in_implementation false [get_files $dcp] 118 | 119 | ##### END BRAM##### 120 | 121 | 122 | set_property used_in_implementation false [get_files -all ./mig_phy.srcs/sources_1/ip/ddr4_0/sw/calibration_0/Debug/calibration_ddr.elf] 123 | 124 | set_property used_in_implementation false [get_files -all ./mig_phy.srcs/sources_1/ip/ddr4_0/ip_0/mb_bootloop_le.elf] 125 | 126 | set_property used_in_implementation false [get_files -all ./mig_phy.srcs/sources_1/ip/ddr4_0/bd_0/ip/ip_0/data/mb_bootloop_le.elf] 127 | 128 | cd $CONST_PATH 129 | #read_xdc ./example_design_ADM_9V3.xdc 130 | #set_property used_in_implementation false [get_files ./example_design_ADM_9V3.xdc] 131 | #set_property processing_order LATE [get_files ./example_design_ADM_9V3.xdc] 132 | read_xdc ./example_design.xdc 133 | set_property used_in_implementation false [get_files ./example_design.xdc] 134 | set_property processing_order LATE [get_files ./example_design.xdc] 135 | 136 | cd $IP_PATH 137 | read_xdc ./mig_phy.runs/ddr4_0_synth_1/dont_touch.xdc 138 | set_property used_in_implementation false [get_files ./mig_phy.runs/ddr4_0_synth_1/dont_touch.xdc] 139 | 140 | read_xdc ./../../../Xi_BRAM/IP/bram_512x64/bram.runs/blk_mem_gen_0_synth_1/dont_touch.xdc 141 | set_property used_in_implementation false [get_files ./../../../Xi_BRAM/IP/bram_512x64/bram.runs/blk_mem_gen_0_synth_1/dont_touch.xdc] 142 | 143 | read_xdc ./../../../Xi_BRAM/IP/bram_528x64/bram_528x64.runs/blk_mem_gen_528x64_synth_1/dont_touch.xdc 144 | set_property used_in_implementation false [get_files ./../../../Xi_BRAM/IP/bram_528x64/bram_528x64.runs/blk_mem_gen_528x64_synth_1/dont_touch.xdc] 145 | 146 | read_xdc ./../../../Xi_BRAM/IP/bram_528x8/bram_528x8.runs/blk_mem_gen_528x8_synth_1/dont_touch.xdc 147 | set_property used_in_implementation false [get_files ./../../../Xi_BRAM/IP/bram_528x8/bram_528x8.runs/blk_mem_gen_528x8_synth_1/dont_touch.xdc] 148 | 149 | read_xdc ./../../../Xi_BRAM/IP/bram_52x4/bram_52x4.runs/blk_mem_gen_52x4_synth_1/dont_touch.xdc 150 | set_property used_in_implementation false [get_files ./../../../Xi_BRAM/IP/bram_52x4/bram_52x4.runs/blk_mem_gen_52x4_synth_1/dont_touch.xdc] 151 | 152 | cd $SYNTH_RES_PATH 153 | file mkdir .Xil 154 | synth_design -top tb_ddr4_ch_ctrl -flatten_hierarchy rebuilt -include_dirs ../../../validation/tb_ddr4_ch_ctrl/ -verilog_define FPGA -verilog_define DDR4 -verilog_define SYNTHESIS -verilog_define PULP_FPGA_EMUL -verilog_define NEW_TGEN > synth.log 155 | # disable binary constraint mode for synth run checkpoints 156 | set_param constraints.enableBinaryConstraints false 157 | write_xdc -force -file synth.xdc 158 | write_checkpoint -force -noxdef example_top_synth.dcp 159 | write_verilog example_top_synth.v -force -mode design 160 | report_utilization -file example_top_utilization_synth.rpt -pb example_top_utilization_synth.pb 161 | report_timing_summary -file timing_syn.rpt 162 | -------------------------------------------------------------------------------- /validation/README.md: -------------------------------------------------------------------------------- 1 | # VALIDATION FOLDER HOLDS ALL TESTBENCHES 2 | 3 | To run testbench in Modelsim 4 | vsim -do run.tcl -------------------------------------------------------------------------------- /validation/tb_ddr4_ch_ctrl/glbl.v: -------------------------------------------------------------------------------- 1 | // $Header: /devl/xcs/repo/env/Databases/CAEInterfaces/verunilibs/data/glbl.v,v 1.14 2010/10/28 20:44:00 fphillip Exp $ 2 | `ifndef GLBL 3 | `define GLBL 4 | `timescale 1 ps / 1 ps 5 | 6 | module glbl (); 7 | 8 | parameter ROC_WIDTH = 100000; 9 | parameter TOC_WIDTH = 0; 10 | 11 | //-------- STARTUP Globals -------------- 12 | wire GSR; 13 | wire GTS; 14 | wire GWE; 15 | wire PRLD; 16 | tri1 p_up_tmp; 17 | tri (weak1, strong0) PLL_LOCKG = p_up_tmp; 18 | 19 | wire PROGB_GLBL; 20 | wire CCLKO_GLBL; 21 | wire FCSBO_GLBL; 22 | wire [3:0] DO_GLBL; 23 | wire [3:0] DI_GLBL; 24 | 25 | reg GSR_int; 26 | reg GTS_int; 27 | reg PRLD_int; 28 | 29 | //-------- JTAG Globals -------------- 30 | wire JTAG_TDO_GLBL; 31 | wire JTAG_TCK_GLBL; 32 | wire JTAG_TDI_GLBL; 33 | wire JTAG_TMS_GLBL; 34 | wire JTAG_TRST_GLBL; 35 | 36 | reg JTAG_CAPTURE_GLBL; 37 | reg JTAG_RESET_GLBL; 38 | reg JTAG_SHIFT_GLBL; 39 | reg JTAG_UPDATE_GLBL; 40 | reg JTAG_RUNTEST_GLBL; 41 | 42 | reg JTAG_SEL1_GLBL = 0; 43 | reg JTAG_SEL2_GLBL = 0 ; 44 | reg JTAG_SEL3_GLBL = 0; 45 | reg JTAG_SEL4_GLBL = 0; 46 | 47 | reg JTAG_USER_TDO1_GLBL = 1'bz; 48 | reg JTAG_USER_TDO2_GLBL = 1'bz; 49 | reg JTAG_USER_TDO3_GLBL = 1'bz; 50 | reg JTAG_USER_TDO4_GLBL = 1'bz; 51 | 52 | assign (strong1, weak0) GSR = GSR_int; 53 | assign (strong1, weak0) GTS = GTS_int; 54 | assign (weak1, weak0) PRLD = PRLD_int; 55 | 56 | initial begin 57 | GSR_int = 1'b1; 58 | PRLD_int = 1'b1; 59 | #(ROC_WIDTH) 60 | GSR_int = 1'b0; 61 | PRLD_int = 1'b0; 62 | end 63 | 64 | initial begin 65 | GTS_int = 1'b1; 66 | #(TOC_WIDTH) 67 | GTS_int = 1'b0; 68 | end 69 | 70 | endmodule 71 | `endif 72 | -------------------------------------------------------------------------------- /validation/tb_ddr4_ch_ctrl/light_phy.svh: -------------------------------------------------------------------------------- 1 | // AUTHOR: Jan Lappas 2 | // Date : 09.03.2018 3 | `ifndef LIGHT_PHY_SVH 4 | `define LIGHT_PHY_SVH 5 | 6 | interface if_io_config; 7 | // Slew Rate Control 8 | logic [1:0] td_ctrl_n; 9 | logic tdqs_trim_n; 10 | // Impedance Calibration Off Chip Driver 11 | logic [4:0] pd_en_a; 12 | logic [4:0] pd_en_n_a; 13 | logic [4:0] pu_en_a; 14 | logic [4:0] pu_en_n_a; 15 | //---------------------------- 16 | logic [4:0] pd_en_b; 17 | logic [4:0] pd_en_n_b; 18 | logic [4:0] pu_en_b; 19 | logic [4:0] pu_en_n_b; 20 | 21 | // PHY Side 22 | //*************************************** 23 | modport phy 24 | ( 25 | output td_ctrl_n, output tdqs_trim_n, 26 | output pd_en_a, output pd_en_n_a, output pu_en_a, output pu_en_n_a, 27 | output pd_en_b, output pd_en_n_b, output pu_en_b, output pu_en_n_b 28 | ); 29 | 30 | // Off Chip Driver Side 31 | //*************************************** 32 | modport ocd 33 | ( 34 | input td_ctrl_n, input tdqs_trim_n, 35 | input pd_en_a, input pd_en_n_a, input pu_en_a, input pu_en_n_a, 36 | input pd_en_b, input pd_en_n_b, input pu_en_b, input pu_en_n_b 37 | ); 38 | 39 | endinterface // if_config_io 40 | 41 | interface if_impedance_cntrl; 42 | // Impedance Control Off Chip Driver 43 | logic [4:0] pdat_en_a; 44 | logic [4:0] ndat_nen_a; 45 | //--------------------------- 46 | logic [4:0] pdat_en_b; 47 | logic [4:0] ndat_nen_b; 48 | 49 | // PHY Side 50 | //*************************************** 51 | modport phy 52 | ( 53 | output pdat_en_a, output ndat_nen_a, 54 | output pdat_en_b, output ndat_nen_b 55 | ); 56 | 57 | // Off Chip Driver Side 58 | //*************************************** 59 | modport ocd 60 | ( 61 | input pdat_en_a, input ndat_nen_a, 62 | input pdat_en_b, input ndat_nen_b 63 | ); 64 | endinterface // if_impedance_cntrl 65 | 66 | interface if_ocd; 67 | logic pdat_ev_a; 68 | logic ndat_ev_a; 69 | logic pdat_od_a; 70 | logic ndat_od_a; 71 | //---------------------------- 72 | // Driver Signals Channel B 73 | logic pdat_ev_b; 74 | logic ndat_ev_b; 75 | logic pdat_od_b; 76 | logic ndat_od_b; 77 | 78 | // PHY Side 79 | //*************************************** 80 | modport phy 81 | ( 82 | output pdat_ev_a, output ndat_ev_a, 83 | output pdat_od_a, output ndat_od_a, 84 | output pdat_ev_b, output ndat_ev_b, 85 | output pdat_od_b, output ndat_od_b 86 | ); 87 | 88 | // Off Chip Driver Side 89 | //*************************************** 90 | modport ocd 91 | ( 92 | input pdat_ev_a, input ndat_ev_a, 93 | input pdat_od_a, input ndat_od_a, 94 | input pdat_ev_b, input ndat_ev_b, 95 | input pdat_od_b, input ndat_od_b 96 | ); 97 | endinterface // if_ocd 98 | 99 | interface if_rcv_dq; 100 | // Receiver Channel A 101 | //logic dq_a_in; 102 | logic en_rcv2_a; 103 | logic en_rcv1_bias_a; 104 | logic en_rcv2_bias_a; 105 | logic parkh_n_a; 106 | // Receiver Channel B 107 | //logic dq_b_in; 108 | logic en_rcv2_b; 109 | logic en_rcv1_bias_b; 110 | logic en_rcv2_bias_b; 111 | logic parkh_n_b; 112 | //---------------------------- 113 | logic rdy_n; 114 | logic iddq_n; 115 | 116 | // PHY Side 117 | //*************************************** 118 | modport phy 119 | ( 120 | output en_rcv2_a, output en_rcv1_bias_a, output en_rcv2_bias_a, 121 | output parkh_n_a, 122 | output en_rcv2_b, output en_rcv1_bias_b, output en_rcv2_bias_b, 123 | output parkh_n_b, 124 | input rdy_n , output iddq_n 125 | ); 126 | 127 | // Data Receiver Side 128 | //*************************************** 129 | modport rcv_dq 130 | ( 131 | input en_rcv2_a, input en_rcv1_bias_a, input en_rcv2_bias_a, 132 | input parkh_n_a, 133 | input en_rcv2_b, input en_rcv1_bias_b, input en_rcv2_bias_b, 134 | input parkh_n_b, 135 | output rdy_n , input iddq_n 136 | ); 137 | endinterface // if_rcv 138 | 139 | interface if_rcv_dqs; 140 | // DQS Receiver 141 | // logic dqs_in; 142 | // logic dqs_n_in; 143 | //--------DQS_IN---------------------- 144 | logic en_rcv2_bias_a; 145 | logic en_rcv2_a; 146 | logic parkh_n_a; 147 | //---------DQS_N_IN-------------------- 148 | logic en_rcv2_bias_b; 149 | logic en_rcv2_b; 150 | logic parkh_n_b; 151 | //--------------------------------- 152 | logic rdy_n; 153 | logic en_rcv1_bias; 154 | logic iddq_n; 155 | 156 | // PHY Side 157 | //*************************************** 158 | modport phy 159 | ( 160 | input rdy_n, 161 | output en_rcv2_bias_a, output en_rcv2_a, output parkh_n_a, 162 | output en_rcv2_bias_b, output en_rcv2_b, output parkh_n_b, 163 | output en_rcv1_bias, output iddq_n 164 | ); 165 | 166 | // Data Strobe Receiver Side 167 | //*************************************** 168 | modport rcv_dqs 169 | ( 170 | output rdy_n, 171 | input en_rcv2_bias_a, input en_rcv2_a, input parkh_n_a, 172 | input en_rcv2_bias_b, input en_rcv2_b, input parkh_n_b, 173 | input en_rcv1_bias, input iddq_n 174 | ); 175 | endinterface // if_rcv 176 | 177 | interface if_mem_data #(pAXI_ID_WIDTH = 16); 178 | // INPUT MEM_CNTRL FIFO READ 179 | logic data_rd_valid; 180 | // INPUT MEM_CNTRL FIFO READ - DATA 181 | logic [63:0] data_rd; 182 | // INPUT MEM_CNTRL FIFO READ - DATA ID 183 | logic [pAXI_ID_WIDTH-1:0] data_rd_id; 184 | // INPUT FOR PHY - DATA ID FROM MEM_CNTRL 185 | logic [pAXI_ID_WIDTH-1:0] data_id; 186 | // OUTPUT FROM MEM_CNTRL FIFO 187 | logic [63:0] data_wr; 188 | // MEM_CNTRL PUSH DATA INTO WR-DATA BUFFER IN THE LIGHT_PHY 189 | logic grant_wr_data; 190 | 191 | // DATA BUS READY - tell MEM_CNTRL if data bus is ready (calibration etc.) 192 | //logic bus_rdy; 193 | 194 | // PHY Side 195 | //*************************************** 196 | modport phy 197 | ( 198 | output data_rd_valid, output data_rd, output data_rd_id, 199 | output grant_wr_data, 200 | input data_id, input data_wr 201 | ); 202 | 203 | // DATA SLICE Side 204 | //*************************************** 205 | modport data_slice 206 | ( 207 | output data_rd_valid, output data_rd, output data_rd_id, 208 | output grant_wr_data, 209 | input data_id, input data_wr 210 | ); 211 | 212 | // Memory Controller Side 213 | //*************************************** 214 | modport mem_cntrl 215 | ( 216 | input data_rd_valid, input data_rd, input data_rd_id, 217 | input grant_wr_data, 218 | output data_id, output data_wr 219 | ); 220 | 221 | endinterface // if_mem_data 222 | 223 | interface if_mem_adr_cmd; 224 | // Input Off Chip Driver 225 | logic [3:0] [2:0] ba; 226 | logic [3:0] [15:0] adr; 227 | logic [3:0] [4:0] cmd; // CKE,nCS, nRAS,nCAS,nWE [4:0] 228 | logic reset_m_n; 229 | // -------------------------------------------- 230 | logic clk_oe; 231 | logic ocd_oe; 232 | // PHY Side 233 | //*************************************** 234 | modport phy 235 | ( 236 | input ba, input adr, input cmd, input reset_m_n, input clk_oe, 237 | input ocd_oe 238 | ); 239 | 240 | // Memory Controller Side 241 | //*************************************** 242 | modport mem_cntrl 243 | ( 244 | output ba, output adr, output cmd, output reset_m_n, output clk_oe, 245 | output ocd_oe 246 | ); 247 | endinterface // if_mem_adr_cmd 248 | 249 | interface if_phy_io_cal_config; 250 | // IMPEDANCE SELECTION 251 | logic [4:0] ron_data; 252 | logic [4:0] rtt_data; 253 | //logic [4:0] ron_adr_cmd; 254 | // IMPEDANCE CALIBRATION OVERRIGHT DEBUG 255 | logic [4:0] pu_en_ocd_cal; 256 | logic [4:0] pd_en_ocd_cal; 257 | logic disable_ocd_cal; 258 | // SLEW RATE CONFIG 259 | logic [1:0] td_ctrl_n_data; 260 | logic tdqs_trim_n_data; 261 | //logic [1:0] td_ctrl_n_adr_cmd; 262 | //logic tdqs_trim_n_adr_cmd; 263 | 264 | // PHY Side 265 | //*************************************** 266 | modport phy 267 | ( 268 | input ron_data, input rtt_data, 269 | input pu_en_ocd_cal, input pd_en_ocd_cal, input disable_ocd_cal, 270 | input td_ctrl_n_data, input tdqs_trim_n_data); 271 | // DRAM INIT UNIT Side 272 | //*************************************** 273 | modport mem_cntrl 274 | ( 275 | output ron_data, output rtt_data, 276 | output pu_en_ocd_cal, output pd_en_ocd_cal, output disable_ocd_cal, 277 | output td_ctrl_n_data, output tdqs_trim_n_data); 278 | endinterface // if_dram_init 279 | 280 | 281 | localparam cRON_60 = 5'b01011; 282 | localparam cRON_48 = 5'b10011; 283 | localparam cRON_40 = 5'b10111; 284 | localparam cRON_34 = 5'b11111; 285 | 286 | localparam cRTT_120 = 5'b01000; 287 | localparam cRTT_60 = 5'b10000; 288 | localparam cRTT_40 = 5'b11000; 289 | localparam cRTT_30 = 5'b10110; 290 | localparam cRTT_20 = 5'b10101; 291 | 292 | `endif 293 | -------------------------------------------------------------------------------- /validation/tb_ddr4_mem_ch_top/glbl.v: -------------------------------------------------------------------------------- 1 | // $Header: /devl/xcs/repo/env/Databases/CAEInterfaces/verunilibs/data/glbl.v,v 1.14 2010/10/28 20:44:00 fphillip Exp $ 2 | `ifndef GLBL 3 | `define GLBL 4 | `timescale 1 ps / 1 ps 5 | 6 | module glbl (); 7 | 8 | parameter ROC_WIDTH = 100000; 9 | parameter TOC_WIDTH = 0; 10 | 11 | //-------- STARTUP Globals -------------- 12 | wire GSR; 13 | wire GTS; 14 | wire GWE; 15 | wire PRLD; 16 | tri1 p_up_tmp; 17 | tri (weak1, strong0) PLL_LOCKG = p_up_tmp; 18 | 19 | wire PROGB_GLBL; 20 | wire CCLKO_GLBL; 21 | wire FCSBO_GLBL; 22 | wire [3:0] DO_GLBL; 23 | wire [3:0] DI_GLBL; 24 | 25 | reg GSR_int; 26 | reg GTS_int; 27 | reg PRLD_int; 28 | 29 | //-------- JTAG Globals -------------- 30 | wire JTAG_TDO_GLBL; 31 | wire JTAG_TCK_GLBL; 32 | wire JTAG_TDI_GLBL; 33 | wire JTAG_TMS_GLBL; 34 | wire JTAG_TRST_GLBL; 35 | 36 | reg JTAG_CAPTURE_GLBL; 37 | reg JTAG_RESET_GLBL; 38 | reg JTAG_SHIFT_GLBL; 39 | reg JTAG_UPDATE_GLBL; 40 | reg JTAG_RUNTEST_GLBL; 41 | 42 | reg JTAG_SEL1_GLBL = 0; 43 | reg JTAG_SEL2_GLBL = 0 ; 44 | reg JTAG_SEL3_GLBL = 0; 45 | reg JTAG_SEL4_GLBL = 0; 46 | 47 | reg JTAG_USER_TDO1_GLBL = 1'bz; 48 | reg JTAG_USER_TDO2_GLBL = 1'bz; 49 | reg JTAG_USER_TDO3_GLBL = 1'bz; 50 | reg JTAG_USER_TDO4_GLBL = 1'bz; 51 | 52 | assign (strong1, weak0) GSR = GSR_int; 53 | assign (strong1, weak0) GTS = GTS_int; 54 | assign (weak1, weak0) PRLD = PRLD_int; 55 | 56 | initial begin 57 | GSR_int = 1'b1; 58 | PRLD_int = 1'b1; 59 | #(ROC_WIDTH) 60 | GSR_int = 1'b0; 61 | PRLD_int = 1'b0; 62 | end 63 | 64 | initial begin 65 | GTS_int = 1'b1; 66 | #(TOC_WIDTH) 67 | GTS_int = 1'b0; 68 | end 69 | 70 | endmodule 71 | `endif 72 | -------------------------------------------------------------------------------- /validation/tb_ddr4_mem_ch_top/light_phy.svh: -------------------------------------------------------------------------------- 1 | // AUTHOR: Jan Lappas 2 | // Date : 09.03.2018 3 | `ifndef LIGHT_PHY_SVH 4 | `define LIGHT_PHY_SVH 5 | 6 | interface if_io_config; 7 | // Slew Rate Control 8 | logic [1:0] td_ctrl_n; 9 | logic tdqs_trim_n; 10 | // Impedance Calibration Off Chip Driver 11 | logic [4:0] pd_en_a; 12 | logic [4:0] pd_en_n_a; 13 | logic [4:0] pu_en_a; 14 | logic [4:0] pu_en_n_a; 15 | //---------------------------- 16 | logic [4:0] pd_en_b; 17 | logic [4:0] pd_en_n_b; 18 | logic [4:0] pu_en_b; 19 | logic [4:0] pu_en_n_b; 20 | 21 | // PHY Side 22 | //*************************************** 23 | modport phy 24 | ( 25 | output td_ctrl_n, output tdqs_trim_n, 26 | output pd_en_a, output pd_en_n_a, output pu_en_a, output pu_en_n_a, 27 | output pd_en_b, output pd_en_n_b, output pu_en_b, output pu_en_n_b 28 | ); 29 | 30 | // Off Chip Driver Side 31 | //*************************************** 32 | modport ocd 33 | ( 34 | input td_ctrl_n, input tdqs_trim_n, 35 | input pd_en_a, input pd_en_n_a, input pu_en_a, input pu_en_n_a, 36 | input pd_en_b, input pd_en_n_b, input pu_en_b, input pu_en_n_b 37 | ); 38 | 39 | endinterface // if_config_io 40 | 41 | interface if_impedance_cntrl; 42 | // Impedance Control Off Chip Driver 43 | logic [4:0] pdat_en_a; 44 | logic [4:0] ndat_nen_a; 45 | //--------------------------- 46 | logic [4:0] pdat_en_b; 47 | logic [4:0] ndat_nen_b; 48 | 49 | // PHY Side 50 | //*************************************** 51 | modport phy 52 | ( 53 | output pdat_en_a, output ndat_nen_a, 54 | output pdat_en_b, output ndat_nen_b 55 | ); 56 | 57 | // Off Chip Driver Side 58 | //*************************************** 59 | modport ocd 60 | ( 61 | input pdat_en_a, input ndat_nen_a, 62 | input pdat_en_b, input ndat_nen_b 63 | ); 64 | endinterface // if_impedance_cntrl 65 | 66 | interface if_ocd; 67 | logic pdat_ev_a; 68 | logic ndat_ev_a; 69 | logic pdat_od_a; 70 | logic ndat_od_a; 71 | //---------------------------- 72 | // Driver Signals Channel B 73 | logic pdat_ev_b; 74 | logic ndat_ev_b; 75 | logic pdat_od_b; 76 | logic ndat_od_b; 77 | 78 | // PHY Side 79 | //*************************************** 80 | modport phy 81 | ( 82 | output pdat_ev_a, output ndat_ev_a, 83 | output pdat_od_a, output ndat_od_a, 84 | output pdat_ev_b, output ndat_ev_b, 85 | output pdat_od_b, output ndat_od_b 86 | ); 87 | 88 | // Off Chip Driver Side 89 | //*************************************** 90 | modport ocd 91 | ( 92 | input pdat_ev_a, input ndat_ev_a, 93 | input pdat_od_a, input ndat_od_a, 94 | input pdat_ev_b, input ndat_ev_b, 95 | input pdat_od_b, input ndat_od_b 96 | ); 97 | endinterface // if_ocd 98 | 99 | interface if_rcv_dq; 100 | // Receiver Channel A 101 | //logic dq_a_in; 102 | logic en_rcv2_a; 103 | logic en_rcv1_bias_a; 104 | logic en_rcv2_bias_a; 105 | logic parkh_n_a; 106 | // Receiver Channel B 107 | //logic dq_b_in; 108 | logic en_rcv2_b; 109 | logic en_rcv1_bias_b; 110 | logic en_rcv2_bias_b; 111 | logic parkh_n_b; 112 | //---------------------------- 113 | logic rdy_n; 114 | logic iddq_n; 115 | 116 | // PHY Side 117 | //*************************************** 118 | modport phy 119 | ( 120 | output en_rcv2_a, output en_rcv1_bias_a, output en_rcv2_bias_a, 121 | output parkh_n_a, 122 | output en_rcv2_b, output en_rcv1_bias_b, output en_rcv2_bias_b, 123 | output parkh_n_b, 124 | input rdy_n , output iddq_n 125 | ); 126 | 127 | // Data Receiver Side 128 | //*************************************** 129 | modport rcv_dq 130 | ( 131 | input en_rcv2_a, input en_rcv1_bias_a, input en_rcv2_bias_a, 132 | input parkh_n_a, 133 | input en_rcv2_b, input en_rcv1_bias_b, input en_rcv2_bias_b, 134 | input parkh_n_b, 135 | output rdy_n , input iddq_n 136 | ); 137 | endinterface // if_rcv 138 | 139 | interface if_rcv_dqs; 140 | // DQS Receiver 141 | // logic dqs_in; 142 | // logic dqs_n_in; 143 | //--------DQS_IN---------------------- 144 | logic en_rcv2_bias_a; 145 | logic en_rcv2_a; 146 | logic parkh_n_a; 147 | //---------DQS_N_IN-------------------- 148 | logic en_rcv2_bias_b; 149 | logic en_rcv2_b; 150 | logic parkh_n_b; 151 | //--------------------------------- 152 | logic rdy_n; 153 | logic en_rcv1_bias; 154 | logic iddq_n; 155 | 156 | // PHY Side 157 | //*************************************** 158 | modport phy 159 | ( 160 | input rdy_n, 161 | output en_rcv2_bias_a, output en_rcv2_a, output parkh_n_a, 162 | output en_rcv2_bias_b, output en_rcv2_b, output parkh_n_b, 163 | output en_rcv1_bias, output iddq_n 164 | ); 165 | 166 | // Data Strobe Receiver Side 167 | //*************************************** 168 | modport rcv_dqs 169 | ( 170 | output rdy_n, 171 | input en_rcv2_bias_a, input en_rcv2_a, input parkh_n_a, 172 | input en_rcv2_bias_b, input en_rcv2_b, input parkh_n_b, 173 | input en_rcv1_bias, input iddq_n 174 | ); 175 | endinterface // if_rcv 176 | 177 | interface if_mem_data #(pAXI_ID_WIDTH = 16); 178 | // INPUT MEM_CNTRL FIFO READ 179 | logic data_rd_valid; 180 | // INPUT MEM_CNTRL FIFO READ - DATA 181 | logic [63:0] data_rd; 182 | // INPUT MEM_CNTRL FIFO READ - DATA ID 183 | logic [pAXI_ID_WIDTH-1:0] data_rd_id; 184 | // INPUT FOR PHY - DATA ID FROM MEM_CNTRL 185 | logic [pAXI_ID_WIDTH-1:0] data_id; 186 | // OUTPUT FROM MEM_CNTRL FIFO 187 | logic [63:0] data_wr; 188 | // MEM_CNTRL PUSH DATA INTO WR-DATA BUFFER IN THE LIGHT_PHY 189 | logic grant_wr_data; 190 | 191 | // DATA BUS READY - tell MEM_CNTRL if data bus is ready (calibration etc.) 192 | //logic bus_rdy; 193 | 194 | // PHY Side 195 | //*************************************** 196 | modport phy 197 | ( 198 | output data_rd_valid, output data_rd, output data_rd_id, 199 | output grant_wr_data, 200 | input data_id, input data_wr 201 | ); 202 | 203 | // DATA SLICE Side 204 | //*************************************** 205 | modport data_slice 206 | ( 207 | output data_rd_valid, output data_rd, output data_rd_id, 208 | output grant_wr_data, 209 | input data_id, input data_wr 210 | ); 211 | 212 | // Memory Controller Side 213 | //*************************************** 214 | modport mem_cntrl 215 | ( 216 | input data_rd_valid, input data_rd, input data_rd_id, 217 | input grant_wr_data, 218 | output data_id, output data_wr 219 | ); 220 | 221 | endinterface // if_mem_data 222 | 223 | interface if_mem_adr_cmd; 224 | // Input Off Chip Driver 225 | logic [3:0] [2:0] ba; 226 | logic [3:0] [15:0] adr; 227 | logic [3:0] [4:0] cmd; // CKE,nCS, nRAS,nCAS,nWE [4:0] 228 | logic reset_m_n; 229 | // -------------------------------------------- 230 | logic clk_oe; 231 | logic ocd_oe; 232 | // PHY Side 233 | //*************************************** 234 | modport phy 235 | ( 236 | input ba, input adr, input cmd, input reset_m_n, input clk_oe, 237 | input ocd_oe 238 | ); 239 | 240 | // Memory Controller Side 241 | //*************************************** 242 | modport mem_cntrl 243 | ( 244 | output ba, output adr, output cmd, output reset_m_n, output clk_oe, 245 | output ocd_oe 246 | ); 247 | endinterface // if_mem_adr_cmd 248 | 249 | interface if_phy_io_cal_config; 250 | // IMPEDANCE SELECTION 251 | logic [4:0] ron_data; 252 | logic [4:0] rtt_data; 253 | //logic [4:0] ron_adr_cmd; 254 | // IMPEDANCE CALIBRATION OVERRIGHT DEBUG 255 | logic [4:0] pu_en_ocd_cal; 256 | logic [4:0] pd_en_ocd_cal; 257 | logic disable_ocd_cal; 258 | // SLEW RATE CONFIG 259 | logic [1:0] td_ctrl_n_data; 260 | logic tdqs_trim_n_data; 261 | //logic [1:0] td_ctrl_n_adr_cmd; 262 | //logic tdqs_trim_n_adr_cmd; 263 | 264 | // PHY Side 265 | //*************************************** 266 | modport phy 267 | ( 268 | input ron_data, input rtt_data, 269 | input pu_en_ocd_cal, input pd_en_ocd_cal, input disable_ocd_cal, 270 | input td_ctrl_n_data, input tdqs_trim_n_data); 271 | // DRAM INIT UNIT Side 272 | //*************************************** 273 | modport mem_cntrl 274 | ( 275 | output ron_data, output rtt_data, 276 | output pu_en_ocd_cal, output pd_en_ocd_cal, output disable_ocd_cal, 277 | output td_ctrl_n_data, output tdqs_trim_n_data); 278 | endinterface // if_dram_init 279 | 280 | 281 | localparam cRON_60 = 5'b01011; 282 | localparam cRON_48 = 5'b10011; 283 | localparam cRON_40 = 5'b10111; 284 | localparam cRON_34 = 5'b11111; 285 | 286 | localparam cRTT_120 = 5'b01000; 287 | localparam cRTT_60 = 5'b10000; 288 | localparam cRTT_40 = 5'b11000; 289 | localparam cRTT_30 = 5'b10110; 290 | localparam cRTT_20 = 5'b10101; 291 | 292 | `endif 293 | --------------------------------------------------------------------------------