aboutsummaryrefslogtreecommitdiffstats
path: root/sources/hdl
diff options
context:
space:
mode:
Diffstat (limited to 'sources/hdl')
-rw-r--r--sources/hdl/header_verilog/encoding.vh103
-rw-r--r--sources/hdl/header_verilog/parameters.vh21
-rw-r--r--sources/hdl/sim_verilog/example_top.sv557
-rw-r--r--sources/hdl/sim_verilog/tb_decode_stage.v26
-rw-r--r--sources/hdl/sim_verilog/tb_frontend.v0
-rw-r--r--sources/hdl/sim_verilog/tb_softmc_top.v42
-rw-r--r--sources/hdl/verilog/ddr_pipeline.v206
-rw-r--r--sources/hdl/verilog/decode_stage.v318
-rw-r--r--sources/hdl/verilog/diff_shift_reg.v69
-rw-r--r--sources/hdl/verilog/dll_toggler.v206
-rw-r--r--sources/hdl/verilog/exe_pipeline.v191
-rw-r--r--sources/hdl/verilog/execute_stage.v194
-rw-r--r--sources/hdl/verilog/fetch_stage.v147
-rw-r--r--sources/hdl/verilog/frontend.v237
-rw-r--r--sources/hdl/verilog/maintenance_controller.v265
-rw-r--r--sources/hdl/verilog/pop_count4.v68
-rw-r--r--sources/hdl/verilog/pre_decode.v39
-rw-r--r--sources/hdl/verilog/readback_engine.v244
-rw-r--r--sources/hdl/verilog/reg_mem.v33
-rw-r--r--sources/hdl/verilog/register_file.v92
-rw-r--r--sources/hdl/verilog/softmc_pipeline.v178
-rw-r--r--sources/hdl/verilog/softmc_top.v838
22 files changed, 4074 insertions, 0 deletions
diff --git a/sources/hdl/header_verilog/encoding.vh b/sources/hdl/header_verilog/encoding.vh
new file mode 100644
index 0000000..f5d5697
--- /dev/null
+++ b/sources/hdl/header_verilog/encoding.vh
@@ -0,0 +1,103 @@
+// SoftMC instructions
+`define FU_CODE_OFFSET 48
+`define BRANCH_OFFSET 62
+`define DDR_OFFSET 63
+`define INFO_OFFSET 61
+`define MEM_OFFSET 60
+`define BW_OFFSET 59
+`define DEC_RS1 0
+`define DEC_RS2 4
+`define DEC_IMD1 4
+`define DEC_IMD2 0
+`define DEC_IMD3 24
+`define DEC_RT 20
+`define DEC_WO 20
+`define DEC_JUMP_OFFSET 0
+`define DEC_SLEEP_OFFSET 0
+`define DEC_BR_TGT_OFFSET 8
+`define SR_OFFSET 56
+// DDR related
+`define DDR_CODE_OFFSET 12
+`define DEC_CAR 4
+`define DEC_BAR 0
+`define DEC_RAR 4
+`define DEC_INC_BAR 10
+`define DEC_PRE_ALL 11
+`define DEC_INC_RAR 11
+`define DEC_INC_CAR 11
+`define DEC_AP 9
+`define DEC_BL4 8
+// function codes - exe
+`define ADD 0
+`define ADDI 1
+`define SUB 2
+`define SUBI 3
+`define MV 4
+`define SRC 5
+`define LI 6
+`define LDWD 7
+`define LDPC 8
+`define SRE 0 //DDR command but no space left in ISA DDR instructions.
+`define SRX 1 //DDR command but no space left in ISA DDR instructions.
+`define BL 0
+`define BEQ 1
+`define JUMP 2
+`define SLEEP 3
+`define LD 0
+`define ST 1
+`define AND 0
+`define OR 1
+`define XOR 2
+// function codes - ddr
+`define WRITE 0
+`define READ 1
+`define PRE 2
+`define ACT 3
+`define ZQ 4
+`define REF 5
+`define NOP 7
+
+// SoftMC ddr uops
+`define IS_WRITE 0
+`define IS_READ 1
+`define IS_PRE 2
+`define IS_ACT 3
+`define IS_ZQ 4
+`define IS_REF 5
+`define CAR 6 // column address register identifier
+`define RAR 10 // row address register identifier
+`define BAR 14 // bank address register identifier
+`define PRE_ALL 18
+`define INC_CAR 19 // increment CAR after executing this
+`define INC_RAR 20
+`define INC_BAR 21
+`define IS_NOP 22
+`define IS_BL4 23
+`define DO_AP 24
+`define IS_SRE 25
+`define IS_SRX 26
+// SoftMC exe uops
+`define IS_ADD 0
+`define IS_SUB 1
+`define IS_MOV 2
+`define IS_LI 3
+`define IS_LDWD 4
+`define HAS_IMD 5
+`define IS_BL 6
+`define IS_BEQ 7
+`define IS_JUMP 8
+`define IS_SLEEP 9
+`define RS1 10
+`define RS2 14
+`define RT 18
+`define IMD 22
+`define IMD2 38
+`define IS_SRC 54
+`define IS_MEM 55
+`define IS_LD 56
+`define IS_ST 57
+`define IS_AND 58
+`define IS_OR 59
+`define IS_XOR 60
+`define IS_LDPC 61
+
diff --git a/sources/hdl/header_verilog/parameters.vh b/sources/hdl/header_verilog/parameters.vh
new file mode 100644
index 0000000..916c973
--- /dev/null
+++ b/sources/hdl/header_verilog/parameters.vh
@@ -0,0 +1,21 @@
+// Fetch
+`define INSTR_WIDTH 64
+`define IMEM_ADDR_WIDTH 11
+
+// Decode - Execute
+`define DDR_UOP_WIDTH 27
+`define EXE_UOP_WIDTH 62
+`define BG_WIDTH 2
+`define BANK_WIDTH 2
+`define COL_WIDTH 10
+`define ROW_WIDTH 17
+
+//Frontend
+`define XDMA_AXI_DATA_WIDTH 256
+`define IMEM_RD_LATENCY 1
+//`define IMEM_SR // please only define when IMEM_RD_LATENCY > 1
+
+//Common
+`define HIGH 1'b1
+`define LOW 1'b0
+
diff --git a/sources/hdl/sim_verilog/example_top.sv b/sources/hdl/sim_verilog/example_top.sv
new file mode 100644
index 0000000..dbf4fea
--- /dev/null
+++ b/sources/hdl/sim_verilog/example_top.sv
@@ -0,0 +1,557 @@
+
+`ifdef MODEL_TECH
+ `ifndef CALIB_SIM
+ `define SIMULATION
+ `endif
+`elsif INCA
+ `ifndef CALIB_SIM
+ `define SIMULATION
+ `endif
+`elsif VCS
+ `ifndef CALIB_SIM
+ `define SIMULATION
+ `endif
+`elsif XILINX_SIMULATOR
+ `ifndef CALIB_SIM
+ `define SIMULATION
+ `endif
+`endif
+
+`timescale 1ps/1ps
+
+// Fetch
+`define INSTR_WIDTH 64
+`define IMEM_ADDR_WIDTH 11
+
+// Decode - Execute
+`define DDR_UOP_WIDTH 27
+`define EXE_UOP_WIDTH 62
+`define BG_WIDTH 2
+`define BANK_WIDTH 2
+`define COL_WIDTH 10
+`define ROW_WIDTH 17
+
+//Frontend
+`define XDMA_AXI_DATA_WIDTH 256
+`define IMEM_RD_LATENCY 1
+//`define IMEM_SR // please only define when IMEM_RD_LATENCY > 1
+
+//Common
+`define HIGH 1'b1
+`define LOW 1'b0
+
+
+
+`define UDIMM_x8
+
+`define DQ_WIDTH 64
+`define ODT_WIDTH 2
+`define CS_WIDTH 2
+`define CKE_WIDTH 2
+`define CK_WIDTH 1
+`define ROW_ADDR_WIDTH 17
+
+
+module example_top #
+ (
+ parameter SIMULATION = "FALSE"
+ )
+ (
+
+ // common signals
+ input c0_sys_clk_p,
+ input c0_sys_clk_n,
+ input sys_rst,
+
+ // iob <> ddr4 sdram ip signals
+ output c0_ddr4_act_n,
+ output [`ROW_ADDR_WIDTH-1:0] c0_ddr4_adr,
+ output [1:0] c0_ddr4_ba,
+ output [1:0] c0_ddr4_bg,
+ output [`CKE_WIDTH-1:0] c0_ddr4_cke,
+ output [`ODT_WIDTH-1:0] c0_ddr4_odt,
+ output [`CS_WIDTH-1:0] c0_ddr4_cs_n,
+ output [`CK_WIDTH-1:0] c0_ddr4_ck_t,
+ output [`CK_WIDTH-1:0] c0_ddr4_ck_c,
+ output c0_ddr4_reset_n,
+
+ `ifdef RDIMM_x4
+ inout [17:0] c0_ddr4_dqs_c,
+ inout [17:0] c0_ddr4_dqs_t,
+ inout [71:0] c0_ddr4_dq,
+ output c0_ddr4_parity,
+ `elsif UDIMM_x8
+ inout [7:0] c0_ddr4_dqs_c,
+ inout [7:0] c0_ddr4_dqs_t,
+ inout [63:0] c0_ddr4_dq,
+ inout [7:0] c0_ddr4_dm_dbi_n,
+ output c0_ddr4_parity,
+ `elsif RDIMM_x8
+ inout [8:0] c0_ddr4_dqs_c,
+ inout [8:0] c0_ddr4_dqs_t,
+ inout [71:0] c0_ddr4_dq,
+ inout [8:0] c0_ddr4_dm_dbi_n,
+ output c0_ddr4_parity,
+ `endif
+
+ output c0_init_calib_complete,
+ output c0_data_compare_error
+);
+
+ `ifdef RDIMM_x4
+ assign c0_ddr4_odt[1] = 1'b0;
+ assign c0_ddr4_cs_n[1] = 1'b1;
+ assign c0_ddr4_cke[1] = 1'b0;
+ `elsif RDIMM_x8
+ assign c0_ddr4_odt[1] = 1'b0;
+ assign c0_ddr4_cs_n[1] = 1'b1;
+ assign c0_ddr4_cke[1] = 1'b0;
+ //assign c0_ddr4_parity = 1'b0;
+ `elsif UDIMM_x8
+ assign c0_ddr4_odt[1] = 1'b0;
+ assign c0_ddr4_cs_n[1] = 1'b1;
+ assign c0_ddr4_cke[1] = 1'b0;
+ assign c0_ddr4_parity = 1'b0;
+ `endif
+
+ // Frontend control signals
+ wire softmc_fin;
+ wire user_rst;
+
+ // Frontend <-> Fetch signals
+ wire [`IMEM_ADDR_WIDTH-1:0] fr_addr_in;
+ wire fr_valid_in;
+ wire [`INSTR_WIDTH-1:0] fr_data_out;
+ wire fr_valid_out;
+ wire [`IMEM_ADDR_WIDTH-1:0] fr_addr_out;
+ wire fr_ready_out;
+
+ // Frontend <-> misc. control signals
+ wire per_rd_init;
+ wire per_zq_init;
+ wire rbe_switch_mode;
+
+ // AXI streaming ports
+ wire [`XDMA_AXI_DATA_WIDTH-1:0] m_axis_h2c_tdata_0,xdma_h2c_tdata_0;
+ wire m_axis_h2c_tlast_0, xdma_h2c_tlast_0;
+ wire m_axis_h2c_tvalid_0, xdma_h2c_tvalid_0;
+ wire m_axis_h2c_tready_0, xdma_h2c_tready_0;
+ wire [`XDMA_AXI_DATA_WIDTH/8-1:0] m_axis_h2c_tkeep_0, xdma_h2c_tkeep_0;
+ wire [`XDMA_AXI_DATA_WIDTH-1:0] s_axis_c2h_tdata_0, xdma_c2h_tdata_0;
+ wire s_axis_c2h_tlast_0, xdma_c2h_tlast_0;
+ wire s_axis_c2h_tvalid_0, xdma_c2h_tvalid_0;
+ wire s_axis_c2h_tready_0, xdma_c2h_tready_0;
+ wire [`XDMA_AXI_DATA_WIDTH/8-1:0] s_axis_c2h_tkeep_0, xdma_c2h_tkeep_0;
+
+ // ddr_pipeline <-> outer module if
+ wire [3:0] ddr_write;
+ wire [3:0] ddr_read;
+ wire [3:0] ddr_pre;
+ wire [3:0] ddr_act;
+ wire [3:0] ddr_ref;
+ wire [3:0] ddr_zq;
+ wire [3:0] ddr_nop;
+ wire [3:0] ddr_sre;
+ wire [3:0] ddr_srx;
+ wire [3:0] ddr_ap;
+ wire [3:0] ddr_pall;
+ wire [3:0] ddr_half_bl;
+ wire [4*`BG_WIDTH-1:0] ddr_bg;
+ wire [4*`BANK_WIDTH-1:0] ddr_bank;
+ wire [4*`COL_WIDTH-1:0] ddr_col;
+ wire [4*`ROW_WIDTH-1:0] ddr_row;
+ wire [511:0] ddr_wdata;
+
+ // periodic maintenance signals
+ wire ddr_maint_read;
+
+ // phy <-> ddr adapter and dlltoggler signals
+ // dlltoggler
+ wire clk_sel = 0;
+ wire [7:0] dllt_mc_ACT_n;
+ wire [135:0] dllt_mc_ADR;
+ wire [15:0] dllt_mc_BA;
+ wire [15:0] dllt_mc_BG;
+ wire [7:0] dllt_mc_CKE;
+ wire [7:0] dllt_mc_CS_n;
+ wire dllt_done;
+ // adapter
+ wire [4:0] dBufAdr;
+ wire [`DQ_WIDTH*8-1:0] wrData;
+ wire [`DQ_WIDTH-1:0] wrDataMask;
+ wire [511:0] rdData;
+ wire [4:0] rdDataAddr;
+ wire [0:0] rdDataEn;
+ wire [0:0] rdDataEnd;
+ wire [0:0] per_rd_done;
+ wire [0:0] rmw_rd_done;
+ wire [4:0] wrDataAddr;
+ wire [0:0] wrDataEn;
+ wire [7:0] mc_ACT_n;
+ wire [135:0] mc_ADR;
+ wire [15:0] mc_BA;
+ wire [15:0] mc_BG;
+ wire [`CKE_WIDTH*8-1:0] mc_CKE;
+ wire [`CS_WIDTH*8-1:0] mc_CS_n;
+ wire [`ODT_WIDTH*8-1:0] mc_ODT;
+ wire [0:0] mcRdCAS;
+ wire [0:0] mcWrCAS;
+ wire [0:0] winInjTxn;
+ wire [0:0] winRmw;
+ wire [4:0] winBuf;
+ wire [1:0] winRank;
+ wire [5:0] tCWL;
+ wire dbg_clk;
+ wire c0_wr_rd_complete;
+ wire c0_ddr4_clk;
+ wire c0_ddr4_dll_off_clk;
+ wire ddr4_ui_clk;
+ wire c0_ddr4_rst;
+ wire [511:0] dbg_bus;
+ wire [1:0] mcCasSlot;
+ wire mcCasSlot2;
+ wire gt_data_ready;
+
+ wire read_seq_incoming; // next few instructions will read from DRAM
+ wire [11:0] incoming_reads; // how many reads next few instructions will issue
+ wire [11:0] buffer_space; // remaining buffer size
+
+ // There is a possibility that these signals are on
+ // the critical path as observed in
+ // the previous iteration of SoftMC
+ reg c0_init_calib_complete_r, sys_rst_r;
+ wire iq_full, processing_iseq, rdback_fifo_empty;
+ reg dllt_active = 1'b0;
+
+ reg toggle_dll = 1'b0;
+ reg dont = 1'b1;
+
+ always @(posedge c0_ddr4_clk) begin
+ c0_init_calib_complete_r <= c0_init_calib_complete;
+ sys_rst_r <= sys_rst;
+ `ifdef ENABLE_DLL_TOGGLER
+ if(c0_init_calib_complete_r && dont) begin
+ toggle_dll <= 1'b1;
+ dont <= 1'b0;
+ end
+ if(toggle_dll) begin
+ dllt_active <= ~dllt_active;
+ toggle_dll <= 1'b0;
+ end
+ if(dllt_done) begin
+ dllt_active <= ~dllt_active;
+ end
+ `endif
+ end
+
+
+ `ifdef UDIMM_x8
+ phy_ddr4_udimm phy_ddr4_i(
+ .sys_rst (sys_rst),
+ .c0_sys_clk_p (c0_sys_clk_p),
+ .c0_sys_clk_n (c0_sys_clk_n),
+
+ `ifdef ENABLE_DLL_TOGGLER
+ .c0_ddr4_ui_clk (ddr4_ui_clk),
+ .addn_ui_clkout1 (c0_ddr4_dll_off_clk),
+ `else
+ .c0_ddr4_ui_clk (c0_ddr4_clk),
+ `endif
+ .c0_ddr4_ui_clk_sync_rst (c0_ddr4_rst),
+ .c0_init_calib_complete (c0_init_calib_complete),
+ .dbg_clk (dbg_clk),
+ .c0_ddr4_act_n (c0_ddr4_act_n),
+ .c0_ddr4_adr (c0_ddr4_adr),
+ .c0_ddr4_ba (c0_ddr4_ba),
+ .c0_ddr4_bg (c0_ddr4_bg),
+ .c0_ddr4_cke (c0_ddr4_cke),
+ .c0_ddr4_odt (c0_ddr4_odt),
+ .c0_ddr4_cs_n (c0_ddr4_cs_n),
+ .c0_ddr4_ck_t (c0_ddr4_ck_t),
+ .c0_ddr4_ck_c (c0_ddr4_ck_c),
+ .c0_ddr4_reset_n (c0_ddr4_reset_n),
+ //.ddr4_par (c0_ddr4_parity),
+ .c0_ddr4_dq (c0_ddr4_dq),
+ .c0_ddr4_dqs_c (c0_ddr4_dqs_c),
+ .c0_ddr4_dqs_t (c0_ddr4_dqs_t),
+ .c0_ddr4_dm_dbi_n (c0_ddr4_dm_dbi_n),
+
+ .dBufAdr (dBufAdr),
+ .wrData (wrData),
+ .rdData (rdData),
+ .rdDataAddr (rdDataAddr),
+ .rdDataEn (rdDataEn),
+ .rdDataEnd (rdDataEnd),
+ .per_rd_done (per_rd_done),
+ .rmw_rd_done (rmw_rd_done),
+ .wrDataAddr (wrDataAddr),
+ .wrDataEn (wrDataEn),
+ .wrDataMask (wrDataMask),
+
+ .mc_ACT_n (dllt_active ? dllt_mc_ACT_n : mc_ACT_n),
+ .mc_ADR (dllt_active ? dllt_mc_ADR : mc_ADR),
+ .mc_BA (dllt_active ? dllt_mc_BA : mc_BA),
+ .mc_BG (dllt_active ? dllt_mc_BG : mc_BG),
+ // DRAM CKE. 8 bits for each DRAM pin. The mc_CKE signal is always set to '1'.
+ .mc_CKE (dllt_active ? dllt_mc_CKE : {8{1'b1}}),
+ .mc_CS_n (dllt_active ? dllt_mc_CS_n : mc_CS_n),
+ .mc_ODT (mc_ODT),
+ // CAS command slot select. Slot0 is enabled for example design.
+ .mcCasSlot (dllt_active ? 0 : mcCasSlot),
+ // CAS slot 2 select. mcCasSlot2 serves a similar purpose as the mcCasSlot[1:0] signal, but mcCasSlot2 is used in timing
+ // critical logic in the Phy. Slot0 is enabled for example design.
+ .mcCasSlot2 (dllt_active ? 0 : mcCasSlot2),
+ .mcRdCAS (dllt_active ? 0 : mcRdCAS),
+ .mcWrCAS (dllt_active ? 0 : mcWrCAS),
+ // Optional read command type indication. The winInjTxn signal is set to '0' for example design.
+ .winInjTxn ({1{1'b0}}),
+ // Optional read command type indication. The winRmw signal is set to '0' for example design.
+ .winRmw ({1{1'b0}}),
+ // Update VT Tracking. The gt_data_ready signal is set to '0' in this example design.
+ // This signal must be asserted periodically to keep the DQS Gate aligned as voltage and temperature drift.
+ // For more information, Refer to PG150 document.
+ .gt_data_ready (gt_data_ready),
+ .winBuf (winBuf),
+ .winRank (winRank),
+ .tCWL (tCWL),
+ // Debug Port
+ .dbg_bus (dbg_bus)
+ );
+ `endif
+
+ `ifdef ENABLE_DLL_TOGGLER
+ //BUFGMUX:GeneralClockMuxBuffer
+ //UltraScale
+ //XilinxHDLLibrariesGuide, version2014.4
+ BUFGMUX#(.CLK_SEL_TYPE("SYNC") //ASYNC,SYNC
+ )BUFGMUX_inst(
+ .O(c0_ddr4_clk), //1-bitoutput:Clockoutput
+ .I0(ddr4_ui_clk), //1-bitinput:Clockinput(S=0)
+ .I1(c0_ddr4_dll_off_clk), //1-bitinput:Clockinput(S=1)
+ .S(clk_sel) //1-bitinput:Clockselect
+ );
+ //End of BUFGMUX_inst instantiation
+ `endif
+
+ softmc_pipeline pipeline(
+ .clk(c0_ddr4_clk),
+ .rst(c0_ddr4_rst || user_rst || ~c0_init_calib_complete_r),
+
+ .softmc_end(softmc_fin),
+ .read_size(incoming_reads),
+ .read_seq_incoming(read_seq_incoming),
+ .buffer_space(buffer_space),
+
+ .addr_out(fr_addr_in),
+ .valid_out(fr_valid_in),
+ .data_in(fr_data_out),
+ .valid_in(fr_valid_out),
+ .addr_in(fr_addr_out),
+ .ready_out(fr_ready_out),
+
+ .ddr_write(ddr_write),
+ .ddr_read(ddr_read),
+ .ddr_pre(ddr_pre),
+ .ddr_act(ddr_act),
+ .ddr_ref(ddr_ref),
+ .ddr_zq(ddr_zq),
+ .ddr_nop(ddr_nop),
+ .ddr_sre(ddr_sre),
+ .ddr_srx(ddr_srx),
+ .ddr_ap(ddr_ap),
+ .ddr_pall(ddr_pall),
+ .ddr_half_bl(ddr_half_bl),
+ .ddr_bg(ddr_bg),
+ .ddr_bank(ddr_bank),
+ .ddr_col(ddr_col),
+ .ddr_row(ddr_row),
+ .ddr_wdata(ddr_wdata)
+ );
+
+ wire frontend_ready;
+
+ reg keep_frontend_reset = 1'b1;
+
+ `ifdef ENABLE_DLL_TOGGLER
+ always @(posedge c0_ddr4_clk) begin
+ keep_frontend_reset <= c0_init_calib_complete_r;
+ end
+ `endif
+
+ frontend #(.SIM_MEM("true"))frontend(
+ .clk(c0_ddr4_clk),
+ .rst(c0_ddr4_rst || ~keep_frontend_reset || ~c0_init_calib_complete_r || dllt_active),
+
+ .init_calib_complete(c0_init_calib_complete_r),
+ .softmc_fin(softmc_fin),
+ .user_rst(user_rst),
+ //.dllt_begin(toggle_dll),
+
+ // indicates read_back unit is ready for the next iseq
+ .frontend_ready(frontend_ready),
+
+ // frontend <-> fetch stage if
+ .addr_in(fr_addr_in),
+ .valid_in(fr_valid_in),
+ .data_out(fr_data_out),
+ .valid_out(fr_valid_out),
+ .addr_out(fr_addr_out),
+ .ready_in(fr_ready_out),
+
+ // frontend <-> xdma interface
+ .h2c_tdata_0(m_axis_h2c_tdata_0),
+ .h2c_tlast_0(m_axis_h2c_tlast_0),
+ .h2c_tvalid_0(m_axis_h2c_tvalid_0),
+ .h2c_tready_0(m_axis_h2c_tready_0),
+ .h2c_tkeep_0(m_axis_h2c_tkeep_0),
+
+ .per_rd_init(per_rd_init),
+ .per_zq_init(per_zq_init),
+ .rbe_switch_mode(rbe_switch_mode)
+ );
+
+ ddr4_adapter #(
+ .DQ_WIDTH(`DQ_WIDTH)
+ ) ddr4_adapter
+ (
+ .clk(c0_ddr4_clk),
+ .rst(c0_ddr4_rst || user_rst || ~c0_init_calib_complete_r),
+ .init_calib_complete(c0_init_calib_complete_r),
+ //.io_config_strobe,
+ //.io_config,
+ .dBufAdr(dBufAdr), // Reserved. Should be tied low.
+ .wrData(wrData), // DRAM write data. There are 8 bits for each DQ lane on the DRAM bus.
+ .wrDataMask(wrDataMask),// DRAM write DM/DBI port.There is one bit for each byte of the wrData port.
+ .wrDataEn(wrDataEn), // Write data Enable. The Phy will assert this port for one cycle for each write CAS command.
+ .mc_ACT_n(mc_ACT_n), // DRAM ACT_n command signal for four DRAM clock cycles.
+ .mc_ADR(mc_ADR), // DRAM address. There are 8 bits in the fabric interface for each address bit on the DRAM bus.
+ .mc_BA(mc_BA), // DRAM bank address. 8 bits for each DRAM bank address.
+ .mc_BG(mc_BG), // DRAM bank group address.
+ .mc_CS_n(mc_CS_n), // DRAM CS_n
+ //.mc_CKE(mc_CKE), // DRAM CKE
+ //.mc_ODT(mc_ODT), // DRAM ODT
+ .mcRdCAS(mcRdCAS), // Read CAS command issued.
+ .mcWrCAS(mcWrCAS), // Write CAS command issued.
+ .winRank(winRank), // Target rank for CAS commands. This value indicates which rank a CAS command is issued to.
+ .winBuf(winBuf), // Optional control signal. When either mcRdCAS or mcWrCAS is asserted, the Phy will store the value on the winBuf signal.
+ //.rdData(rdData), // DRAM read data.
+ .rdDataEn(rdDataEn), // Read data valid. This signal asserts for one fabric cycle for each completed read operation.
+ .rdDataEnd(rdDataEnd), // Unused. Tied high.
+ .mcCasSlot(mcCasSlot),
+ .mcCasSlot2(mcCasSlot2),
+ .gt_data_ready(gt_data_ready),
+ .ddr_write(ddr_write),
+ .ddr_read(ddr_read),
+ .ddr_pre(ddr_pre),
+ .ddr_act(ddr_act),
+ .ddr_ref(ddr_ref),
+ .ddr_zq(ddr_zq),
+ .ddr_nop(ddr_nop),
+ //.ddr_sre(ddr_sre),
+ //.ddr_srx(ddr_srx),
+ .ddr_ap(ddr_ap),
+ .ddr_pall(ddr_pall),
+ .ddr_half_bl(ddr_half_bl),
+ .ddr_bg(ddr_bg),
+ .ddr_bank(ddr_bank),
+ .ddr_col(ddr_col),
+ .ddr_row(ddr_row),
+ .ddr_wdata(ddr_wdata),
+
+ .ddr_maint_read(per_rd_init)
+ );
+
+ localparam ODTWRDEL = 5'd9;
+ localparam ODTWRDUR = 4'd6;
+ localparam ODTWRODEL = 5'd9;
+ localparam ODTWRODUR = 4'd6;
+ localparam ODTRDDEL = 5'd10;
+ localparam ODTRDDUR = 4'd6;
+ localparam ODTRDODEL = 5'd9;
+ localparam ODTRDODUR = 4'd6;
+ localparam ODTNOP = 16'h0000;
+ localparam ODTWR = 16'h0001;
+ localparam ODTRD = 16'h0000;
+
+
+ wire tranSentC;
+ assign tranSentC = mcRdCAS | mcWrCAS;
+
+ //synthesis translate_on
+ //*******************************************************************************
+ ddr4_mc_odt # (
+ .ODTWR (ODTWR)
+ ,.ODTWRDEL (ODTWRDEL)
+ ,.ODTWRDUR (ODTWRDUR)
+ ,.ODTWRODEL (ODTWRODEL)
+ ,.ODTWRODUR (ODTWRODUR)
+
+ ,.ODTRD (ODTRD)
+ ,.ODTRDDEL (ODTRDDEL)
+ ,.ODTRDDUR (ODTRDDUR)
+ ,.ODTRDODEL (ODTRDODEL)
+ ,.ODTRDODUR (ODTRDODUR)
+
+ ,.ODTNOP (ODTNOP)
+ ,.ODTBITS (`ODT_WIDTH)
+ ,.TCQ (0.1)
+ )u_ddr_tb_odt(
+ .clk (c0_ddr4_clk)
+ ,.rst (c0_ddr4_rst)
+ ,.mc_ODT (mc_ODT)
+ ,.casSlot (mcCasSlot)
+ ,.casSlot2 (mcCasSlot2)
+ ,.rank (winRank)
+ ,.winRead (mcRdCAS)
+ ,.winWrite (mcWrCAS)
+ ,.tranSentC (tranSentC)
+ );
+
+ readback_engine rbe(
+
+ // common signals
+ .clk(c0_ddr4_clk),
+ .rst(c0_ddr4_rst || user_rst || ~c0_init_calib_complete_r),
+
+ // other ctrl signals
+ .flush(frontend_ready),
+ .switch_mode(rbe_switch_mode),
+ .read_seq_incoming(read_seq_incoming), // next few instructions will read from DRAM
+ .incoming_reads(incoming_reads), // how many reads next few instructions will issue
+ .buffer_space(buffer_space), // remaining buffer size
+ // DRAM <-> engine if
+ .rd_data(rdData),
+ .rd_valid(rdDataEn),
+
+ // rbe <-> rf interface
+ .ddr_wdata(ddr_wdata),
+
+ .per_rd_init(per_rd_init),
+ .per_zq_init(per_zq_init),
+
+ // rbe <-> xdma if
+ .c2h_tdata_0(s_axis_c2h_tdata_0),
+ .c2h_tlast_0(s_axis_c2h_tlast_0),
+ .c2h_tvalid_0(s_axis_c2h_tvalid_0),
+ .c2h_tready_0(1'b1),
+ .c2h_tkeep_0(s_axis_c2h_tkeep_0)
+
+ );
+
+ `ifdef ENABLE_DLL_TOGGLER
+ dll_toggler dllt
+ (
+ .clk(c0_ddr4_clk),
+ .rst(c0_ddr4_rst || user_rst || ~c0_init_calib_complete_r),
+ .toggle_valid(toggle_dll),
+ .dllt_done(dllt_done),
+ .mc_ACT_n(dllt_mc_ACT_n), // DRAM ACT_n command signal for four DRAM clock cycles.
+ .mc_ADR(dllt_mc_ADR), // DRAM address. There are 8 bits in the fabric interface for each address bit on the DRAM bus.
+ .mc_BA(dllt_mc_BA), // DRAM bank address. 8 bits for each DRAM bank address.
+ .mc_BG(dllt_mc_BG), // DRAM bank group address.
+ .mc_CS_n(dllt_mc_CS_n), // DRAM CS_n
+ .mc_CKE(dllt_mc_CKE),
+ .clk_sel(clk_sel)
+ );
+ `endif
+endmodule
diff --git a/sources/hdl/sim_verilog/tb_decode_stage.v b/sources/hdl/sim_verilog/tb_decode_stage.v
new file mode 100644
index 0000000..1842cf7
--- /dev/null
+++ b/sources/hdl/sim_verilog/tb_decode_stage.v
@@ -0,0 +1,26 @@
+module tb_decode_stage(
+
+ );
+
+ reg [63:0] instr;
+ reg [11:0] instr_pc;
+ reg instr_valid;
+
+ decode_stage ds(
+ .instr(instr),
+ .instr_pc(instr_pc),
+ .instr_valid(instr_valid)
+ );
+
+ reg clk = 0, rst = 1;
+
+ initial begin
+ #100;
+ rst = 0;
+ end
+
+ always begin
+ #5;
+ clk = ~clk;
+ end
+endmodule
diff --git a/sources/hdl/sim_verilog/tb_frontend.v b/sources/hdl/sim_verilog/tb_frontend.v
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/sources/hdl/sim_verilog/tb_frontend.v
diff --git a/sources/hdl/sim_verilog/tb_softmc_top.v b/sources/hdl/sim_verilog/tb_softmc_top.v
new file mode 100644
index 0000000..6a61f44
--- /dev/null
+++ b/sources/hdl/sim_verilog/tb_softmc_top.v
@@ -0,0 +1,42 @@
+`timescale 1ns / 1ps
+//////////////////////////////////////////////////////////////////////////////////
+// Company:
+// Engineer:
+//
+// Create Date: 12/06/2018 05:43:09 PM
+// Design Name:
+// Module Name: tb_softmc_top
+// Project Name:
+// Target Devices:
+// Tool Versions:
+// Description:
+//
+// Dependencies:
+//
+// Revision:
+// Revision 0.01 - File Created
+// Additional Comments:
+//
+//////////////////////////////////////////////////////////////////////////////////
+
+
+module tb_only_softmc(
+
+ );
+
+ reg clk = 0, rst = 1;
+ softmc_top smct(
+ .clk(clk),
+ .rst(rst)
+ );
+
+ initial begin
+ #50;
+ rst = 0;
+ end
+
+ always begin
+ #5;
+ clk = ~clk;
+ end
+endmodule
diff --git a/sources/hdl/verilog/ddr_pipeline.v b/sources/hdl/verilog/ddr_pipeline.v
new file mode 100644
index 0000000..f8ae5aa
--- /dev/null
+++ b/sources/hdl/verilog/ddr_pipeline.v
@@ -0,0 +1,206 @@
+`include "parameters.vh"
+`include "encoding.vh"
+
+module ddr_pipeline(
+
+ // common signals
+ input clk,
+ input rst,
+
+ // execute_stage <-> ddr_pipeline if
+ input ddr_valid,
+ input [`DDR_UOP_WIDTH*4-1:0] ddr_uop,
+
+ // ddr_pipeline <-> outer DDRX IP interface
+ output [3:0] ddr_write,
+ output [3:0] ddr_read,
+ output [3:0] ddr_pre,
+ output [3:0] ddr_act,
+ output [3:0] ddr_ref,
+ output [3:0] ddr_zq,
+ output [3:0] ddr_nop,
+ output [3:0] ddr_sre,
+ output [3:0] ddr_srx,
+ output [3:0] ddr_ap,
+ output [3:0] ddr_pall,
+ output [3:0] ddr_half_bl,
+ output [4*`BG_WIDTH-1:0] ddr_bg,
+ output [4*`BANK_WIDTH-1:0] ddr_bank,
+ output [4*`COL_WIDTH-1:0] ddr_col,
+ output [4*`ROW_WIDTH-1:0] ddr_row,
+ output [511:0] ddr_wdata,
+
+ // ddr_pipeline <-> regfile interface
+ input [511:0] wide_reg,
+ output [7:0] update_en,
+ output [4*8-1:0] update_ids,
+ output [32*8-1:0] update_vals,
+ input [`COL_WIDTH-1:0] casr,
+ input [`BANK_WIDTH+`BG_WIDTH-1:0] basr,
+ input [`ROW_WIDTH-1:0] rasr,
+ output [4*8-1:0] reg_ids, // registers we need to read
+ input [32*8-1:0] reg_vals // register values
+ );
+
+ //Split input uop into four ways
+ wire [`DDR_UOP_WIDTH-1:0] uop [3:0];
+ genvar uops;
+ generate
+ for(uops = 0 ; uops < 4 ; uops = uops + 1) begin: split_uops
+ assign uop[uops] = ddr_uop[`DDR_UOP_WIDTH*uops +: `DDR_UOP_WIDTH];
+ end
+ endgenerate
+
+ // Figure out reg ids in the bubble cycle
+ reg [4*8-1:0] reg_ids_ns, reg_ids_r;
+
+ reg s2_valid;
+ reg [`DDR_UOP_WIDTH-1:0] s2_uop [3:0];
+ reg [7:0] s2_update_en; // which registers will we update
+ reg [8*32-1:0] s2_update_val;
+
+ reg [3:0] ddr_write_ns, ddr_write_r;
+ reg [3:0] ddr_read_ns, ddr_read_r;
+ reg [3:0] ddr_pre_ns, ddr_pre_r;
+ reg [3:0] ddr_act_ns, ddr_act_r;
+ reg [3:0] ddr_ref_ns, ddr_ref_r;
+ reg [3:0] ddr_sre_ns, ddr_sre_r;
+ reg [3:0] ddr_srx_ns, ddr_srx_r;
+ reg [3:0] ddr_zq_ns, ddr_zq_r;
+ reg [3:0] ddr_nop_ns, ddr_nop_r;
+ reg [3:0] ddr_ap_ns, ddr_ap_r;
+ reg [3:0] ddr_pall_ns, ddr_pall_r;
+ reg [3:0] ddr_half_bl_ns, ddr_half_bl_r;
+ reg [4*`BG_WIDTH-1:0] ddr_bg_ns, ddr_bg_r;
+ reg [4*`BANK_WIDTH-1:0] ddr_bank_ns, ddr_bank_r;
+ reg [4*`COL_WIDTH-1:0] ddr_col_ns, ddr_col_r;
+ reg [4*`ROW_WIDTH-1:0] ddr_row_ns, ddr_row_r;
+ reg [511:0] ddr_data_r;
+
+ assign update_vals = s2_update_val;
+ assign update_en = s2_update_en;
+ assign update_ids = reg_ids_r;
+ assign reg_ids = reg_ids_r;
+ // these values are registered before
+ // being offloaded to the outer module
+ assign ddr_write = ddr_write_r;
+ assign ddr_read = ddr_read_r;
+ assign ddr_pre = ddr_pre_r;
+ assign ddr_act = ddr_act_r;
+ assign ddr_ref = ddr_ref_r;
+ assign ddr_sre = ddr_sre_r;
+ assign ddr_srx = ddr_srx_r;
+ assign ddr_zq = ddr_zq_r;
+ assign ddr_nop = ddr_nop_r;
+ assign ddr_ap = ddr_ap_r;
+ assign ddr_pall = ddr_pall_r;
+ assign ddr_half_bl = ddr_half_bl_r;
+ assign ddr_bg = ddr_bg_r;
+ assign ddr_bank = ddr_bank_r;
+ assign ddr_col = ddr_col_r;
+ assign ddr_row = ddr_row_r;
+ assign ddr_wdata = ddr_data_r;
+
+ integer i;
+ always @* begin
+ ddr_nop_ns = {4{`HIGH}};
+ s2_update_en = {4{`LOW}};
+ reg_ids_ns = reg_ids_r;
+ s2_update_val = 8*32'bX;
+ for(i = 0 ; i < 4 ; i = i + 1) begin: gen_ddrx_sigs
+ // Decide which registers to read in stage 1
+ if(uop[i][`IS_WRITE] || uop[i][`IS_READ]) begin
+ reg_ids_ns[i*8 +: 4] = uop[i][`BAR +: 4];
+ reg_ids_ns[i*8+4 +: 4] = uop[i][`CAR +: 4];
+ end
+ if(uop[i][`IS_PRE]) begin
+ reg_ids_ns[i*8 +: 4] = uop[i][`BAR +: 4];
+ end
+ if(uop[i][`IS_ACT]) begin
+ reg_ids_ns[i*8 +: 4] = uop[i][`BAR +: 4];
+ reg_ids_ns[i*8+4 +: 4] = uop[i][`RAR +: 4];
+ end
+ // stage 2 control sigs
+ ddr_pall_ns[i] = s2_uop[i][`PRE_ALL] & s2_uop[i][`IS_PRE];
+ ddr_write_ns[i] = s2_uop[i][`IS_WRITE];
+ ddr_read_ns[i] = s2_uop[i][`IS_READ];
+ ddr_pre_ns[i] = s2_uop[i][`IS_PRE];
+ ddr_act_ns[i] = s2_uop[i][`IS_ACT];
+ ddr_zq_ns[i] = s2_uop[i][`IS_ZQ];
+ ddr_ref_ns[i] = s2_uop[i][`IS_REF];
+ ddr_sre_ns[i] = s2_uop[i][`IS_SRE];
+ ddr_srx_ns[i] = s2_uop[i][`IS_SRX];
+ ddr_ap_ns[i] = s2_uop[i][`DO_AP] & (s2_uop[i][`IS_WRITE] | s2_uop[i][`IS_READ]);
+ ddr_half_bl_ns[i] = s2_uop[i][`IS_BL4] & (s2_uop[i][`IS_WRITE] | s2_uop[i][`IS_READ]);
+ ddr_nop_ns[i] = s2_valid ? s2_uop[i][`IS_NOP] : {4{`HIGH}};
+ // stage 2 address calculation
+ ddr_row_ns[i*`ROW_WIDTH +: `ROW_WIDTH]
+ = reg_vals[i*64+32 +: `ROW_WIDTH];
+ ddr_bank_ns[i*`BANK_WIDTH +: `BANK_WIDTH]
+ = reg_vals[i*64 +: `BANK_WIDTH];
+ ddr_bg_ns[i*`BG_WIDTH +: `BG_WIDTH]
+ = reg_vals[i*64+`BANK_WIDTH +: `BG_WIDTH];
+ ddr_col_ns[i*`COL_WIDTH +: `COL_WIDTH]
+ = reg_vals[i*64+32 +: `COL_WIDTH];
+ // stage 2 reg update
+ if(s2_uop[i][`INC_CAR] & (s2_uop[i][`IS_WRITE] | s2_uop[i][`IS_READ])) begin
+ s2_update_en[i*2+1] = `HIGH;
+ s2_update_val[i*64+32 +: 32] = reg_vals[i*64+32 +: `COL_WIDTH]
+ + casr;
+ end
+ else if(s2_uop[i][`INC_RAR] & (s2_uop[i][`IS_ACT])) begin
+ s2_update_en[i*2+1] = `HIGH;
+ s2_update_val[i*64+32 +: 32] = reg_vals[i*64+32 +: `ROW_WIDTH]
+ + rasr;
+ end
+ if(s2_uop[i][`INC_BAR]) begin
+ s2_update_en[i*2] = `HIGH;
+ s2_update_val[i*64 +: 32] = reg_vals[i*64 +: `BANK_WIDTH+`BG_WIDTH]
+ + basr;
+ end
+ end // for
+ end
+
+ always @(posedge clk) begin
+ if(rst) begin
+ s2_valid <= `LOW;
+ for(i = 0 ; i < 4 ; i = i + 1)
+ s2_uop[i] <= {`DDR_UOP_WIDTH{`LOW}};
+ ddr_write_r <= {4{`LOW}};
+ ddr_read_r <= {4{`LOW}};
+ ddr_pre_r <= {4{`LOW}};
+ ddr_act_r <= {4{`LOW}};
+ ddr_ref_r <= {4{`LOW}};
+ ddr_sre_r <= {4{`LOW}};
+ ddr_srx_r <= {4{`LOW}};
+ ddr_zq_r <= {4{`LOW}};
+ ddr_nop_r <= {4{`HIGH}};
+ ddr_ap_r <= {4{`LOW}};
+ ddr_half_bl_r <= {4{`LOW}};
+ end
+ else begin
+ reg_ids_r <= reg_ids_ns;
+ s2_valid <= ddr_valid;
+ for(i = 0 ; i < 4 ; i = i + 1)
+ s2_uop[i] <= uop[i];
+ ddr_write_r <= ddr_write_ns;
+ ddr_read_r <= ddr_read_ns;
+ ddr_pre_r <= ddr_pre_ns;
+ ddr_act_r <= ddr_act_ns;
+ ddr_ref_r <= ddr_ref_ns;
+ ddr_sre_r <= ddr_sre_ns;
+ ddr_srx_r <= ddr_srx_ns;
+ ddr_zq_r <= ddr_zq_ns;
+ ddr_nop_r <= ddr_nop_ns;
+ ddr_ap_r <= ddr_ap_ns;
+ ddr_pall_r <= ddr_pall_ns;
+ ddr_half_bl_r <= ddr_half_bl_ns;
+ ddr_bg_r <= ddr_bg_ns;
+ ddr_bank_r <= ddr_bank_ns;
+ ddr_col_r <= ddr_col_ns;
+ ddr_row_r <= ddr_row_ns;
+ ddr_data_r <= wide_reg;
+ end
+ end
+
+endmodule
diff --git a/sources/hdl/verilog/decode_stage.v b/sources/hdl/verilog/decode_stage.v
new file mode 100644
index 0000000..7f40cba
--- /dev/null
+++ b/sources/hdl/verilog/decode_stage.v
@@ -0,0 +1,318 @@
+`include "parameters.vh"
+`include "encoding.vh"
+
+module decode_stage(
+
+ input clk,
+ input rst,
+
+ // fetch stage <-> decode stage interface
+ input [`INSTR_WIDTH-1:0] instr,
+ input [`IMEM_ADDR_WIDTH-1:0] instr_pc,
+ input instr_valid,
+
+ // decode stage <-> execute stage interface
+ output ddr_valid,
+ output exe_valid,
+ output [`DDR_UOP_WIDTH*4-1:0] ddr_uop,
+ output [`EXE_UOP_WIDTH-1:0] exe_uop,
+ output [`IMEM_ADDR_WIDTH-1:0] exe_pc,
+ output [32*7-1:0] ddr_stat
+ );
+
+ reg ddr_valid_r, ddr_valid_ns;
+ reg exe_valid_r, exe_valid_ns;
+ reg [`IMEM_ADDR_WIDTH-1:0] exe_pc_r;
+
+ reg [`DDR_UOP_WIDTH-1:0] ddr_uop_r [3:0], ddr_uop_ns [3:0];
+ reg [`EXE_UOP_WIDTH-1:0] exe_uop_r, exe_uop_ns;
+ reg[31:0] ddr_stat_r[0:6]; //WRITE, READ, PRE, ACT, ZQ, REF, CYC counts
+
+ // split the instr into four individual insts
+ localparam div = 16;
+ wire [`INSTR_WIDTH/4-1:0] ddr_insts [3:0];
+ assign ddr_insts[0] = instr [0 +: div];
+ assign ddr_insts[1] = instr [div +: div];
+ assign ddr_insts[2] = instr [div*2 +: div];
+ assign ddr_insts[3] = instr [div*3 +: div];
+ // gather all ddr uops into one output (¯\_(ツ)_/¯)
+ // verilog does not let us define output vectors
+ genvar uops;
+ generate
+ for(uops = 0 ; uops < 4 ; uops = uops + 1) begin: gather_uops
+ assign ddr_uop[uops*`DDR_UOP_WIDTH +: `DDR_UOP_WIDTH] =
+ ddr_uop_r[uops];
+ end
+ endgenerate
+ assign exe_uop = exe_uop_r;
+ assign exe_pc = exe_pc_r;
+ assign ddr_valid = ddr_valid_r;
+ assign exe_valid = exe_valid_r;
+ assign ddr_stat = {ddr_stat_r[6], ddr_stat_r[5],
+ ddr_stat_r[4], ddr_stat_r[3],
+ ddr_stat_r[2], ddr_stat_r[1],
+ ddr_stat_r[0]};
+
+ reg is_started = 0;
+ reg[26:0] imd;
+ integer i;
+
+ always @* begin
+ ddr_valid_ns = `LOW;
+ exe_valid_ns = `LOW;
+ exe_uop_ns = {`EXE_UOP_WIDTH{`LOW}};
+ for(i = 0 ; i < 4 ; i = i + 1)
+ ddr_uop_ns[i] = {`DDR_UOP_WIDTH{`LOW}};
+ if(instr_valid) begin
+ // Decoding a DDR packet
+ if(instr[`DDR_OFFSET]) begin
+ ddr_valid_ns = `HIGH;
+ for(i = 0 ; i < 4 ; i = i + 1) begin: gen_ddr_uops
+ case(ddr_insts[i][`DDR_CODE_OFFSET +: 3])
+ `WRITE: begin
+ ddr_uop_ns[i][`IS_WRITE] = `HIGH;
+ ddr_uop_ns[i][`INC_CAR] = ddr_insts[i][`DEC_INC_CAR];
+ ddr_uop_ns[i][`INC_BAR] = ddr_insts[i][`DEC_INC_BAR];
+ ddr_uop_ns[i][`CAR+:4] = ddr_insts[i][`DEC_CAR+:4];
+ ddr_uop_ns[i][`BAR+:4] = ddr_insts[i][`DEC_BAR+:4];
+ ddr_uop_ns[i][`DO_AP] = ddr_insts[i][`DEC_AP];
+ ddr_uop_ns[i][`IS_BL4] = ddr_insts[i][`DEC_BL4];
+ end
+ `READ: begin
+ ddr_uop_ns[i][`IS_READ] = `HIGH;
+ ddr_uop_ns[i][`INC_CAR] = ddr_insts[i][`DEC_INC_CAR];
+ ddr_uop_ns[i][`INC_BAR] = ddr_insts[i][`DEC_INC_BAR];
+ ddr_uop_ns[i][`CAR+:4] = ddr_insts[i][`DEC_CAR+:4];
+ ddr_uop_ns[i][`BAR+:4] = ddr_insts[i][`DEC_BAR+:4];
+ ddr_uop_ns[i][`DO_AP] = ddr_insts[i][`DEC_AP];
+ ddr_uop_ns[i][`IS_BL4] = ddr_insts[i][`DEC_BL4];
+ end
+ `PRE: begin
+ ddr_uop_ns[i][`IS_PRE] = `HIGH;
+ ddr_uop_ns[i][`PRE_ALL] = ddr_insts[i][`DEC_PRE_ALL];
+ ddr_uop_ns[i][`INC_BAR] = ddr_insts[i][`DEC_INC_BAR];
+ ddr_uop_ns[i][`BAR+:4] = ddr_insts[i][`DEC_BAR+:4];
+ end
+ `ACT: begin
+ ddr_uop_ns[i][`IS_ACT] = `HIGH;
+ ddr_uop_ns[i][`INC_RAR] = ddr_insts[i][`DEC_INC_RAR];
+ ddr_uop_ns[i][`INC_BAR] = ddr_insts[i][`DEC_INC_BAR];
+ ddr_uop_ns[i][`RAR+:4] = ddr_insts[i][`DEC_RAR+:4];
+ ddr_uop_ns[i][`BAR+:4] = ddr_insts[i][`DEC_BAR+:4];
+ end
+ `ZQ: begin
+ ddr_uop_ns[i][`IS_ZQ] = `HIGH;
+ end
+ `REF: begin
+ ddr_uop_ns[i][`IS_REF] = `HIGH;
+ end
+ `NOP: begin
+ ddr_uop_ns[i][`IS_NOP] = `HIGH;
+ end
+ endcase
+ end
+ end
+ else if(instr[`SR_OFFSET]) begin
+ ddr_valid_ns = `HIGH;
+ case(instr[`FU_CODE_OFFSET])
+ `SRE: begin
+ ddr_uop_ns[0][`IS_SRE] = `HIGH;
+ ddr_uop_ns[1][`IS_NOP] = `HIGH;
+ ddr_uop_ns[2][`IS_NOP] = `HIGH;
+ ddr_uop_ns[3][`IS_NOP] = `HIGH;
+ end
+ `SRX: begin
+ ddr_uop_ns[0][`IS_SRX] = `HIGH;
+ ddr_uop_ns[1][`IS_NOP] = `HIGH;
+ ddr_uop_ns[2][`IS_NOP] = `HIGH;
+ ddr_uop_ns[3][`IS_NOP] = `HIGH;
+ end
+ endcase
+ end
+ else begin
+ exe_valid_ns = `HIGH;
+ // Decoding a branch instruction
+ if(instr[`BRANCH_OFFSET]) begin
+ case(instr[`FU_CODE_OFFSET +: 8])
+ `BL: begin
+ exe_uop_ns[`RS1 +: 4] = instr[`DEC_RS1 +: 4];
+ exe_uop_ns[`RS2 +: 4] = instr[`DEC_RS2 +: 4];
+ exe_uop_ns[`IMD +: 19] = instr[`DEC_BR_TGT_OFFSET +: 19];
+ exe_uop_ns[`IS_BL] = `HIGH;
+ end
+ `BEQ: begin
+ exe_uop_ns[`RS1 +: 4] = instr[`DEC_RS1 +: 4];
+ exe_uop_ns[`RS2 +: 4] = instr[`DEC_RS2 +: 4];
+ exe_uop_ns[`IMD +: 19] = instr[`DEC_BR_TGT_OFFSET +: 19];
+ exe_uop_ns[`IS_BEQ] = `HIGH;
+ end
+ `JUMP: begin
+ exe_uop_ns[`IMD +: 27] = instr[`DEC_JUMP_OFFSET +: 27];
+ exe_uop_ns[`IS_JUMP] = `HIGH;
+ end
+ `SLEEP: begin
+ exe_uop_ns[`IS_SLEEP] = `HIGH;
+ exe_uop_ns[`IMD +: 27] = instr[`DEC_SLEEP_OFFSET +: 27];
+ end
+ endcase
+ end
+ else if(instr[`MEM_OFFSET]) begin
+ case(instr[`FU_CODE_OFFSET +: 8])
+ `LD: begin
+ exe_uop_ns[`RS1 +: 4] = instr[`DEC_RS1 +: 4];
+ exe_uop_ns[`RT +: 4] = instr[`DEC_RT +: 4];
+ exe_uop_ns[`IMD +: 16] = instr[`DEC_IMD1 +: 16];
+ exe_uop_ns[`IS_MEM] = `HIGH;
+ exe_uop_ns[`IS_LD] = `HIGH;
+ exe_uop_ns[`HAS_IMD] = `HIGH;
+ end
+ `ST: begin
+ exe_uop_ns[`RS1 +: 4] = instr[`DEC_RS1 +: 4]; // The address base to write to
+ exe_uop_ns[`RS2 +: 4] = instr[`DEC_RT +: 4]; // The value to write
+ exe_uop_ns[`IMD +: 16] = instr[`DEC_IMD1 +: 16];
+ exe_uop_ns[`IS_MEM] = `HIGH;
+ exe_uop_ns[`IS_ST] = `HIGH;
+ exe_uop_ns[`HAS_IMD] = `HIGH;
+ end
+ endcase
+ end
+ else if(instr[`BW_OFFSET]) begin
+ case(instr[`FU_CODE_OFFSET +: 8])
+ `AND: begin
+ exe_uop_ns[`RS1 +: 4] = instr[`DEC_RS1 +: 4];
+ exe_uop_ns[`RS2 +: 4] = instr[`DEC_RS2 +: 4];
+ exe_uop_ns[`RT +: 4] = instr[`DEC_RT +: 4];
+ exe_uop_ns[`IS_AND] = `HIGH;
+ end
+ `OR: begin
+ exe_uop_ns[`RS1 +: 4] = instr[`DEC_RS1 +: 4];
+ exe_uop_ns[`RS2 +: 4] = instr[`DEC_RS2 +: 4];
+ exe_uop_ns[`RT +: 4] = instr[`DEC_RT +: 4];
+ exe_uop_ns[`IS_OR] = `HIGH;
+ end
+ `XOR: begin
+ exe_uop_ns[`RS1 +: 4] = instr[`DEC_RS1 +: 4];
+ exe_uop_ns[`RS2 +: 4] = instr[`DEC_RS2 +: 4];
+ exe_uop_ns[`RT +: 4] = instr[`DEC_RT +: 4];
+ exe_uop_ns[`IS_XOR] = `HIGH;
+ end
+ endcase
+ end
+ // Decoding a normal instruction
+ else begin
+ case(instr[`FU_CODE_OFFSET +: 8])
+ `ADD: begin
+ exe_uop_ns[`RS1 +: 4] = instr[`DEC_RS1 +: 4];
+ exe_uop_ns[`RS2 +: 4] = instr[`DEC_RS2 +: 4];
+ exe_uop_ns[`RT +: 4] = instr[`DEC_RT +: 4];
+ exe_uop_ns[`IS_ADD] = `HIGH;
+ end
+ `ADDI: begin
+ exe_uop_ns[`RS1 +: 4] = instr[`DEC_RS1 +: 4];
+ exe_uop_ns[`IMD +: 16] = instr[`DEC_IMD1 +: 16];
+ exe_uop_ns[`RT +: 4] = instr[`DEC_RT +: 4];
+ exe_uop_ns[`IS_ADD] = `HIGH;
+ exe_uop_ns[`HAS_IMD] = `HIGH;
+ end
+ `SUB: begin
+ exe_uop_ns[`RS1 +: 4] = instr[`DEC_RS1 +: 4];
+ exe_uop_ns[`RS2 +: 4] = instr[`DEC_RS2 +: 4];
+ exe_uop_ns[`RT +: 4] = instr[`DEC_RT +: 4];
+ exe_uop_ns[`IS_SUB] = `HIGH;
+ end
+ `SUBI: begin
+ exe_uop_ns[`RS1 +: 4] = instr[`DEC_RS1 +: 4];
+ exe_uop_ns[`IMD +: 16] = instr[`DEC_IMD1 +: 16];
+ exe_uop_ns[`RT +: 4] = instr[`DEC_RT +: 4];
+ exe_uop_ns[`IS_SUB] = `HIGH;
+ exe_uop_ns[`HAS_IMD] = `HIGH;
+ end
+ `MV: begin
+ exe_uop_ns[`RS1 +: 4] = instr[`DEC_RS1 +: 4];
+ exe_uop_ns[`RT +: 4] = instr[`DEC_RT +: 4];
+ exe_uop_ns[`IS_MOV] = `HIGH;
+ end
+ `SRC: begin
+ exe_uop_ns[`RS1 +: 4] = instr[`DEC_RS1 +: 4];
+ exe_uop_ns[`RT +: 4] = instr[`DEC_RT +: 4];
+ exe_uop_ns[`IS_SRC] = `HIGH;
+ end
+ `LI: begin
+ exe_uop_ns[`RT +: 4] = instr[`DEC_RT +: 4];
+ exe_uop_ns[`IS_LI] = `HIGH;
+ exe_uop_ns[`IMD +: 16] = instr[`DEC_IMD1 +: 16];
+ exe_uop_ns[`IMD2 +: 16]= instr[`DEC_IMD3 +: 16];
+ exe_uop_ns[`HAS_IMD] = `HIGH;
+ end
+ `LDWD: begin
+ exe_uop_ns[`RS1 +: 4] = instr[`DEC_RS1 +: 4];
+ // used to select word offset in wide write data register
+ exe_uop_ns[`RT +: 4] = instr[`DEC_WO +: 4];
+ exe_uop_ns[`IS_LDWD] = `HIGH;
+ end
+ `LDPC: begin
+ exe_uop_ns[`RS1 +: 4] = instr[`DEC_RS1 +: 4];
+ exe_uop_ns[`RT +: 4] = instr[`DEC_RT +: 4];
+ exe_uop_ns[`IS_LDPC] = `HIGH;
+ end
+ endcase
+ end
+ end
+ end
+ end
+
+ always @(posedge clk) begin
+
+ if(rst) begin
+ exe_pc_r <= {`IMEM_ADDR_WIDTH{`LOW}};
+ exe_uop_r <= {`EXE_UOP_WIDTH{`LOW}};
+ exe_valid_r <= `LOW;
+ ddr_valid_r <= `LOW;
+ for(i = 0 ; i < 4 ; i = i + 1)
+ ddr_uop_r[i] <= {`DDR_UOP_WIDTH{`LOW}};
+ is_started <= `LOW;
+ end
+ else begin
+ exe_uop_r <= exe_uop_ns;
+ exe_valid_r <= exe_valid_ns;
+ ddr_valid_r <= ddr_valid_ns;
+ for(i = 0 ; i < 4 ; i = i + 1)
+ ddr_uop_r[i] <= ddr_uop_ns[i];
+ exe_pc_r <= instr_pc;
+ end
+
+ if(~is_started) begin
+ for(i = 0 ; i < 7 ; i = i + 1) begin
+ ddr_stat_r[i] <= 0;
+ end
+ if(instr_pc == 1)
+ is_started <= 1;
+ end
+ else begin
+ ddr_stat_r[6] <= ddr_stat_r[6] + 1;
+ if(instr_valid) begin
+ if(instr[`DDR_OFFSET]) begin
+ for(i = 0 ; i < 4 ; i = i + 1) begin
+ case(ddr_insts[i][`DDR_CODE_OFFSET +: 3])
+ `WRITE:
+ ddr_stat_r[0] <= ddr_stat_r[0] + 1;
+ `READ:
+ ddr_stat_r[1] <= ddr_stat_r[1] + 1;
+ `PRE:
+ ddr_stat_r[2] <= ddr_stat_r[2] + 1;
+ `ACT:
+ ddr_stat_r[3] <= ddr_stat_r[3] + 1;
+ `ZQ:
+ ddr_stat_r[4] <= ddr_stat_r[4] + 1;
+ `REF:
+ ddr_stat_r[5] <= ddr_stat_r[5] + 1;
+ endcase
+ end
+ end
+ end
+ end
+ end
+
+
+
+endmodule
diff --git a/sources/hdl/verilog/diff_shift_reg.v b/sources/hdl/verilog/diff_shift_reg.v
new file mode 100644
index 0000000..ae39c3a
--- /dev/null
+++ b/sources/hdl/verilog/diff_shift_reg.v
@@ -0,0 +1,69 @@
+`timescale 1ns / 1ps
+//////////////////////////////////////////////////////////////////////////////////
+// Company:
+// Engineer:
+//
+// Create Date: 12/19/2018 01:07:06 PM
+// Design Name:
+// Module Name: diff_shift_reg
+// Project Name:
+// Target Devices:
+// Tool Versions:
+// Description:
+//
+// Dependencies:
+//
+// Revision:
+// Revision 0.01 - File Created
+// Additional Comments:
+//
+//////////////////////////////////////////////////////////////////////////////////
+
+
+module diff_shift_reg(
+ input clk,
+ input rst,
+
+ input flush,
+
+ input [15:0] in,
+ input in_valid,
+
+ output[511:0] out,
+ output out_valid
+ );
+
+ reg [4:0] ctr_r;
+ reg [511:0] shift_r;
+ reg valid_r;
+
+ always @(posedge clk) begin
+ if(rst) begin
+ shift_r <= 512'bX;
+ ctr_r <= 5'b0;
+ valid_r <= 1'b0;
+ end
+ else begin
+ if(flush) begin
+ valid_r <= `HIGH;
+ ctr_r <= 5'b0;
+ end
+ else begin
+ if(in_valid) begin
+ shift_r[16 +: 16*31] <= shift_r[0 +: 16*31];
+ shift_r[0 +: 16] <= in;
+ ctr_r <= ctr_r + 1;
+ end
+ else begin
+ ctr_r <= ctr_r;
+ shift_r <= shift_r;
+ end
+ valid_r <= (|ctr_r) && in_valid;
+ end
+ end
+ end
+
+ assign out_valid = valid_r;
+ assign out = shift_r;
+
+endmodule
diff --git a/sources/hdl/verilog/dll_toggler.v b/sources/hdl/verilog/dll_toggler.v
new file mode 100644
index 0000000..a6cb5bf
--- /dev/null
+++ b/sources/hdl/verilog/dll_toggler.v
@@ -0,0 +1,206 @@
+`include "parameters.vh"
+
+module dll_toggler #(parameter CKE_WIDTH = 1, RANK_WIDTH = 1, DQ_WIDTH = 64, DRAM_CMD_SLOTS = 4,
+ DATA_BUF_ADDR_WIDTH = 5, DBUF_WIDTH = 4, DQ_BURST = 8)
+
+(
+
+ input clk,
+ input rst,
+ input toggle_valid,
+ output reg dllt_done,
+
+ // ---------- DDR4 Signals ----------
+ output [7:0] mc_ACT_n, // DRAM ACT_n command signal for four DRAM clock cycles.
+ output [`ADDR_WIDTH*8-1:0] mc_ADR, // DRAM address. There are 8 bits in the fabric interface for each address bit on the DRAM bus.
+ output [`BANK_WIDTH*8-1:0] mc_BA, // DRAM bank address. 8 bits for each DRAM bank address.
+ output [`BG_WIDTH*8-1:0] mc_BG, // DRAM bank group address.
+ output [`CS_WIDTH*8-1:0] mc_CS_n, // DRAM CS_n
+
+ // NOTE: CKE is transmitted within another clock domain that is 4x faster than fabric clock.
+ output [`CKE_WIDTH*8-1:0] mc_CKE,
+ output clk_sel
+
+ );
+
+ wire [13:0] MR1_CONF = 14'b00001100000000;
+
+ reg [`ADDR_WIDTH*8-1:0] ADR_ns, ADR_r;
+ reg [`BANK_WIDTH*8-1:0] BA_ns, BA_r;
+ reg [`BG_WIDTH*8-1:0] BG_ns, BG_r;
+ reg [`CS_WIDTH*8-1:0] CS_n_ns, CS_n_r;
+ reg [`ODT_WIDTH*8-1:0] ODT_ns, ODT_r;
+ reg [`CKE_WIDTH*8-1:0] CKE_ns, CKE_r;
+
+ reg clk_sel_ns, clk_sel_r;
+
+ assign mc_ACT_n = {8{`HIGH}};
+ assign mc_ADR = ADR_r;
+ assign mc_BA = BA_r;
+ assign mc_BG = BG_r;
+ assign mc_CS_n = CS_n_r;
+ assign mc_CKE = CKE_r;
+ assign clk_sel = clk_sel_r;
+
+
+ // TODO we need to implement the following routine (TO TURN DLL OFF ONLY)
+ // 1 - Precharge all banks (IDLE STATE)
+ // 2 - Set MR1 A0 to 1 (DISABLE DLL), wait tMOD
+ // 3 - Enter self-refresh mode, wait until tCKSRE/tCKSRE_PAR
+ // 4 - Change clock frequency
+ // 5 - Wait at least tCKSRX (until clock signal stabilizes)
+ // 6 - Exit self-refresh mode, keep CKE high from now on
+ // if any ODT feature was enabled in self-ref. mode
+ // ODT signal must be LOW.
+ // 7 - Wait tXS and set mode registers to appropriate values
+ // (UG says that CL, CWL and WR may need to be updated),
+ // wait for another tMOD
+
+ localparam IDLE_S = 0;
+ localparam IDLE_WAIT_S = 1;
+ localparam SET_MR_1_S = 2;
+ localparam WAIT_MR_1_S = 3;
+ localparam ENTER_SELF_REF_S = 4;
+ localparam WAIT_ENTER_SELF_REF_S = 5;
+ localparam CHANGE_CLK_FREQ_S = 6;
+ localparam WAIT_CHANGE_CLK_FREQ_S = 7;
+ localparam EXIT_SELF_REF_S = 8;
+ localparam WAIT_EXIT_SELF_REF_S = 9;
+
+ localparam T_PRECHARGE = 5; // in terms of MC cycles (which is 4x less frequent than the DDR4)
+ localparam T_MOD = 24; // Max(24CK,15ns)
+ localparam T_CKSRE = 300; // Max(5CK,10ns)
+ localparam T_CKSRX = 300; // Max(5CK, 10ns) + additional room for clock to stabilize;
+ localparam T_XS = 1000;
+
+
+ reg[3:0] state_r, state_ns;
+
+ reg[9:0] wait_r, wait_ns;
+
+ integer adr_bit_i;
+
+ always @* begin
+ // Set bank and bank group signals
+ dllt_done = `LOW;
+ ADR_ns = {`ADDR_WIDTH*8{`HIGH}};
+ BG_ns = {`BG_WIDTH*8{`LOW}};
+ BA_ns = {`BANK_WIDTH*8{`LOW}};
+ CS_n_ns = {`CS_WIDTH*8{`HIGH}}; // by default we don't issue any commands
+ CKE_ns = CKE_r; // register this signal because it needs to be LOW during self-ref.
+ wait_ns = wait_r;
+ state_ns = state_r;
+ clk_sel_ns = clk_sel_r;
+ case (state_r)
+ IDLE_S: begin
+ if(toggle_valid) begin
+ CS_n_ns[1:0] = {2*`CS_WIDTH{`LOW}};
+ ADR_ns[`ADDR_WIDTH*8-3*8 +: 2] = {2{`LOW}}; // WE
+ ADR_ns[`ADDR_WIDTH*8-2*8 +: 2] = {2{`HIGH}}; // ~CAS
+ ADR_ns[`ADDR_WIDTH*8-8 +: 2] = {2{`LOW}}; // RAS
+ ADR_ns[10*8 +: 2] = {2{`HIGH}}; // Pre ALL
+ wait_ns = T_PRECHARGE;
+ state_ns = IDLE_WAIT_S;
+ end
+ end
+ IDLE_WAIT_S: begin
+ if(wait_r > 0)
+ wait_ns = wait_r - 1'b1;
+ else
+ state_ns = SET_MR_1_S;
+ end
+ SET_MR_1_S: begin
+ CS_n_ns[1:0] = {2*`CS_WIDTH{`LOW}};
+ ADR_ns[`ADDR_WIDTH*8-3*8 +: 2] = {2{`LOW}}; // WE
+ ADR_ns[`ADDR_WIDTH*8-2*8 +: 2] = {2{`LOW}}; // CAS
+ ADR_ns[`ADDR_WIDTH*8-8 +: 2] = {2{`LOW}}; // RAS
+ for(adr_bit_i = 0 ; adr_bit_i < 14 ; adr_bit_i = adr_bit_i + 1) begin
+ ADR_ns[adr_bit_i*8 +: 2] =
+ {2{MR1_CONF[adr_bit_i]}};
+ end
+ // Bank + Bank group bits indicate which register this MRS is writing to.
+ BA_ns[0 +: 2] = {2{`HIGH}}; // Select MR1
+ ADR_ns[0 +: 2] = {2{`LOW}}; // Set A0 to 0
+ state_ns = WAIT_MR_1_S;
+ wait_ns = T_MOD;
+ end
+ WAIT_MR_1_S: begin
+ if(wait_r > 0)
+ wait_ns = wait_r - 1'b1;
+ else
+ state_ns = ENTER_SELF_REF_S;
+ end
+ ENTER_SELF_REF_S: begin
+ CKE_ns = `LOW;
+ CS_n_ns[1:0] = {2*`CS_WIDTH{`LOW}};
+ ADR_ns[`ADDR_WIDTH*8-3*8 +: 2] = {2{`HIGH}}; // ~WE
+ ADR_ns[`ADDR_WIDTH*8-2*8 +: 2] = {2{`LOW}}; // CAS
+ ADR_ns[`ADDR_WIDTH*8-8 +: 2] = {2{`LOW}}; // RAS
+ state_ns = WAIT_ENTER_SELF_REF_S;
+ wait_ns = T_CKSRE;
+ end
+ WAIT_ENTER_SELF_REF_S: begin
+ if(wait_r > 0)
+ wait_ns = wait_r - 1'b1;
+ else begin
+ state_ns = CHANGE_CLK_FREQ_S;
+ end
+ end
+ CHANGE_CLK_FREQ_S: begin
+ clk_sel_ns = ~clk_sel_r;
+ wait_ns = T_CKSRX;
+ state_ns = WAIT_CHANGE_CLK_FREQ_S;
+ end
+ WAIT_CHANGE_CLK_FREQ_S: begin
+ if(wait_r > 0)
+ wait_ns = wait_r - 1'b1;
+ else begin
+ state_ns = EXIT_SELF_REF_S;
+ end
+ end
+ EXIT_SELF_REF_S: begin
+ CKE_ns = {`CKE_WIDTH*8{`HIGH}};
+ CS_n_ns[7:0] = {8*`CS_WIDTH{`HIGH}};
+ ADR_ns[`ADDR_WIDTH*8-3*8 +: 2] = {2{`HIGH}}; // ~WE
+ ADR_ns[`ADDR_WIDTH*8-2*8 +: 2] = {2{`HIGH}}; // CAS
+ ADR_ns[`ADDR_WIDTH*8-8 +: 2] = {2{`HIGH}}; // RAS
+ state_ns = WAIT_EXIT_SELF_REF_S;
+ wait_ns = T_XS;
+ end
+ WAIT_EXIT_SELF_REF_S: begin
+ CS_n_ns[7:0] = {8*`CS_WIDTH{`HIGH}};
+ if(wait_r > 0)
+ wait_ns = wait_r - 1'b1;
+ else begin
+ state_ns = IDLE_S;
+ dllt_done = `HIGH;
+ end
+ end
+ endcase
+
+ end
+
+ always @(posedge clk) begin
+ if(rst) begin
+ state_r <= IDLE_S;
+ wait_r <= `LOW;
+ clk_sel_r <= `LOW;
+ CKE_r <= {`CKE_WIDTH*8{`HIGH}};
+ ADR_r = {`ADDR_WIDTH*8{`LOW}};
+ BG_r = {`BG_WIDTH*8{`LOW}};
+ BA_r = {`BANK_WIDTH*8{`LOW}};
+ CS_n_r = {`CS_WIDTH*8{`HIGH}};
+ end
+ else begin
+ state_r <= state_ns;
+ wait_r <= wait_ns;
+ clk_sel_r <= clk_sel_ns;
+ CKE_r <= CKE_ns;
+ ADR_r <= ADR_ns;
+ BA_r <= BA_ns;
+ BG_r <= BG_ns;
+ CS_n_r <= CS_n_ns;
+ end
+ end
+
+endmodule
diff --git a/sources/hdl/verilog/exe_pipeline.v b/sources/hdl/verilog/exe_pipeline.v
new file mode 100644
index 0000000..e2111a3
--- /dev/null
+++ b/sources/hdl/verilog/exe_pipeline.v
@@ -0,0 +1,191 @@
+`include "parameters.vh"
+`include "encoding.vh"
+
+module exe_pipeline(
+ // common signals
+ input clk,
+ input rst,
+
+ // exe_pipeline <-> execution stage if
+ input exe_valid,
+ input [`EXE_UOP_WIDTH-1:0] exe_uop,
+ input [`IMEM_ADDR_WIDTH-1:0] exe_pc,
+
+ // branch unit if
+ output br_resolve,
+ output [`IMEM_ADDR_WIDTH-1:0] br_target,
+
+ // exe_pipeline <-> register file if
+ output wide_wen,
+ output [31:0] rf_wdata,
+ output rf_wen,
+ output [7:0] rf_raddr,
+ output [3:0] rf_waddr,
+ input [2*32-1:0] rf_rdata,
+ input [32*7-1:0] ddr_stat,
+
+ // exe_pipeline <-> scratchpad
+ output mem_wen,
+ output mem_ren,
+ output [9:0] mem_addr,
+ output [31:0] mem_wdata,
+ input [31:0] mem_rdata
+ );
+
+ // calculated at stage one, registers
+ reg s2_valid;
+ reg [`EXE_UOP_WIDTH-1:0] s2_uop;
+ reg [`IMEM_ADDR_WIDTH-1:0] s2_pc;
+ reg [3:0] s2_rs1;
+ reg [3:0] s2_rs2;
+ reg [3:0] s2_rt;
+ reg s2_wen;
+ reg s2_mem_ren;
+ reg s2_mem_wen;
+ reg s3_wen; // for loads
+ reg [3:0] s3_rt; // for loads
+ reg s2_wide_wen;
+ reg [31:0] s2_imd_r, s2_imd_ns;
+
+ // delayed branch resolution signals
+ // calculated at stage two, registers
+ reg s3_br_resolve;
+ reg [`IMEM_ADDR_WIDTH-1:0] s3_br_target;
+
+ // combinational elements
+ reg [31:0] s2_wdata;
+ wire [31:0] s2_rs1_data, s2_rs2_data;
+ reg [31:0] s2_mem_wdata;
+ reg [`IMEM_ADDR_WIDTH-1:0] fetch_pc;
+
+ assign wide_wen = s2_wide_wen;
+ assign rf_wdata = s3_wen ? mem_rdata : s2_wdata;
+ assign rf_wen = s2_wen || s3_wen;
+ assign rf_raddr[0+:4] = s2_rs1;
+ assign rf_raddr[4+:4] = s2_rs2;
+ assign rf_waddr = s3_wen ? s3_rt : s2_rt;
+
+ assign s2_rs1_data = rf_rdata[0+:32];
+ assign s2_rs2_data = rf_rdata[32+:32];
+ assign br_resolve = s3_br_resolve;
+ assign br_target = s3_br_target;
+
+ assign mem_addr = s2_rs1_data + s2_imd_r;
+ assign mem_wen = s2_mem_wen;
+ assign mem_ren = s2_mem_ren;
+ assign mem_wdata = s2_mem_wdata;
+
+ always @* begin
+ // stage one, decode immediate value
+ s2_mem_wen = `LOW;
+ s2_imd_ns = s2_imd_r;
+ fetch_pc = {`IMEM_ADDR_WIDTH{1'bX}};
+ s2_wdata = 32'bX;
+ s2_mem_wen = `LOW;
+ s2_mem_ren = `LOW;
+ if(exe_uop[`HAS_IMD]) begin
+ s2_imd_ns[15:0] = exe_uop[`IMD +: 16];
+ s2_imd_ns[31:16] = {16{`LOW}};
+ end
+ if(exe_uop[`IS_LI]) begin
+ s2_imd_ns[31:16] = exe_uop[`IMD2 +: 16];
+ end
+ if(exe_uop[`IS_BL] | exe_uop[`IS_BEQ]) begin
+ s2_imd_ns[31:0] = exe_uop[`IMD +: 19];
+ end
+ if(exe_uop[`IS_JUMP]) begin
+ s2_imd_ns[31:0] = exe_uop[`IMD +: 27];
+ end
+ // stage two, actual computation
+ if(s2_uop[`IS_ADD]) begin
+ if(s2_uop[`HAS_IMD])
+ s2_wdata = s2_rs1_data + s2_imd_r;
+ else
+ s2_wdata = s2_rs1_data + s2_rs2_data;
+ end
+ if(s2_uop[`IS_SUB]) begin
+ if(s2_uop[`HAS_IMD])
+ s2_wdata = s2_rs1_data - s2_imd_r;
+ else
+ s2_wdata = s2_rs1_data - s2_rs2_data;
+ end
+ if(s2_uop[`IS_MOV] || s2_uop[`IS_LDWD]) begin
+ s2_wdata = s2_rs1_data;
+ end
+ if(s2_uop[`IS_LI]) begin
+ s2_wdata = s2_imd_r;
+ end
+ if(s2_uop[`IS_LDPC]) begin
+ s2_wdata = ddr_stat[s2_rs1*32 +: 32];
+ end
+ if(s2_uop[`IS_SRC]) begin
+ s2_wdata[30:0] = s2_rs1_data[31:1];
+ s2_wdata[31] = s2_rs1_data[0];
+ end
+ // Bitwise ops
+ if(s2_uop[`IS_AND]) begin
+ s2_wdata = s2_rs1_data & s2_rs2_data;
+ end
+ if(s2_uop[`IS_OR]) begin
+ s2_wdata = s2_rs1_data | s2_rs2_data;
+ end
+ if(s2_uop[`IS_XOR]) begin
+ s2_wdata = s2_rs1_data ^ s2_rs2_data;
+ end
+ // mem unit
+ if(s2_uop[`IS_LD]) begin
+ s2_mem_ren = `HIGH;
+ end
+ if(s2_uop[`IS_ST]) begin
+ s2_mem_wdata = s2_rs2_data;
+ s2_mem_wen = `HIGH;
+ end
+
+ // branch unit
+ if(s2_uop[`IS_BL]) begin
+ if(s2_rs1_data < s2_rs2_data)
+ fetch_pc = s2_imd_r;
+ else // not taken
+ fetch_pc = s2_pc + 1;
+ end
+ if(s2_uop[`IS_BEQ]) begin
+ if(s2_rs1_data == s2_rs2_data)
+ fetch_pc = s2_imd_r;
+ else // not taken
+ fetch_pc = s2_pc + 1;
+ end
+ if(s2_uop[`IS_JUMP]) begin
+ fetch_pc = s2_imd_r;
+ end
+ if(s2_uop[`IS_SLEEP]) begin
+ // not implemented
+ // frontent/fetch handles api sleeps
+ end
+
+ end
+
+ always @(posedge clk) begin
+ // stage one, further decode
+ s2_valid <= exe_valid;
+ s2_uop <= exe_uop;
+ s2_pc <= exe_pc;
+ s2_rs1 <= exe_uop[`RS1 +: 4];
+ s2_rs2 <= exe_uop[`RS2 +: 4];
+ s2_rt <= exe_uop[`RT +: 4];
+ s2_imd_r <= s2_imd_ns;
+ s2_wen <= exe_uop[`IS_ADD] || exe_uop[`IS_SUB] ||
+ exe_uop[`IS_MOV] || exe_uop[`IS_LI] ||
+ exe_uop[`IS_LDWD] || exe_uop[`IS_SRC] ||
+ exe_uop[`IS_AND] || exe_uop[`IS_OR] ||
+ exe_uop[`IS_XOR] || exe_uop[`IS_LDPC];
+ s2_wide_wen <= exe_uop[`IS_LDWD];
+ // stage two, delayed branch signals
+ s3_br_resolve <= s2_valid && (s2_uop[`IS_BL] ||
+ s2_uop[`IS_BEQ] ||
+ s2_uop[`IS_JUMP]);
+ s3_br_target <= fetch_pc;
+ s3_wen <= s2_uop[`IS_LD]; // write path for loads
+ s3_rt <= s2_uop[`RT +: 4];
+ end
+
+endmodule
diff --git a/sources/hdl/verilog/execute_stage.v b/sources/hdl/verilog/execute_stage.v
new file mode 100644
index 0000000..0b690f8
--- /dev/null
+++ b/sources/hdl/verilog/execute_stage.v
@@ -0,0 +1,194 @@
+`include "parameters.vh"
+
+module execute_stage(
+
+ // common signals
+ input clk,
+ input rst,
+
+ // decode stage <-> execute stage if
+ input ddr_valid,
+ input exe_valid,
+ input [`DDR_UOP_WIDTH*4-1:0] ddr_uop,
+ input [`EXE_UOP_WIDTH-1:0] exe_uop,
+ input [`IMEM_ADDR_WIDTH-1:0] exe_pc,
+
+ // branch unit <-> fetch stage if
+ output br_resolve,
+ output [`IMEM_ADDR_WIDTH-1:0] br_target,
+
+ // execute <-> outer DDRX IP interface
+ output [3:0] ddr_write,
+ output [3:0] ddr_read,
+ output [3:0] ddr_pre,
+ output [3:0] ddr_act,
+ output [3:0] ddr_ref,
+ output [3:0] ddr_sre,
+ output [3:0] ddr_srx,
+ output [3:0] ddr_zq,
+ output [3:0] ddr_nop,
+ output [3:0] ddr_ap,
+ output [3:0] ddr_pall,
+ output [3:0] ddr_half_bl,
+ output [4*`BG_WIDTH-1:0] ddr_bg,
+ output [4*`BANK_WIDTH-1:0] ddr_bank,
+ output [4*`COL_WIDTH-1:0] ddr_col,
+ output [4*`ROW_WIDTH-1:0] ddr_row,
+ output [511:0] ddr_wdata,
+
+ // execute <-> reg file if
+ output rf_wide_wen,
+ output [3:0] rf_wide_offset,
+ input [32*8-1:0] rf_rdata,
+ output [32*8-1:0] rf_wdata,
+ output [7:0] rf_wen,
+ output [4*8-1:0] rf_raddr,
+ output [4*8-1:0] rf_waddr,
+ input [`COL_WIDTH-1:0] casr,
+ input [`BANK_WIDTH+`BG_WIDTH-1:0] basr,
+ input [`ROW_WIDTH-1:0] rasr,
+ input [511:0] wide_reg,
+
+ // update stride registers, wen is OH (3'b001 = update rasr)
+ output [31:0] srf_value,
+ output [2:0] srf_wen,
+ input [32*7-1:0] ddr_stat
+ );
+
+ reg s2_exe; // exe_pipeline has regfile ports
+
+ // ddr operations can optionally update
+ // registers. TODO when do we read the
+ // stride values?
+ wire [7:0] rf_wen_ddr;
+ wire [4*8-1:0] rf_waddr_ddr;
+ wire [32*8-1:0] rf_wdata_ddr;
+ wire [4*8-1:0] rf_raddr_ddr;
+
+ ddr_pipeline dp(
+ .clk(clk),
+ .rst(rst),
+
+ // execute <-> ddr_pipe if
+ .ddr_valid(ddr_valid),
+ .ddr_uop(ddr_uop),
+
+ // ddr_pipeline <-> outer DDRX IP interface
+ .ddr_write(ddr_write),
+ .ddr_read(ddr_read),
+ .ddr_pre(ddr_pre),
+ .ddr_act(ddr_act),
+ .ddr_ref(ddr_ref),
+ .ddr_sre(ddr_sre),
+ .ddr_srx(ddr_srx),
+ .ddr_zq(ddr_zq),
+ .ddr_nop(ddr_nop),
+ .ddr_ap(ddr_ap),
+ .ddr_pall(ddr_pall),
+ .ddr_half_bl(ddr_half_bl),
+ .ddr_bg(ddr_bg),
+ .ddr_bank(ddr_bank),
+ .ddr_col(ddr_col),
+ .ddr_row(ddr_row),
+ .ddr_wdata(ddr_wdata),
+ // ddr_pipeline <-> regfile interface
+ .update_en(rf_wen_ddr),
+ .update_ids(rf_waddr_ddr),
+ .update_vals(rf_wdata_ddr),
+ .casr(casr),
+ .basr(basr),
+ .rasr(rasr),
+ .reg_ids(rf_raddr_ddr), // registers we need to read
+ .reg_vals(rf_rdata), // register values
+ .wide_reg(wide_reg) // write data register
+ );
+
+
+ wire[31:0] rf_wdata_exe;
+ wire[7:0] rf_raddr_exe;
+ wire[3:0] rf_waddr_exe;
+ wire rf_wen_exe;
+ wire rf_wide_wen_exe;
+
+ wire mem_wen;
+ wire mem_ren;
+ wire[9:0] mem_addr;
+ wire[31:0] mem_wdata;
+ wire[31:0] mem_rdata;
+
+ exe_pipeline ep(
+ .clk(clk),
+ .rst(rst),
+
+ // exe_pipeline <-> execute stage if
+ .exe_valid(exe_valid),
+ .exe_uop(exe_uop),
+ .exe_pc(exe_pc),
+
+ // branch unit <-> fetch stage if
+ .br_resolve(br_resolve),
+ .br_target(br_target),
+
+ // exe_pipeline <-> regfile if
+ .wide_wen(rf_wide_wen_exe),
+ .rf_wdata(rf_wdata_exe),
+ .rf_wen(rf_wen_exe),
+ .rf_raddr(rf_raddr_exe),
+ .rf_rdata(rf_rdata[0 +: 32*2]),
+ .rf_waddr(rf_waddr_exe),
+
+ // exe_pipeline <-> data_mem
+ .mem_wen(mem_wen),
+ .mem_ren(mem_ren),
+ .mem_addr(mem_addr),
+ .mem_wdata(mem_wdata),
+ .mem_rdata(mem_rdata),
+ .ddr_stat(ddr_stat)
+
+ );
+`ifdef XILINX_SIMULATOR
+ reg_mem data_mem(
+ .addr(mem_addr),
+ .clk(clk),
+ .din(mem_wdata),
+ .dout(mem_rdata),
+ .en(mem_wen || mem_ren),
+ .we(mem_wen)
+ );
+`else
+ scratchpad data_mem(
+ .addra(mem_addr),
+ .clka(clk),
+ .dina(mem_wdata),
+ .douta(mem_rdata),
+ .ena(mem_wen || mem_ren),
+ .wea(mem_wen)
+ );
+`endif
+
+ wire exe_target_srf = rf_waddr_exe == 4'b0000 ||
+ rf_waddr_exe == 4'b0001 ||
+ rf_waddr_exe == 4'b0010;
+
+ assign rf_wide_wen = rf_wide_wen_exe;
+ assign rf_wide_offset = rf_waddr_exe;
+ assign rf_wdata[32 +: 7*32] = rf_wdata_ddr[32 +: 7*32];
+ assign rf_wdata[0 +: 32] = rf_wen_exe ? rf_wdata_exe : rf_wdata_ddr[0 +: 32];
+ assign rf_wen = (rf_wen_exe & ~rf_wide_wen_exe & ~exe_target_srf) | rf_wen_ddr;
+ assign rf_raddr[8 +: 6*4] = rf_raddr_ddr[8 +: 6*4];
+ assign rf_raddr[0 +: 2*4] = s2_exe ? rf_raddr_exe : rf_raddr_ddr[0 +: 2*8];
+ assign rf_waddr[4 +: 7*4] = rf_waddr_ddr[4 +: 7*4];
+ assign rf_waddr[0 +: 4] = rf_wen_exe ? rf_waddr_exe : rf_waddr_ddr[0 +: 4];
+
+ // First 3 register ids implicitly target stride registers
+ assign srf_wen[0] = rf_wen_exe & ~rf_wide_wen_exe & (rf_waddr_exe == 4'b0000);
+ assign srf_wen[1] = rf_wen_exe & ~rf_wide_wen_exe & (rf_waddr_exe == 4'b0001);
+ assign srf_wen[2] = rf_wen_exe & ~rf_wide_wen_exe & (rf_waddr_exe == 4'b0010);
+
+ assign srf_value = rf_wdata_exe;
+
+ always @(posedge clk) begin
+ s2_exe <= exe_valid;
+ end
+
+endmodule
diff --git a/sources/hdl/verilog/fetch_stage.v b/sources/hdl/verilog/fetch_stage.v
new file mode 100644
index 0000000..bd72fe5
--- /dev/null
+++ b/sources/hdl/verilog/fetch_stage.v
@@ -0,0 +1,147 @@
+`include "parameters.vh"
+
+module fetch_stage(
+ // common signals
+ input clk,
+ input rst,
+
+ // other control signals
+ output softmc_end,
+ output [11:0] read_size,
+ output reg read_seq_incoming,
+ input [11:0] buffer_space,
+
+ // branch unit <-> fetch stage interface
+ input br_resolve,
+ input [`IMEM_ADDR_WIDTH-1:0] br_target,
+
+ // fetch stage <-> frontend interface
+ output [`IMEM_ADDR_WIDTH-1:0] addr_out,
+ output valid_out,
+ input [`INSTR_WIDTH-1:0] data_in,
+ input valid_in,
+ input [`IMEM_ADDR_WIDTH-1:0] addr_in,
+ input ready_out, // frontend is ready for a valid request
+
+ // fetch stage <-> decode stage interface
+ output [`INSTR_WIDTH-1:0] instr,
+ output [`IMEM_ADDR_WIDTH-1:0] instr_pc,
+ output instr_valid
+ );
+
+ wire inst_is_br, is_end, is_ddr_start, need_flush, is_sleep;
+
+ reg [31:0] sleep_ctr_r, sleep_ctr_ns;
+
+ localparam WAIT_RESOLVE_S = 0;
+ localparam FETCH_NEXT_LINE_S = 1;
+ localparam WAIT_BUFFER_SPACE_S = 2;
+ localparam WAIT_SLEEP_S = 3;
+
+ reg [2:0] state_r, state_ns;
+
+ // kind of confusing but these PCs map to
+ // an instruction instead of to a byte.
+ // i.e. each PC addresses an instruction.
+ reg [`IMEM_ADDR_WIDTH-1:0] pc_r, pc_ns;
+
+ // register outputs, decode will receive
+ // stuff we've received with one cycle latency
+ // i.e. marks the end of fetch_stage cycle
+ reg [`IMEM_ADDR_WIDTH-1:0] instr_pc_r, instr_pc_ns;
+ reg [`INSTR_WIDTH-1:0] instr_r, instr_ns;
+ reg instr_valid_r, instr_valid_ns;
+
+ pre_decode pdec(
+ .buffer_space(buffer_space),
+ .read_size(read_size),
+ .instruction(state_r == WAIT_BUFFER_SPACE_S ? instr_r : data_in),
+ .is_branch(inst_is_br),
+ .is_end(is_end),
+ .is_ddr_start(is_ddr_start),
+ .need_flush(need_flush),
+ .is_sleep(is_sleep)
+ );
+
+ assign instr = instr_r;
+ assign instr_valid = instr_valid_r;
+ assign instr_pc = instr_pc_r;
+
+ // request instr @ pc from frontend
+ assign valid_out = ready_out && (state_r == FETCH_NEXT_LINE_S) && ~need_flush && ~(valid_in && is_sleep);
+ assign addr_out = pc_r;
+
+ assign softmc_end = is_end && valid_in && (state_r == FETCH_NEXT_LINE_S);
+
+ always @* begin
+ sleep_ctr_ns = sleep_ctr_r;
+ state_ns = state_r;
+ pc_ns = pc_r;
+ instr_ns = instr_r;
+ instr_pc_ns = instr_pc_r;
+ instr_valid_ns = ~is_end && valid_in && (state_r == FETCH_NEXT_LINE_S)
+ && ~is_ddr_start;
+ read_seq_incoming = `LOW;
+ case(state_r)
+ WAIT_RESOLVE_S: begin
+ if(br_resolve) begin
+ state_ns = FETCH_NEXT_LINE_S;
+ pc_ns = br_target;
+ end
+ end
+ FETCH_NEXT_LINE_S: begin
+ if(ready_out && valid_out)
+ pc_ns = pc_r + 1;
+ if(valid_in) begin
+ instr_ns = data_in;
+ instr_pc_ns = addr_in;
+ if(is_sleep) begin
+ sleep_ctr_ns = data_in[31:0];
+ state_ns = WAIT_SLEEP_S;
+ end
+ if(is_ddr_start && ~need_flush && (|data_in[9:0]))
+ read_seq_incoming = `HIGH;
+ if(inst_is_br && ~is_sleep) // we don't have the ability to perform well
+ state_ns = WAIT_RESOLVE_S;
+ else if(is_end)
+ pc_ns = {`IMEM_ADDR_WIDTH{`LOW}};
+ else if(need_flush) begin
+ state_ns = WAIT_BUFFER_SPACE_S;
+ pc_ns = addr_in; // register the info packet
+ // as the next instruction to fetch
+ end
+ end
+ end
+ WAIT_BUFFER_SPACE_S: begin
+ if(~need_flush) begin
+ state_ns = FETCH_NEXT_LINE_S;
+ end
+ end
+ WAIT_SLEEP_S: begin
+ sleep_ctr_ns = sleep_ctr_r - 1;
+ if(sleep_ctr_r == 32'b1)
+ state_ns = FETCH_NEXT_LINE_S;
+ end
+ endcase
+ end
+
+ always @(posedge clk) begin
+ if (rst) begin
+ pc_r <= {`IMEM_ADDR_WIDTH{`LOW}};
+ state_r <= FETCH_NEXT_LINE_S;
+ instr_valid_r <= `LOW;
+ instr_r <= {`INSTR_WIDTH{`LOW}};
+ instr_pc_r <= {`IMEM_ADDR_WIDTH{`LOW}};
+ sleep_ctr_r <= {32{`LOW}};
+ end
+ else begin
+ state_r <= state_ns;
+ pc_r <= pc_ns;
+ instr_r <= instr_ns;
+ instr_pc_r <= instr_pc_ns;
+ instr_valid_r <= instr_valid_ns;
+ sleep_ctr_r <= sleep_ctr_ns;
+ end
+ end
+
+endmodule
diff --git a/sources/hdl/verilog/frontend.v b/sources/hdl/verilog/frontend.v
new file mode 100644
index 0000000..9225bd9
--- /dev/null
+++ b/sources/hdl/verilog/frontend.v
@@ -0,0 +1,237 @@
+`include "parameters.vh"
+/*
+ * This module is responsible for the interface
+ * between XDMA IP and the fetch stage.
+ * This module encapsulates a X KiB BRAM which
+ * is used as an instruction memory.
+ */
+module frontend#(parameter SIM_MEM = "false")(
+ // common signals
+ input clk,
+ input rst,
+
+ // other control signals
+ input softmc_fin,
+ output user_rst,
+ input init_calib_complete,
+ output reg rbe_switch_mode,
+ output reg dllt_begin,
+ output frontend_ready,
+
+ // frontend <-> fetch stage interface
+ input [`IMEM_ADDR_WIDTH-1:0] addr_in,
+ input valid_in,
+ output [`INSTR_WIDTH-1:0] data_out,
+ output valid_out,
+ output [`IMEM_ADDR_WIDTH-1:0] addr_out,
+ output ready_in,
+
+ // frontend <-> xdma interface
+ input [`XDMA_AXI_DATA_WIDTH-1:0] h2c_tdata_0,
+ input h2c_tlast_0,
+ input h2c_tvalid_0,
+ output h2c_tready_0,
+ input [`XDMA_AXI_DATA_WIDTH/8-1:0] h2c_tkeep_0,
+
+ // maintenance signals
+ output per_rd_init,
+ output per_zq_init,
+ output per_ref_init
+ );
+
+ reg[31:0] delay_fin;
+
+ always @(posedge clk) begin
+ if(rst || user_rst)
+ delay_fin <= 32'b0;
+ else
+ delay_fin[1+:31] <= delay_fin[0+:31];
+ delay_fin[0] <= softmc_fin;
+ end
+
+ assign frontend_ready = delay_fin[31];
+
+ wire imem_wr_en, imem_rd_en;
+ wire [`IMEM_ADDR_WIDTH-1:0] imem_addr;
+ wire [`INSTR_WIDTH-1:0] imem_wr_data, imem_rd_data;
+
+ generate
+ if(SIM_MEM == "true") begin
+ instr_blk_mem_sim imem(
+ .addra(imem_addr),
+ .clka(clk),
+ .dina(imem_wr_data),
+ .douta(imem_rd_data),
+ .ena(imem_rd_en || imem_wr_en),
+ .wea(imem_wr_en)
+ );
+ end
+ else begin
+ instr_blk_mem imem(
+ .addra(imem_addr),
+ .clka(clk),
+ .dina(imem_wr_data),
+ .douta(imem_rd_data),
+ .ena(imem_rd_en || imem_wr_en),
+ .wea(imem_wr_en)
+ );
+ end
+ endgenerate
+
+ wire [`INSTR_WIDTH-1:0] maint_inst;
+ wire maint_valid;
+ wire [`IMEM_ADDR_WIDTH-1:0] maint_addr;
+ wire maint_req;
+ reg maint_ack;
+ wire maint_process;
+ wire program_process;
+ reg aref_en;
+ reg aref_en_valid;
+
+ maintenance_controller maint_ctrl
+ (
+ .clk(clk),
+ .rst(rst | user_rst),
+
+ .init_calib_complete(init_calib_complete),
+ .softmc_fin(softmc_fin),
+
+ .aref_en(aref_en),
+ .aref_en_valid(aref_en_valid),
+ .maint_req(maint_req),
+ .maint_ack(maint_ack),
+ .per_rd_init(per_rd_init),
+ .per_zq_init(per_zq_init),
+ .per_ref_init(per_ref_init),
+ .maint_process(maint_process),
+ .program_process(program_process),
+
+ .in_addr(addr_in),
+ .in_valid(valid_in),
+
+ .out_data(maint_inst),
+ .out_valid(maint_valid),
+ .out_addr(maint_addr)
+ );
+
+ localparam IDLE_S = 2'd0;
+ localparam INIT_MEM_S = 2'd1;
+ localparam EXECUTE_S = 2'd2;
+
+ reg [1:0] state_r, state_ns;
+
+ reg [4:0] rst_ctr_ns, rst_ctr_r;
+ reg [`IMEM_ADDR_WIDTH-1:0] xfer_ctr_r, xfer_ctr_ns;
+ reg [`IMEM_RD_LATENCY-1:0] valid_out_sr;
+ reg [(`IMEM_RD_LATENCY * `IMEM_ADDR_WIDTH)-1:0] addr_out_sr;
+
+ assign user_rst = (|rst_ctr_r);
+
+ // imem <-> xdma interface
+ // TODO do we need tkeep?
+ assign h2c_tready_0 = state_r == INIT_MEM_S;
+ assign imem_wr_en = h2c_tvalid_0 && (state_r == INIT_MEM_S);
+ assign imem_wr_data = h2c_tdata_0[`INSTR_WIDTH-1:0];
+ assign imem_addr = state_r == INIT_MEM_S ? xfer_ctr_r : addr_in;
+ // imem <-> pipeline interface
+ assign imem_rd_en = valid_in && (program_process);
+ assign data_out = program_process ? imem_rd_data : maint_inst;
+ assign valid_out = program_process ? valid_out_sr[0] : maint_valid;
+ assign addr_out = program_process ? addr_out_sr[`IMEM_ADDR_WIDTH-1:0] : maint_addr;
+
+ generate
+ if(SIM_MEM=="false")
+ assign ready_in = state_r == EXECUTE_S;
+ else
+ assign ready_in = state_r == EXECUTE_S && ~rst;
+ endgenerate
+ assign program_process = (state_r == EXECUTE_S) && ~maint_process;
+
+ always @* begin
+ aref_en_valid = `LOW;
+ aref_en = `LOW;
+ state_ns = state_r;
+ xfer_ctr_ns = xfer_ctr_r;
+ rst_ctr_ns = {5{`LOW}};
+ maint_ack = `LOW;
+ rbe_switch_mode = `LOW;
+ dllt_begin = `LOW;
+ case (state_r)
+ IDLE_S: begin
+ if(~((|delay_fin) || softmc_fin)) begin
+ if(h2c_tvalid_0)
+ state_ns = INIT_MEM_S;
+ else begin
+ if(maint_req) begin
+ maint_ack = `HIGH;
+ state_ns = EXECUTE_S;
+ end
+ end
+ end
+ end
+ INIT_MEM_S: begin
+ if(h2c_tvalid_0) begin
+ if(h2c_tdata_0[`INSTR_WIDTH]) //indicates a reset
+ rst_ctr_ns = {5{1'b1}};
+ else if(h2c_tdata_0[`INSTR_WIDTH+1]) // indicate switch between readback modes
+ rbe_switch_mode = `HIGH;
+ else if(h2c_tdata_0[`INSTR_WIDTH+2]) // indicate dll toggle off WIP
+ dllt_begin = `HIGH;
+ else if(h2c_tdata_0[`INSTR_WIDTH+3]) begin // enable-disable autoref
+ aref_en_valid = `HIGH;
+ aref_en = h2c_tdata_0[0];
+ state_ns = IDLE_S;
+ end
+ else begin
+ xfer_ctr_ns = xfer_ctr_r + 1;
+ if(h2c_tlast_0) begin
+ state_ns = EXECUTE_S;
+ xfer_ctr_ns = {`IMEM_ADDR_WIDTH{`LOW}};
+ end
+ end
+ end
+ end
+ EXECUTE_S: begin
+ if(h2c_tvalid_0) begin
+ if(h2c_tdata_0[`INSTR_WIDTH]) //indicates a reset
+ rst_ctr_ns = {5{1'b1}};
+ end
+ if(softmc_fin)
+ state_ns = IDLE_S;
+ end
+ endcase
+
+ end
+
+ always @(posedge clk) begin
+ if(rst || (|rst_ctr_r)) begin
+ if(SIM_MEM == "false")
+ state_r <= IDLE_S;
+ else
+ state_r <= EXECUTE_S;
+ xfer_ctr_r <= {`IMEM_ADDR_WIDTH{`LOW}};
+ valid_out_sr <= {`IMEM_RD_LATENCY{`LOW}};
+ addr_out_sr <= 0;
+ if(rst_ctr_r > 0)
+ rst_ctr_r <= rst_ctr_r - 1;
+ else
+ rst_ctr_r <= 0;
+ end
+ else begin
+ state_r <= state_ns;
+ xfer_ctr_r <= xfer_ctr_ns;
+ rst_ctr_r <= rst_ctr_ns;
+ // compute when we should assert valid data to
+ // fetch stage.
+ valid_out_sr[`IMEM_RD_LATENCY-1] <= valid_in && (state_r == EXECUTE_S);
+ addr_out_sr[`IMEM_RD_LATENCY*`IMEM_ADDR_WIDTH-1 :
+ (`IMEM_RD_LATENCY-1)*`IMEM_ADDR_WIDTH] <= addr_in;
+ `ifdef IMEM_SR
+ valid_out_sr[`IMEM_RD_LATENCY-1:0] <= valid_out_sr >> 1;
+ addr_out_sr[(`IMEM_RD_LATENCY-1)*`IMEM_ADDR_WIDTH-1:0]
+ <= addr_out_sr >> `IMEM_ADDR_WIDTH;
+ `endif
+ end
+ end
+endmodule
+
diff --git a/sources/hdl/verilog/maintenance_controller.v b/sources/hdl/verilog/maintenance_controller.v
new file mode 100644
index 0000000..9354d17
--- /dev/null
+++ b/sources/hdl/verilog/maintenance_controller.v
@@ -0,0 +1,265 @@
+`include "parameters.vh"
+
+module maintenance_controller#(parameter tCK = 1500)(
+
+ input clk,
+ input rst,
+
+ input init_calib_complete,
+ input softmc_fin,
+
+ input aref_en,
+ input aref_en_valid,
+
+ input maint_ack,
+ output maint_req,
+ output per_rd_init,
+ output per_zq_init,
+ output per_ref_init,
+ output maint_process,
+ input program_process,
+
+ input [`IMEM_ADDR_WIDTH-1:0] in_addr,
+ input in_valid,
+
+ output [`INSTR_WIDTH-1:0] out_data,
+ output reg out_valid,
+ output [`IMEM_ADDR_WIDTH-1:0] out_addr
+ );
+
+ wire zq_ack, per_rd_ack, ref_ack;
+ reg zq_request, zq_process;
+ reg per_rd_request, per_rd_process;
+ reg pr_ref_request, pr_ref_process;
+
+ wire [`INSTR_WIDTH-1 : 0] pr_read_out, pr_zq_out, pr_ref_out;
+
+ assign maint_req = per_rd_request | zq_request | pr_ref_request;
+ assign out_addr = {`IMEM_ADDR_WIDTH{`HIGH}};
+ assign out_data = zq_process ? pr_zq_out : per_rd_process ? pr_read_out : pr_ref_out;
+ assign per_ref_init = maint_ack && pr_ref_request && ~per_rd_request && ~zq_request;
+ assign per_rd_init = maint_ack && per_rd_request && ~zq_request;
+ assign per_zq_init = maint_ack && zq_request;
+ assign maint_process = zq_process || per_rd_process || pr_ref_process;
+
+ assign zq_ack = softmc_fin && zq_process;
+ assign per_rd_ack = softmc_fin && per_rd_process;
+ assign ref_ack = softmc_fin && pr_ref_process;
+
+ pr_read_mem prm
+ (
+ .addra(in_addr[3:0]),
+ .clka(clk),
+ .douta(pr_read_out),
+ .dina(64'bX),
+ .wea(`LOW),
+ .ena(in_valid && per_rd_process)
+ );
+
+ zq_calib_mem pzm
+ (
+ .addra(in_addr[5:0]),
+ .clka(clk),
+ .douta(pr_zq_out),
+ .dina(64'bX),
+ .wea(`LOW),
+ .ena(in_valid && zq_process)
+ );
+
+ pr_ref_mem prefm
+ (
+ .addra(in_addr[6:0]),
+ .clka(clk),
+ .douta(pr_ref_out),
+ .dina(64'bX),
+ .wea(`LOW),
+ .ena(in_valid && pr_ref_process)
+ );
+
+ always @(posedge clk) begin
+ if(rst) begin
+ zq_process <= `LOW;
+ per_rd_process <= `LOW;
+ out_valid <= `LOW;
+ pr_ref_process <= `LOW;
+ end
+ else begin
+ if(softmc_fin) begin
+ if(zq_process)
+ zq_process <= `LOW;
+ if(per_rd_process)
+ per_rd_process <= `LOW;
+ if(pr_ref_process)
+ pr_ref_process <= `LOW;
+ out_valid <= `LOW;
+ end
+ else if(maint_ack) begin
+ if(zq_request)
+ zq_process <= `HIGH;
+ else if(per_rd_request)
+ per_rd_process <= `HIGH;
+ else if(pr_ref_request)
+ pr_ref_process <= `HIGH;
+ out_valid <= `LOW;
+ end
+ else begin
+ zq_process <= zq_process;
+ per_rd_process <= per_rd_process;
+ pr_ref_process <= pr_ref_process;
+ if(maint_process)
+ out_valid <= in_valid;
+ else
+ out_valid <= `LOW;
+ end
+ end
+ end
+
+ // Maintenance control logic
+ // Set request bits according to timers
+
+ localparam MAINT_PRESCALER_PERIOD = 500_000; // .5 us
+
+ function integer clogb2 (input integer size); // ceiling logb2
+ begin
+ size = size - 1;
+ for (clogb2=1; size>1; clogb2=clogb2+1)
+ size = size >> 1;
+ end
+ endfunction // clogb2
+
+ localparam MAINT_PRESCALER_DIV = MAINT_PRESCALER_PERIOD/(tCK * 4); // softmc is clocked 4 times slower than the memory interface
+ localparam MAINT_PRESCALER_WIDTH = clogb2(MAINT_PRESCALER_DIV + 1);
+ localparam ONE = 1;
+
+ reg maint_prescaler_tick_r_lcl;
+ reg [MAINT_PRESCALER_WIDTH-1:0] maint_prescaler_r;
+ reg [MAINT_PRESCALER_WIDTH-1:0] maint_prescaler_ns;
+
+ wire maint_prescaler_tick_ns = (maint_prescaler_r == ONE[MAINT_PRESCALER_WIDTH-1:0]);
+
+ always @(/*AS*/init_calib_complete or maint_prescaler_r
+ or maint_prescaler_tick_ns) begin
+ maint_prescaler_ns = maint_prescaler_r;
+ if (~init_calib_complete || maint_prescaler_tick_ns)
+ maint_prescaler_ns = MAINT_PRESCALER_DIV[MAINT_PRESCALER_WIDTH-1:0];
+ else if (|maint_prescaler_r)
+ maint_prescaler_ns = maint_prescaler_r - ONE[MAINT_PRESCALER_WIDTH-1:0];
+ end
+
+ always @(posedge clk) maint_prescaler_r <= maint_prescaler_ns;
+
+ always @(posedge clk) maint_prescaler_tick_r_lcl <= maint_prescaler_tick_ns;
+
+ localparam tPRDI = 1_000_000;
+ localparam PERIODIC_RD_TIMER_DIV = tPRDI/MAINT_PRESCALER_PERIOD;
+ localparam PERIODIC_RD_TIMER_WIDTH = clogb2(PERIODIC_RD_TIMER_DIV + /*idle state*/ 1);
+
+ reg [PERIODIC_RD_TIMER_WIDTH-1:0] periodic_rd_timer_r, periodic_rd_timer;
+
+ always @* begin
+ periodic_rd_timer = periodic_rd_timer_r;
+
+ if(~init_calib_complete) begin
+ periodic_rd_timer = {PERIODIC_RD_TIMER_WIDTH{1'b0}};
+ end
+ else if (per_rd_ack || program_process) begin
+ periodic_rd_timer = PERIODIC_RD_TIMER_DIV[0+:PERIODIC_RD_TIMER_WIDTH];
+ end
+ else if (|periodic_rd_timer_r && maint_prescaler_tick_r_lcl) begin
+ periodic_rd_timer = periodic_rd_timer_r - ONE[0+:PERIODIC_RD_TIMER_WIDTH];
+ end
+ end //always
+
+ wire periodic_rd_timer_one = maint_prescaler_tick_r_lcl && (periodic_rd_timer_r == ONE[0+:PERIODIC_RD_TIMER_WIDTH]);
+
+ wire periodic_rd_request = ~rst && (/*((PERIODIC_RD_TIMER_DIV != 0) && ~dfi_init_complete) ||*/
+ (~per_rd_ack && (per_rd_request || periodic_rd_timer_one)));
+
+ always @(posedge clk) begin
+ if(~init_calib_complete)
+ periodic_rd_timer_r <= PERIODIC_RD_TIMER_DIV[0+:PERIODIC_RD_TIMER_WIDTH];
+ else
+ periodic_rd_timer_r <= periodic_rd_timer;
+ per_rd_request <= periodic_rd_request;
+ end //always
+
+ // ZQ timebase. Nominally 128 mS
+ localparam MAINT_PRESCALER_PERIOD_NS = MAINT_PRESCALER_PERIOD / 1000;
+ localparam tZQI = 128_000_000;
+ localparam ZQ_TIMER_DIV = tZQI/MAINT_PRESCALER_PERIOD_NS;
+ localparam ZQ_TIMER_WIDTH = clogb2(ZQ_TIMER_DIV + 1);
+
+ generate
+ begin : zq_cntrl
+ reg zq_tick = 1'b0;
+
+ if (ZQ_TIMER_DIV !=0) begin : zq_timer
+ reg [ZQ_TIMER_WIDTH-1:0] zq_timer_r;
+ reg [ZQ_TIMER_WIDTH-1:0] zq_timer_ns;
+
+ always @(/*AS*/init_calib_complete or maint_prescaler_tick_r_lcl or zq_tick or zq_timer_r or program_process) begin
+ zq_timer_ns = zq_timer_r;
+ if (~init_calib_complete || zq_tick || program_process)
+ zq_timer_ns = ZQ_TIMER_DIV[ZQ_TIMER_WIDTH-1:0];
+ else if (|zq_timer_r && maint_prescaler_tick_r_lcl)
+ zq_timer_ns = zq_timer_r - ONE[ZQ_TIMER_WIDTH-1:0];
+ end
+
+ always @(posedge clk) zq_timer_r <= zq_timer_ns;
+
+ always @(/*AS*/maint_prescaler_tick_r_lcl or zq_timer_r)
+ zq_tick = (zq_timer_r == ONE[ZQ_TIMER_WIDTH-1:0] && maint_prescaler_tick_r_lcl);
+ end // zq_timer
+
+ // ZQ request. Set request with timer tick, and when exiting PHY init. Never
+ // request if ZQ_TIMER_DIV == 0.
+ begin : zq_request_logic
+ wire zq_clear = zq_ack;
+ reg zq_request_r;
+ wire zq_request_ns = ~rst && ((~init_calib_complete && (ZQ_TIMER_DIV != 0)) ||
+ (zq_request_r && ~zq_clear) || zq_tick);
+
+ always @(posedge clk) zq_request_r <= zq_request_ns;
+
+ always @(/*AS*/init_calib_complete or zq_request_r)
+ zq_request = init_calib_complete && zq_request_r;
+ end // zq_request_logic
+ end
+ endgenerate
+
+ localparam tAREF = 7_800;
+ localparam PERIODIC_REF_TIMER_DIV = tAREF/MAINT_PRESCALER_PERIOD_NS;
+ localparam PERIODIC_REF_TIMER_WIDTH = clogb2(PERIODIC_REF_TIMER_DIV + /*idle state*/ 1);
+
+ reg [PERIODIC_REF_TIMER_WIDTH-1:0] autoref_timer_r, autoref_timer;
+ reg aref_switch_ns, aref_switch_r;
+
+ always @* begin
+ aref_switch_ns = aref_en_valid ? aref_en : aref_switch_r;
+ pr_ref_request = `LOW;
+ autoref_timer = autoref_timer_r;
+ if(~aref_switch_r || ~init_calib_complete)
+ autoref_timer = PERIODIC_REF_TIMER_DIV[PERIODIC_REF_TIMER_WIDTH-1:0];
+ else begin
+ if(autoref_timer_r > 1 && maint_prescaler_tick_r_lcl) // you were here
+ autoref_timer = autoref_timer_r - ONE[PERIODIC_REF_TIMER_WIDTH-1:0];
+ else if(autoref_timer_r == 1) begin
+ pr_ref_request = `HIGH;
+ if(ref_ack)
+ autoref_timer = PERIODIC_REF_TIMER_DIV[PERIODIC_REF_TIMER_WIDTH-1:0];
+ end
+ end
+ end
+
+ always @(posedge clk) begin
+ if(rst) begin
+ aref_switch_r <= `LOW;
+ autoref_timer_r = PERIODIC_REF_TIMER_DIV[PERIODIC_REF_TIMER_WIDTH-1:0];
+ end
+ else begin
+ aref_switch_r <= aref_switch_ns;
+ autoref_timer_r <= autoref_timer;
+ end
+ end
+
+endmodule
diff --git a/sources/hdl/verilog/pop_count4.v b/sources/hdl/verilog/pop_count4.v
new file mode 100644
index 0000000..80bea46
--- /dev/null
+++ b/sources/hdl/verilog/pop_count4.v
@@ -0,0 +1,68 @@
+`timescale 1ns / 1ps
+//////////////////////////////////////////////////////////////////////////////////
+// Company:
+// Engineer:
+//
+// Create Date: 12/19/2018 10:51:52 AM
+// Design Name:
+// Module Name: pop_count4
+// Project Name:
+// Target Devices:
+// Tool Versions:
+// Description:
+//
+// Dependencies:
+//
+// Revision:
+// Revision 0.01 - File Created
+// Additional Comments:
+//
+//////////////////////////////////////////////////////////////////////////////////
+
+
+module pop_count4(
+ input [3:0] in,
+ output [2:0] out
+ );
+
+ reg [2:0] out_r;
+
+ always @* begin
+ out_r = 3'd0;
+ case(in)
+ 4'b0000:
+ out_r = 3'd0;
+ 4'b0001:
+ out_r = 3'd1;
+ 4'b0010:
+ out_r = 3'd1;
+ 4'b0011:
+ out_r = 3'd2;
+ 4'b0100:
+ out_r = 3'd1;
+ 4'b0101:
+ out_r = 3'd2;
+ 4'b0110:
+ out_r = 3'd2;
+ 4'b0111:
+ out_r = 3'd3;
+ 4'b1000:
+ out_r = 3'd1;
+ 4'b1001:
+ out_r = 3'd2;
+ 4'b1010:
+ out_r = 3'd2;
+ 4'b1011:
+ out_r = 3'd3;
+ 4'b1100:
+ out_r = 3'd2;
+ 4'b1101:
+ out_r = 3'd3;
+ 4'b1111:
+ out_r = 3'd4;
+ endcase
+ end
+
+ assign out = out_r;
+
+endmodule
diff --git a/sources/hdl/verilog/pre_decode.v b/sources/hdl/verilog/pre_decode.v
new file mode 100644
index 0000000..7621b24
--- /dev/null
+++ b/sources/hdl/verilog/pre_decode.v
@@ -0,0 +1,39 @@
+`include "parameters.vh"
+`include "encoding.vh"
+
+/*
+ * This combinational logic will output
+ * whether or not an instruction is a branch
+ * or not, for now.
+ */
+module pre_decode(
+ input [`INSTR_WIDTH-1:0] instruction,
+ // available readback_fifo entries in terms of read count
+ input [11:0] buffer_space,
+ output [11:0] read_size,
+ output is_branch,
+ output is_end,
+ output is_ddr_start,
+ output need_flush,
+ output is_sleep
+ );
+
+ // When an instruction is non_ddr and has
+ // is_branch flag set
+ assign is_branch = instruction[`BRANCH_OFFSET]
+ && ~instruction[`DDR_OFFSET];
+
+ assign is_end = &(~instruction);
+
+ // encountered a ddr command segments
+ assign is_ddr_start = instruction[`INFO_OFFSET]
+ && ~instruction[`DDR_OFFSET];
+
+ assign read_size = instruction[9:0];
+ // if there are more reads than we can buffer
+ assign need_flush = is_ddr_start && (read_size > buffer_space);
+
+ assign is_sleep = instruction[`BRANCH_OFFSET] &&
+ instruction[`FU_CODE_OFFSET +: 8] == `SLEEP;
+
+endmodule
diff --git a/sources/hdl/verilog/readback_engine.v b/sources/hdl/verilog/readback_engine.v
new file mode 100644
index 0000000..496d83e
--- /dev/null
+++ b/sources/hdl/verilog/readback_engine.v
@@ -0,0 +1,244 @@
+`include "parameters.vh"
+
+// Process data coming from DRAM before sending it to the host.
+module readback_engine(
+
+ // common signals
+ input clk,
+ input rst,
+
+ // other control signals
+ input flush,
+ input read_seq_incoming, // next few instructions will read from DRAM
+ input [11:0] incoming_reads, // how many reads next few instructions will issue
+ output[11:0] buffer_space, // remaining buffer size
+ input switch_mode,
+
+ // DRAM <-> engine if
+ input [511:0] rd_data,
+ input rd_valid,
+
+ input per_rd_init,
+ input per_zq_init,
+ input per_ref_init,
+
+ // engine <-> regfile if
+ input [511:0] ddr_wdata, // to compare read data against
+
+ // readback <-> XDMA if
+ output [`XDMA_AXI_DATA_WIDTH-1:0] c2h_tdata_0,
+ output c2h_tlast_0,
+ output c2h_tvalid_0,
+ input c2h_tready_0,
+ output [`XDMA_AXI_DATA_WIDTH/8-1:0] c2h_tkeep_0
+
+ );
+
+
+ localparam READ_MODE = 0;
+ localparam DIFF_MODE = 1;
+ reg mode_r, mode_ns; // Switch between diff count and read modes
+
+ reg rd_valid_r;
+ reg ignore_read_r, ignore_read_ns;
+ reg ignore_flush_r, ignore_flush_ns;
+
+ // Popcount computation part
+ reg[511:0] read_diff;
+ reg diff_valid;
+ always @(posedge clk) begin
+ if(rst) begin
+ read_diff <= 512'bX;
+ diff_valid <= `LOW;
+ end
+ read_diff <= rd_valid ? rd_data ^ ddr_wdata : read_diff;
+ diff_valid <= rd_valid && ~ignore_read_r && mode_r == DIFF_MODE ? `HIGH : `LOW;
+ end
+
+ genvar pcs; // popcount modules
+
+ wire[2:0] pc_out [127:0];
+ reg[3:0] pc_out_l2 [63:0];
+ reg[4:0] pc_out_l3 [31:0];
+ reg[5:0] pc_out_l4 [15:0];
+ reg[6:0] pc_out_l5 [7:0];
+ reg[7:0] pc_out_l6 [3:0];
+ reg[8:0] pc_out_l7 [1:0];
+ reg[15:0] pop_count_value;
+ reg pop_count_valid;
+
+ generate
+ for(pcs = 0 ; pcs < 128 ; pcs = pcs + 1) begin: gen_pcs
+ pop_count4 pci
+ (
+ .in(read_diff[pcs*4 +: 4]),
+ .out(pc_out[pcs])
+ );
+ end
+ endgenerate
+
+ integer l1, l2, l3, l4, l5, l6;
+ always @* begin
+ for(l1 = 0 ; l1 < 64 ; l1 = l1+1)
+ pc_out_l2[l1] = pc_out[2*l1] + pc_out[2*l1+1];
+ for(l2 = 0 ; l2 < 32 ; l2 = l2+1)
+ pc_out_l3[l2] = pc_out_l2[2*l2] + pc_out_l2[2*l2+1];
+ for(l3 = 0 ; l3 < 16 ; l3 = l3+1)
+ pc_out_l4[l3] = pc_out_l3[2*l3] + pc_out_l3[2*l3+1];
+ for(l4 = 0 ; l4 < 8 ; l4 = l4+1)
+ pc_out_l5[l4] = pc_out_l4[2*l4] + pc_out_l4[2*l4+1];
+ for(l5 = 0 ; l5 < 4 ; l5 = l5+1)
+ pc_out_l6[l5] = pc_out_l5[2*l5] + pc_out_l5[2*l5+1];
+ for(l6 = 0 ; l6 < 2 ; l6 = l6+1)
+ pc_out_l7[l6] = pc_out_l6[2*l6] + pc_out_l6[2*l6+1];
+ end
+
+ always @(posedge clk) begin
+ if(rst) begin
+ pop_count_value <= 16'bX;
+ pop_count_valid <= `LOW;
+ end
+ else begin
+ pop_count_value <= diff_valid ? pc_out_l7[0] + pc_out_l7[1] : pop_count_value;
+ pop_count_valid <= diff_valid ? `HIGH : `LOW;
+ end
+ end
+
+ wire[511:0] dsr_out;
+ wire dsr_valid;
+ // We put popcounted data into a shift register
+ // to fill up 512 bit I/O fifo.
+ diff_shift_reg dsr(
+ .clk(clk),
+ .rst(rst),
+
+ .in(pop_count_value),
+ .in_valid(pop_count_valid),
+
+ .flush(flush&~ignore_flush_r),
+
+ .out(dsr_out),
+ .out_valid(dsr_valid)
+ );
+ // End popcount computation part
+
+ // Count up to 1024 32-byte transfers
+ reg[9:0] xctr_r;
+
+ reg tlast; // indicating c2h's last transfer
+
+ // We read DQ_WIDTH*DQ_BURST (512 as of now) bits
+ // from DRAM, and have to pipe 256 bit partitions of
+ // it to the PCI. We may read data each cycle from
+ // DRAM and have to buffer some of those.
+ wire rbf_empty, rbf_rd_valid, fifo_almost_full, fifo_valid;
+ (*KEEP = "TRUE"*) wire rbf_full;
+ (*KEEP = "TRUE"*) reg [19:0] dbg_rd_ctr;
+ rdback_fifo rbf(
+ .full(rbf_full),
+ .prog_full(fifo_almost_full),
+ .empty(rbf_empty),
+ .wr_en(mode_r == READ_MODE ? rd_valid && ~ignore_read_r: dsr_valid),
+ // shuffle data because fifo outputs them on wrong order
+ .din(mode_r == READ_MODE ? {rd_data[255:0],rd_data[511:256]} : {dsr_out[255:0],dsr_out[511:256]}),
+ .rd_en(c2h_tready_0),
+ .dout(c2h_tdata_0),
+ .valid(fifo_valid),
+ .clk(clk),
+ .srst(rst)
+ );
+
+ reg proc_flush_ns, proc_flush_r;
+ // we count the remaining space in terms of
+ // AXI transactions
+ // e.g. 1024 reads will take up 2048
+ reg [11:0] buffer_space_ns, buffer_space_r;
+
+ always @* begin
+ tlast = `LOW;
+ ignore_read_ns = ignore_read_r;
+ ignore_flush_ns = ignore_flush_r;
+ buffer_space_ns = buffer_space_r;
+ if(per_rd_init || per_zq_init || per_ref_init) begin
+ ignore_read_ns = per_rd_init;
+ ignore_flush_ns = `HIGH;
+ end
+ if(rd_valid_r)
+ ignore_read_ns = `LOW;
+ proc_flush_ns = proc_flush_r;
+ if(flush) begin
+ if(ignore_flush_r)
+ ignore_flush_ns = `LOW;
+ else
+ proc_flush_ns = `HIGH;
+ end
+ mode_ns = mode_r;
+ if(switch_mode)
+ mode_ns = ~mode_r;
+ if(&xctr_r && (c2h_tready_0 && c2h_tvalid_0)) begin
+ tlast = `HIGH;
+ end
+ // Send what's remaining in the fifo
+ // to host with a random length transfer
+ // (tlast is not based on the counter value)
+ if(proc_flush_r) begin
+ if(c2h_tready_0 && rbf_empty && ~dsr_valid) begin
+ tlast = `HIGH;
+ proc_flush_ns = `LOW;
+ end
+ else
+ proc_flush_ns = `HIGH;
+ end
+ if(read_seq_incoming) begin
+ if(c2h_tvalid_0 && c2h_tready_0) begin
+ buffer_space_ns = (buffer_space_r - (incoming_reads << 1)) + 1;
+ end
+ else begin
+ buffer_space_ns = (buffer_space_r - (incoming_reads << 1));
+ end
+ end
+ else begin
+ if(c2h_tvalid_0 && c2h_tready_0) begin
+ if(~(proc_flush_r && rbf_empty && ~dsr_valid))
+ buffer_space_ns = buffer_space_r + 1;
+ end
+ end
+ end
+
+ always @(posedge clk) begin
+ if(rst) begin
+ dbg_rd_ctr <= 20'b0;
+ xctr_r <= 15'b0;
+ proc_flush_r <= `LOW;
+ mode_r <= READ_MODE;
+ ignore_read_r <= 1'b0;
+ ignore_flush_r <= 1'b0;
+ rd_valid_r <= 1'b0;
+ buffer_space_r <= 12'd2048;
+ end
+ else begin
+ if(rd_valid && ~ignore_read_r && ~rbf_full)
+ dbg_rd_ctr <= dbg_rd_ctr + 1'b1;
+ else
+ dbg_rd_ctr <= dbg_rd_ctr;
+ buffer_space_r <= buffer_space_ns;
+ mode_r <= mode_ns;
+ rd_valid_r <= rd_valid;
+ ignore_read_r <= ignore_read_ns;
+ ignore_flush_r <= ignore_flush_ns;
+ if(proc_flush_r && tlast)
+ xctr_r <= 15'b0;
+ else if(c2h_tready_0 && c2h_tvalid_0) begin
+ xctr_r <= xctr_r + 1;
+ end
+ proc_flush_r <= proc_flush_ns;
+ end
+ end
+
+ assign c2h_tkeep_0 = {(`XDMA_AXI_DATA_WIDTH/8){1'b1}};
+ assign c2h_tlast_0 = tlast;
+ assign c2h_tvalid_0 = proc_flush_r && rbf_empty && ~dsr_valid ? `HIGH : fifo_valid;
+
+ assign buffer_space = buffer_space_r >> 1;
+
+endmodule
diff --git a/sources/hdl/verilog/reg_mem.v b/sources/hdl/verilog/reg_mem.v
new file mode 100644
index 0000000..a8d37cd
--- /dev/null
+++ b/sources/hdl/verilog/reg_mem.v
@@ -0,0 +1,33 @@
+`timescale 1ns / 1ps
+
+module reg_mem(
+ input [9:0] addr,
+ input clk,
+ input [31:0] din,
+ output [31:0] dout,
+ input en,
+ input we
+ );
+
+ reg [31:0] mem [1023:0];
+
+ integer i;
+ initial
+ begin
+ for(i=0; i<1024; i=i+1)
+ mem[i]=0;
+ end
+
+ reg [31:0] out;
+
+ assign dout=out;
+
+ always @(posedge clk)
+ begin
+ if(we)
+ mem[addr]<=din;
+ else if(en)
+ out<=mem[addr];
+ end
+
+endmodule
diff --git a/sources/hdl/verilog/register_file.v b/sources/hdl/verilog/register_file.v
new file mode 100644
index 0000000..2d3b693
--- /dev/null
+++ b/sources/hdl/verilog/register_file.v
@@ -0,0 +1,92 @@
+`include "parameters.vh"
+
+/*
+ * An 8 read 8 write port reg file
+ * satisfying ddr pipeline's needs
+ */
+module register_file(
+
+ // common signals
+ input clk,
+ input rst,
+
+ // execute stage <-> reg file if
+ input rf_wide_wen,
+ input [3:0] rf_wide_offset,
+ output [511:0] rf_wide_data,
+ output [32*8-1:0] rf_rdata,
+ input [32*8-1:0] rf_wdata,
+ input [7:0] rf_wen,
+ input [4*8-1:0] rf_raddr,
+ input [4*8-1:0] rf_waddr,
+ output [`COL_WIDTH-1:0] casr,
+ output [`BANK_WIDTH+`BG_WIDTH-1:0] basr,
+ output [`ROW_WIDTH-1:0] rasr,
+ // update stride registers, wen is OH (3'b001 = update rasr)
+ input [31:0] srf_value,
+ input [2:0] srf_wen
+ );
+
+ // Stride registers
+ reg [31:0] casr_r, basr_r, rasr_r;
+
+ assign casr = casr_r;
+ assign basr = basr_r;
+ assign rasr = rasr_r;
+
+ // Update stride registers
+ always @(posedge clk) begin
+ if(srf_wen[0]) begin
+ casr_r <= srf_value;
+ end
+ if(srf_wen[1]) begin
+ basr_r <= srf_value;
+ end
+ if(srf_wen[2]) begin
+ rasr_r <= srf_value;
+ end
+ end
+
+ // General purpose registers
+ reg [31:0] reg_file [15:0];
+
+ // split r&w data signals into human readable form
+ // also drive rdata with appropriate register values
+ wire [31:0] wdata [7:0];
+ wire wen [7:0];
+ wire [3:0] waddr [7:0];
+ wire [3:0] raddr [7:0];
+ genvar i;
+ generate
+ for(i = 0 ; i < 8 ; i = i + 1) begin: gen_ports
+ assign wdata[i] = rf_wdata[32*i +: 32];
+ assign wen[i] = rf_wen[i];
+ assign waddr[i] = rf_waddr[4*i +: 4];
+ assign raddr[i] = rf_raddr[4*i +: 4];
+ // TODO will this compile?
+ assign rf_rdata[32*i +: 32] = raddr[i] == 0 ? casr_r :
+ raddr[i] == 1 ? basr_r :
+ raddr[i] == 2 ? rasr_r : reg_file[raddr[i]];
+ end
+ endgenerate
+
+ integer j;
+ // Write to the register file
+ always @(posedge clk) begin
+ for(j = 0 ; j < 8 ; j = j+1) begin: regfile_write
+ if(wen[j])
+ reg_file[waddr[j]] <= wdata[j];
+ end
+ end
+
+ // DDR4 8-burst write data register
+ reg [511:0] wide_reg;
+ always @(posedge clk) begin
+ // TODO this probably won't compile
+ if(rf_wide_wen)
+ wide_reg[rf_wide_offset*32 +: 32] <= wdata[0];
+ end
+
+ assign rf_wide_data = wide_reg;
+
+endmodule
diff --git a/sources/hdl/verilog/softmc_pipeline.v b/sources/hdl/verilog/softmc_pipeline.v
new file mode 100644
index 0000000..07c106e
--- /dev/null
+++ b/sources/hdl/verilog/softmc_pipeline.v
@@ -0,0 +1,178 @@
+`include "parameters.vh"
+
+module softmc_pipeline(
+
+ // common signals
+ input clk,
+ input rst,
+
+ // readback <-> fetch_stage backpressure
+
+ output softmc_end,
+ output [11:0] read_size,
+ output read_seq_incoming,
+ input [11:0] buffer_space,
+
+ // frontend <-> fetch stage interface
+ output [`IMEM_ADDR_WIDTH-1:0] addr_out,
+ output valid_out,
+ input [`INSTR_WIDTH-1:0] data_in,
+ input valid_in,
+ input [`IMEM_ADDR_WIDTH-1:0] addr_in,
+ input ready_out,
+
+ // ddr_pipeline <-> outer DDR module
+ output [3:0] ddr_write,
+ output [3:0] ddr_read,
+ output [3:0] ddr_pre,
+ output [3:0] ddr_act,
+ output [3:0] ddr_ref,
+ output [3:0] ddr_sre,
+ output [3:0] ddr_srx,
+ output [3:0] ddr_zq,
+ output [3:0] ddr_nop,
+ output [3:0] ddr_ap,
+ output [3:0] ddr_pall,
+ output [3:0] ddr_half_bl,
+ output [4*`BG_WIDTH-1:0] ddr_bg,
+ output [4*`BANK_WIDTH-1:0] ddr_bank,
+ output [4*`COL_WIDTH-1:0] ddr_col,
+ output [4*`ROW_WIDTH-1:0] ddr_row,
+ output [511:0] ddr_wdata
+ );
+
+ wire br_resolve;
+ wire [`IMEM_ADDR_WIDTH-1:0] br_target;
+
+ wire [`INSTR_WIDTH-1:0] dec_instr;
+ wire dec_instr_valid;
+ wire [`IMEM_ADDR_WIDTH-1:0] dec_instr_pc;
+
+ fetch_stage fs(
+ .clk(clk),
+ .rst(rst),
+
+ .softmc_end(softmc_end),
+ .read_size(read_size),
+ .read_seq_incoming(read_seq_incoming),
+ .buffer_space(buffer_space),
+
+
+ .addr_out(addr_out),
+ .valid_out(valid_out),
+ .data_in(data_in),
+ .valid_in(valid_in),
+ .addr_in(addr_in),
+ .ready_out(ready_out),
+
+ .br_resolve(br_resolve),
+ .br_target(br_target),
+
+ .instr(dec_instr),
+ .instr_pc(dec_instr_pc),
+ .instr_valid(dec_instr_valid)
+ );
+
+ wire ddr_valid, exe_valid;
+ wire [`DDR_UOP_WIDTH*4-1:0] ddr_uop;
+ wire [`EXE_UOP_WIDTH-1:0] exe_uop;
+ wire [`IMEM_ADDR_WIDTH-1:0] exe_pc;
+ wire [32*7-1:0] ddr_stat;
+
+ decode_stage ds(
+ .clk(clk),
+ .rst(rst),
+
+ .instr(dec_instr),
+ .instr_pc(dec_instr_pc),
+ .instr_valid(dec_instr_valid),
+
+ .ddr_valid(ddr_valid),
+ .exe_valid(exe_valid),
+ .ddr_uop(ddr_uop),
+ .exe_uop(exe_uop),
+ .exe_pc(exe_pc),
+ .ddr_stat(ddr_stat)
+ );
+
+ wire rf_wide_wen;
+ wire [3:0] rf_wide_offset;
+ wire [511:0] rf_wide_data;
+ wire [32*8-1:0] rf_rdata;
+ wire [32*8-1:0] rf_wdata;
+ wire [7:0] rf_wen;
+ wire [4*8-1:0] rf_raddr;
+ wire [4*8-1:0] rf_waddr;
+ wire [`COL_WIDTH-1:0] casr;
+ wire [`BANK_WIDTH+`BG_WIDTH-1:0] basr;
+ wire [`ROW_WIDTH-1:0] rasr;
+ wire [31:0] srf_value;
+ wire [2:0] srf_wen;
+
+ execute_stage es(
+ .clk(clk),
+ .rst(rst),
+
+ .br_resolve(br_resolve),
+ .br_target(br_target),
+
+ .ddr_valid(ddr_valid),
+ .exe_valid(exe_valid),
+ .ddr_uop(ddr_uop),
+ .exe_uop(exe_uop),
+ .exe_pc(exe_pc),
+
+ .rf_wide_wen(rf_wide_wen),
+ .rf_wide_offset(rf_wide_offset),
+ .wide_reg(rf_wide_data),
+ .rf_rdata(rf_rdata),
+ .rf_wdata(rf_wdata),
+ .rf_wen(rf_wen),
+ .rf_raddr(rf_raddr),
+ .rf_waddr(rf_waddr),
+ .casr(casr),
+ .basr(basr),
+ .rasr(rasr),
+ .srf_value(srf_value),
+ .srf_wen(srf_wen),
+ .ddr_stat(ddr_stat),
+
+ .ddr_write(ddr_write),
+ .ddr_read(ddr_read),
+ .ddr_pre(ddr_pre),
+ .ddr_act(ddr_act),
+ .ddr_ref(ddr_ref),
+ .ddr_sre(ddr_sre),
+ .ddr_srx(ddr_srx),
+ .ddr_zq(ddr_zq),
+ .ddr_nop(ddr_nop),
+ .ddr_ap(ddr_ap),
+ .ddr_pall(ddr_pall),
+ .ddr_half_bl(ddr_half_bl),
+ .ddr_bg(ddr_bg),
+ .ddr_bank(ddr_bank),
+ .ddr_col(ddr_col),
+ .ddr_row(ddr_row),
+ .ddr_wdata(ddr_wdata)
+ );
+
+ register_file rf(
+ .clk(clk),
+ .rst(rst),
+
+ .rf_wide_wen(rf_wide_wen),
+ .rf_wide_offset(rf_wide_offset),
+ .rf_wide_data(rf_wide_data),
+ .rf_rdata(rf_rdata),
+ .rf_wdata(rf_wdata),
+ .rf_wen(rf_wen),
+ .rf_raddr(rf_raddr),
+ .rf_waddr(rf_waddr),
+ .casr(casr),
+ .basr(basr),
+ .rasr(rasr),
+ .srf_value(srf_value),
+ .srf_wen(srf_wen)
+ );
+
+endmodule
diff --git a/sources/hdl/verilog/softmc_top.v b/sources/hdl/verilog/softmc_top.v
new file mode 100644
index 0000000..c5b1c76
--- /dev/null
+++ b/sources/hdl/verilog/softmc_top.v
@@ -0,0 +1,838 @@
+`include "parameters.vh"
+`include "project.vh"
+
+`ifdef XUPP3R_x4
+ `define XUPP3R
+`elsif XUPP3R_x8
+ `define XUPP3R
+`elsif XUPP3R_x8_1R_UDIMM
+ `define XUPP3R
+`endif
+
+
+module softmc_top #(parameter tCK = 1500, SIM = "false")
+ (
+ // common signals
+ input c0_sys_clk_p,
+ input c0_sys_clk_n,
+ input sys_rst_l,
+
+ // iob <> ddr4 sdram ip signals
+ output c0_ddr4_act_n,
+ output [16:0] c0_ddr4_adr,
+ output [1:0] c0_ddr4_ba,
+ output [1:0] c0_ddr4_bg,
+ output [`CKE_WIDTH-1:0] c0_ddr4_cke,
+ output [`ODT_WIDTH-1:0] c0_ddr4_odt,
+ output [`CS_WIDTH-1:0] c0_ddr4_cs_n,
+ output [`CK_WIDTH-1:0] c0_ddr4_ck_t,
+ output [`CK_WIDTH-1:0] c0_ddr4_ck_c,
+ output c0_ddr4_reset_n,
+ `ifdef XUPP3R_x4
+ inout [17:0] c0_ddr4_dqs_c,
+ inout [17:0] c0_ddr4_dqs_t,
+ inout [71:0] c0_ddr4_dq,
+ output c0_ddr4_parity,
+ `elsif XUPP3R_x8
+ inout [8:0] c0_ddr4_dm_dbi_n,
+ inout [71:0] c0_ddr4_dq,
+ inout [8:0] c0_ddr4_dqs_c,
+ inout [8:0] c0_ddr4_dqs_t,
+ output c0_ddr4_parity,
+ `else
+ inout [7:0] c0_ddr4_dm_dbi_n,
+ inout [63:0] c0_ddr4_dq,
+ inout [7:0] c0_ddr4_dqs_c,
+ inout [7:0] c0_ddr4_dqs_t,
+ `endif
+ // xdma signals
+ input clk_ref_p,
+ input clk_ref_n,
+ input pcie_rst,
+ output [7:0] pci_exp_txp,
+ output [7:0] pci_exp_txn,
+ input [7:0] pci_exp_rxp,
+ input [7:0] pci_exp_rxn
+
+ );
+
+ // Frontend control signals
+ wire softmc_fin;
+ wire user_rst;
+
+ // Frontend <-> Fetch signals
+ wire [`IMEM_ADDR_WIDTH-1:0] fr_addr_in;
+ wire fr_valid_in;
+ wire [`INSTR_WIDTH-1:0] fr_data_out;
+ wire fr_valid_out;
+ wire [`IMEM_ADDR_WIDTH-1:0] fr_addr_out;
+ wire fr_ready_out;
+
+ // Frontend <-> misc. control signals
+ wire per_rd_init;
+ wire per_zq_init;
+ wire per_ref_init;
+ wire rbe_switch_mode;
+ wire toggle_dll;
+
+ // AXI streaming ports
+ wire [`XDMA_AXI_DATA_WIDTH-1:0] m_axis_h2c_tdata_0,xdma_h2c_tdata_0;
+ wire m_axis_h2c_tlast_0, xdma_h2c_tlast_0;
+ wire m_axis_h2c_tvalid_0, xdma_h2c_tvalid_0;
+ wire m_axis_h2c_tready_0, xdma_h2c_tready_0;
+ wire [`XDMA_AXI_DATA_WIDTH/8-1:0] m_axis_h2c_tkeep_0, xdma_h2c_tkeep_0;
+ wire [`XDMA_AXI_DATA_WIDTH-1:0] s_axis_c2h_tdata_0, xdma_c2h_tdata_0;
+ wire s_axis_c2h_tlast_0, xdma_c2h_tlast_0;
+ wire s_axis_c2h_tvalid_0, xdma_c2h_tvalid_0;
+ wire s_axis_c2h_tready_0, xdma_c2h_tready_0;
+ wire [`XDMA_AXI_DATA_WIDTH/8-1:0] s_axis_c2h_tkeep_0, xdma_c2h_tkeep_0;
+
+ // ddr_pipeline <-> outer module if
+ wire [3:0] ddr_write;
+ wire [3:0] ddr_read;
+ wire [3:0] ddr_pre;
+ wire [3:0] ddr_act;
+ wire [3:0] ddr_ref;
+ wire [3:0] ddr_sre;
+ wire [3:0] ddr_srx;
+ wire [3:0] ddr_zq;
+ wire [3:0] ddr_nop;
+ wire [3:0] ddr_ap;
+ wire [3:0] ddr_pall;
+ wire [3:0] ddr_half_bl;
+ wire [4*`BG_WIDTH-1:0] ddr_bg;
+ wire [4*`BANK_WIDTH-1:0] ddr_bank;
+ wire [4*`COL_WIDTH-1:0] ddr_col;
+ wire [4*`ROW_WIDTH-1:0] ddr_row;
+ wire [511:0] ddr_wdata;
+
+ // periodic maintenance signals
+ wire ddr_maint_read;
+
+ // phy <-> ddr adapter and xdma app signals
+ // dlltoggler
+ wire clk_sel = 0;
+ wire [7:0] dllt_mc_ACT_n;
+ wire [135:0] dllt_mc_ADR;
+ wire [15:0] dllt_mc_BA;
+ wire [15:0] dllt_mc_BG;
+ wire [7:0] dllt_mc_CKE;
+ wire [7:0] dllt_mc_CS_n;
+ wire dllt_done;
+ // ddr adapter
+ wire [4:0] dBufAdr;
+ wire [`DQ_WIDTH*8-1:0] wrData;
+ wire [`DQ_WIDTH-1:0] wrDataMask;
+ wire [511:0] rdData;
+ wire [4:0] rdDataAddr;
+ wire [0:0] rdDataEn;
+ wire [0:0] rdDataEnd;
+ wire [0:0] per_rd_done;
+ wire [0:0] rmw_rd_done;
+ wire [4:0] wrDataAddr;
+ wire [0:0] wrDataEn;
+ wire [7:0] mc_ACT_n;
+ wire [135:0] mc_ADR;
+ wire [15:0] mc_BA;
+ wire [15:0] mc_BG;
+ wire [`CKE_WIDTH*8-1:0] mc_CKE;
+ wire [`CS_WIDTH*8-1:0] mc_CS_n;
+ wire [`ODT_WIDTH*8-1:0] mc_ODT;
+ wire [0:0] mcRdCAS;
+ wire [0:0] mcWrCAS;
+ wire [0:0] winInjTxn;
+ wire [0:0] winRmw;
+ wire [4:0] winBuf;
+ wire [1:0] winRank;
+ wire [5:0] tCWL;
+ wire dbg_clk;
+ wire c0_wr_rd_complete;
+ wire c0_ddr4_clk;
+ wire c0_ddr4_dll_off_clk;
+ wire ddr4_ui_clk;
+ wire c0_ddr4_rst;
+ wire [511:0] dbg_bus;
+ wire [1:0] mcCasSlot;
+ wire mcCasSlot2;
+ wire gt_data_ready;
+
+ wire read_seq_incoming; // next few instructions will read from DRAM
+ wire [11:0] incoming_reads; // how many reads next few instructions will issue
+ wire [11:0] buffer_space; // remaining buffer size
+
+ wire sys_rst = ~sys_rst_l; // low active signal
+ wire c0_init_calib_complete;
+
+ // There is a possibility that these signals are on
+ // the critical path as observed in
+ // the previous iteration of SoftMC
+ reg c0_init_calib_complete_r, sys_rst_r;
+ wire iq_full, processing_iseq, rdback_fifo_empty;
+
+ always @(posedge c0_ddr4_clk) begin
+ c0_init_calib_complete_r <= c0_init_calib_complete;
+ sys_rst_r <= sys_rst;
+ end
+
+ reg dllt_active = 1'b0;
+
+ `ifdef ENABLE_DLL_TOGGLER
+ always @(posedge c0_ddr4_clk) begin
+ if(toggle_dll) begin
+ dllt_active <= ~dllt_active;
+ end
+ if(dllt_done) begin
+ dllt_active <= ~dllt_active;
+ end
+ end
+ `endif
+
+ `ifdef XUPP3R_x8
+ phy_ddr4_x8 phy_ddr4_i(
+ .sys_rst (sys_rst),
+ .c0_sys_clk_p (c0_sys_clk_p),
+ .c0_sys_clk_n (c0_sys_clk_n),
+ `ifdef ENABLE_DLL_TOGGLER
+ .c0_ddr4_ui_clk (ddr4_ui_clk),
+ .addn_ui_clkout1 (c0_ddr4_dll_off_clk),
+ `else
+ .c0_ddr4_ui_clk (c0_ddr4_clk),
+ `endif
+ .c0_ddr4_ui_clk_sync_rst (c0_ddr4_rst),
+ .c0_init_calib_complete (c0_init_calib_complete),
+ .dbg_clk (dbg_clk),
+ .c0_ddr4_act_n (c0_ddr4_act_n),
+ .c0_ddr4_adr (c0_ddr4_adr),
+ .c0_ddr4_ba (c0_ddr4_ba),
+ .c0_ddr4_bg (c0_ddr4_bg),
+ .c0_ddr4_cke (c0_ddr4_cke),
+ .c0_ddr4_odt (c0_ddr4_odt),
+ .c0_ddr4_cs_n (c0_ddr4_cs_n),
+ .c0_ddr4_ck_t (c0_ddr4_ck_t),
+ .c0_ddr4_ck_c (c0_ddr4_ck_c),
+ .c0_ddr4_reset_n (c0_ddr4_reset_n),
+ .c0_ddr4_parity (c0_ddr4_parity),
+ .wrDataMask (wrDataMask),
+ .c0_ddr4_dm_dbi_n (c0_ddr4_dm_dbi_n),
+ .c0_ddr4_dq (c0_ddr4_dq),
+ .c0_ddr4_dqs_c (c0_ddr4_dqs_c),
+ .c0_ddr4_dqs_t (c0_ddr4_dqs_t),
+
+ .dBufAdr (dBufAdr),
+ .wrData (wrData),
+ .rdData (rdData),
+ .rdDataAddr (rdDataAddr),
+ .rdDataEn (rdDataEn),
+ .rdDataEnd (rdDataEnd),
+ .per_rd_done (per_rd_done),
+ .rmw_rd_done (rmw_rd_done),
+ .wrDataAddr (wrDataAddr),
+ .wrDataEn (wrDataEn),
+
+ .mc_ACT_n (dllt_active ? dllt_mc_ACT_n : mc_ACT_n),
+ .mc_ADR (dllt_active ? dllt_mc_ADR : mc_ADR),
+ .mc_BA (dllt_active ? dllt_mc_BA : mc_BA),
+ .mc_BG (dllt_active ? dllt_mc_BG : mc_BG),
+ .mc_CKE (dllt_active ? dllt_mc_CKE : mc_CKE),
+ .mc_CS_n (dllt_active ? dllt_mc_CS_n : mc_CS_n),
+ .mc_ODT (mc_ODT),
+ // CAS command slot select. Slot0 is enabled for example design.
+ .mcCasSlot (dllt_active ? 2'b0 : mcCasSlot),
+ // CAS slot 2 select. mcCasSlot2 serves a similar purpose as the mcCasSlot[1:0] signal, but mcCasSlot2 is used in timing
+ // critical logic in the Phy. Slot0 is enabled for example design.
+ .mcCasSlot2 (dllt_active ? 1'b0 : mcCasSlot2),
+ .mcRdCAS (dllt_active ? 1'b0 : mcRdCAS),
+ .mcWrCAS (dllt_active ? 1'b0 : mcWrCAS),
+ // Optional read command type indication. The winInjTxn signal is set to '0' for example design.
+ .winInjTxn ({1{1'b0}}),
+ // Optional read command type indication. The winRmw signal is set to '0' for example design.
+ .winRmw ({1{1'b0}}),
+ // Update VT Tracking. The gt_data_ready signal is set to '0' in this example design.
+ // This signal must be asserted periodically to keep the DQS Gate aligned as voltage and temperature drift.
+ // For more information, Refer to PG150 document.
+ .gt_data_ready (gt_data_ready),
+ .winBuf (winBuf),
+ .winRank (winRank),
+ .tCWL (tCWL),
+ // Debug Port
+ .dbg_bus (dbg_bus)
+ );
+ `elsif XUPP3R_x4
+ phy_ddr4 phy_ddr4_i(
+ .sys_rst (sys_rst),
+ .c0_sys_clk_p (c0_sys_clk_p),
+ .c0_sys_clk_n (c0_sys_clk_n),
+
+ `ifdef ENABLE_DLL_TOGGLER
+ .c0_ddr4_ui_clk (ddr4_ui_clk),
+ .addn_ui_clkout1 (c0_ddr4_dll_off_clk),
+ `else
+ .c0_ddr4_ui_clk (c0_ddr4_clk),
+ `endif
+ .c0_ddr4_ui_clk_sync_rst (c0_ddr4_rst),
+ .c0_init_calib_complete (c0_init_calib_complete),
+ .dbg_clk (dbg_clk),
+ .c0_ddr4_act_n (c0_ddr4_act_n),
+ .c0_ddr4_adr (c0_ddr4_adr),
+ .c0_ddr4_ba (c0_ddr4_ba),
+ .c0_ddr4_bg (c0_ddr4_bg),
+ .c0_ddr4_cke (c0_ddr4_cke),
+ .c0_ddr4_odt (c0_ddr4_odt),
+ .c0_ddr4_cs_n (c0_ddr4_cs_n),
+ .c0_ddr4_ck_t (c0_ddr4_ck_t),
+ .c0_ddr4_ck_c (c0_ddr4_ck_c),
+ .c0_ddr4_reset_n (c0_ddr4_reset_n),
+ .c0_ddr4_parity (c0_ddr4_parity),
+ .c0_ddr4_dq (c0_ddr4_dq),
+ .c0_ddr4_dqs_c (c0_ddr4_dqs_c),
+ .c0_ddr4_dqs_t (c0_ddr4_dqs_t),
+
+ .dBufAdr (dBufAdr),
+ .wrData (wrData),
+ .rdData (rdData),
+ .rdDataAddr (rdDataAddr),
+ .rdDataEn (rdDataEn),
+ .rdDataEnd (rdDataEnd),
+ .per_rd_done (per_rd_done),
+ .rmw_rd_done (rmw_rd_done),
+ .wrDataAddr (wrDataAddr),
+ .wrDataEn (wrDataEn),
+
+ .mc_ACT_n (dllt_active ? dllt_mc_ACT_n : mc_ACT_n),
+ .mc_ADR (dllt_active ? dllt_mc_ADR : mc_ADR),
+ .mc_BA (dllt_active ? dllt_mc_BA : mc_BA),
+ .mc_BG (dllt_active ? dllt_mc_BG : mc_BG),
+ .mc_CKE (dllt_active ? dllt_mc_CKE : mc_CKE),
+ .mc_CS_n (dllt_active ? dllt_mc_CS_n : mc_CS_n),
+ .mc_ODT (mc_ODT),
+ // CAS command slot select. Slot0 is enabled for example design.
+ .mcCasSlot (dllt_active ? 0 : mcCasSlot),
+ // CAS slot 2 select. mcCasSlot2 serves a similar purpose as the mcCasSlot[1:0] signal, but mcCasSlot2 is used in timing
+ // critical logic in the Phy. Slot0 is enabled for example design.
+ .mcCasSlot2 (dllt_active ? 0 : mcCasSlot2),
+ .mcRdCAS (dllt_active ? 0 : mcRdCAS),
+ .mcWrCAS (dllt_active ? 0 : mcWrCAS),
+ // Optional read command type indication. The winInjTxn signal is set to '0' for example design.
+ .winInjTxn ({1{1'b0}}),
+ // Optional read command type indication. The winRmw signal is set to '0' for example design.
+ .winRmw ({1{1'b0}}),
+ // Update VT Tracking. The gt_data_ready signal is set to '0' in this example design.
+ // This signal must be asserted periodically to keep the DQS Gate aligned as voltage and temperature drift.
+ // For more information, Refer to PG150 document.
+ .gt_data_ready (gt_data_ready),
+ .winBuf (winBuf),
+ .winRank (winRank),
+ .tCWL (tCWL),
+ // Debug Port
+ .dbg_bus (dbg_bus)
+ );
+ `elsif XUPP3R_x8_1R_UDIMM
+ phy_ddr4_udimm phy_ddr4_i(
+ .sys_rst (sys_rst),
+ .c0_sys_clk_p (c0_sys_clk_p),
+ .c0_sys_clk_n (c0_sys_clk_n),
+ `ifdef ENABLE_DLL_TOGGLER
+ .c0_ddr4_ui_clk (ddr4_ui_clk),
+ .addn_ui_clkout1 (c0_ddr4_dll_off_clk),
+ `else
+ .c0_ddr4_ui_clk (c0_ddr4_clk),
+ `endif
+ .c0_ddr4_ui_clk_sync_rst (c0_ddr4_rst),
+ .c0_init_calib_complete (c0_init_calib_complete),
+ .dbg_clk (dbg_clk),
+ .c0_ddr4_act_n (c0_ddr4_act_n),
+ .c0_ddr4_adr (c0_ddr4_adr),
+ .c0_ddr4_ba (c0_ddr4_ba),
+ .c0_ddr4_bg (c0_ddr4_bg),
+ .c0_ddr4_cke (c0_ddr4_cke),
+ .c0_ddr4_odt (c0_ddr4_odt),
+ .c0_ddr4_cs_n (c0_ddr4_cs_n),
+ .c0_ddr4_ck_t (c0_ddr4_ck_t),
+ .c0_ddr4_ck_c (c0_ddr4_ck_c),
+ .c0_ddr4_reset_n (c0_ddr4_reset_n),
+ .wrDataMask (wrDataMask),
+ .c0_ddr4_dm_dbi_n (c0_ddr4_dm_dbi_n),
+ .c0_ddr4_dq (c0_ddr4_dq),
+ .c0_ddr4_dqs_c (c0_ddr4_dqs_c),
+ .c0_ddr4_dqs_t (c0_ddr4_dqs_t),
+
+ .dBufAdr (dBufAdr),
+ .wrData (wrData),
+ .rdData (rdData),
+ .rdDataAddr (rdDataAddr),
+ .rdDataEn (rdDataEn),
+ .rdDataEnd (rdDataEnd),
+ .per_rd_done (per_rd_done),
+ .rmw_rd_done (rmw_rd_done),
+ .wrDataAddr (wrDataAddr),
+ .wrDataEn (wrDataEn),
+
+ .mc_ACT_n (dllt_active ? dllt_mc_ACT_n : mc_ACT_n),
+ .mc_ADR (dllt_active ? dllt_mc_ADR : mc_ADR),
+ .mc_BA (dllt_active ? dllt_mc_BA : mc_BA),
+ .mc_BG (dllt_active ? dllt_mc_BG : mc_BG),
+ .mc_CKE (dllt_active ? dllt_mc_CKE : mc_CKE),
+ .mc_CS_n (dllt_active ? dllt_mc_CS_n : mc_CS_n),
+ .mc_ODT (mc_ODT),
+ // CAS command slot select. Slot0 is enabled for example design.
+ .mcCasSlot (dllt_active ? 2'b0 : mcCasSlot),
+ // CAS slot 2 select. mcCasSlot2 serves a similar purpose as the mcCasSlot[1:0] signal, but mcCasSlot2 is used in timing
+ // critical logic in the Phy. Slot0 is enabled for example design.
+ .mcCasSlot2 (dllt_active ? 1'b0 : mcCasSlot2),
+ .mcRdCAS (dllt_active ? 1'b0 : mcRdCAS),
+ .mcWrCAS (dllt_active ? 1'b0 : mcWrCAS),
+ // Optional read command type indication. The winInjTxn signal is set to '0' for example design.
+ .winInjTxn ({1{1'b0}}),
+ // Optional read command type indication. The winRmw signal is set to '0' for example design.
+ .winRmw ({1{1'b0}}),
+ // Update VT Tracking. The gt_data_ready signal is set to '0' in this example design.
+ // This signal must be asserted periodically to keep the DQS Gate aligned as voltage and temperature drift.
+ // For more information, Refer to PG150 document.
+ .gt_data_ready (gt_data_ready),
+ .winBuf (winBuf),
+ .winRank (winRank),
+ .tCWL (tCWL),
+ // Debug Port
+ .dbg_bus (dbg_bus)
+ );
+ `else
+ phy_ddr4 phy_ddr4_i(
+ .sys_rst (sys_rst),
+ .c0_sys_clk_p (c0_sys_clk_p),
+ .c0_sys_clk_n (c0_sys_clk_n),
+
+ `ifdef ENABLE_DLL_TOGGLER
+ .c0_ddr4_ui_clk (ddr4_ui_clk),
+ .addn_ui_clkout1 (c0_ddr4_dll_off_clk),
+ `else
+ .c0_ddr4_ui_clk (c0_ddr4_clk),
+ `endif
+ .c0_ddr4_ui_clk_sync_rst (c0_ddr4_rst),
+ .c0_init_calib_complete (c0_init_calib_complete),
+ .dbg_clk (dbg_clk),
+ .c0_ddr4_act_n (c0_ddr4_act_n),
+ .c0_ddr4_adr (c0_ddr4_adr),
+ .c0_ddr4_ba (c0_ddr4_ba),
+ .c0_ddr4_bg (c0_ddr4_bg),
+ .c0_ddr4_cke (c0_ddr4_cke),
+ .c0_ddr4_odt (c0_ddr4_odt),
+ .c0_ddr4_cs_n (c0_ddr4_cs_n),
+ .c0_ddr4_ck_t (c0_ddr4_ck_t),
+ .c0_ddr4_ck_c (c0_ddr4_ck_c),
+ .c0_ddr4_reset_n (c0_ddr4_reset_n),
+ .wrDataMask (wrDataMask),
+ .c0_ddr4_dm_dbi_n (c0_ddr4_dm_dbi_n),
+ .c0_ddr4_dq (c0_ddr4_dq),
+ .c0_ddr4_dqs_c (c0_ddr4_dqs_c),
+ .c0_ddr4_dqs_t (c0_ddr4_dqs_t),
+
+ .dBufAdr (dBufAdr),
+ .wrData (wrData),
+ .rdData (rdData),
+ .rdDataAddr (rdDataAddr),
+ .rdDataEn (rdDataEn),
+ .rdDataEnd (rdDataEnd),
+ .per_rd_done (per_rd_done),
+ .rmw_rd_done (rmw_rd_done),
+ .wrDataAddr (wrDataAddr),
+ .wrDataEn (wrDataEn),
+
+ .mc_ACT_n (dllt_active ? dllt_mc_ACT_n : mc_ACT_n),
+ .mc_ADR (dllt_active ? dllt_mc_ADR : mc_ADR),
+ .mc_BA (dllt_active ? dllt_mc_BA : mc_BA),
+ .mc_BG (dllt_active ? dllt_mc_BG : mc_BG),
+ .mc_CKE (dllt_active ? dllt_mc_CKE : mc_CKE),
+ .mc_CS_n (dllt_active ? dllt_mc_CS_n : mc_CS_n),
+ .mc_ODT (mc_ODT),
+ // CAS command slot select. Slot0 is enabled for example design.
+ .mcCasSlot (dllt_active ? 0 : mcCasSlot),
+ // CAS slot 2 select. mcCasSlot2 serves a similar purpose as the mcCasSlot[1:0] signal, but mcCasSlot2 is used in timing
+ // critical logic in the Phy. Slot0 is enabled for example design.
+ .mcCasSlot2 (dllt_active ? 0 : mcCasSlot2),
+ .mcRdCAS (dllt_active ? 0 : mcRdCAS),
+ .mcWrCAS (dllt_active ? 0 : mcWrCAS),
+ // Optional read command type indication. The winInjTxn signal is set to '0' for example design.
+ .winInjTxn ({1{1'b0}}),
+ // Optional read command type indication. The winRmw signal is set to '0' for example design.
+ .winRmw ({1{1'b0}}),
+ // Update VT Tracking. The gt_data_ready signal is set to '0' in this example design.
+ // This signal must be asserted periodically to keep the DQS Gate aligned as voltage and temperature drift.
+ // For more information, Refer to PG150 document.
+ .gt_data_ready (gt_data_ready),
+ .winBuf (winBuf),
+ .winRank (winRank),
+ .tCWL (tCWL),
+ // Debug Port
+ .dbg_bus (dbg_bus)
+ );
+ `endif
+
+ softmc_pipeline pipeline(
+ .clk(c0_ddr4_clk),
+ .rst(c0_ddr4_rst || user_rst),
+
+ .softmc_end(softmc_fin),
+ .read_size(incoming_reads),
+ .read_seq_incoming(read_seq_incoming),
+ .buffer_space(buffer_space),
+
+ .addr_out(fr_addr_in),
+ .valid_out(fr_valid_in),
+ .data_in(fr_data_out),
+ .valid_in(fr_valid_out),
+ .addr_in(fr_addr_out),
+ .ready_out(fr_ready_out),
+
+ .ddr_write(ddr_write),
+ .ddr_read(ddr_read),
+ .ddr_pre(ddr_pre),
+ .ddr_act(ddr_act),
+ .ddr_ref(ddr_ref),
+ .ddr_sre(ddr_sre),
+ .ddr_srx(ddr_srx),
+ .ddr_zq(ddr_zq),
+ .ddr_nop(ddr_nop),
+ .ddr_ap(ddr_ap),
+ .ddr_pall(ddr_pall),
+ .ddr_half_bl(ddr_half_bl),
+ .ddr_bg(ddr_bg),
+ .ddr_bank(ddr_bank),
+ .ddr_col(ddr_col),
+ .ddr_row(ddr_row),
+ .ddr_wdata(ddr_wdata)
+ );
+
+ `ifdef ENABLE_DLL_TOGGLER
+ //BUFGMUX:GeneralClockMuxBuffer
+ //UltraScale
+ //XilinxHDLLibrariesGuide, version2014.4
+ BUFGMUX#(.CLK_SEL_TYPE("SYNC") //ASYNC,SYNC
+ )BUFGMUX_inst(
+ .O(c0_ddr4_clk), //1-bitoutput:Clockoutput
+ .I0(ddr4_ui_clk), //1-bitinput:Clockinput(S=0)
+ .I1(c0_ddr4_dll_off_clk), //1-bitinput:Clockinput(S=1)
+ .S(clk_sel) //1-bitinput:Clockselect
+ );
+ //End of BUFGMUX_inst instantiation
+ `endif
+
+
+ wire frontend_ready;
+
+ frontend #(.SIM_MEM(SIM)) frontend(
+ .clk(c0_ddr4_clk),
+ .rst(c0_ddr4_rst),
+
+ .init_calib_complete(c0_init_calib_complete_r),
+ .softmc_fin(softmc_fin),
+ .user_rst(user_rst),
+
+ .dllt_begin(toggle_dll),
+
+ // indicates read_back unit is ready for the next iseq
+ .frontend_ready(frontend_ready),
+
+ // frontend <-> fetch stage if
+ .addr_in(fr_addr_in),
+ .valid_in(fr_valid_in),
+ .data_out(fr_data_out),
+ .valid_out(fr_valid_out),
+ .addr_out(fr_addr_out),
+ .ready_in(fr_ready_out),
+
+ // frontend <-> xdma interface
+ .h2c_tdata_0(m_axis_h2c_tdata_0),
+ .h2c_tlast_0(m_axis_h2c_tlast_0),
+ .h2c_tvalid_0(m_axis_h2c_tvalid_0),
+ .h2c_tready_0(m_axis_h2c_tready_0),
+ .h2c_tkeep_0(m_axis_h2c_tkeep_0),
+
+ .per_rd_init(per_rd_init),
+ .per_zq_init(per_zq_init),
+ .per_ref_init(per_ref_init),
+ .rbe_switch_mode(rbe_switch_mode)
+ );
+
+ ddr4_adapter#(
+ `ifdef XUPP3R
+ `ifdef XUPP3R_x8_1R_UDIMM
+ .DQ_WIDTH(64)
+ `else
+ .DQ_WIDTH(72)
+ `endif
+ `endif
+ ) ddr4_adapter
+ (
+ .clk(c0_ddr4_clk),
+ .rst(c0_ddr4_rst || user_rst),
+ .init_calib_complete(c0_init_calib_complete_r),
+ //.io_config_strobe,
+ //.io_config,
+ .dBufAdr(dBufAdr), // Reserved. Should be tied low.
+ .wrData(wrData), // DRAM write data. There are 8 bits for each DQ lane on the DRAM bus.
+ .wrDataMask(wrDataMask),// DRAM write DM/DBI port.There is one bit for each byte of the wrData port.
+ .wrDataEn(wrDataEn), // Write data Enable. The Phy will assert this port for one cycle for each write CAS command.
+ .mc_ACT_n(mc_ACT_n), // DRAM ACT_n command signal for four DRAM clock cycles.
+ .mc_ADR(mc_ADR), // DRAM address. There are 8 bits in the fabric interface for each address bit on the DRAM bus.
+ .mc_BA(mc_BA), // DRAM bank address. 8 bits for each DRAM bank address.
+ .mc_BG(mc_BG), // DRAM bank group address.
+ .mc_CS_n(mc_CS_n), // DRAM CS_n
+ .mc_CKE(mc_CKE), // DRAM CKE
+ //.mc_ODT(mc_ODT), // DRAM ODT
+ .mcRdCAS(mcRdCAS), // Read CAS command issued.
+ .mcWrCAS(mcWrCAS), // Write CAS command issued.
+ .winRank(winRank), // Target rank for CAS commands. This value indicates which rank a CAS command is issued to.
+ .winBuf(winBuf), // Optional control signal. When either mcRdCAS or mcWrCAS is asserted, the Phy will store the value on the winBuf signal.
+ //.rdData(rdData), // DRAM read data.
+ .rdDataEn(rdDataEn), // Read data valid. This signal asserts for one fabric cycle for each completed read operation.
+ .rdDataEnd(rdDataEnd), // Unused. Tied high.
+ .mcCasSlot(mcCasSlot),
+ .mcCasSlot2(mcCasSlot2),
+ .gt_data_ready(gt_data_ready),
+ .ddr_write(ddr_write),
+ .ddr_read(ddr_read),
+ .ddr_pre(ddr_pre),
+ .ddr_act(ddr_act),
+ .ddr_ref(ddr_ref),
+ .ddr_sre(ddr_sre),
+ .ddr_srx(ddr_srx),
+ .ddr_zq(ddr_zq),
+ .ddr_nop(ddr_nop),
+ .ddr_ap(ddr_ap),
+ .ddr_pall(ddr_pall),
+ .ddr_half_bl(ddr_half_bl),
+ .ddr_bg(ddr_bg),
+ .ddr_bank(ddr_bank),
+ .ddr_col(ddr_col),
+ .ddr_row(ddr_row),
+ .ddr_wdata(ddr_wdata),
+
+ .ddr_maint_read(per_rd_init)
+ );
+ `ifdef XUPP3R_x8
+ localparam ODTWRDEL = 5'd9;
+ localparam ODTWRDUR = 4'd6;
+ localparam ODTWRODEL = 5'd9;
+ localparam ODTWRODUR = 4'd6;
+ localparam ODTRDDEL = 5'd10;
+ localparam ODTRDDUR = 4'd6;
+ localparam ODTRDODEL = 5'd9;
+ localparam ODTRDODUR = 4'd6;
+ localparam ODTNOP = 16'h0000;
+ localparam ODTWR = 16'h0021;
+ localparam ODTRD = 16'h0012;
+ `elsif XUPP3R_x8_1R_UDIMM
+ localparam ODTWRDEL = 5'd9;
+ localparam ODTWRDUR = 4'd6;
+ localparam ODTWRODEL = 5'd9;
+ localparam ODTWRODUR = 4'd6;
+ localparam ODTRDDEL = 5'd9;
+ localparam ODTRDDUR = 4'd6;
+ localparam ODTRDODEL = 5'd9;
+ localparam ODTRDODUR = 4'd6;
+ localparam ODTNOP = 16'h0000;
+ localparam ODTWR = 16'h0001;
+ localparam ODTRD = 16'h0000;
+ `else
+ localparam ODTWRDEL = 5'd11;
+ localparam ODTWRDUR = 4'd6;
+ localparam ODTWRODEL = 5'd9;
+ localparam ODTWRODUR = 4'd6;
+ localparam ODTRDDEL = 5'd11;
+ localparam ODTRDDUR = 4'd6;
+ localparam ODTRDODEL = 5'd9;
+ localparam ODTRDODUR = 4'd6;
+ localparam ODTNOP = 16'h0000;
+ localparam ODTWR = 16'h0001;
+ localparam ODTRD = 16'h0000;
+ `endif
+
+ wire tranSentC;
+ assign tranSentC = mcRdCAS | mcWrCAS;
+
+ //synthesis translate_on
+ //*******************************************************************************
+ ddr4_mc_odt # (
+ .ODTWR (ODTWR)
+ ,.ODTWRDEL (ODTWRDEL)
+ ,.ODTWRDUR (ODTWRDUR)
+ ,.ODTWRODEL (ODTWRODEL)
+ ,.ODTWRODUR (ODTWRODUR)
+
+ ,.ODTRD (ODTRD)
+ ,.ODTRDDEL (ODTRDDEL)
+ ,.ODTRDDUR (ODTRDDUR)
+ ,.ODTRDODEL (ODTRDODEL)
+ ,.ODTRDODUR (ODTRDODUR)
+
+ ,.ODTNOP (ODTNOP)
+ ,.ODTBITS (`ODT_WIDTH)
+ ,.TCQ (0.1)
+ )u_ddr_tb_odt(
+ .clk (c0_ddr4_clk)
+ ,.rst (c0_ddr4_rst)
+ ,.mc_ODT (mc_ODT)
+ ,.casSlot (mcCasSlot)
+ ,.casSlot2 (mcCasSlot2)
+ ,.rank (winRank)
+ ,.winRead (mcRdCAS)
+ ,.winWrite (mcWrCAS)
+ ,.tranSentC (tranSentC)
+ );
+
+ wire sys_clk, sys_clk_gt;
+ wire [2:0] msi_vector_width;
+ wire msi_enable;
+ wire user_lnk_up, usr_irq_req, usr_irq_ack;
+ `ifdef XUPP3R
+ IBUFDS_GTE4 refclk_ibuf (.O(sys_clk_gt), .ODIV2(sys_clk), .I(clk_ref_p), .CEB(1'b0), .IB(clk_ref_n));
+ `else
+ IBUFDS_GTE3 # (.REFCLK_HROW_CK_SEL(2'b01)) refclk_ibuf (.O(sys_clk_gt), .ODIV2(sys_clk), .I(clk_ref_p), .CEB(1'b0), .IB(clk_ref_n));
+ `endif
+ wire axi_clk, axi_rst;
+
+ xdma xdma_i
+ (
+ //---------------------------------------------------------------------------------------//
+ // PCI Express (pci_exp) Interface //
+ //---------------------------------------------------------------------------------------//
+ .sys_rst_n ( pcie_rst ),
+ .sys_clk ( sys_clk ),
+ .sys_clk_gt ( sys_clk_gt),
+
+ // Tx
+ .pci_exp_txn ( pci_exp_txn ),
+ .pci_exp_txp ( pci_exp_txp ),
+
+ // Rx
+ .pci_exp_rxn ( pci_exp_rxn ),
+ .pci_exp_rxp ( pci_exp_rxp ),
+
+ // AXI streaming ports
+ .s_axis_c2h_tdata_0(xdma_c2h_tdata_0),
+ .s_axis_c2h_tlast_0(xdma_c2h_tlast_0),
+ .s_axis_c2h_tvalid_0(xdma_c2h_tvalid_0),
+ .s_axis_c2h_tready_0(xdma_c2h_tready_0),
+ .s_axis_c2h_tkeep_0(xdma_c2h_tkeep_0),
+ .m_axis_h2c_tdata_0(xdma_h2c_tdata_0),
+ .m_axis_h2c_tlast_0(xdma_h2c_tlast_0),
+ .m_axis_h2c_tvalid_0(xdma_h2c_tvalid_0),
+ .m_axis_h2c_tready_0(xdma_h2c_tready_0),
+ .m_axis_h2c_tkeep_0(xdma_h2c_tkeep_0),
+
+ .usr_irq_req (1'b0),
+ .usr_irq_ack (usr_irq_ack),
+ .msi_enable (msi_enable),
+ .msi_vector_width (msi_vector_width),
+
+
+ // Config managemnet interface
+ .cfg_mgmt_addr ( 19'b0 ),
+ .cfg_mgmt_write ( 1'b0 ),
+ .cfg_mgmt_write_data ( 32'b0 ),
+ .cfg_mgmt_byte_enable ( 4'b0 ),
+ .cfg_mgmt_read ( 1'b0 ),
+ .cfg_mgmt_read_data (),
+ .cfg_mgmt_read_write_done (),
+ `ifndef XUPP3R
+ .cfg_mgmt_type1_cfg_reg_access ( 1'b0 ),
+ //---------- Shared Logic Internal -------------------------
+ .int_qpll1lock_out ( ),
+ .int_qpll1outrefclk_out ( ),
+ .int_qpll1outclk_out ( ),
+ `endif
+
+ //-- AXI Global
+ .axi_aclk (axi_clk), // AXI i-face clock driven from pcie clk
+ .axi_aresetn (axi_rst), // reset synchronous to axi_clk
+
+ .user_lnk_up ( user_lnk_up )
+ );
+
+ // Clock converter for the c2h interface
+ axis_clock_converter axis_clk_conv_i0
+ (
+ .s_axis_tvalid(s_axis_c2h_tvalid_0),
+ .s_axis_tlast(s_axis_c2h_tlast_0),
+ .s_axis_tdata(s_axis_c2h_tdata_0),
+ .s_axis_tkeep(s_axis_c2h_tkeep_0),
+ .s_axis_tready(s_axis_c2h_tready_0),
+ .m_axis_tvalid(xdma_c2h_tvalid_0),
+ .m_axis_tlast(xdma_c2h_tlast_0),
+ .m_axis_tdata(xdma_c2h_tdata_0),
+ .m_axis_tkeep(xdma_c2h_tkeep_0),
+ .m_axis_tready(xdma_c2h_tready_0),
+ .s_axis_aresetn(~c0_ddr4_rst),
+ .s_axis_aclk(c0_ddr4_clk),
+ .m_axis_aresetn(axi_rst),
+ .m_axis_aclk(axi_clk)
+ );
+
+ // Clock converter for the h2c interface
+ axis_clock_converter axis_clk_conv_i1
+ (
+ .m_axis_tvalid(m_axis_h2c_tvalid_0),
+ .m_axis_tlast(m_axis_h2c_tlast_0),
+ .m_axis_tdata(m_axis_h2c_tdata_0),
+ .m_axis_tkeep(m_axis_h2c_tkeep_0),
+ .m_axis_tready(m_axis_h2c_tready_0),
+ .s_axis_tvalid(xdma_h2c_tvalid_0),
+ .s_axis_tlast(xdma_h2c_tlast_0),
+ .s_axis_tdata(xdma_h2c_tdata_0),
+ .s_axis_tkeep(xdma_h2c_tkeep_0),
+ .s_axis_tready(xdma_h2c_tready_0),
+ .m_axis_aresetn(~c0_ddr4_rst),
+ .m_axis_aclk(c0_ddr4_clk),
+ .s_axis_aresetn(axi_rst),
+ .s_axis_aclk(axi_clk)
+ );
+
+ readback_engine rbe(
+
+ // common signals
+ .clk(c0_ddr4_clk),
+ .rst(c0_ddr4_rst || user_rst),
+
+ // other ctrl signals
+ .flush(frontend_ready),
+ .switch_mode(rbe_switch_mode),
+ .read_seq_incoming(read_seq_incoming), // next few instructions will read from DRAM
+ .incoming_reads(incoming_reads), // how many reads next few instructions will issue
+ .buffer_space(buffer_space), // remaining buffer size
+ // DRAM <-> engine if
+ .rd_data(rdData),
+ .rd_valid(rdDataEn),
+
+ // rbe <-> rf interface
+ .ddr_wdata(ddr_wdata),
+
+ .per_rd_init(per_rd_init),
+ .per_zq_init(per_zq_init),
+ .per_ref_init(per_ref_init),
+
+ // rbe <-> xdma if
+ .c2h_tdata_0(s_axis_c2h_tdata_0),
+ .c2h_tlast_0(s_axis_c2h_tlast_0),
+ .c2h_tvalid_0(s_axis_c2h_tvalid_0),
+ .c2h_tready_0(s_axis_c2h_tready_0),
+ .c2h_tkeep_0(s_axis_c2h_tkeep_0)
+
+ );
+
+ `ifdef ENABLE_DLL_TOGGLER
+ dll_toggler dllt
+ (
+ .clk(c0_ddr4_clk),
+ .rst(c0_ddr4_rst || user_rst || ~c0_init_calib_complete_r),
+ .toggle_valid(toggle_dll),
+ .mc_ACT_n(dllt_mc_ACT_n), // DRAM ACT_n command signal for four DRAM clock cycles.
+ .mc_ADR(dllt_mc_ADR), // DRAM address. There are 8 bits in the fabric interface for each address bit on the DRAM bus.
+ .mc_BA(dllt_mc_BA), // DRAM bank address. 8 bits for each DRAM bank address.
+ .mc_BG(dllt_mc_BG), // DRAM bank group address.
+ .mc_CS_n(dllt_mc_CS_n), // DRAM CS_n
+ .mc_CKE(dllt_mc_CKE),
+ .clk_sel(clk_sel),
+ .dllt_done(dllt_done)
+ );
+ `endif
+endmodule