├── doc └── README.md ├── bitstreams ├── README.md └── HTG-VKUS-V095 │ ├── example_top.bit │ └── example_top.ltx ├── ips ├── README.md ├── axi_slice │ ├── src_files.yml │ ├── README.md │ ├── axi_b_buffer.sv │ ├── axi_w_buffer.sv │ ├── axi_r_buffer.sv │ ├── axi_aw_buffer.sv │ ├── axi_ar_buffer.sv │ └── LICENSE ├── ems_lib │ ├── comp_sel_grt │ │ └── comp_sel_grt.sv │ ├── mux_generic │ │ └── mux_generic.sv │ ├── demux_1_4 │ │ └── demux_1_4.sv │ ├── mux_8_1 │ │ └── mux_8_1.sv │ ├── pulp_clock_gating │ │ └── pulp_clock_gating.sv │ ├── priority_arbiter_8 │ │ └── priority_arbiter_8.sv │ ├── priority_arbiter_generic │ │ ├── priority_arbiter_generic.sv │ │ ├── priority_encoder.sv │ │ └── priority_mux.sv │ ├── min_8 │ │ └── lowest_nr_identifier.sv │ ├── min_generic │ │ └── lowest_nr_identifier.sv │ ├── lfsr │ │ └── lfsr_gen.sv │ ├── dual_clock_fifo │ │ └── dual_clock_fifo.sv │ ├── axi_tgen │ │ ├── verif_utils.sv │ │ └── params_tgen_axi.sv │ ├── generic_fifo │ │ ├── generic_fifo.sv │ │ ├── bram_fifo_52x4.sv │ │ ├── bram_fifo_528x8.sv │ │ ├── bram_fifo_512x64.sv │ │ └── bram_fifo_528x64.sv │ └── mem_tgen_checker │ │ └── mem_tgen_checker.sv ├── Xi_Phy │ ├── Sim_CompileLib.tcl │ ├── ip_setup.tcl │ └── Mig_phy_only_ip.tcl └── Xi_BRAM │ ├── ip_setup.tcl │ ├── BRAM_512x64.tcl │ ├── BRAM_52x4.tcl │ ├── BRAM_528x8.tcl │ └── BRAM_528x64.tcl ├── implementation ├── README.md └── syn │ ├── config_bus_slave │ ├── reg_bus_if.sv │ └── reg_bus_pkg.sv │ ├── xiphy_if │ ├── bit_packing_xiphy_ultrascale.sv │ └── xiphy_ultrascale_if.sv │ ├── bus_shuffler_4 │ └── bus_shuffler_4.sv │ ├── bankfsm_cmdmux_if │ └── bankfsm_cmdmux_if.sv │ ├── congen │ └── congen.v │ ├── mem_ctrl │ └── mem_ctrl_if.sv │ └── ch_ctrl_rank_fsm │ └── ch_ctrl_rank_fsm_wrapper.sv ├── validation ├── README.md ├── tb_ddr4_ch_ctrl │ ├── glbl.v │ └── light_phy.svh └── tb_ddr4_mem_ch_top │ ├── glbl.v │ └── light_phy.svh ├── .gitignore ├── runs └── FPGA │ ├── example_bit.tcl │ ├── example_impl.tcl │ └── example_synth.tcl └── README.md /doc/README.md: -------------------------------------------------------------------------------- 1 | # Documentation -------------------------------------------------------------------------------- /bitstreams/README.md: -------------------------------------------------------------------------------- 1 | # Bitstreams -------------------------------------------------------------------------------- /ips/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oprecomp/DDR4_controller/HEAD/ips/README.md -------------------------------------------------------------------------------- /implementation/README.md: -------------------------------------------------------------------------------- 1 | # Implementation Folder 2 | 3 | * implementation <-- Holds RTL-Models -------------------------------------------------------------------------------- /validation/README.md: -------------------------------------------------------------------------------- 1 | # VALIDATION FOLDER HOLDS ALL TESTBENCHES 2 | 3 | To run testbench in Modelsim 4 | vsim -do run.tcl -------------------------------------------------------------------------------- /bitstreams/HTG-VKUS-V095/example_top.bit: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oprecomp/DDR4_controller/HEAD/bitstreams/HTG-VKUS-V095/example_top.bit -------------------------------------------------------------------------------- /ips/axi_slice/src_files.yml: -------------------------------------------------------------------------------- 1 | axi_slice: 2 | files: [ 3 | axi_ar_buffer.sv, 4 | axi_aw_buffer.sv, 5 | axi_b_buffer.sv, 6 | axi_buffer.sv, 7 | axi_r_buffer.sv, 8 | axi_slice.sv, 9 | axi_w_buffer.sv, 10 | ] 11 | -------------------------------------------------------------------------------- /ips/axi_slice/README.md: -------------------------------------------------------------------------------- 1 | # AXI Slice 2 | 3 | This IP provides AXI slices, i.e. it can be inserted in AXI channels and adds a 4 | FIFO there to ease timing closure. 5 | 6 | It uses a generic FIFO which is not part of this IP. For the generic FIFO see 7 | either the PULP common cells or the PULPino RTL sources. 8 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /ips/Xi_Phy/Sim_CompileLib.tcl: -------------------------------------------------------------------------------- 1 | source ip_setup.tcl 2 | 3 | file mkdir $SIM_LIB_PATH/compile_simlib/modelsim 4 | puts $MODELSIM_EXE_PATH 5 | compile_simlib -simulator modelsim -simulator_exec_path $MODELSIM_EXE_PATH -family all -language all -library all -dir $SIM_LIB_PATH/compile_simlib/modelsim -force 6 | 7 | cd $SIM_LIB_PATH/compile_simlib/modelsim 8 | file copy modelsim.ini $MEMCTRL_DIR/validation/tb_ddr4_mem_ch_top 9 | file copy modelsim.ini $MEMCTRL_DIR/validation/tb_ddr4_ch_ctrl 10 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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/Xi_BRAM/ip_setup.tcl: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # TU KL MIG Phy IP Setup 3 | # AUTHOR: Chirag Sudarshan 4 | # DATE : 15.01.2020 5 | # Script: ip_setup.tcl 6 | ############################################################################### 7 | 8 | #Full Path of the location where TU-KL memory controller is cloned - Should be configured 9 | set MEMCTRL_DIR C:/MyFiles/chirag/memctrl/Open_source_FPGA/DDR4_controller 10 | 11 | #Do not disturb 12 | set IP_DIR $MEMCTRL_DIR/ips/Xi_BRAM 13 | 14 | #Set the location for Xilinx specific Modelsim compiled lib - Should be configured 15 | #set SIM_LIB_PATH "C:/Users/chirag/project_3/project_1.cache/compile_simlib/modelsim" 16 | set SIM_LIB_PATH "$MEMCTRL_DIR/validation" 17 | 18 | #Set the Modelsim executatble folder path 19 | set MODELSIM_EXE_PATH "C:/modeltech64_2019.1/win64" 20 | 21 | #Should be configured 22 | #set PART "xcvu3p-ffvc1517-2-e" 23 | set PART "xcvu095-ffvb2104-2-e" 24 | -------------------------------------------------------------------------------- /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; 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/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/priority_arbiter_generic/priority_mux.sv: -------------------------------------------------------------------------------- 1 | module priority_mux 2 | #( 3 | parameter NR_WIDTH = 8, 4 | parameter NR_INPUTS = 8, 5 | parameter DATA_WIDTH = 8 6 | ) 7 | ( 8 | input [NR_INPUTS-1:0][NR_WIDTH-1:0] priority_nr_in, 9 | input [NR_INPUTS-1:0] req, 10 | input [NR_INPUTS-1:0][DATA_WIDTH-1:0] data_in, 11 | 12 | output [DATA_WIDTH-1:0] data_out, 13 | output [NR_WIDTH-1:0] lowest_nr, 14 | output logic [$clog2(NR_INPUTS)-1:0] lowest_line, 15 | output logic lowest_valid 16 | ); 17 | 18 | // This module will select and output the lowest number among the eight 19 | // input numbers. It also will indicate on which input line the lowest number 20 | // was signaled. 21 | // This for same nr req, lowest line is the id of highest 22 | 23 | //To find lowest number among all reqs, we need 7 compare unit in 3 stages for 8 input device 24 | logic [$clog2(NR_INPUTS):0][NR_INPUTS-1:0][NR_WIDTH-1:0] comp_lowest; 25 | logic [$clog2(NR_INPUTS):0][NR_INPUTS-1:0][DATA_WIDTH-1:0] comp_data; 26 | logic [$clog2(NR_INPUTS):0][NR_INPUTS-1:0] comp_res_v; 27 | logic [$clog2(NR_INPUTS):1][(NR_INPUTS/2)-1:0] comp_low_line; 28 | logic [$clog2(NR_INPUTS):0][NR_INPUTS-1:0][$clog2(NR_INPUTS)-1:0] lowest_line_tmp; 29 | logic [$clog2(NR_INPUTS)-1:0][(NR_INPUTS/2)-1:0] sign; 30 | logic [$clog2(NR_INPUTS)-1:0][(NR_INPUTS/2)-1:0][NR_WIDTH+1:0] sub; 31 | 32 | assign comp_lowest[0] = priority_nr_in; 33 | assign comp_data[0] = data_in; 34 | assign comp_res_v[0] = req; 35 | 36 | generate 37 | for(genvar j=0; j 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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /ips/Xi_Phy/Mig_phy_only_ip.tcl: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # TU KL MIG Phy IP Generator Script 3 | # AUTHOR: Chirag Sudarshan 4 | # DATE : 30.11.2019 5 | # Script: Mig_phy_only_ip.tcl 6 | ############################################################################### 7 | 8 | source ip_setup.tcl 9 | 10 | file mkdir IP/mig_phy 11 | 12 | create_project -force mig_phy IP/mig_phy -part $PART 13 | create_ip -name ddr4 -vendor xilinx.com -library ip -version 2.2 -module_name $IP_NAME 14 | #set_property -dict [list CONFIG.Phy_Only {Phy_Only_Single} CONFIG.C0.DDR4_TimePeriod {1250} CONFIG.C0.DDR4_InputClockPeriod {3334} CONFIG.C0.DDR4_CLKOUT0_DIVIDE {6} CONFIG.C0.DDR4_MemoryType {Components} CONFIG.C0.DDR4_MemoryPart {MT40A1G8PM-075E} CONFIG.C0.DDR4_DataWidth {64} CONFIG.C0.DDR4_CasLatency {11} CONFIG.C0.DDR4_CasWriteLatency {11}] [get_ips $IP_NAME] 15 | set_property -dict [list CONFIG.Phy_Only {Phy_Only_Single} CONFIG.C0.DDR4_TimePeriod {1250} CONFIG.C0.DDR4_InputClockPeriod {5000} CONFIG.C0.DDR4_CLKOUT0_DIVIDE {7} CONFIG.C0.DDR4_MemoryType {Components} CONFIG.C0.DDR4_MemoryPart {MT40A1G8PM-075E} CONFIG.C0.DDR4_DataWidth {64} CONFIG.C0.DDR4_CasLatency {11} CONFIG.C0.DDR4_CasWriteLatency {11}] [get_ips $IP_NAME] 16 | 17 | 18 | generate_target {instantiation_template} [get_files $IP_DIR/IP/mig_phy/mig_phy.srcs/sources_1/ip/$IP_NAME/${IP_NAME}.xci] 19 | #update_compile_order -fileset sources_1 20 | 21 | generate_target all [get_files $IP_DIR/IP/mig_phy/mig_phy.srcs/sources_1/ip/$IP_NAME/${IP_NAME}.xci] 22 | 23 | catch { config_ip_cache -export [get_ips -all $IP_NAME] } 24 | 25 | export_ip_user_files -of_objects [get_files $IP_DIR/IP/mig_phy/mig_phy.srcs/sources_1/ip/$IP_NAME/${IP_NAME}.xci] -no_script -sync -force -quiet 26 | 27 | create_ip_run [get_files -of_objects [get_fileset sources_1] $IP_DIR/IP/mig_phy/mig_phy.srcs/sources_1/ip/$IP_NAME/${IP_NAME}.xci] 28 | 29 | launch_runs -jobs 4 ${IP_NAME}_synth_1 30 | 31 | generate_target {example} [get_files $IP_DIR/IP/mig_phy/mig_phy.srcs/sources_1/ip/$IP_NAME/${IP_NAME}.xci] 32 | 33 | #move the files in folder tb/ddr4_model/ to tb. This is done for simulation, as the auto gen sim scripts expects dram model files in tb folder 34 | set contents [glob -directory $IP_DIR/IP/mig_phy/mig_phy.srcs/sources_1/ip/$IP_NAME/tb/ddr4_model/ * ] 35 | foreach item $contents { 36 | file copy $item $IP_DIR/IP/mig_phy/mig_phy.srcs/sources_1/ip/$IP_NAME/tb/ddr_model/.. } 37 | 38 | #move the files in folder tb/ddr4_model/ to tb. This is done for simulation, as the auto gen sim scripts expects dram model files in tb folder 39 | #file copy $IP_DIR/IP/mig_phy/mig_phy.srcs/sources_1/ip/$IP_NAME/tb/ddr_model/ $IP_DIR/IP/mig_phy/mig_phy.srcs/sources_1/ip/$IP_NAME/tb/ 40 | 41 | set projDir [get_property DIRECTORY [current_project]] 42 | set importDir [file join $projDir imports] 43 | puts $importDir 44 | file mkdir $importDir 45 | 46 | set_property TOP [lindex [find_top] 0] [current_fileset] 47 | 48 | #export_ip_user_files -no_script -force 49 | 50 | #compile_simlib -simulator modelsim -simulator_exec_path {C:/modeltech64_2019.1/win64} -family all -language all -library all -dir {$sim_lib_path} -force 51 | 52 | export_simulation -of_objects [get_files $IP_DIR/IP/mig_phy/mig_phy.srcs/sources_1/ip/$IP_NAME/${IP_NAME}.xci] -simulator modelsim -directory $IP_DIR/IP/mig_phy/mig_phy.ip_user_files/sim_scripts -ip_user_files_dir $IP_DIR/IP/mig_phy/mig_phy.ip_user_files -ipstatic_source_dir $IP_DIR/IP/mig_phy/mig_phy.ip_user_files/ipstatic -lib_map_path $SIM_LIB_PATH -use_ip_compiled_libs -force -quiet 53 | 54 | #export_simulation -lib_map_path "c:/Users/chirag/project_3/project_1.cache/compile_simlib/modelsim" -directory "SIM" -simulator modelsim -use_ip_compiled_libs 55 | 56 | #this is only a fix for windows PC . On linux PC this line will not make any difference 57 | file mkdir $IP_DIR/IP/mig_phy/mig_phy.ip_user_files/sim_scripts/$IP_NAME/modelsim/modelsim_lib 58 | 59 | close_project 60 | -------------------------------------------------------------------------------- /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/axi_slice/axi_b_buffer.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 | // Company: Multitherman Laboratory @ DEIS - University of Bologna // 12 | // Viale Risorgimento 2 40136 // 13 | // Bologna - fax 0512093785 - // 14 | // // 15 | // Engineer: Davide Rossi - davide.rossi@unibo.it // 16 | // // 17 | // // 18 | // Additional contributions by: // 19 | // // 20 | // // 21 | // // 22 | // Create Date: 01/02/2014 // 23 | // Design Name: AXI 4 INTERCONNECT // 24 | // Module Name: axi_b_buffer // 25 | // Project Name: PULP // 26 | // Language: SystemVerilog // 27 | // // 28 | // Description: master slice ( FIFO wrapper ) for backward write channel // 29 | // // 30 | // Revision: // 31 | // Revision v0.1 - 01/02/2014 : File Created // 32 | // // 33 | // // 34 | // // 35 | // // 36 | // // 37 | // // 38 | // ============================================================================= // 39 | 40 | module axi_b_buffer 41 | #( 42 | parameter ID_WIDTH = 4, 43 | parameter USER_WIDTH = 6, 44 | parameter BUFFER_DEPTH = 8 45 | ) 46 | ( 47 | 48 | input logic clk_i, 49 | input logic rst_ni, 50 | input logic test_en_i, 51 | 52 | input logic slave_valid_i, 53 | input logic [1:0] slave_resp_i, 54 | input logic [ID_WIDTH-1:0] slave_id_i, 55 | input logic [USER_WIDTH-1:0] slave_user_i, 56 | output logic slave_ready_o, 57 | 58 | output logic master_valid_o, 59 | output logic [1:0] master_resp_o, 60 | output logic [ID_WIDTH-1:0] master_id_o, 61 | output logic [USER_WIDTH-1:0] master_user_o, 62 | input logic master_ready_i 63 | ); 64 | 65 | logic [2+USER_WIDTH+ID_WIDTH-1:0] s_data_in; 66 | logic [2+USER_WIDTH+ID_WIDTH-1:0] s_data_out; 67 | 68 | assign s_data_in = {slave_id_i, slave_user_i, slave_resp_i}; 69 | assign {master_id_o, master_user_o, master_resp_o} = s_data_out; 70 | 71 | 72 | generic_fifo 73 | #( 74 | .DATA_WIDTH ( 2+USER_WIDTH+ID_WIDTH ), 75 | .DATA_DEPTH ( BUFFER_DEPTH ) 76 | ) 77 | buffer_i 78 | ( 79 | .clk ( clk_i ), 80 | .rst_n ( rst_ni ), 81 | .data_i ( s_data_in ), 82 | .valid_i ( slave_valid_i ), 83 | .grant_o ( slave_ready_o ), 84 | .data_o ( s_data_out ), 85 | .valid_o ( master_valid_o ), 86 | .grant_i ( master_ready_i ), 87 | .test_mode_i ( test_en_i ) 88 | ); 89 | 90 | endmodule 91 | -------------------------------------------------------------------------------- /ips/axi_slice/axi_w_buffer.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 | // ============================================================================= // 12 | // Company: Multitherman Laboratory @ DEIS - University of Bologna // 13 | // Viale Risorgimento 2 40136 // 14 | // Bologna - fax 0512093785 - // 15 | // // 16 | // Engineer: Davide Rossi - davide.rossi@unibo.it // 17 | // // 18 | // // 19 | // Additional contributions by: // 20 | // // 21 | // // 22 | // // 23 | // Create Date: 01/02/2014 // 24 | // Design Name: AXI 4 INTERCONNECT // 25 | // Module Name: axi_w_buffer // 26 | // Project Name: PULP // 27 | // Language: SystemVerilog // 28 | // // 29 | // Description: master slice ( FIFO wrapper ) for write channel // 30 | // // 31 | // Revision: // 32 | // Revision v0.1 - 01/02/2014 : File Created // 33 | // // 34 | // // 35 | // // 36 | // // 37 | // // 38 | // // 39 | // ============================================================================= // 40 | 41 | 42 | module axi_w_buffer 43 | #( 44 | parameter DATA_WIDTH = 64, 45 | parameter USER_WIDTH = 6, 46 | parameter BUFFER_DEPTH = 2, 47 | parameter STRB_WIDTH = DATA_WIDTH/8 // DO NOT OVERRIDE 48 | ) 49 | ( 50 | input logic clk_i, 51 | input logic rst_ni, 52 | input logic test_en_i, 53 | 54 | input logic slave_valid_i, 55 | input logic [DATA_WIDTH-1:0] slave_data_i, 56 | input logic [STRB_WIDTH-1:0] slave_strb_i, 57 | input logic [USER_WIDTH-1:0] slave_user_i, 58 | input logic slave_last_i, 59 | output logic slave_ready_o, 60 | 61 | output logic master_valid_o, 62 | output logic [DATA_WIDTH-1:0] master_data_o, 63 | output logic [STRB_WIDTH-1:0] master_strb_o, 64 | output logic [USER_WIDTH-1:0] master_user_o, 65 | output logic master_last_o, 66 | input logic master_ready_i 67 | ); 68 | 69 | logic [DATA_WIDTH+STRB_WIDTH+USER_WIDTH:0] s_data_in; 70 | logic [DATA_WIDTH+STRB_WIDTH+USER_WIDTH:0] s_data_out; 71 | 72 | assign s_data_in = { slave_user_i, slave_strb_i, slave_data_i, slave_last_i }; 73 | assign { master_user_o, master_strb_o, master_data_o, master_last_o } = s_data_out; 74 | 75 | 76 | generic_fifo 77 | #( 78 | .DATA_WIDTH ( 1+DATA_WIDTH+STRB_WIDTH+USER_WIDTH ), 79 | .DATA_DEPTH ( BUFFER_DEPTH ) 80 | ) 81 | buffer_i 82 | ( 83 | .clk ( clk_i ), 84 | .rst_n ( rst_ni ), 85 | .data_i ( s_data_in ), 86 | .valid_i ( slave_valid_i ), 87 | .grant_o ( slave_ready_o ), 88 | .data_o ( s_data_out ), 89 | .valid_o ( master_valid_o ), 90 | .grant_i ( master_ready_i ), 91 | .test_mode_i ( test_en_i ) 92 | ); 93 | 94 | endmodule 95 | -------------------------------------------------------------------------------- /ips/axi_slice/axi_r_buffer.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 | // ============================================================================= // 12 | // Company: Multitherman Laboratory @ DEIS - University of Bologna // 13 | // Viale Risorgimento 2 40136 // 14 | // Bologna - fax 0512093785 - // 15 | // // 16 | // Engineer: Davide Rossi - davide.rossi@unibo.it // 17 | // // 18 | // // 19 | // Additional contributions by: // 20 | // // 21 | // // 22 | // // 23 | // Create Date: 01/02/2014 // 24 | // Design Name: AXI 4 INTERCONNECT // 25 | // Module Name: axi_r_buffer // 26 | // Project Name: PULP // 27 | // Language: SystemVerilog // 28 | // // 29 | // Description: master slice ( FIFO wrapper ) for read channel // 30 | // // 31 | // Revision: // 32 | // Revision v0.1 - 01/02/2014 : File Created // 33 | // // 34 | // // 35 | // // 36 | // // 37 | // // 38 | // // 39 | // ============================================================================= // 40 | 41 | module axi_r_buffer 42 | #( 43 | parameter ID_WIDTH = 4, 44 | parameter DATA_WIDTH = 64, 45 | parameter USER_WIDTH = 6, 46 | parameter BUFFER_DEPTH = 8, 47 | parameter STRB_WIDTH = DATA_WIDTH/8 // DO NOT OVERRIDE 48 | ) 49 | ( 50 | input logic clk_i, 51 | input logic rst_ni, 52 | input logic test_en_i, 53 | 54 | input logic slave_valid_i, 55 | input logic [DATA_WIDTH-1:0] slave_data_i, 56 | input logic [1:0] slave_resp_i, 57 | input logic [USER_WIDTH-1:0] slave_user_i, 58 | input logic [ID_WIDTH-1:0] slave_id_i, 59 | input logic slave_last_i, 60 | output logic slave_ready_o, 61 | 62 | output logic master_valid_o, 63 | output logic [DATA_WIDTH-1:0] master_data_o, 64 | output logic [1:0] master_resp_o, 65 | output logic [USER_WIDTH-1:0] master_user_o, 66 | output logic [ID_WIDTH-1:0] master_id_o, 67 | output logic master_last_o, 68 | input logic master_ready_i 69 | ); 70 | 71 | logic [2+DATA_WIDTH+USER_WIDTH+ID_WIDTH:0] s_data_in; 72 | logic [2+DATA_WIDTH+USER_WIDTH+ID_WIDTH:0] s_data_out; 73 | 74 | 75 | assign s_data_in = {slave_id_i, slave_user_i, slave_data_i, slave_resp_i, slave_last_i}; 76 | assign {master_id_o, master_user_o, master_data_o, master_resp_o, master_last_o} = s_data_out; 77 | 78 | 79 | generic_fifo 80 | #( 81 | .DATA_WIDTH ( 3+DATA_WIDTH+USER_WIDTH+ID_WIDTH ), 82 | .DATA_DEPTH ( BUFFER_DEPTH ) 83 | ) 84 | buffer_i 85 | ( 86 | .clk ( clk_i ), 87 | .rst_n ( rst_ni ), 88 | .data_i ( s_data_in ), 89 | .valid_i ( slave_valid_i ), 90 | .grant_o ( slave_ready_o ), 91 | .data_o ( s_data_out ), 92 | .valid_o ( master_valid_o ), 93 | .grant_i ( master_ready_i ), 94 | .test_mode_i ( test_en_i ) 95 | ); 96 | 97 | 98 | endmodule 99 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /implementation/syn/xiphy_if/xiphy_ultrascale_if.sv: -------------------------------------------------------------------------------- 1 | // This module translates the custom memctrl signals to signals as specified in Xilinx PG150 Phy Only Interface (October 30, 2019) page 160. 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=160 5 | 6 | module xiphy_ultrascale_if 7 | #( 8 | parameter DRAM_ADDR_WIDTH = 8, 9 | parameter CLK_RATIO = 4, 10 | parameter DRAM_BANKS = 8, 11 | parameter AXI4_ID_WIDTH = 16, 12 | parameter DRAM_CMD_WIDTH = 5 13 | ) 14 | ( 15 | input clk, 16 | input rst_n, 17 | 18 | input [CLK_RATIO-1:0][DRAM_ADDR_WIDTH-1:0] ctrl_addr, 19 | input [CLK_RATIO-1:0][$clog2(DRAM_BANKS)-1:0] ctrl_bank, 20 | input [CLK_RATIO-1:0][DRAM_CMD_WIDTH-1:0] ctrl_cmd, 21 | input [CLK_RATIO-1:0] ctrl_act_n, 22 | //output [CLK_RATIO-1:0] ctrl_cs_n 23 | //output [CLK_RATIO-1:0] ctrl_cke 24 | input ctrl_valid, 25 | input [AXI4_ID_WIDTH-1:0] ctrl_cas_cmd_id, 26 | //input ctrl_cas_cmd_id_valid,//NA 27 | input ctrl_write, 28 | input ctrl_read, 29 | input [$clog2(CLK_RATIO)-1:0] ctrl_cas_slot, 30 | input rdDataEn, 31 | 32 | output [4:0] dBufAdr, 33 | 34 | output [7:0] mc_ACT_n, 35 | output [135:0] mc_ADR, 36 | output [15:0] mc_BA, 37 | output [15:0] mc_BG, 38 | output [7:0] mc_CKE, 39 | output [7:0] mc_CS_n, 40 | output [7:0] mc_ODT, 41 | output [1:0] mcCasSlot, 42 | output [0:0] mcCasSlot2, 43 | output [0:0] mcRdCAS, 44 | output [0:0] mcWrCAS, 45 | output [0:0] winInjTxn, 46 | output [0:0] winRmw, 47 | output logic gt_data_ready, 48 | output [4:0] winBuf, 49 | output [1:0] winRank 50 | ); 51 | 52 | 53 | // cas control signals 54 | assign mcRdCAS = ctrl_read; 55 | assign mcWrCAS = ctrl_write; 56 | assign mcCasSlot = ctrl_cas_slot; 57 | assign mcCasSlot2 = ctrl_cas_slot[1]; 58 | 59 | // VT tracking signals that has to be considered later 60 | assign winInjTxn = 0; 61 | 62 | // Read modified write -- works for with ECC only 63 | assign winRmw = 0; 64 | 65 | // to be considered later for multi rank 66 | assign winRank = 0; 67 | 68 | assign winBuf = 0; 69 | 70 | // dBufAdr is a reserved signal in Xilinx ultrascale phy, should be tied low 71 | assign dBufAdr = 0; 72 | 73 | logic [CLK_RATIO-1:0] ctrl_write_lcl,ctrl_write_q; 74 | logic [CLK_RATIO-1:0] mc_ODT_lcl; 75 | 76 | always_ff @(posedge clk, negedge rst_n) 77 | begin 78 | if(rst_n == 1'b0) 79 | ctrl_write_q <='0; 80 | else 81 | ctrl_write_q <=ctrl_write_lcl; 82 | end 83 | 84 | // gt_data_read signal has to sent every 1us. gt_data_ready has to be asserted after readDataEN 85 | logic[9:0] counter; 86 | 87 | always_ff @(posedge clk, negedge rst_n) 88 | begin 89 | if(rst_n == 1'b0) begin 90 | gt_data_ready <= '0; 91 | counter <= 100; 92 | end 93 | else begin 94 | if (counter == '0) begin 95 | if(rdDataEn) begin 96 | counter <= 100; 97 | gt_data_ready <= 1'b1; 98 | end 99 | else begin 100 | gt_data_ready <= 1'b0; 101 | counter <= 0; 102 | end 103 | end 104 | else begin 105 | counter <= counter - 1; 106 | gt_data_ready <= 1'b0; 107 | end // else: !if(counter == '0) 108 | end // else: !if(rst_n == 1'b0) 109 | end // always_ff @ (posedge clk, negedge rst_n) 110 | 111 | 112 | always_comb 113 | begin 114 | mc_ODT_lcl = {CLK_RATIO{(ctrl_write && ctrl_valid)}} | ctrl_write_q; 115 | case(ctrl_cas_slot) 116 | 2'b00:begin 117 | ctrl_write_lcl={'0 ,{(ctrl_write && ctrl_valid)}}; 118 | end 119 | 2'b01:begin 120 | ctrl_write_lcl={'0 ,{2{(ctrl_write && ctrl_valid)}}}; 121 | end 122 | 2'b10:begin 123 | ctrl_write_lcl={'0,{3{(ctrl_write && ctrl_valid)}}}; 124 | end 125 | 2'b11:begin 126 | ctrl_write_lcl={4{(ctrl_write && ctrl_valid)}}; 127 | end 128 | endcase // case (ctrl_cas_slot) 129 | end // always_comb 130 | 131 | bit_packing_xiphy_ultrascale 132 | #( 133 | .DATA_WIDTH(1'b1), 134 | .CLK_RATIO(CLK_RATIO), 135 | .DUPLICATES(2) 136 | ) addr_bit_packing_odt 137 | ( 138 | .data_i(mc_ODT_lcl), 139 | .data_o(mc_ODT) 140 | ); 141 | 142 | bit_packing_xiphy_ultrascale 143 | #( 144 | .DATA_WIDTH($clog2(DRAM_BANKS)), 145 | .CLK_RATIO(CLK_RATIO), 146 | .DUPLICATES(2) 147 | ) bg_ba_bit_packing_bank 148 | ( 149 | .data_i(ctrl_bank), 150 | .data_o({mc_BG,mc_BA}) 151 | ); 152 | 153 | 154 | bit_packing_xiphy_ultrascale 155 | #( 156 | .DATA_WIDTH(DRAM_ADDR_WIDTH), 157 | .CLK_RATIO(CLK_RATIO), 158 | .DUPLICATES(2) 159 | ) addr_bit_packing_addr 160 | ( 161 | .data_i(ctrl_addr), 162 | .data_o(mc_ADR) 163 | ); 164 | 165 | bit_packing_xiphy_ultrascale 166 | #( 167 | .DATA_WIDTH(1'b1), 168 | .CLK_RATIO(CLK_RATIO), 169 | .DUPLICATES(2) 170 | ) addr_bit_packing_act 171 | ( 172 | .data_i(ctrl_act_n), 173 | .data_o(mc_ACT_n) 174 | ); 175 | 176 | // Cmd order | cke | cs_n | ras_n | cas_n | we_n | 177 | bit_packing_xiphy_ultrascale 178 | #( 179 | .DATA_WIDTH(1'b1), 180 | .CLK_RATIO(CLK_RATIO), 181 | .DUPLICATES(2) 182 | ) addr_bit_packing_cs 183 | ( 184 | .data_i({ctrl_cmd[3][3],ctrl_cmd[2][3],ctrl_cmd[1][3],ctrl_cmd[0][3]}), 185 | .data_o(mc_CS_n) 186 | ); 187 | 188 | bit_packing_xiphy_ultrascale 189 | #( 190 | .DATA_WIDTH(1'b1), 191 | .CLK_RATIO(CLK_RATIO), 192 | .DUPLICATES(2) 193 | ) addr_bit_packing_cke 194 | ( 195 | .data_i({ctrl_cmd[3][4],ctrl_cmd[2][4],ctrl_cmd[1][4],ctrl_cmd[0][4]}), 196 | .data_o(mc_CKE) 197 | ); 198 | 199 | endmodule // xiphy_ultrascale_if 200 | 201 | -------------------------------------------------------------------------------- /ips/axi_slice/axi_aw_buffer.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 | // ============================================================================= // 12 | // Company: Multitherman Laboratory @ DEIS - University of Bologna // 13 | // Viale Risorgimento 2 40136 // 14 | // Bologna - fax 0512093785 - // 15 | // // 16 | // Engineer: Davide Rossi - davide.rossi@unibo.it // 17 | // // 18 | // // 19 | // Additional contributions by: // 20 | // // 21 | // // 22 | // // 23 | // Create Date: 01/02/2014 // 24 | // Design Name: AXI 4 INTERCONNECT // 25 | // Module Name: axi_aw_buffer // 26 | // Project Name: PULP // 27 | // Language: SystemVerilog // 28 | // // 29 | // Description: master slice ( FIFO wrapper ) for address write channel // 30 | // // 31 | // Revision: // 32 | // Revision v0.1 - 01/02/2014 : File Created // 33 | // // 34 | // // 35 | // // 36 | // // 37 | // // 38 | // // 39 | // ============================================================================= // 40 | 41 | module axi_aw_buffer 42 | #( 43 | parameter ID_WIDTH = 4, 44 | parameter ADDR_WIDTH = 32, 45 | parameter USER_WIDTH = 6, 46 | parameter BUFFER_DEPTH = 2 47 | ) 48 | ( 49 | 50 | input logic clk_i, 51 | input logic rst_ni, 52 | input logic test_en_i, 53 | 54 | input logic slave_valid_i, 55 | input logic [ADDR_WIDTH-1:0] slave_addr_i, 56 | input logic [2:0] slave_prot_i, 57 | input logic [3:0] slave_region_i, 58 | input logic [7:0] slave_len_i, 59 | input logic [2:0] slave_size_i, 60 | input logic [1:0] slave_burst_i, 61 | input logic slave_lock_i, 62 | input logic [3:0] slave_cache_i, 63 | input logic [3:0] slave_qos_i, 64 | input logic [ID_WIDTH-1:0] slave_id_i, 65 | input logic [USER_WIDTH-1:0] slave_user_i, 66 | output logic slave_ready_o, 67 | 68 | output logic master_valid_o, 69 | output logic [ADDR_WIDTH-1:0] master_addr_o, 70 | output logic [2:0] master_prot_o, 71 | output logic [3:0] master_region_o, 72 | output logic [7:0] master_len_o, 73 | output logic [2:0] master_size_o, 74 | output logic [1:0] master_burst_o, 75 | output logic master_lock_o, 76 | output logic [3:0] master_cache_o, 77 | output logic [3:0] master_qos_o, 78 | output logic [ID_WIDTH-1:0] master_id_o, 79 | output logic [USER_WIDTH-1:0] master_user_o, 80 | input logic master_ready_i 81 | ); 82 | 83 | logic [29+ADDR_WIDTH+USER_WIDTH+ID_WIDTH-1:0] s_data_in; 84 | logic [29+ADDR_WIDTH+USER_WIDTH+ID_WIDTH-1:0] s_data_out; 85 | 86 | 87 | 88 | assign s_data_in = {slave_cache_i, slave_prot_i, slave_lock_i, slave_burst_i, slave_size_i, slave_len_i, slave_qos_i, slave_region_i, slave_addr_i, slave_user_i, slave_id_i}; 89 | assign {master_cache_o, master_prot_o, master_lock_o, master_burst_o, master_size_o, master_len_o, master_qos_o, master_region_o, master_addr_o, master_user_o, master_id_o} = s_data_out; 90 | 91 | 92 | generic_fifo 93 | #( 94 | .DATA_WIDTH ( 29+ADDR_WIDTH+USER_WIDTH+ID_WIDTH ), 95 | .DATA_DEPTH ( BUFFER_DEPTH ) 96 | ) 97 | buffer_i 98 | ( 99 | .clk ( clk_i ), 100 | .rst_n ( rst_ni ), 101 | .data_i ( s_data_in ), 102 | .valid_i ( slave_valid_i ), 103 | .grant_o ( slave_ready_o ), 104 | .data_o ( s_data_out ), 105 | .valid_o ( master_valid_o ), 106 | .grant_i ( master_ready_i ), 107 | .test_mode_i ( test_en_i ) 108 | ); 109 | 110 | 111 | endmodule 112 | -------------------------------------------------------------------------------- /ips/axi_slice/axi_ar_buffer.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 | // ============================================================================= // 12 | // Company: Multitherman Laboratory @ DEIS - University of Bologna // 13 | // Viale Risorgimento 2 40136 // 14 | // Bologna - fax 0512093785 - // 15 | // // 16 | // Engineer: Davide Rossi - davide.rossi@unibo.it // 17 | // // 18 | // // 19 | // Additional contributions by: // 20 | // // 21 | // // 22 | // // 23 | // Create Date: 01/02/2014 // 24 | // Design Name: AXI 4 INTERCONNECT // 25 | // Module Name: axi_ar_buffer // 26 | // Project Name: PULP // 27 | // Language: SystemVerilog // 28 | // // 29 | // Description: master slice ( FIFO wrapper) for address read channel // 30 | // // 31 | // Revision: // 32 | // Revision v0.1 - 01/02/2014 : File Created // 33 | // // 34 | // // 35 | // // 36 | // // 37 | // // 38 | // // 39 | // ============================================================================= // 40 | 41 | module axi_ar_buffer 42 | #( 43 | parameter ID_WIDTH = 4, 44 | parameter ADDR_WIDTH = 32, 45 | parameter USER_WIDTH = 6, 46 | parameter BUFFER_DEPTH = 2 47 | ) 48 | ( 49 | 50 | input logic clk_i, 51 | input logic rst_ni, 52 | input logic test_en_i, 53 | 54 | input logic slave_valid_i, 55 | input logic [ADDR_WIDTH-1:0] slave_addr_i, 56 | input logic [2:0] slave_prot_i, 57 | input logic [3:0] slave_region_i, 58 | input logic [7:0] slave_len_i, 59 | input logic [2:0] slave_size_i, 60 | input logic [1:0] slave_burst_i, 61 | input logic slave_lock_i, 62 | input logic [3:0] slave_cache_i, 63 | input logic [3:0] slave_qos_i, 64 | input logic [ID_WIDTH-1:0] slave_id_i, 65 | input logic [USER_WIDTH-1:0] slave_user_i, 66 | output logic slave_ready_o, 67 | 68 | output logic master_valid_o, 69 | output logic [ADDR_WIDTH-1:0] master_addr_o, 70 | output logic [2:0] master_prot_o, 71 | output logic [3:0] master_region_o, 72 | output logic [7:0] master_len_o, 73 | output logic [2:0] master_size_o, 74 | output logic [1:0] master_burst_o, 75 | output logic master_lock_o, 76 | output logic [3:0] master_cache_o, 77 | output logic [3:0] master_qos_o, 78 | output logic [ID_WIDTH-1:0] master_id_o, 79 | output logic [USER_WIDTH-1:0] master_user_o, 80 | input logic master_ready_i 81 | 82 | ); 83 | 84 | logic [29+ADDR_WIDTH+USER_WIDTH+ID_WIDTH-1:0] s_data_in; 85 | logic [29+ADDR_WIDTH+USER_WIDTH+ID_WIDTH-1:0] s_data_out; 86 | 87 | assign s_data_in = {slave_cache_i, slave_prot_i, slave_lock_i, slave_burst_i, slave_size_i, slave_len_i, slave_qos_i, slave_region_i, slave_addr_i, slave_user_i, slave_id_i} ; 88 | assign {master_cache_o, master_prot_o, master_lock_o, master_burst_o, master_size_o, master_len_o, master_qos_o, master_region_o, master_addr_o, master_user_o, master_id_o} = s_data_out; 89 | 90 | 91 | 92 | 93 | generic_fifo 94 | #( 95 | .DATA_WIDTH ( 29+ADDR_WIDTH+USER_WIDTH+ID_WIDTH ), 96 | .DATA_DEPTH ( BUFFER_DEPTH ) 97 | ) 98 | buffer_i 99 | ( 100 | .clk ( clk_i ), 101 | .rst_n ( rst_ni ), 102 | .data_i ( s_data_in ), 103 | .valid_i ( slave_valid_i ), 104 | .grant_o ( slave_ready_o ), 105 | .data_o ( s_data_out ), 106 | .valid_o ( master_valid_o ), 107 | .grant_i ( master_ready_i ), 108 | .test_mode_i ( test_en_i ) 109 | ); 110 | 111 | endmodule 112 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /ips/ems_lib/axi_tgen/params_tgen_axi.sv: -------------------------------------------------------------------------------- 1 | `ifdef CORNER_WC 2 | `define CLK_PERIOD_SYS 8.0 // WC corner 6-5-5 CWL 5 3 | `else 4 | `ifdef DLL_OFF 5 | `define CLK_PERIOD_SYS 24.0 // dll off default 6-4-4 CWL 6 setting 6 | `else 7 | `define CLK_PERIOD_SYS 12.0 // default 7-6-6 CWL 6 setting 8 | `endif 9 | `endif 10 | //`define CLK_PERIOD_SYS 32 // DLL off 11 | // 12 | `define DRAM_INIT_TIME_ns 1000 //50 ns //DEEPAK --Check this 13 | `define NUM_TRANSACTIONS 5000 14 | //`define STOP_SIM_MASK 1 15 | `define AXI_TRAFFIC_MODE "RANDOM_W_RANDOM_R"//"RANDOM_WR" //"FILL_R" "FILL_W_FILL_R" "RANDOM_WR" "RANDOM_W_RANDOM_R" "PIM_DOUBLE_BUFFER" "MANUAL" "EXTERNAL" 16 | `define TRAFFIC_NUM_WORDS 1 // AXI Burst length 17 | `define TRAFFIC_RANDOM_NUM_WORDS 10 18 | `define AXI_TRAFFIC_WORKING_SET_SIZE 10 //DEEPAK //Used only for AXI_TRAFFIC_ADDR_MODE = UNIFORM_LOCAL 19 | `define AXI_TRAFFIC_ADDR_MODE "UNIFORM_ALL" // "FIXED_ZERO" "UNIFORM_LOCAL" //Check GENERATE_ADDRESS function for details 20 | `define NUM_CONSECUTIVE_WRITES 1 21 | `define NUM_CONSECUTIVE_READS 1 22 | `define VAR_CONSECUTIVE_WRITES 0 23 | `define VAR_CONSECUTIVE_READS 0 24 | `define DELAY_AFTER_CONSECUTIVE_WRITES 0 //DEEPAK-- for generating random delay between consecutive writes 25 | `define DELAY_AFTER_CONSECUTIVE_READS 0 26 | `define TRAFFIC_INITIAL_DELAY 0 27 | `define TRAFFIC_INITIAL_JITTER 0 28 | `define TRAFFIC_IAT_DELAY 0 29 | `define TRAFFIC_IAT_JITTER 0 30 | `define THROTTLING_JITTER 0 31 | `define TRAFFIC_MASK 1 32 | `define NOP_CMD 0 33 | `define WRITE_CMD 1 34 | `define READ_CMD 2 35 | `ifdef GATE_LEVEL 36 | `define SOD 2 37 | `elsif GATE_LEVEL2 38 | `define SOD 2 39 | `else 40 | `define SOD 0 41 | `endif 42 | `define TOTAL_MEM_SIZE 2**(29) 43 | `define ROW_ADDR_WDTH 14 44 | `define BA_ADDR_WDTH 4 45 | `define COL_ADDR_WIDTH 10 46 | `define RBC//RBC //Address Mapping BRC (Bank-Row-Col) or RBC (Row-Bank-Col) 47 | /*************************************************************/ 48 | /////////////////////// _params.axi /////////////////////////// 49 | /*************************************************************/ 50 | `define N_INIT_PORT 1 51 | `define N_TARG_PORT 1 52 | `define AXI_DATA_W 512 53 | //`define AXI_ID_IN (`EVAL_LOG2(44)) 54 | //`define N_REGION 1 55 | `define AXI_BURST_LENGTH 1 56 | `define MAX_INFLIGHT_TRANS 128 //DEEPAK -- Number of transactions in the controller 57 | `define TID_ALLOCATION_MODE "READY_QUEUE" 58 | //***************************** 59 | `define REPORT_PASSED_TRANSACTIONS "TRUE" 60 | `define REPORT_RACED_TRANSACTIONS "TRUE" 61 | `define REPORT_UNINIT_TRANSACTIONS "TRUE" 62 | //`define PERIODIC_REPORT_PERIOD 50000 63 | `define VERIFY_READ_WRITE 64 | //`define MEASURE_LINK_STATISTICS 65 | `define READY_QUEUE_ENABLED 66 | //`define COARSE_BURST_MULTIPLEXING 67 | /**********************************************************************/ 68 | //////////////params_global/////////////////////////////////////////// 69 | /**********************************************************************/ 70 | //`ifndef PARAMS_GLOBAL_HEADER 71 | //`define PARAMS_GLOBAL_HEADER 72 | 73 | //`define SOD 0.01 74 | 75 | // DEFINITIONS ONLY (NOT THE PARAMETERS) 76 | 77 | // Notice: This function is Ceil{Log2{X}}, so EVAL_LOG2(3) = 2 78 | `define EVAL_LOG2(VALUE) ((VALUE) <= ( 1 ) ? 0 : (VALUE) <= ( 2 ) ? 1 : (VALUE) <= ( 4 ) ? 2 : (VALUE) <= (8) ? 3 :(VALUE) <= ( 16 ) ? 4 : (VALUE) <= ( 32 ) ? 5 : (VALUE) <= ( 64 ) ? 6 : (VALUE) <= ( 128 ) ? 7 : (VALUE) <= ( 256 ) ? 8 : (VALUE) <= ( 512 ) ? 9 : (VALUE) <= ( 1024 ) ? 10 : (VALUE) <= ( 2048 ) ? 11 : (VALUE) <= ( 4096 ) ? 12 : (VALUE) <= ( 8192 ) ? 13 : (VALUE) <= ( 16384 ) ? 14 : (VALUE) <= ( 32768 ) ? 15 : 15) 79 | 80 | // Notice: This function has been manipulated to avoid zero-sized arrays. So it returns 1 instead of 0 when its input argument is equal to 1 81 | `define EVAL_LOG2_MANIPULATED(VALUE) ((VALUE) <= ( 2 ) ? 1 : (VALUE) <= ( 4 ) ? 2 : (VALUE) <= (8) ? 3 :(VALUE) <= ( 16 ) ? 4 : (VALUE) <= ( 32 ) ? 5 : (VALUE) <= ( 64 ) ? 6 : (VALUE) <= ( 128 ) ? 7 : (VALUE) <= ( 256 ) ? 8 : (VALUE) <= ( 512 ) ? 9 : (VALUE) <= ( 1024 ) ? 10 : (VALUE) <= ( 2048 ) ? 11 : (VALUE) <= ( 4096 ) ? 12 : (VALUE) <= ( 8192 ) ? 13 : (VALUE) <= ( 16384 ) ? 14 : (VALUE) <= ( 32768 ) ? 15 : 15) 82 | 83 | // Ceil Function 84 | `define INT_DIV(A,B) (unsigned'((A- (int' (A/B))* B > 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/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/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/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_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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /ips/axi_slice/LICENSE: -------------------------------------------------------------------------------- 1 | SOLDERPAD HARDWARE LICENSE version 0.51 2 | 3 | This license is based closely on the Apache License Version 2.0, but is not 4 | approved or endorsed by the Apache Foundation. A copy of the non-modified 5 | Apache License 2.0 can be found at http://www.apache.org/licenses/LICENSE-2.0. 6 | 7 | As this license is not currently OSI or FSF approved, the Licensor permits any 8 | Work licensed under this License, at the option of the Licensee, to be treated 9 | as licensed under the Apache License Version 2.0 (which is so approved). 10 | 11 | This License is licensed under the terms of this License and in particular 12 | clause 7 below (Disclaimer of Warranties) applies in relation to its use. 13 | 14 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 15 | 16 | 1. Definitions. 17 | 18 | “License” shall mean the terms and conditions for use, reproduction, and 19 | distribution as defined by Sections 1 through 9 of this document. 20 | 21 | “Licensor” shall mean the Rights owner or entity authorized by the Rights owner 22 | that is granting the License. 23 | 24 | “Legal Entity” shall mean the union of the acting entity and all other entities 25 | that control, are controlled by, or are under common control with that entity. 26 | For the purposes of this definition, “control” means (i) the power, direct or 27 | indirect, to cause the direction or management of such entity, whether by 28 | contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the 29 | outstanding shares, or (iii) beneficial ownership of such entity. 30 | 31 | “You” (or “Your”) shall mean an individual or Legal Entity exercising 32 | permissions granted by this License. 33 | 34 | “Rights” means copyright and any similar right including design right (whether 35 | registered or unregistered), semiconductor topography (mask) rights and 36 | database rights (but excluding Patents and Trademarks). 37 | 38 | “Source” form shall mean the preferred form for making modifications, including 39 | but not limited to source code, net lists, board layouts, CAD files, 40 | documentation source, and configuration files. 41 | 42 | “Object” form shall mean any form resulting from mechanical transformation or 43 | translation of a Source form, including but not limited to compiled object 44 | code, generated documentation, the instantiation of a hardware design and 45 | conversions to other media types, including intermediate forms such as 46 | bytecodes, FPGA bitstreams, artwork and semiconductor topographies (mask 47 | works). 48 | 49 | “Work” shall mean the work of authorship, whether in Source form or other 50 | Object form, made available under the License, as indicated by a Rights notice 51 | that is included in or attached to the work (an example is provided in the 52 | Appendix below). 53 | 54 | “Derivative Works” shall mean any work, whether in Source or Object form, that 55 | is based on (or derived from) the Work and for which the editorial revisions, 56 | annotations, elaborations, or other modifications represent, as a whole, an 57 | original work of authorship. For the purposes of this License, Derivative Works 58 | shall not include works that remain separable from, or merely link (or bind by 59 | name) or physically connect to or interoperate with the interfaces of, the Work 60 | and Derivative Works thereof. 61 | 62 | “Contribution” shall mean any design or work of authorship, including the 63 | original version of the Work and any modifications or additions to that Work or 64 | Derivative Works thereof, that is intentionally submitted to Licensor for 65 | inclusion in the Work by the Rights owner or by an individual or Legal Entity 66 | authorized to submit on behalf of the Rights owner. For the purposes of this 67 | definition, “submitted” means any form of electronic, verbal, or written 68 | communication sent to the Licensor or its representatives, including but not 69 | limited to communication on electronic mailing lists, source code control 70 | systems, and issue tracking systems that are managed by, or on behalf of, the 71 | Licensor for the purpose of discussing and improving the Work, but excluding 72 | communication that is conspicuously marked or otherwise designated in writing 73 | by the Rights owner as “Not a Contribution.” 74 | 75 | “Contributor” shall mean Licensor and any individual or Legal Entity on behalf 76 | of whom a Contribution has been received by Licensor and subsequently 77 | incorporated within the Work. 78 | 79 | 2. Grant of License. Subject to the terms and conditions of this License, each 80 | Contributor hereby grants to You a perpetual, worldwide, non-exclusive, 81 | no-charge, royalty-free, irrevocable license under the Rights to reproduce, 82 | prepare Derivative Works of, publicly display, publicly perform, sublicense, 83 | and distribute the Work and such Derivative Works in Source or Object form and 84 | do anything in relation to the Work as if the Rights did not exist. 85 | 86 | 3. Grant of Patent License. Subject to the terms and conditions of this 87 | License, each Contributor hereby grants to You a perpetual, worldwide, 88 | non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this 89 | section) patent license to make, have made, use, offer to sell, sell, import, 90 | and otherwise transfer the Work, where such license applies only to those 91 | patent claims licensable by such Contributor that are necessarily infringed by 92 | their Contribution(s) alone or by combination of their Contribution(s) with the 93 | Work to which such Contribution(s) was submitted. If You institute patent 94 | litigation against any entity (including a cross-claim or counterclaim in a 95 | lawsuit) alleging that the Work or a Contribution incorporated within the Work 96 | constitutes direct or contributory patent infringement, then any patent 97 | licenses granted to You under this License for that Work shall terminate as of 98 | the date such litigation is filed. 99 | 100 | 4. Redistribution. You may reproduce and distribute copies of the Work or 101 | Derivative Works thereof in any medium, with or without modifications, and in 102 | Source or Object form, provided that You meet the following conditions: 103 | 104 | You must give any other recipients of the Work or Derivative Works a copy 105 | of this License; and 106 | 107 | You must cause any modified files to carry prominent notices stating that 108 | You changed the files; and 109 | 110 | You must retain, in the Source form of any Derivative Works that You 111 | distribute, all copyright, patent, trademark, and attribution notices from 112 | the Source form of the Work, excluding those notices that do not pertain to 113 | any part of the Derivative Works; and 114 | 115 | If the Work includes a “NOTICE” text file as part of its distribution, then 116 | any Derivative Works that You distribute must include a readable copy of 117 | the attribution notices contained within such NOTICE file, excluding those 118 | notices that do not pertain to any part of the Derivative Works, in at 119 | least one of the following places: within a NOTICE text file distributed as 120 | part of the Derivative Works; within the Source form or documentation, if 121 | provided along with the Derivative Works; or, within a display generated by 122 | the Derivative Works, if and wherever such third-party notices normally 123 | appear. The contents of the NOTICE file are for informational purposes only 124 | and do not modify the License. You may add Your own attribution notices 125 | within Derivative Works that You distribute, alongside or as an addendum to 126 | the NOTICE text from the Work, provided that such additional attribution 127 | notices cannot be construed as modifying the License. You may add Your own 128 | copyright statement to Your modifications and may provide additional or 129 | different license terms and conditions for use, reproduction, or 130 | distribution of Your modifications, or for any such Derivative Works as a 131 | whole, provided Your use, reproduction, and distribution of the Work 132 | otherwise complies with the conditions stated in this License. 133 | 134 | 5. Submission of Contributions. Unless You explicitly state otherwise, any 135 | Contribution intentionally submitted for inclusion in the Work by You to the 136 | Licensor shall be under the terms and conditions of this License, without any 137 | additional terms or conditions. Notwithstanding the above, nothing herein shall 138 | supersede or modify the terms of any separate license agreement you may have 139 | executed with Licensor regarding such Contributions. 140 | 141 | 6. Trademarks. This License does not grant permission to use the trade names, 142 | trademarks, service marks, or product names of the Licensor, except as required 143 | for reasonable and customary use in describing the origin of the Work and 144 | reproducing the content of the NOTICE file. 145 | 146 | 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in 147 | writing, Licensor provides the Work (and each Contributor provides its 148 | Contributions) on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 149 | KIND, either express or implied, including, without limitation, any warranties 150 | or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 151 | PARTICULAR PURPOSE. You are solely responsible for determining the 152 | appropriateness of using or redistributing the Work and assume any risks 153 | associated with Your exercise of permissions under this License. 154 | 155 | 8. Limitation of Liability. In no event and under no legal theory, whether in 156 | tort (including negligence), contract, or otherwise, unless required by 157 | applicable law (such as deliberate and grossly negligent acts) or agreed to in 158 | writing, shall any Contributor be liable to You for damages, including any 159 | direct, indirect, special, incidental, or consequential damages of any 160 | character arising as a result of this License or out of the use or inability to 161 | use the Work (including but not limited to damages for loss of goodwill, work 162 | stoppage, computer failure or malfunction, or any and all other commercial 163 | damages or losses), even if such Contributor has been advised of the 164 | possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing the Work or 167 | Derivative Works thereof, You may choose to offer, and charge a fee for, 168 | acceptance of support, warranty, indemnity, or other liability obligations 169 | and/or rights consistent with this License. However, in accepting such 170 | obligations, You may act only on Your own behalf and on Your sole 171 | responsibility, not on behalf of any other Contributor, and only if You agree 172 | to indemnify, defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason of your 174 | accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | --------------------------------------------------------------------------------