Commit b8040cc2 authored by Andrey Filippov's avatar Andrey Filippov

Continue re-organizing memory controller for x393

parent 27c9f81a
// This file may be used to define same pre-processor macros to be included into each parsed file
// It can be used to check different `ifdef branches
//`define XIL_TIMING //Simprim
`define IVERILOG
\ No newline at end of file
`define IVERILOG
// defines for memory channels
// chn 0 is read from memory
`define def_enable_mem_chn0
`define def_read_mem_chn0
// chn 1 is write to memory
`define def_enable_mem_chn1
`undef def_read_mem_chn1
// chn 2 is read from memory
`define def_enable_mem_chn2
`define def_read_mem_chn2
// chn 3 is write to memory
`define def_enable_mem_chn3
`undef def_read_mem_chn3
// chn 4 is disabled
`undef def_enable_mem_chn4
// chn 5 is disabled
`undef def_enable_mem_chn5
// chn 6 is disabled
`undef def_enable_mem_chn6
// chn 7 is disabled
`undef def_enable_mem_chn7
// chn 8 is disabled
`undef def_enable_mem_chn8
// chn 9 is disabled
`undef def_enable_mem_chn9
// chn 10 is disabled
`undef def_enable_mem_chn10
// chn 11 is disabled
`undef def_enable_mem_chn11
// chn 12 is disabled
`undef def_enable_mem_chn12
// chn 13 is disabled
`undef def_enable_mem_chn13
// chn 14 is disabled
`undef def_enable_mem_chn14
// chn 15 is disabled
`undef def_enable_mem_chn15
\ No newline at end of file
0x1000..103f - 0- bit data (set/reset)
parameter MCONTR_PHY_0BIT_ADDR = 'h020, // address to set sequnecer channel and run (4 LSB-s - channel)
parameter MCONTR_PHY_0BIT_ADDR_MASK = 'h3f0, // address mask to generate sequencer channel/run
0x1020 - DLY_SET // 0 bits -set pre-programmed delays
0x1024..1025 - CMDA_EN // 0 bits - enable/disable command/address outputs
0x1026..1027 - SDRST_ACT // 0 bits - enable/disable active-low reset signal to DDR3 memory
0x1028..1029 - CKE_EN // 0 bits - enable/disable CKE signal to memory
0x102a..102b - DCI_RST // 0 bits - enable/disable CKE signal to memory
0x102c..102d - DLY_RST // 0 bits - enable/disable CKE signal to memory
parameter MCONTR_PHY_0BIT_DLY_SET = 'h0, // set pre-programmed delays
parameter MCONTR_PHY_0BIT_CMDA_EN = 'h4, // enable/disable command/address outputs
parameter MCONTR_PHY_0BIT_SDRST_ACT = 'h6, // enable/disable active-low reset signal to DDR3 memory
parameter MCONTR_PHY_0BIT_CKE_EN = 'h8, // enable/disable CKE signal to memory
parameter MCONTR_PHY_0BIT_DCI_RST = 'ha, // enable/disable CKE signal to memory
parameter MCONTR_PHY_0BIT_DLY_RST = 'hc, // enable/disable CKE signal to memory
0x1040..107f - 16-bit data
0x1050..1057: MCONTR_PHY16
parameter MCONTR_PHY_16BIT_ADDR = 'h050, // address to set sequnecer channel and run (4 LSB-s - channel)
parameter MCONTR_PHY_16BIT_ADDR_MASK = 'h3f8, // address mask to generate sequencer channel/run
0x1050 - PATTERNS // 16 bits
0x1051 - PATTERNS_TRI // 16-bit address to set DQM and DQS tristate on/off patterns {dqs_off,dqs_on, dq_off,dq_on} - 4 bits each
0x1052 - WBUF_DELAY // 4 bits - extra delay (in mclk cycles) to add to write buffer enable (DDR3 read data)
0x1053 - EXTRA_REL // 1 bit - set extra parameters (currently just inv_clk_div)
0x1054 - STATUS_CNTRL // 8 bits - write to status control
parameter MCONTR_PHY_16BIT_PATTERNS = 'h0, // set DQM and DQS patterns (16'h0055)
parameter MCONTR_PHY_16BIT_PATTERNS_TRI = 'h1, // 16-bit address to set DQM and DQS tristate on/off patterns {dqs_off,dqs_on, dq_off,dq_on} - 4 bits each
parameter MCONTR_PHY_16BIT_WBUF_DELAY = 'h2, // 4 bits - extra delay (in mclk cycles) to add to write buffer enable (DDR3 read data)
parameter MCONTR_PHY_16BIT_EXTRA_REL = 'h3, // 1 bit - set extra parameters (currently just inv_clk_div)
parameter MCONTR_PHY_STATUS_CNTRL = 'h4, // 8 bits - write to status control
// Status read address
parameter STATUS_ADDR = 'h1400, // AXI write address of status read registers
parameter STATUS_ADDR_MASK = 'h1400, // AXI write address of status registers
parameter STATUS_DEPTH= 8, // 256 cells, maybe just 16..64 are enough?
parameter MCONTR_PHY_STATUS_REG_ADDR= 'h0, // 8 or less bits: status register address to use for memory controller phy
================================ OLD =======================================================
Control addresses (in original ddrc_test01)
0x1000..100f - RUN_CHN // address to set sequnecer channel and run (4 LSB-s - channel) - bits?
0x1020 - PATTERNS // 16 bits
0x1021 - PATTERNS_TRI // 16-bit address to set DQM and DQS tristate on/off patterns {dqs_off,dqs_on, dq_off,dq_on} - 4 bits each
0x1022 - WBUF_DELAY // 4? bits - extra delay (in mclk cycles) to add to write buffer enable (DDR3 read data)
0x1023 - PAGES // will be removed! 8 bits - address to set buffer pages {port1_page[1:0], port1_int_page[1:0], port0_page[1:0], port0_int_page[1:0]}
0x1024..1025 - CMDA_EN // 0 bits - enable/disable command/address outputs
0x1026..1027 - SDRST_ACT // 0 bits - enable/disable active-low reset signal to DDR3 memory
0x1028..1029 - CKE_EN // 0 bits - enable/disable CKE signal to memory
0x102a..102b - DCI_RST // 0 bits - enable/disable CKE signal to memory
0x102c..102d - DLY_RST // 0 bits - enable/disable CKE signal to memory
0x102e - EXTRA_REL // ? bits - set extra parameters (currently just inv_clk_div)
0x102f - X
0x1030..1031 - REFRESH_EN // 0 bits - enable/disable DDR refresh
0x1032 - REFRESH_PER // 16? bits - refresh period in 32 x tCK
0x1033 - REFRESH_ADDR // 16? bits - sequencer start address for DDR refresh
0x1070 - DLY_SET // 0 bits (set bit delays)
0x1080..10ff - DLY_LD // 8 bits :
0x1080..109f - set delay for SDD0-SDD7
0x10a0..10bf - set delay for SDD8-SDD15
0x10c0..10df - set delay for SD_CMDA
0x10e0 - set delay for MMCM
parameter WBUF_DELAY_REL_MASK = 'h3ff, // address mask to set extra delay
parameter PAGES_REL = 'h023, // address to set buffer pages {port1_page[1:0],port1_int_page[1:0],port0_page[1:0],port0_int_page[1:0]}
parameter PAGES_REL_MASK = 'h3ff, // address mask to set DQM and DQS patterns
parameter CMDA_EN_REL = 'h024, // address to enable('h825)/disable('h824) command/address outputs
parameter CMDA_EN_REL_MASK = 'h3fe, // address mask for command/address outputs
parameter SDRST_ACT_REL = 'h026, // address to activate('h827)/deactivate('h826) active-low reset signal to DDR3 memory
parameter SDRST_ACT_REL_MASK = 'h3fe, // address mask for reset DDR3
parameter CKE_EN_REL = 'h028, // address to enable('h829)/disable('h828) CKE signal to memory
parameter CKE_EN_REL_MASK = 'h3fe, // address mask for command/address outputs
parameter DCI_RST_REL = 'h02a, // address to activate('h82b)/deactivate('h82a) Zynq DCI calibrate circuitry
parameter DCI_RST_REL_MASK = 'h3fe, // address mask for DCI calibrate circuitry
parameter DLY_RST_REL = 'h02c, // address to activate('h82d)/deactivate('h82c) delay calibration circuitry
parameter DLY_RST_REL_MASK = 'h3fe, // address mask for delay calibration circuitry
parameter EXTRA_REL = 'h02e, // address to set extra parameters (currently just inv_clk_div)
parameter EXTRA_REL_MASK = 'h3ff, // address mask for extra parameters
parameter REFRESH_EN_REL = 'h030, // address to enable('h31) and disable ('h30) DDR refresh
parameter REFRESH_EN_REL_MASK = 'h3fe, // address mask to enable/disable DDR refresh
parameter REFRESH_PER_REL = 'h032, // address to set refresh period in 32 x tCK
parameter REFRESH_PER_REL_MASK = 'h3ff, // address mask set refresh period
parameter REFRESH_ADDR_REL = 'h033, // address to set sequencer start address for DDR refresh
parameter REFRESH_ADDR_REL_MASK = 'h3ff // address mask set refresh sequencer address
......@@ -1689,7 +1689,6 @@ simul_axi_read simul_axi_read_i(
@(posedge CLK)
axi_write_single(cmd_addr, data);
cmd_addr <= cmd_addr + 4;
end
// nop
......
......@@ -22,7 +22,56 @@
`define use200Mhz 1
`define DEBUG_FIFO 1
module memctrl16 #(
parameter pri_width=16,
//command interface parameters
parameter DLY_LD = 'h080, // address to generate delay load
parameter DLY_LD_MASK = 'h380, // address mask to generate delay load
//0x1000..103f - 0- bit data (set/reset)
parameter MCONTR_PHY_0BIT_ADDR = 'h020, // address to set sequnecer channel and run (4 LSB-s - channel)
parameter MCONTR_PHY_0BIT_ADDR_MASK = 'h3f0, // address mask to generate sequencer channel/run
// 0x1020 - DLY_SET // 0 bits -set pre-programmed delays
// 0x1024..1025 - CMDA_EN // 0 bits - enable/disable command/address outputs
// 0x1026..1027 - SDRST_ACT // 0 bits - enable/disable active-low reset signal to DDR3 memory
// 0x1028..1029 - CKE_EN // 0 bits - enable/disable CKE signal to memory
// 0x102a..102b - DCI_RST // 0 bits - enable/disable CKE signal to memory
// 0x102c..102d - DLY_RST // 0 bits - enable/disable CKE signal to memory
parameter MCONTR_PHY_0BIT_DLY_SET = 'h0, // set pre-programmed delays
parameter MCONTR_PHY_0BIT_CMDA_EN = 'h4, // enable/disable command/address outputs
parameter MCONTR_PHY_0BIT_SDRST_ACT = 'h6, // enable/disable active-low reset signal to DDR3 memory
parameter MCONTR_PHY_0BIT_CKE_EN = 'h8, // enable/disable CKE signal to memory
parameter MCONTR_PHY_0BIT_DCI_RST = 'ha, // enable/disable CKE signal to memory
parameter MCONTR_PHY_0BIT_DLY_RST = 'hc, // enable/disable CKE signal to memory
//0x1040..107f - 16-bit data
// 0x1040..104f - RUN_CHN // address to set sequncer channel and run (4 LSB-s - channel) - bits?
// parameter RUN_CHN_REL = 'h040, // address to set sequnecer channel and run (4 LSB-s - channel)
// parameter RUN_CHN_REL_MASK = 'h3f0, // address mask to generate sequencer channel/run
// 0x1050..1057: MCONTR_PHY16
parameter MCONTR_PHY_16BIT_ADDR = 'h050, // address to set sequnecer channel and run (4 LSB-s - channel)
parameter MCONTR_PHY_16BIT_ADDR_MASK = 'h3f8, // address mask to generate sequencer channel/run
// 0x1050 - PATTERNS // 16 bits
// 0x1051 - PATTERNS_TRI // 16-bit address to set DQM and DQS tristate on/off patterns {dqs_off,dqs_on, dq_off,dq_on} - 4 bits each
// 0x1052 - WBUF_DELAY // 4 bits - extra delay (in mclk cycles) to add to write buffer enable (DDR3 read data)
// 0x1053 - EXTRA_REL // 1 bit - set extra parameters (currently just inv_clk_div)
// 0x1054 - STATUS_CNTRL // 8 bits - write to status control
parameter MCONTR_PHY_16BIT_PATTERNS = 'h0, // set DQM and DQS patterns (16'h0055)
parameter MCONTR_PHY_16BIT_PATTERNS_TRI = 'h1, // 16-bit address to set DQM and DQS tristate on/off patterns {dqs_off,dqs_on, dq_off,dq_on} - 4 bits each
parameter MCONTR_PHY_16BIT_WBUF_DELAY = 'h2, // 4? bits - extra delay (in mclk cycles) to add to write buffer enable (DDR3 read data)
parameter MCONTR_PHY_16BIT_EXTRA = 'h3, // ? bits - set extra parameters (currently just inv_clk_div)
parameter MCONTR_PHY_STATUS_CNTRL = 'h4, // write to status control (8-bit)
// Status read address
parameter MCONTR_PHY_STATUS_REG_ADDR= 'h0, // 8 or less bits: status register address to use for memory controller phy
parameter CHNBUF_READ_LATENCY = 0, // external channel buffer extra read latency ( 0 - data available next cycle after re (but prev. data))
parameter DFLT_DQS_PATTERN= 8'h55,
parameter DFLT_DQM_PATTERN= 8'h00, // 8'h00
parameter DFLT_DQ_TRI_ON_PATTERN= 4'h7, // DQ tri-state control word, first when enabling output
parameter DFLT_DQ_TRI_OFF_PATTERN= 4'he, // DQ tri-state control word, first after disabling output
parameter DFLT_DQS_TRI_ON_PATTERN= 4'h3, // DQS tri-state control word, first when enabling output
parameter DFLT_DQS_TRI_OFF_PATTERN=4'hc,// DQS tri-state control word, first after disabling output
parameter DFLT_WBUF_DELAY= 4'h6, // write levelling - 7!
parameter DFLT_INV_CLK_DIV= 1'b0,
parameter integer ADDRESS_NUMBER=15,
// parameter pri_width=16,
parameter PHASE_WIDTH = 8,
parameter SLEW_DQ = "SLOW",
parameter SLEW_DQS = "SLOW",
......@@ -55,69 +104,337 @@ module memctrl16 #(
parameter SS_MODE = "CENTER_HIGH",
parameter SS_MOD_PERIOD = 10000,
parameter CMD_PAUSE_BITS= 10,
parameter CMD_DONE_BIT= 10,
parameter AXI_WR_ADDR_BITS = 13,
parameter AXI_RD_ADDR_BITS = 13,
parameter CONTROL_ADDR = 'h1000, // AXI write address of control write registers
parameter CONTROL_ADDR_MASK = 'h1400, // AXI write address of control registers
parameter STATUS_ADDR = 'h1400, // AXI write address of status read registers
parameter STATUS_ADDR_MASK = 'h1400, // AXI write address of status registers
parameter BUSY_WR_ADDR = 'h1800, // AXI write address to generate busy
parameter BUSY_WR_ADDR_MASK = 'h1c00, // AXI write address mask to generate busy
parameter CMD0_ADDR = 'h0800, // AXI write to command sequence memory
parameter CMD0_ADDR_MASK = 'h1800, // AXI read address mask for the command sequence memory
parameter PORT0_RD_ADDR = 'h0000, // AXI read address to generate busy
parameter PORT0_RD_ADDR_MASK = 'h1c00, // AXI read address mask to generate busy
parameter PORT1_WR_ADDR = 'h0400, // AXI read address to generate busy
parameter PORT1_WR_ADDR_MASK = 'h1c00, // AXI read address mask to generate busy
// parameters below to be ORed with CONTROL_ADDR and CONTROL_ADDR_MASK respectively
parameter DLY_LD_REL = 'h080, // address to generate delay load
parameter DLY_LD_REL_MASK = 'h380, // address mask to generate delay load
parameter DLY_SET_REL = 'h070, // address to generate delay set
parameter DLY_SET_REL_MASK = 'h3ff, // address mask to generate delay set
parameter RUN_CHN_REL = 'h000, // address to set sequnecer channel and run (4 LSB-s - channel)
parameter RUN_CHN_REL_MASK = 'h3f0, // address mask to generate sequencer channel/run
parameter PATTERNS_REL = 'h020, // address to set DQM and DQS patterns (16'h0055)
parameter PATTERNS_REL_MASK = 'h3ff, // address mask to set DQM and DQS patterns
parameter PATTERNS_TRI_REL = 'h021, // address to set DQM and DQS tristate on/off patterns {dqs_off,dqs_on, dq_off,dq_on} - 4 bits each
parameter PATTERNS_TRI_REL_MASK = 'h3ff, // address mask to set DQM and DQS tristate patterns
parameter WBUF_DELAY_REL = 'h022, // extra delay (in mclk cycles) to add to write buffer enable (DDR3 read data)
parameter WBUF_DELAY_REL_MASK = 'h3ff, // address mask to set extra delay
parameter PAGES_REL = 'h023, // address to set buffer pages {port1_page[1:0],port1_int_page[1:0],port0_page[1:0],port0_int_page[1:0]}
parameter PAGES_REL_MASK = 'h3ff, // address mask to set DQM and DQS patterns
parameter CMDA_EN_REL = 'h024, // address to enable('h825)/disable('h824) command/address outputs
parameter CMDA_EN_REL_MASK = 'h3fe, // address mask for command/address outputs
parameter SDRST_ACT_REL = 'h026, // address to activate('h827)/deactivate('h826) active-low reset signal to DDR3 memory
parameter SDRST_ACT_REL_MASK = 'h3fe, // address mask for reset DDR3
parameter CKE_EN_REL = 'h028, // address to enable('h829)/disable('h828) CKE signal to memory
parameter CKE_EN_REL_MASK = 'h3fe, // address mask for command/address outputs
parameter DCI_RST_REL = 'h02a, // address to activate('h82b)/deactivate('h82a) Zynq DCI calibrate circuitry
parameter DCI_RST_REL_MASK = 'h3fe, // address mask for DCI calibrate circuitry
parameter DLY_RST_REL = 'h02c, // address to activate('h82d)/deactivate('h82c) delay calibration circuitry
parameter DLY_RST_REL_MASK = 'h3fe, // address mask for delay calibration circuitry
parameter EXTRA_REL = 'h02e, // address to set extra parameters (currently just inv_clk_div)
parameter EXTRA_REL_MASK = 'h3ff, // address mask for extra parameters
parameter REFRESH_EN_REL = 'h030, // address to enable('h31) and disable ('h30) DDR refresh
parameter REFRESH_EN_REL_MASK = 'h3fe, // address mask to enable/disable DDR refresh
parameter REFRESH_PER_REL = 'h032, // address to set refresh period in 32 x tCK
parameter REFRESH_PER_REL_MASK = 'h3ff, // address mask set refresh period
parameter REFRESH_ADDR_REL = 'h033, // address to set sequencer start address for DDR refresh
parameter REFRESH_ADDR_REL_MASK = 'h3ff // address mask set refresh sequencer address
parameter CMD_DONE_BIT= 10
) (
input rst,
input clk,
input clk_in,
input rst_in,
output mclk, // global clock, half DDR3 clock, synchronizes all I/O thorough the command port
/*
input [15:0] want_rq, // both want_rq and need_rq should go inactive after being granted
input [15:0] need_rq,
output [15:0] channel_pgm_en, // channel can program sequence data
input [511:0] seq_data, //16x32 data to be written to the sequencer (and start address for software-based sequencer)
input [15:0] seq_wr, // strobe for writing sequencer data (address is autoincremented)
input [15:0] seq_done, // channel sequencer data is written. If no seq_wr pulses before seq_done, seq_data contains software sequencer start address
*/
// programming interface
input [7:0] cmd_ad, // byte-serial command address/data (up to 6 bytes: AL-AH-D0-D1-D2-D3
input cmd_stb, // strobe (with first byte) for the command a/d
output [7:0] status_ad, // status address/data - up to 5 bytes: A - {seq,status[1:0]} - status[2:9] - status[10:17] - status[18:25]
output status_rq, // input request to send status downstream
input status_start, // Acknowledge of the first status packet byte (address)
// channel interfaces TODO: move request/grant here, add "done"
// channel 0 interface
`ifdef def_enable_mem_chn0
input want_rq0, // both want_rq and need_rq should go inactive after being granted
input need_rq0,
output channel_pgm_en0, // channel can program sequence data
input [31:0] seq_data0, //16x32 data to be written to the sequencer (and start address for software-based sequencer)
input seq_wr0, // strobe for writing sequencer data (address is autoincremented)
input seq_done0, // channel sequencer data is written. If no seq_wr pulses before seq_done, seq_data contains software sequencer start address
`ifdef def_read_mem_chn0
output buf_wr_chn0,
output [6:0] buf_waddr_chn0,
output [63:0] buf_wdata_chn0,
`else
output buf_rd_chn0,
output [6:0] buf_raddr_chn0,
input [63:0] buf_rdata_chn0,
`endif
`endif
// channel 1 interface
`ifdef def_enable_mem_chn1
input want_rq1, // both want_rq and need_rq should go inactive after being granted
input need_rq1,
output channel_pgm_en1, // channel can program sequence data
input [31:0] seq_data1, //16x32 data to be written to the sequencer (and start address for software-based sequencer)
input seq_wr1, // strobe for writing sequencer data (address is autoincremented)
input seq_done1, // channel sequencer data is written. If no seq_wr pulses before seq_done, seq_data contains software sequencer start address
`ifdef def_read_mem_chn1
output buf_wr_chn1,
output [6:0] buf_waddr_chn1,
output [63:0] buf_wdata_chn1,
`else
output buf_rd_chn1,
output [6:0] buf_raddr_chn1,
input [63:0] buf_rdata_chn1,
`endif
`endif
// channel 2 interface
`ifdef def_enable_mem_chn2
input want_rq2, // both want_rq and need_rq should go inactive after being granted
input need_rq2,
output channel_pgm_en2, // channel can program sequence data
input [31:0] seq_data2, //16x32 data to be written to the sequencer (and start address for software-based sequencer)
input seq_wr2, // strobe for writing sequencer data (address is autoincremented)
input seq_done2, // channel sequencer data is written. If no seq_wr pulses before seq_done, seq_data contains software sequencer start address
`ifdef def_read_mem_chn2
output buf_wr_chn2,
output [6:0] buf_waddr_chn2,
output [63:0] buf_wdata_chn2,
`else
output buf_rd_chn2,
output [6:0] buf_raddr_chn2,
input [63:0] buf_rdata_chn2,
`endif
`endif
// channel 3 interface
`ifdef def_enable_mem_chn3
input want_rq3, // both want_rq and need_rq should go inactive after being granted
input need_rq3,
output channel_pgm_en3, // channel can program sequence data
input [31:0] seq_data3, //16x32 data to be written to the sequencer (and start address for software-based sequencer)
input seq_wr3, // strobe for writing sequencer data (address is autoincremented)
input seq_done3, // channel sequencer data is written. If no seq_wr pulses before seq_done, seq_data contains software sequencer start address
`ifdef def_read_mem_chn3
output buf_wr_chn3,
output [6:0] buf_waddr_chn3,
output [63:0] buf_wdata_chn3,
`else
output buf_rd_chn3,
output [6:0] buf_raddr_chn3,
input [63:0] buf_rdata_chn3,
`endif
`endif
// channel 4 interface
`ifdef def_enable_mem_chn4
input want_rq4, // both want_rq and need_rq should go inactive after being granted
input need_rq4,
output channel_pgm_en4, // channel can program sequence data
input [31:0] seq_data4, //16x32 data to be written to the sequencer (and start address for software-based sequencer)
input seq_wr4, // strobe for writing sequencer data (address is autoincremented)
input seq_done4, // channel sequencer data is written. If no seq_wr pulses before seq_done, seq_data contains software sequencer start address
`ifdef def_read_mem_chn4
output buf_wr_chn4,
output [6:0] buf_waddr_chn4,
output [63:0] buf_wdata_chn4,
`else
output buf_rd_chn4,
output [6:0] buf_raddr_chn4,
input [63:0] buf_rdata_chn4,
`endif
`endif
// channel 5 interface
`ifdef def_enable_mem_chn5
input want_rq5, // both want_rq and need_rq should go inactive after being granted
input need_rq5,
output channel_pgm_en5, // channel can program sequence data
input [31:0] seq_data5, //16x32 data to be written to the sequencer (and start address for software-based sequencer)
input seq_wr5, // strobe for writing sequencer data (address is autoincremented)
input seq_done5, // channel sequencer data is written. If no seq_wr pulses before seq_done, seq_data contains software sequencer start address
`ifdef def_read_mem_chn5
output buf_wr_chn5,
output [6:0] buf_waddr_chn5,
output [63:0] buf_wdata_chn5,
`else
output buf_rd_chn5,
output [6:0] buf_raddr_chn5,
input [63:0] buf_rdata_chn5,
`endif
`endif
// channel 6 interface
`ifdef def_enable_mem_chn6
input want_rq6, // both want_rq and need_rq should go inactive after being granted
input need_rq6,
output channel_pgm_en6, // channel can program sequence data
input [31:0] seq_data6, //16x32 data to be written to the sequencer (and start address for software-based sequencer)
input seq_wr6, // strobe for writing sequencer data (address is autoincremented)
input seq_done6, // channel sequencer data is written. If no seq_wr pulses before seq_done, seq_data contains software sequencer start address
`ifdef def_read_mem_chn6
output buf_wr_chn6,
output [6:0] buf_waddr_chn6,
output [63:0] buf_wdata_chn6,
`else
output buf_rd_chn6,
output [6:0] buf_raddr_chn6,
input [63:0] buf_rdata_chn6,
`endif
`endif
// channel 7 interface
`ifdef def_enable_mem_chn7
input want_rq7, // both want_rq and need_rq should go inactive after being granted
input need_rq7,
output channel_pgm_en7, // channel can program sequence data
input [31:0] seq_data7, //16x32 data to be written to the sequencer (and start address for software-based sequencer)
input seq_wr7, // strobe for writing sequencer data (address is autoincremented)
input seq_done7, // channel sequencer data is written. If no seq_wr pulses before seq_done, seq_data contains software sequencer start address
`ifdef def_read_mem_chn7
output buf_wr_chn7,
output [6:0] buf_waddr_chn7,
output [63:0] buf_wdata_chn7,
`else
output buf_rd_chn7,
output [6:0] buf_raddr_chn7,
input [63:0] buf_rdata_chn7,
`endif
`endif
// channel 8 interface
`ifdef def_enable_mem_chn8
input want_rq8, // both want_rq and need_rq should go inactive after being granted
input need_rq8,
output channel_pgm_en8, // channel can program sequence data
input [31:0] seq_data8, //16x32 data to be written to the sequencer (and start address for software-based sequencer)
input seq_wr8, // strobe for writing sequencer data (address is autoincremented)
input seq_done8, // channel sequencer data is written. If no seq_wr pulses before seq_done, seq_data contains software sequencer start address
`ifdef def_read_mem_chn8
output buf_wr_chn8,
output [6:0] buf_waddr_chn8,
output [63:0] buf_wdata_chn8,
`else
output buf_rd_chn8,
output [6:0] buf_raddr_chn8,
input [63:0] buf_rdata_chn8,
`endif
`endif
// channel 9 interface
`ifdef def_enable_mem_chn9
input want_rq9, // both want_rq and need_rq should go inactive after being granted
input need_rq9,
output channel_pgm_en9, // channel can program sequence data
input [31:0] seq_data9, //16x32 data to be written to the sequencer (and start address for software-based sequencer)
input seq_wr9, // strobe for writing sequencer data (address is autoincremented)
input seq_done9, // channel sequencer data is written. If no seq_wr pulses before seq_done, seq_data contains software sequencer start address
`ifdef def_read_mem_chn9
output buf_wr_chn9,
output [6:0] buf_waddr_chn9,
output [63:0] buf_wdata_chn9,
`else
output buf_rd_chn9,
output [6:0] buf_raddr_chn9,
input [63:0] buf_rdata_chn9,
`endif
`endif
// channel 10 interface
`ifdef def_enable_mem_chn10
input want_rq10, // both want_rq and need_rq should go inactive after being granted
input need_rq10,
output channel_pgm_en10, // channel can program sequence data
input [31:0] seq_data10, //16x32 data to be written to the sequencer (and start address for software-based sequencer)
input seq_wr10, // strobe for writing sequencer data (address is autoincremented)
input seq_done10, // channel sequencer data is written. If no seq_wr pulses before seq_done, seq_data contains software sequencer start address
`ifdef def_read_mem_chn10
output buf_wr_chn10,
output [6:0] buf_waddr_chn10,
output [63:0] buf_wdata_chn10,
`else
output buf_rd_chn10,
output [6:0] buf_raddr_chn10,
input [63:0] buf_rdata_chn10,
`endif
`endif
// channel 11 interface
`ifdef def_enable_mem_chn11
input want_rq11, // both want_rq and need_rq should go inactive after being granted
input need_rq11,
output channel_pgm_en11, // channel can program sequence data
input [31:0] seq_data11, //16x32 data to be written to the sequencer (and start address for software-based sequencer)
input seq_wr11, // strobe for writing sequencer data (address is autoincremented)
input seq_done11, // channel sequencer data is written. If no seq_wr pulses before seq_done, seq_data contains software sequencer start address
`ifdef def_read_mem_chn11
output buf_wr_chn11,
output [6:0] buf_waddr_chn11,
output [63:0] buf_wdata_chn11,
`else
output buf_rd_chn11,
output [6:0] buf_raddr_chn11,
input [63:0] buf_rdata_chn11,
`endif
`endif
// channel 12 interface
`ifdef def_enable_mem_chn12
input want_rq12, // both want_rq and need_rq should go inactive after being granted
input need_rq12,
output channel_pgm_en12, // channel can program sequence data
input [31:0] seq_data12, //16x32 data to be written to the sequencer (and start address for software-based sequencer)
input seq_wr12, // strobe for writing sequencer data (address is autoincremented)
input seq_done12, // channel sequencer data is written. If no seq_wr pulses before seq_done, seq_data contains software sequencer start address
`ifdef def_read_mem_chn12
output buf_wr_chn12,
output [6:0] buf_waddr_chn12,
output [63:0] buf_wdata_chn12,
`else
output buf_rd_chn12,
output [6:0] buf_raddr_chn12,
input [63:0] buf_rdata_chn12,
`endif
`endif
// channel 13 interface
`ifdef def_enable_mem_chn13
input want_rq13, // both want_rq and need_rq should go inactive after being granted
input need_rq13,
output channel_pgm_en13, // channel can program sequence data
input [31:0] seq_data13, //16x32 data to be written to the sequencer (and start address for software-based sequencer)
input seq_wr13, // strobe for writing sequencer data (address is autoincremented)
input seq_done13, // channel sequencer data is written. If no seq_wr pulses before seq_done, seq_data contains software sequencer start address
`ifdef def_read_mem_chn13
output buf_wr_chn13,
output [6:0] buf_waddr_chn13,
output [63:0] buf_wdata_chn13,
`else
output buf_rd_chn13,
output [6:0] buf_raddr_chn13,
input [63:0] buf_rdata_chn13,
`endif
`endif
// channel 14 interface
`ifdef def_enable_mem_chn14
input want_rq14, // both want_rq and need_rq should go inactive after being granted
input need_rq14,
output channel_pgm_en14, // channel can program sequence data
input [31:0] seq_data14, //16x32 data to be written to the sequencer (and start address for software-based sequencer)
input seq_wr14, // strobe for writing sequencer data (address is autoincremented)
input seq_done14, // channel sequencer data is written. If no seq_wr pulses before seq_done, seq_data contains software sequencer start address
`ifdef def_read_mem_chn14
output buf_wr_chn14,
output [6:0] buf_waddr_chn14,
output [63:0] buf_wdata_chn14,
`else
output buf_rd_chn14,
output [6:0] buf_raddr_chn14,
input [63:0] buf_rdata_chn14,
`endif
`endif
// channel 15 interface
`ifdef def_enable_mem_chn15
input want_rq15, // both want_rq and need_rq should go inactive after being granted
input need_rq15,
output channel_pgm_en15, // channel can program sequence data
input [31:0] seq_data15, //16x32 data to be written to the sequencer (and start address for software-based sequencer)
input seq_wr15, // strobe for writing sequencer data (address is autoincremented)
input seq_done15, // channel sequencer data is written. If no seq_wr pulses before seq_done, seq_data contains software sequencer start address
`ifdef def_read_mem_chn15
output buf_wr_chn15,
output [6:0] buf_waddr_chn15,
output [63:0] buf_wdata_chn15,
`else
output buf_rd_chn15,
output [6:0] buf_raddr_chn15,
input [63:0] buf_rdata_chn15,
`endif
`endif
// priority programming
// TODO: Move to ps7 instance in this module
input [3:0] pgm_addr, // channel address to program priority
input [width-1:0] pgm_data, // priority data for the channel
input pgm_en, // enable programming priority data (use different clock?)
// input [3:0] pgm_addr, // channel address to program priority
// input [width-1:0] pgm_data, // priority data for the channel
// input pgm_en, // enable programming priority data (use different clock?)
// DDR3 interface
output SDRST, // DDR3 reset (active low)
output SDCLK, // DDR3 clock differential output, positive
......@@ -140,8 +457,471 @@ module memctrl16 #(
// output DUMMY_TO_KEEP // to keep PS7 signals from "optimization"
// input MEMCLK
);
// TODO: copy from ddrc_test01.v
wire rst=rst_in; // TODO: decide where toi generate
wire ext_buf_rd;
wire [6:0] ext_buf_raddr;
wire [3:0] ext_buf_rchn;
wire [63:0] ext_buf_rdata;
wire ext_buf_wr;
wire [6:0] ext_buf_waddr;
wire [3:0] ext_buf_wchn;
wire [63:0] ext_buf_wdata;
wire [11:0] tmp_debug;
wire [15:0] want_rq; // both want_rq and need_rq should go inactive after being granted
wire [15:0] need_rq;
wire [15:0] channel_pgm_en; // channel can program sequence data
wire [511:0] seq_data; //16x32 data to be written to the sequencer (and start address for software-based sequencer)
wire [15:0] seq_wr; // strobe for writing sequencer data (address is autoincremented)
wire [15:0] seq_done; // channel sequencer data is written. If no seq_wr pulses before seq_done, seq_data contains software sequencer start address
/*
input [15:0] want_rq, // both want_rq and need_rq should go inactive after being granted
input [15:0] need_rq,
output [15:0] channel_pgm_en, // channel can program sequence data
input [511:0] seq_data, //16x32 data to be written to the sequencer (and start address for software-based sequencer)
input [15:0] seq_wr, // strobe for writing sequencer data (address is autoincremented)
input [15:0] seq_done, // channel sequencer data is written. If no seq_wr pulses before seq_done, seq_data contains software sequencer start address
*/
// status data from phy (sequencer)
wire [7:0] status_ad_phy;
wire status_rq_phy;
wire status_start_phy;
// status data from top level controller
wire [7:0] status_ad_mcontr;
wire status_rq_mcontr;
wire status_start_mcontr;
// TODO: implement
assign status_ad_mcontr=0;
assign status_rq_mcontr=0;
// mux status info from the memory controller and other modules
status_router2 status_router2_top_i (
.rst (rst), // input
.clk (mclk), // input
.db_in0 (status_ad_phy), // input[7:0]
.rq_in0 (status_rq_phy), // input
.start_in0 (status_start_phy), // output
.db_in1 (status_ad_mcontr), // input[7:0]
.rq_in1 (status_rq_mcontr), // input
.start_in1 (status_start_mcontr), // output
.db_out (status_ad), // output[7:0]
.rq_out (status_rq), // output
.start_out (status_start) // input
);
/* Instance template for module mcontr_sequencer */
mcontr_sequencer #(
.DLY_LD (DLY_LD),
.DLY_LD_MASK (DLY_LD_MASK),
.MCONTR_PHY_0BIT_ADDR (MCONTR_PHY_0BIT_ADDR),
.MCONTR_PHY_0BIT_ADDR_MASK (MCONTR_PHY_0BIT_ADDR_MASK),
.MCONTR_PHY_0BIT_DLY_SET (MCONTR_PHY_0BIT_DLY_SET),
.MCONTR_PHY_0BIT_CMDA_EN (MCONTR_PHY_0BIT_CMDA_EN),
.MCONTR_PHY_0BIT_SDRST_ACT (MCONTR_PHY_0BIT_SDRST_ACT),
.MCONTR_PHY_0BIT_CKE_EN (MCONTR_PHY_0BIT_CKE_EN),
.MCONTR_PHY_0BIT_DCI_RST (MCONTR_PHY_0BIT_DCI_RST),
.MCONTR_PHY_0BIT_DLY_RST (MCONTR_PHY_0BIT_DLY_RST),
.MCONTR_PHY_STATUS_REG_ADDR (MCONTR_PHY_STATUS_REG_ADDR),
.MCONTR_PHY_16BIT_ADDR (MCONTR_PHY_16BIT_ADDR),
.MCONTR_PHY_16BIT_ADDR_MASK (MCONTR_PHY_16BIT_ADDR_MASK),
.MCONTR_PHY_16BIT_PATTERNS (MCONTR_PHY_16BIT_PATTERNS),
.MCONTR_PHY_16BIT_PATTERNS_TRI (MCONTR_PHY_16BIT_PATTERNS_TRI),
.MCONTR_PHY_16BIT_WBUF_DELAY (MCONTR_PHY_16BIT_WBUF_DELAY),
.MCONTR_PHY_16BIT_EXTRA (MCONTR_PHY_16BIT_EXTRA),
.MCONTR_PHY_STATUS_CNTRL (MCONTR_PHY_STATUS_CNTRL),
.DFLT_DQS_PATTERN (DFLT_DQS_PATTERN),
.DFLT_DQM_PATTERN (DFLT_DQM_PATTERN),
.DFLT_DQ_TRI_ON_PATTERN (DFLT_DQ_TRI_ON_PATTERN),
.DFLT_DQ_TRI_OFF_PATTERN (DFLT_DQ_TRI_OFF_PATTERN),
.DFLT_DQS_TRI_ON_PATTERN (DFLT_DQS_TRI_ON_PATTERN),
.DFLT_DQS_TRI_OFF_PATTERN (DFLT_DQS_TRI_OFF_PATTERN),
.DFLT_WBUF_DELAY (DFLT_WBUF_DELAY),
.DFLT_INV_CLK_DIV (DFLT_INV_CLK_DIV),
.PHASE_WIDTH (PHASE_WIDTH),
.SLEW_DQ (SLEW_DQ),
.SLEW_DQS (SLEW_DQS),
.SLEW_CMDA (SLEW_CMDA),
.SLEW_CLK (SLEW_CLK),
.IBUF_LOW_PWR (IBUF_LOW_PWR),
.REFCLK_FREQUENCY (REFCLK_FREQUENCY),
.HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
.CLKIN_PERIOD (CLKIN_PERIOD),
.CLKFBOUT_MULT (CLKFBOUT_MULT),
.CLKFBOUT_MULT_REF (CLKFBOUT_MULT_REF),
.CLKFBOUT_DIV_REF (CLKFBOUT_DIV_REF),
.DIVCLK_DIVIDE (DIVCLK_DIVIDE),
.CLKFBOUT_PHASE (CLKFBOUT_PHASE),
.SDCLK_PHASE (SDCLK_PHASE),
.CLK_PHASE (CLK_PHASE),
.CLK_DIV_PHASE (CLK_DIV_PHASE),
.MCLK_PHASE (MCLK_PHASE),
.REF_JITTER1 (REF_JITTER1),
.SS_EN (SS_EN),
.SS_MODE (SS_MODE),
.SS_MOD_PERIOD (SS_MOD_PERIOD),
.CMD_PAUSE_BITS (CMD_PAUSE_BITS),
.CMD_DONE_BIT (CMD_DONE_BIT)
) mcontr_sequencer_i (
.SDRST (SDRST), // output
.SDCLK (SDCLK), // output
.SDNCLK (SDNCLK), // output
.SDA (SDA[14:0]), // output[14:0] // BUG with localparam - fixed
.SDBA (SDBA[2:0]), // output[2:0]
.SDWE (SDWE), // output
.SDRAS (SDRAS), // output
.SDCAS (SDCAS), // output
.SDCKE (SDCKE), // output
.SDODT (SDODT), // output
.SDD (SDD[15:0]), // inout[15:0]
.SDDML (SDDML), // inout
.DQSL (DQSL), // inout
.NDQSL (NDQSL), // inout
.SDDMU (SDDMU), // inout
.DQSU (DQSU), // inout
.NDQSU (NDQSU), // inout
.clk_in (clk_in), // axi_aclk), // input
.rst_in (rst_in), // axi_rst), // input TODO: move buffer outside?
.mclk (mclk), // output
.cmd0_clk (axi_aclk), // input
.cmd0_we (en_cmd0_wr), // input
.cmd0_addr (axiwr_bram_waddr[9:0]), // input[9:0]
.cmd0_data (axiwr_bram_wdata[31:0]), // input[31:0]
.cmd1_clk (mclk), // input
// TODO: add - from PL generation of the command sequences
.cmd1_we (1'b0), // input
.cmd1_addr (10'b0), // input[9:0]
.cmd1_data (32'b0), // input[31:0]
.run_addr (run_addr[10:0]), // input[10:0]
.run_chn (run_chn[3:0]), // input[3:0]
.run_seq (run_seq), // input #################### DISABLED ####################
.run_done (), // output
.run_busy (run_busy), // output
.cmd_ad (cmd_ad), // input[7:0]
.cmd_stb (cmd_stb), // input
.status_ad (status_ad_phy), // output[7:0]
.status_rq (status_rq_phy), // output
.status_start (status_start_phy), // input
.ext_buf_rd (ext_buf_rd), // output
.ext_buf_raddr (ext_buf_raddr), // output[6:0]
.ext_buf_rchn (ext_buf_rchn), // output[3:0]
.ext_buf_rdata (ext_buf_rdata), // input[63:0]
.ext_buf_wr (ext_buf_wr), // output
.ext_buf_waddr (ext_buf_waddr), // output[6:0]
.ext_buf_wchn (ext_buf_wchn), // output[3:0]
.ext_buf_wdata (ext_buf_wdata), // output[63:0]
.tmp_debug (tmp_debug) // output[11:0]
);
// Registering existing channel buffers I/Os
`ifdef def_enable_mem_chn0
`ifdef def_read_mem_chn0
mcont_to_chnbuf_reg #(.CHN_NUMBER( 0)) mcont_to_chnbuf_reg0_i(.rst(rst),.clk(mclk),.ext_buf_wr(ext_buf_wr),.ext_buf_waddr(ext_buf_waddr),
.ext_buf_wchn(ext_buf_wchn),.ext_buf_wdata(ext_buf_wdata),.buf_wr_chn(buf_wr_chn0),.buf_waddr_chn(buf_waddr_chn0),.buf_wdata_chn(buf_wdata_chn0));
`else
mcont_from_chnbuf_reg #(.CHN_NUMBER( 0),.CHN_LATENCY(CHNBUF_READ_LATENCY)) mcont_from_chnbuf_reg0_i (.rst(rst),.clk(mclk),.ext_buf_rd(ext_buf_rd),
.ext_buf_raddr(ext_buf_raddr),.ext_buf_rchn(ext_buf_rchn),.ext_buf_rdata(ext_buf_rdata),.buf_rd_chn(buf_rd_chn0),.buf_raddr_chn(buf_raddr_chn0),
.buf_rdata_chn (buf_rdata_chn0));
`endif
`endif
`ifdef def_enable_mem_chn1
`ifdef def_read_mem_chn1
mcont_to_chnbuf_reg #(.CHN_NUMBER( 1)) mcont_to_chnbuf_reg1_i(.rst(rst),.clk(mclk),.ext_buf_wr(ext_buf_wr),.ext_buf_waddr(ext_buf_waddr),
.ext_buf_wchn(ext_buf_wchn),.ext_buf_wdata(ext_buf_wdata),.buf_wr_chn(buf_wr_chn1),.buf_waddr_chn(buf_waddr_chn1),.buf_wdata_chn(buf_wdata_chn1));
`else
mcont_from_chnbuf_reg #(.CHN_NUMBER( 1),.CHN_LATENCY(CHNBUF_READ_LATENCY)) mcont_from_chnbuf_reg1_i (.rst(rst),.clk(mclk),.ext_buf_rd(ext_buf_rd),
.ext_buf_raddr(ext_buf_raddr),.ext_buf_rchn(ext_buf_rchn),.ext_buf_rdata(ext_buf_rdata),.buf_rd_chn(buf_rd_chn1),.buf_raddr_chn(buf_raddr_chn1),
.buf_rdata_chn (buf_rdata_chn1));
`endif
`endif
`ifdef def_enable_mem_chn2
`ifdef def_read_mem_chn2
mcont_to_chnbuf_reg #(.CHN_NUMBER( 2)) mcont_to_chnbuf_reg2_i(.rst(rst),.clk(mclk),.ext_buf_wr(ext_buf_wr),.ext_buf_waddr(ext_buf_waddr),
.ext_buf_wchn(ext_buf_wchn),.ext_buf_wdata(ext_buf_wdata),.buf_wr_chn(buf_wr_chn2),.buf_waddr_chn(buf_waddr_chn2),.buf_wdata_chn(buf_wdata_chn2));
`else
mcont_from_chnbuf_reg #(.CHN_NUMBER( 2),.CHN_LATENCY(CHNBUF_READ_LATENCY)) mcont_from_chnbuf_reg2_i (.rst(rst),.clk(mclk),.ext_buf_rd(ext_buf_rd),
.ext_buf_raddr(ext_buf_raddr),.ext_buf_rchn(ext_buf_rchn),.ext_buf_rdata(ext_buf_rdata),.buf_rd_chn(buf_rd_chn2),.buf_raddr_chn(buf_raddr_chn2),
.buf_rdata_chn (buf_rdata_chn2));
`endif
`endif
`ifdef def_enable_mem_chn3
`ifdef def_read_mem_chn3
mcont_to_chnbuf_reg #(.CHN_NUMBER( 3)) mcont_to_chnbuf_reg3_i(.rst(rst),.clk(mclk),.ext_buf_wr(ext_buf_wr),.ext_buf_waddr(ext_buf_waddr),
.ext_buf_wchn(ext_buf_wchn),.ext_buf_wdata(ext_buf_wdata),.buf_wr_chn(buf_wr_chn3),.buf_waddr_chn(buf_waddr_chn3),.buf_wdata_chn(buf_wdata_chn3));
`else
mcont_from_chnbuf_reg #(.CHN_NUMBER( 3),.CHN_LATENCY(CHNBUF_READ_LATENCY)) mcont_from_chnbuf_reg3_i (.rst(rst),.clk(mclk),.ext_buf_rd(ext_buf_rd),
.ext_buf_raddr(ext_buf_raddr),.ext_buf_rchn(ext_buf_rchn),.ext_buf_rdata(ext_buf_rdata),.buf_rd_chn(buf_rd_chn3),.buf_raddr_chn(buf_raddr_chn3),
.buf_rdata_chn (buf_rdata_chn3));
`endif
`endif
`ifdef def_enable_mem_chn4
`ifdef def_read_mem_chn4
mcont_to_chnbuf_reg #(.CHN_NUMBER( 4)) mcont_to_chnbuf_reg4_i(.rst(rst),.clk(mclk),.ext_buf_wr(ext_buf_wr),.ext_buf_waddr(ext_buf_waddr),
.ext_buf_wchn(ext_buf_wchn),.ext_buf_wdata(ext_buf_wdata),.buf_wr_chn(buf_wr_chn4),.buf_waddr_chn(buf_waddr_chn4),.buf_wdata_chn(buf_wdata_chn4));
`else
mcont_from_chnbuf_reg #(.CHN_NUMBER( 4),.CHN_LATENCY(CHNBUF_READ_LATENCY)) mcont_from_chnbuf_reg4_i (.rst(rst),.clk(mclk),.ext_buf_rd(ext_buf_rd),
.ext_buf_raddr(ext_buf_raddr),.ext_buf_rchn(ext_buf_rchn),.ext_buf_rdata(ext_buf_rdata),.buf_rd_chn(buf_rd_chn4),.buf_raddr_chn(buf_raddr_chn4),
.buf_rdata_chn (buf_rdata_chn4));
`endif
`endif
`ifdef def_enable_mem_chn5
`ifdef def_read_mem_chn5
mcont_to_chnbuf_reg #(.CHN_NUMBER( 5)) mcont_to_chnbuf_reg5_i(.rst(rst),.clk(mclk),.ext_buf_wr(ext_buf_wr),.ext_buf_waddr(ext_buf_waddr),
.ext_buf_wchn(ext_buf_wchn),.ext_buf_wdata(ext_buf_wdata),.buf_wr_chn(buf_wr_chn5),.buf_waddr_chn(buf_waddr_chn5),.buf_wdata_chn(buf_wdata_chn5));
`else
mcont_from_chnbuf_reg #(.CHN_NUMBER( 5),.CHN_LATENCY(CHNBUF_READ_LATENCY)) mcont_from_chnbuf_reg5_i (.rst(rst),.clk(mclk),.ext_buf_rd(ext_buf_rd),
.ext_buf_raddr(ext_buf_raddr),.ext_buf_rchn(ext_buf_rchn),.ext_buf_rdata(ext_buf_rdata),.buf_rd_chn(buf_rd_chn5),.buf_raddr_chn(buf_raddr_chn5),
.buf_rdata_chn (buf_rdata_chn5));
`endif
`endif
`ifdef def_enable_mem_chn6
`ifdef def_read_mem_chn6
mcont_to_chnbuf_reg #(.CHN_NUMBER( 6)) mcont_to_chnbuf_reg6_i(.rst(rst),.clk(mclk),.ext_buf_wr(ext_buf_wr),.ext_buf_waddr(ext_buf_waddr),
.ext_buf_wchn(ext_buf_wchn),.ext_buf_wdata(ext_buf_wdata),.buf_wr_chn(buf_wr_chn6),.buf_waddr_chn(buf_waddr_chn6),.buf_wdata_chn(buf_wdata_chn6));
`else
mcont_from_chnbuf_reg #(.CHN_NUMBER( 6),.CHN_LATENCY(CHNBUF_READ_LATENCY)) mcont_from_chnbuf_reg6_i (.rst(rst),.clk(mclk),.ext_buf_rd(ext_buf_rd),
.ext_buf_raddr(ext_buf_raddr),.ext_buf_rchn(ext_buf_rchn),.ext_buf_rdata(ext_buf_rdata),.buf_rd_chn(buf_rd_chn6),.buf_raddr_chn(buf_raddr_chn6),
.buf_rdata_chn (buf_rdata_chn6));
`endif
`endif
`ifdef def_enable_mem_chn7
`ifdef def_read_mem_chn7
mcont_to_chnbuf_reg #(.CHN_NUMBER( 7)) mcont_to_chnbuf_reg7_i(.rst(rst),.clk(mclk),.ext_buf_wr(ext_buf_wr),.ext_buf_waddr(ext_buf_waddr),
.ext_buf_wchn(ext_buf_wchn),.ext_buf_wdata(ext_buf_wdata),.buf_wr_chn(buf_wr_chn7),.buf_waddr_chn(buf_waddr_chn7),.buf_wdata_chn(buf_wdata_chn7));
`else
mcont_from_chnbuf_reg #(.CHN_NUMBER( 7),.CHN_LATENCY(CHNBUF_READ_LATENCY)) mcont_from_chnbuf_reg7_i (.rst(rst),.clk(mclk),.ext_buf_rd(ext_buf_rd),
.ext_buf_raddr(ext_buf_raddr),.ext_buf_rchn(ext_buf_rchn),.ext_buf_rdata(ext_buf_rdata),.buf_rd_chn(buf_rd_chn7),.buf_raddr_chn(buf_raddr_chn7),
.buf_rdata_chn (buf_rdata_chn7));
`endif
`endif
`ifdef def_enable_mem_chn8
`ifdef def_read_mem_chn8
mcont_to_chnbuf_reg #(.CHN_NUMBER( 8)) mcont_to_chnbuf_reg8_i(.rst(rst),.clk(mclk),.ext_buf_wr(ext_buf_wr),.ext_buf_waddr(ext_buf_waddr),
.ext_buf_wchn(ext_buf_wchn),.ext_buf_wdata(ext_buf_wdata),.buf_wr_chn(buf_wr_chn8),.buf_waddr_chn(buf_waddr_chn8),.buf_wdata_chn(buf_wdata_chn8));
`else
mcont_from_chnbuf_reg #(.CHN_NUMBER( 8),.CHN_LATENCY(CHNBUF_READ_LATENCY)) mcont_from_chnbuf_reg8_i (.rst(rst),.clk(mclk),.ext_buf_rd(ext_buf_rd),
.ext_buf_raddr(ext_buf_raddr),.ext_buf_rchn(ext_buf_rchn),.ext_buf_rdata(ext_buf_rdata),.buf_rd_chn(buf_rd_chn8),.buf_raddr_chn(buf_raddr_chn8),
.buf_rdata_chn (buf_rdata_chn8));
`endif
`endif
`ifdef def_enable_mem_chn9
`ifdef def_read_mem_chn9
mcont_to_chnbuf_reg #(.CHN_NUMBER( 9)) mcont_to_chnbuf_reg9_i(.rst(rst),.clk(mclk),.ext_buf_wr(ext_buf_wr),.ext_buf_waddr(ext_buf_waddr),
.ext_buf_wchn(ext_buf_wchn),.ext_buf_wdata(ext_buf_wdata),.buf_wr_chn(buf_wr_chn9),.buf_waddr_chn(buf_waddr_chn9),.buf_wdata_chn(buf_wdata_chn9));
`else
mcont_from_chnbuf_reg #(.CHN_NUMBER( 9),.CHN_LATENCY(CHNBUF_READ_LATENCY)) mcont_from_chnbuf_reg9_i (.rst(rst),.clk(mclk),.ext_buf_rd(ext_buf_rd),
.ext_buf_raddr(ext_buf_raddr),.ext_buf_rchn(ext_buf_rchn),.ext_buf_rdata(ext_buf_rdata),.buf_rd_chn(buf_rd_chn9),.buf_raddr_chn(buf_raddr_chn9),
.buf_rdata_chn (buf_rdata_chn9));
`endif
`endif
`ifdef def_enable_mem_chn10
`ifdef def_read_mem_chn10
mcont_to_chnbuf_reg #(.CHN_NUMBER( 10)) mcont_to_chnbuf_reg10_i(.rst(rst),.clk(mclk),.ext_buf_wr(ext_buf_wr),.ext_buf_waddr(ext_buf_waddr),
.ext_buf_wchn(ext_buf_wchn),.ext_buf_wdata(ext_buf_wdata),.buf_wr_chn(buf_wr_chn10),.buf_waddr_chn(buf_waddr_chn10),.buf_wdata_chn(buf_wdata_chn10));
`else
mcont_from_chnbuf_reg #(.CHN_NUMBER( 10),.CHN_LATENCY(CHNBUF_READ_LATENCY)) mcont_from_chnbuf_reg10_i (.rst(rst),.clk(mclk),.ext_buf_rd(ext_buf_rd),
.ext_buf_raddr(ext_buf_raddr),.ext_buf_rchn(ext_buf_rchn),.ext_buf_rdata(ext_buf_rdata),.buf_rd_chn(buf_rd_chn10),.buf_raddr_chn(buf_raddr_chn10),
.buf_rdata_chn (buf_rdata_chn10));
`endif
`endif
`ifdef def_enable_mem_chn11
`ifdef def_read_mem_chn11
mcont_to_chnbuf_reg #(.CHN_NUMBER( 11)) mcont_to_chnbuf_reg11_i(.rst(rst),.clk(mclk),.ext_buf_wr(ext_buf_wr),.ext_buf_waddr(ext_buf_waddr),
.ext_buf_wchn(ext_buf_wchn),.ext_buf_wdata(ext_buf_wdata),.buf_wr_chn(buf_wr_chn11),.buf_waddr_chn(buf_waddr_chn11),.buf_wdata_chn(buf_wdata_chn11));
`else
mcont_from_chnbuf_reg #(.CHN_NUMBER( 11),.CHN_LATENCY(CHNBUF_READ_LATENCY)) mcont_from_chnbuf_reg11_i (.rst(rst),.clk(mclk),.ext_buf_rd(ext_buf_rd),
.ext_buf_raddr(ext_buf_raddr),.ext_buf_rchn(ext_buf_rchn),.ext_buf_rdata(ext_buf_rdata),.buf_rd_chn(buf_rd_chn11),.buf_raddr_chn(buf_raddr_chn11),
.buf_rdata_chn (buf_rdata_chn11));
`endif
`endif
`ifdef def_enable_mem_chn12
`ifdef def_read_mem_chn12
mcont_to_chnbuf_reg #(.CHN_NUMBER( 12)) mcont_to_chnbuf_reg12_i(.rst(rst),.clk(mclk),.ext_buf_wr(ext_buf_wr),.ext_buf_waddr(ext_buf_waddr),
.ext_buf_wchn(ext_buf_wchn),.ext_buf_wdata(ext_buf_wdata),.buf_wr_chn(buf_wr_chn12),.buf_waddr_chn(buf_waddr_chn12),.buf_wdata_chn(buf_wdata_chn12));
`else
mcont_from_chnbuf_reg #(.CHN_NUMBER( 12),.CHN_LATENCY(CHNBUF_READ_LATENCY)) mcont_from_chnbuf_reg12_i (.rst(rst),.clk(mclk),.ext_buf_rd(ext_buf_rd),
.ext_buf_raddr(ext_buf_raddr),.ext_buf_rchn(ext_buf_rchn),.ext_buf_rdata(ext_buf_rdata),.buf_rd_chn(buf_rd_chn12),.buf_raddr_chn(buf_raddr_chn12),
.buf_rdata_chn (buf_rdata_chn12));
`endif
`endif
`ifdef def_enable_mem_chn13
`ifdef def_read_mem_chn13
mcont_to_chnbuf_reg #(.CHN_NUMBER( 13)) mcont_to_chnbuf_reg13_i(.rst(rst),.clk(mclk),.ext_buf_wr(ext_buf_wr),.ext_buf_waddr(ext_buf_waddr),
.ext_buf_wchn(ext_buf_wchn),.ext_buf_wdata(ext_buf_wdata),.buf_wr_chn(buf_wr_chn13),.buf_waddr_chn(buf_waddr_chn13),.buf_wdata_chn(buf_wdata_chn13));
`else
mcont_from_chnbuf_reg #(.CHN_NUMBER( 13),.CHN_LATENCY(CHNBUF_READ_LATENCY)) mcont_from_chnbuf_reg13_i (.rst(rst),.clk(mclk),.ext_buf_rd(ext_buf_rd),
.ext_buf_raddr(ext_buf_raddr),.ext_buf_rchn(ext_buf_rchn),.ext_buf_rdata(ext_buf_rdata),.buf_rd_chn(buf_rd_chn13),.buf_raddr_chn(buf_raddr_chn13),
.buf_rdata_chn (buf_rdata_chn13));
`endif
`endif
`ifdef def_enable_mem_chn14
`ifdef def_read_mem_chn14
mcont_to_chnbuf_reg #(.CHN_NUMBER( 14)) mcont_to_chnbuf_reg14_i(.rst(rst),.clk(mclk),.ext_buf_wr(ext_buf_wr),.ext_buf_waddr(ext_buf_waddr),
.ext_buf_wchn(ext_buf_wchn),.ext_buf_wdata(ext_buf_wdata),.buf_wr_chn(buf_wr_chn14),.buf_waddr_chn(buf_waddr_chn14),.buf_wdata_chn(buf_wdata_chn14));
`else
mcont_from_chnbuf_reg #(.CHN_NUMBER( 14),.CHN_LATENCY(CHNBUF_READ_LATENCY)) mcont_from_chnbuf_reg14_i (.rst(rst),.clk(mclk),.ext_buf_rd(ext_buf_rd),
.ext_buf_raddr(ext_buf_raddr),.ext_buf_rchn(ext_buf_rchn),.ext_buf_rdata(ext_buf_rdata),.buf_rd_chn(buf_rd_chn14),.buf_raddr_chn(buf_raddr_chn14),
.buf_rdata_chn (buf_rdata_chn14));
`endif
`endif
`ifdef def_enable_mem_chn15
`ifdef def_read_mem_chn15
mcont_to_chnbuf_reg #(.CHN_NUMBER( 15)) mcont_to_chnbuf_reg15_i(.rst(rst),.clk(mclk),.ext_buf_wr(ext_buf_wr),.ext_buf_waddr(ext_buf_waddr),
.ext_buf_wchn(ext_buf_wchn),.ext_buf_wdata(ext_buf_wdata),.buf_wr_chn(buf_wr_chn15),.buf_waddr_chn(buf_waddr_chn15),.buf_wdata_chn(buf_wdata_chn15));
`else
mcont_from_chnbuf_reg #(.CHN_NUMBER( 15),.CHN_LATENCY(CHNBUF_READ_LATENCY)) mcont_from_chnbuf_reg15_i (.rst(rst),.clk(mclk),.ext_buf_rd(ext_buf_rd),
.ext_buf_raddr(ext_buf_raddr),.ext_buf_rchn(ext_buf_rchn),.ext_buf_rdata(ext_buf_rdata),.buf_rd_chn(buf_rd_chn15),.buf_raddr_chn(buf_raddr_chn15),
.buf_rdata_chn (buf_rdata_chn15));
`endif
`endif
// combining channel control signals to buses
`ifndef def_enable_mem_chn0
wire want_rq0=0, need_rq0=0, seq_wr0=0, seq_done0=0;
wire [31:0] seq_data0=0;
`endif
`ifndef def_enable_mem_chn1
wire want_rq1=0, need_rq1=0, seq_wr1=0, seq_done1=0;
wire [31:0] seq_data1=0;
`endif
`ifndef def_enable_mem_chn2
wire want_rq2=0, need_rq2=0, seq_wr2=0, seq_done2=0;
wire [31:0] seq_data2=0;
`endif
`ifndef def_enable_mem_chn3
wire want_rq3=0, need_rq3=0, seq_wr3=0, seq_done3=0;
wire [31:0] seq_data3=0;
`endif
`ifndef def_enable_mem_chn4
wire want_rq4=0, need_rq4=0, seq_wr4=0, seq_done4=0;
wire [31:0] seq_data4=0;
`endif
`ifndef def_enable_mem_chn5
wire want_rq5=0, need_rq5=0, seq_wr5=0, seq_done5=0;
wire [31:0] seq_data5=0;
`endif
`ifndef def_enable_mem_chn6
wire want_rq6=0, need_rq6=0, seq_wr6=0, seq_done6=0;
wire [31:0] seq_data6=0;
`endif
`ifndef def_enable_mem_chn7
wire want_rq7=0, need_rq7=0, seq_wr7=0, seq_done7=0;
wire [31:0] seq_data7=0;
`endif
`ifndef def_enable_mem_chn8
wire want_rq8=0, need_rq8=0, seq_wr8=0, seq_done8=0;
wire [31:0] seq_data8=0;
`endif
`ifndef def_enable_mem_chn9
wire want_rq9=0, need_rq9=0, seq_wr9=0, seq_done9=0;
wire [31:0] seq_data9=0;
`endif
`ifndef def_enable_mem_chn10
wire want_rq10=0, need_rq10=0, seq_wr10=0, seq_done10=0;
wire [31:0] seq_data10=0;
`endif
`ifndef def_enable_mem_chn11
wire want_rq11=0, need_rq11=0, seq_wr11=0, seq_done11=0;
wire [31:0] seq_data11=0;
`endif
`ifndef def_enable_mem_chn12
wire want_rq12=0, need_rq12=0, seq_wr12=0, seq_done12=0;
wire [31:0] seq_data12=0;
`endif
`ifndef def_enable_mem_chn13
wire want_rq13=0, need_rq13=0, seq_wr13=0, seq_done13=0;
wire [31:0] seq_data13=0;
`endif
`ifndef def_enable_mem_chn14
wire want_rq14=0, need_rq14=0, seq_wr14=0, seq_done14=0;
wire [31:0] seq_data14=0;
`endif
`ifndef def_enable_mem_chn15
wire want_rq15=0, need_rq15=0, seq_wr15=0, seq_done15=0;
wire [31:0] seq_data15=0;
`endif
assign want_rq[15:0]= {want_rq15,want_rq14,want_rq13,want_rq12,want_rq11,want_rq10,want_rq9,want_rq8,
want_rq7,want_rq6,want_rq5,want_rq4,want_rq3,want_rq2,want_rq1,want_rq0};
assign need_rq[15:0]= {need_rq15,need_rq14,need_rq13,need_rq12,need_rq11,need_rq10,need_rq9,need_rq8,
need_rq7,need_rq6,need_rq5,need_rq4,need_rq3,need_rq2,need_rq1,need_rq0};
assign seq_wr[15:0]= {seq_wr15,seq_wr14,seq_wr13,seq_wr12,seq_wr11,seq_wr10,seq_wr9,seq_wr8,
seq_wr7,seq_wr6,seq_wr5,seq_wr4,seq_wr3,seq_wr2,seq_wr1,seq_wr0};
assign seq_done[15:0]= {seq_done15,seq_done14,seq_done13,seq_done12,seq_done11,seq_done10,seq_done9,seq_done8,
seq_done7,seq_done6,seq_done5,seq_done4,seq_done3,seq_done2,seq_done1,seq_done0};
assign seq_data[511:0]= {seq_data15,seq_data14,seq_data13,seq_data12,seq_data11,seq_data10,seq_data9,seq_data8,
seq_data7,seq_data6,seq_data5,seq_data4,seq_data3,seq_data2,seq_data1,seq_data0};
`ifdef def_enable_mem_chn0
assign channel_pgm_en0=channel_pgm_en[0];
`endif
`ifdef def_enable_mem_chn1
assign channel_pgm_en1=channel_pgm_en[1];
`endif
`ifdef def_enable_mem_chn2
assign channel_pgm_en2=channel_pgm_en[2];
`endif
`ifdef def_enable_mem_chn3
assign channel_pgm_en3=channel_pgm_en[3];
`endif
`ifdef def_enable_mem_chn4
assign channel_pgm_en4=channel_pgm_en[4];
`endif
`ifdef def_enable_mem_chn5
assign channel_pgm_en5=channel_pgm_en[5];
`endif
`ifdef def_enable_mem_chn6
assign channel_pgm_en6=channel_pgm_en[6];
`endif
`ifdef def_enable_mem_chn7
assign channel_pgm_en7=channel_pgm_en[7];
`endif
`ifdef def_enable_mem_chn8
assign channel_pgm_en8=channel_pgm_en[8];
`endif
`ifdef def_enable_mem_chn9
assign channel_pgm_en9=channel_pgm_en[9];
`endif
`ifdef def_enable_mem_chn10
assign channel_pgm_en10=channel_pgm_en[10];
`endif
`ifdef def_enable_mem_chn11
assign channel_pgm_en11=channel_pgm_en[11];
`endif
`ifdef def_enable_mem_chn12
assign channel_pgm_en12=channel_pgm_en[12];
`endif
`ifdef def_enable_mem_chn13
assign channel_pgm_en13=channel_pgm_en[13];
`endif
`ifdef def_enable_mem_chn14
assign channel_pgm_en14=channel_pgm_en[14];
`endif
`ifdef def_enable_mem_chn15
assign channel_pgm_en15=channel_pgm_en[15];
`endif
endmodule
/*******************************************************************************
* Module: mcontr_sequencer
* Date:2014-05-16
* Author: Andrey Filippov
* Description: ddr3 sequnecer
*
* Copyright (c) 2014 Elphel, Inc.
* mcontr_sequencer.v is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* mcontr_sequencer.v is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*******************************************************************************/
`timescale 1ns/1ps
module mcontr_sequencer #(
//command interface parameters
parameter DLY_LD = 'h080, // address to generate delay load
parameter DLY_LD_MASK = 'h380, // address mask to generate delay load
//0x1000..103f - 0- bit data (set/reset)
parameter MCONTR_PHY_0BIT_ADDR = 'h020, // address to set sequnecer channel and run (4 LSB-s - channel)
parameter MCONTR_PHY_0BIT_ADDR_MASK = 'h3f0, // address mask to generate sequencer channel/run
// 0x1024..1025 - CMDA_EN // 0 bits - enable/disable command/address outputs
// 0x1026..1027 - SDRST_ACT // 0 bits - enable/disable active-low reset signal to DDR3 memory
// 0x1028..1029 - CKE_EN // 0 bits - enable/disable CKE signal to memory
// 0x102a..102b - DCI_RST // 0 bits - enable/disable CKE signal to memory
// 0x102c..102d - DLY_RST // 0 bits - enable/disable CKE signal to memory
parameter MCONTR_PHY_0BIT_DLY_SET = 'h0, // set pre-programmed delays
parameter MCONTR_PHY_0BIT_CMDA_EN = 'h4, // enable/disable command/address outputs
parameter MCONTR_PHY_0BIT_SDRST_ACT = 'h6, // enable/disable active-low reset signal to DDR3 memory
parameter MCONTR_PHY_0BIT_CKE_EN = 'h8, // enable/disable CKE signal to memory
parameter MCONTR_PHY_0BIT_DCI_RST = 'ha, // enable/disable CKE signal to memory
parameter MCONTR_PHY_0BIT_DLY_RST = 'hc, // enable/disable CKE signal to memory
parameter MCONTR_PHY_STATUS_REG_ADDR= 'h0, // status register address to use for memory controller phy
//0x1040..107f - 16-bit data
// 0x1040..104f - RUN_CHN // address to set sequncer channel and run (4 LSB-s - channel) - bits?
// parameter RUN_CHN_REL = 'h040, // address to set sequnecer channel and run (4 LSB-s - channel)
// parameter RUN_CHN_REL_MASK = 'h3f0, // address mask to generate sequencer channel/run
// 0x1050..1057: MCONTR_PHY16
parameter MCONTR_PHY_16BIT_ADDR = 'h050, // address to set sequnecer channel and run (4 LSB-s - channel)
parameter MCONTR_PHY_16BIT_ADDR_MASK = 'h3f8, // address mask to generate sequencer channel/run
parameter MCONTR_PHY_16BIT_PATTERNS = 'h0, // set DQM and DQS patterns (16'h0055)
parameter MCONTR_PHY_16BIT_PATTERNS_TRI = 'h1, // 16-bit address to set DQM and DQS tristate on/off patterns {dqs_off,dqs_on, dq_off,dq_on} - 4 bits each
parameter MCONTR_PHY_16BIT_WBUF_DELAY = 'h2, // 4? bits - extra delay (in mclk cycles) to add to write buffer enable (DDR3 read data)
parameter MCONTR_PHY_16BIT_EXTRA = 'h3, // ? bits - set extra parameters (currently just inv_clk_div)
parameter MCONTR_PHY_STATUS_CNTRL = 'h4, // write to status control (8-bit)
parameter DFLT_DQS_PATTERN= 8'h55,
parameter DFLT_DQM_PATTERN= 8'h00, // 8'h00
parameter DFLT_DQ_TRI_ON_PATTERN= 4'h7, // DQ tri-state control word, first when enabling output
parameter DFLT_DQ_TRI_OFF_PATTERN= 4'he, // DQ tri-state control word, first after disabling output
parameter DFLT_DQS_TRI_ON_PATTERN= 4'h3, // DQS tri-state control word, first when enabling output
parameter DFLT_DQS_TRI_OFF_PATTERN=4'hc,// DQS tri-state control word, first after disabling output
parameter DFLT_WBUF_DELAY= 4'h6, // write levelling - 7!
parameter DFLT_INV_CLK_DIV= 1'b0,
parameter PHASE_WIDTH = 8,
parameter SLEW_DQ = "SLOW",
parameter SLEW_DQS = "SLOW",
parameter SLEW_CMDA = "SLOW",
parameter SLEW_CLK = "SLOW",
parameter IBUF_LOW_PWR = "TRUE",
parameter real REFCLK_FREQUENCY = 300.0,
parameter HIGH_PERFORMANCE_MODE = "FALSE",
parameter CLKIN_PERIOD = 10, //ns >1.25, 600<Fvco<1200
parameter CLKFBOUT_MULT = 8, // Fvco=Fclkin*CLKFBOUT_MULT_F/DIVCLK_DIVIDE, Fout=Fvco/CLKOUT#_DIVIDE
parameter CLKFBOUT_MULT_REF = 9, // Fvco=Fclkin*CLKFBOUT_MULT_F/DIVCLK_DIVIDE, Fout=Fvco/CLKOUT#_DIVIDE
parameter CLKFBOUT_DIV_REF = 3, // To get 300MHz for the reference clock
parameter DIVCLK_DIVIDE= 1,
parameter CLKFBOUT_PHASE = 0.000,
parameter SDCLK_PHASE = 0.000,
parameter CLK_PHASE = 0.000,
parameter CLK_DIV_PHASE = 0.000,
parameter MCLK_PHASE = 90.000,
parameter REF_JITTER1 = 0.010,
parameter SS_EN = "FALSE",
parameter SS_MODE = "CENTER_HIGH",
parameter SS_MOD_PERIOD = 10000,
parameter CMD_PAUSE_BITS= 10,
parameter CMD_DONE_BIT= 10
)(
// DDR3 interface
output SDRST, // DDR3 reset (active low)
output SDCLK, // DDR3 clock differential output, positive
output SDNCLK,// DDR3 clock differential output, negative
output [ADDRESS_NUMBER-1:0] SDA, // output address ports (14:0) for 4Gb device
output [2:0] SDBA, // output bank address ports
output SDWE, // output WE port
output SDRAS, // output RAS port
output SDCAS, // output CAS port
output SDCKE, // output Clock Enable port
output SDODT, // output ODT port
inout [15:0] SDD, // DQ I/O pads
output SDDML, // LDM I/O pad (actually only output)
inout DQSL, // LDQS I/O pad
inout NDQSL, // ~LDQS I/O pad
output SDDMU, // UDM I/O pad (actually only output)
inout DQSU, // UDQS I/O pad
inout NDQSU, // ~UDQS I/O pad
// clocks, reset
input clk_in,
input rst_in,
output mclk, // global clock, half DDR3 clock, synchronizes all I/O thorough the command port
// command port 0 (filled by software - 32w->32r) - used for mode set, refresh, write levelling, ...
input cmd0_clk,
input cmd0_we,
input [9:0] cmd0_addr,
input [31:0] cmd0_data,
// automatic command port1 , filled by the PL, 32w 32r, used for actual page R/W
input cmd1_clk,
input cmd1_we,
input [9:0] cmd1_addr,
input [31:0] cmd1_data,
// Controller run interface, posedge mclk
input [10:0] run_addr, // controller sequencer start address (0..11'h3ff - cmd0, 11'h400..11'h7ff - cmd1)
input [3:0] run_chn, // data channel to use
input run_seq, // start controller sequence (will and with !ddr_rst for stable mclk)
output run_done, // controller sequence finished
output run_busy, // controller sequence in progress
// programming interface
input [7:0] cmd_ad, // byte-serial command address/data (up to 6 bytes: AL-AH-D0-D1-D2-D3
input cmd_stb, // strobe (with first byte) for the command a/d
output [7:0] status_ad, // status address/data - up to 5 bytes: A - {seq,status[1:0]} - status[2:9] - status[10:17] - status[18:25]
output status_rq, // input request to send status downstream
input status_start, // Acknowledge of the first status packet byte (address)
// Interface to write-to-memory buffers (up to 16)
// There will be =1 cycle external latency in address/re and 1 cycle latency in read data (should match sequence programs)
// Address data is sync to posedge mclk
output ext_buf_rd,
output [6:0] ext_buf_raddr, // valid with ext_buf_rd, 2 page MSB to be generated externally
output [3:0] ext_buf_rchn, // ==run_chn_d valid 1 cycle ahead opf ext_buf_rd!, maybe not needed - will be generated externally
input [63:0] ext_buf_rdata, // Latency of ram_1kx32w_512x64r plus 2
// Interface to memory read channels (up to 16)
// Address/data sync to negedge mclk!, any latency OK - just generate DONE appropriately (through the sequencer with delay?
output ext_buf_wr,
output [6:0] ext_buf_waddr, // valid with ext_buf_wr
output [3:0] ext_buf_wchn, // ==run_chn_d valid 1 cycle ahead opf ext_buf_wr!, maybe not needed - will be generated externally
output [63:0] ext_buf_wdata, // valid with ext_buf_wr
// temporary debug data
output [11:0] tmp_debug
);
localparam ADDRESS_NUMBER = 15;
wire [7:0] dly_data;
wire [6:0] dly_addr;
wire ld_delay;
wire set;
wire [3:0] phy_0bit_addr;
wire phy_0bit_we;
reg cmda_en; // enable (!tristate) command and address lines // not likely to be used
reg ddr_rst=1; // generate reset to DDR3 memory (active high)
reg dci_rst; // active high - reset DCI circuitry
reg dly_rst; // active high - delay calibration circuitry
reg ddr_cke; // DDR clock enable , XOR-ed with command bit
reg [7:0] dqs_pattern=DFLT_DQS_PATTERN; // 8'h55
reg [7:0] dqm_pattern=DFLT_DQM_PATTERN; // 8'h00
reg [ 3:0] dq_tri_on_pattern=DFLT_DQ_TRI_ON_PATTERN; // DQ tri-state control word, first when enabling output
reg [ 3:0] dq_tri_off_pattern=DFLT_DQ_TRI_OFF_PATTERN; // DQ tri-state control word, first after disabling output
reg [ 3:0] dqs_tri_on_pattern=DFLT_DQS_TRI_ON_PATTERN; // DQS tri-state control word, first when enabling output
reg [ 3:0] dqs_tri_off_pattern=DFLT_DQS_TRI_OFF_PATTERN;// DQS tri-state control word, first after disabling output
reg [ 3:0] wbuf_delay=DFLT_WBUF_DELAY;
wire [2:0] phy_16bit_addr;
wire [15:0] phy_16bit_data;
wire phy_16bit_we;
reg inv_clk_div=0;
// Status data:
wire locked_mmcm;
wire locked_pll;
wire dly_ready;
wire dci_ready;
// wire [PHASE_WIDTH-1:0] ps_out;
wire [7:0] ps_out;
wire ps_rdy;
wire locked;
wire [14:0] status_data;
// temporary, debug
wire phy_locked_mmcm; // before clock crossing
wire phy_locked_pll; // before clock crossing
wire phy_dly_ready; // before clock crossing
wire phy_dci_ready; // before clock crossing
// wire [35:0] phy_cmd; // input[35:0]
wire [31:0] phy_cmd_word; // selected output from eithe cmd0 buffer or cmd1 buffer
wire [31:0] phy_cmd0_word; // cmd0 buffer output
wire [31:0] phy_cmd1_word; // cmd1 buffer output
reg [ 6:0] buf_raddr;
reg [ 6:0] buf_waddr_negedge;
reg buf_wr_negedge;
wire [63:0] buf_wdata; // output[63:0]
reg [63:0] buf_wdata_negedge; // output[63:0]
wire [63:0] buf_rdata; // multiplexed input from one of the write channels buffer
// wire [63:0] buf1_rdata;
wire buf_wr; // delayed by specified number of clock cycles
wire buf_wr_ndly; // before dealy
wire buf_rd; // read next 64 bytes from the buffer, need one extra pre-read
wire rst=rst_in;
// wire [ 9:0] next_cmd_addr;
reg [ 9:0] cmd_addr; // command word adderss
reg cmd_sel;
reg [ 2:0] cmd_busy; // bit 0 - immediately,
wire phy_cmd_nop; // decoded command (ras, cas, we) was NOP
wire phy_cmd_add_pause; // decoded from the command word - add one pause command after the current one
reg add_pause; // previos command had phy_cmd_add_pause set
wire sequence_done;
wire [CMD_PAUSE_BITS-1:0] pause_len;
reg cmd_fetch; // previous cycle command was read from the command memory, current: command valid
wire pause; // do not register new data from the command memory
reg [CMD_PAUSE_BITS-1:0] pause_cntr;
// reg [1:0] buf_page; // one of 4 pages in the channel buffer to use for R/W
// reg [15:0] buf_sel_1hot; // 1 hot channel buffer select
reg [3:0] run_chn_d;
reg [3:0] run_chn_d_negedge;
reg run_seq_d;
wire [7:0] tmp_debug_a;
assign tmp_debug[11:0] =
{phy_locked_mmcm,
phy_locked_pll,
phy_dly_ready,
phy_dci_ready,
tmp_debug_a[7:0]};
assign run_done=sequence_done;
assign run_busy=cmd_busy[0]; //earliest
assign pause=cmd_fetch? (phy_cmd_add_pause || (phy_cmd_nop && (pause_len != 0))): (cmd_busy[2] && (pause_cntr[CMD_PAUSE_BITS-1:1]!=0));
/// debugging
assign phy_cmd_word = cmd_sel?phy_cmd1_word:phy_cmd0_word; // TODO: hangs even with 0-s in phy_cmd
/// assign phy_cmd_word = phy_cmd_word?0:0;
// assign buf_rdata[63:0] = ({64{buf_sel_1hot[1]}} & buf1_rdata[63:0]); // ORed with other read channels terms
// External buffers buffer related signals
assign ext_buf_rd= buf_rd;
assign ext_buf_raddr= buf_raddr;
assign ext_buf_rchn= run_chn_d;
assign buf_rdata[63:0] = ext_buf_rdata;
assign ext_buf_wr= buf_wr_negedge;
assign ext_buf_waddr= buf_waddr_negedge;
assign ext_buf_wchn= run_chn_d_negedge;
assign ext_buf_wdata= buf_wdata_negedge;
// generation of the control signals from byte-serial channel
// generate 8-bit delay data
cmd_deser #(
.ADDR (DLY_LD),
.ADDR_MASK (DLY_LD_MASK),
.NUM_CYCLES (3),
.ADDR_WIDTH (7),
.DATA_WIDTH (8)
) cmd_deser_dly_i (
.rst (rst), // input
.clk (mclk), // input
.ad (cmd_ad), // input[7:0]
.stb (cmd_stb), // input
.addr (dly_addr), // output[15:0]
.data (dly_data), // output[31:0]
.we( ld_delay) // output
);
// generate on/off dependent on lsb and 0-bit commands
cmd_deser #(
.ADDR (MCONTR_PHY_0BIT_ADDR),
.ADDR_MASK (MCONTR_PHY_0BIT_ADDR_MASK),
.NUM_CYCLES (2),
.ADDR_WIDTH (4),
.DATA_WIDTH (0)
) cmd_deser_0bit_i (
.rst (rst), // input
.clk (mclk), // input
.ad (cmd_ad), // input[7:0]
.stb (cmd_stb), // input
.addr (phy_0bit_addr), // output[15:0]
.data (), // output[31:0]
.we( phy_0bit_we) // output
);
assign set= phy_0bit_we && (phy_0bit_addr==MCONTR_PHY_0BIT_DLY_SET);
always @ (posedge mclk or posedge rst) begin
if (rst) cmda_en <= 0;
else if (phy_0bit_we && (phy_0bit_addr[3:1]==(MCONTR_PHY_0BIT_CMDA_EN>>1))) cmda_en <= phy_0bit_addr[0];
if (rst) ddr_rst <= 1;
else if (phy_0bit_we && (phy_0bit_addr[3:1]==(MCONTR_PHY_0BIT_SDRST_ACT>>1))) ddr_rst <= phy_0bit_addr[0];
if (rst) dci_rst <= 0;
else if (phy_0bit_we && (phy_0bit_addr[3:1]==(MCONTR_PHY_0BIT_DCI_RST>>1))) dci_rst <= phy_0bit_addr[0];
if (rst) dly_rst <= 0;
else if (phy_0bit_we && (phy_0bit_addr[3:1]==(MCONTR_PHY_0BIT_DLY_RST>>1))) dly_rst <= phy_0bit_addr[0];
if (rst) ddr_cke <= 0;
else if (phy_0bit_we && (phy_0bit_addr[3:1]==(MCONTR_PHY_0BIT_CKE_EN>>1))) ddr_cke <= phy_0bit_addr[0];
end
// generate 16-bit data commands (and set defaults to registers)
cmd_deser #(
.ADDR (MCONTR_PHY_16BIT_ADDR),
.ADDR_MASK (MCONTR_PHY_16BIT_ADDR_MASK),
.NUM_CYCLES (4),
.ADDR_WIDTH (3),
.DATA_WIDTH (16)
) cmd_deser_0bit_i (
.rst (rst), // input
.clk (mclk), // input
.ad (cmd_ad), // input[7:0]
.stb (cmd_stb), // input
.addr (phy_16bit_addr), // output[15:0]
.data (phy_16bit_data), // output[31:0]
.we( phy_16bit_we) // output
);
wire set_patterns;
wire set_patterns_tri;
wire set_wbuf_delay;
wire set_extra;
wire control_status_we; // share with write delay (8-but)?
wire [7:0] contral_status_data;
assign set_patterns= phy_16bit_we && (phy_16bit_addr[2:0]==MCONTR_PHY_16BIT_PATTERNS);
assign set_patterns_tri= phy_16bit_we && (phy_16bit_addr[2:0]==MCONTR_PHY_16BIT_PATTERNS_TRI);
assign set_wbuf_delay= phy_16bit_we && (phy_16bit_addr[2:0]==MCONTR_PHY_16BIT_WBUF_DELAY);
assign set_extra= phy_16bit_we && (phy_16bit_addr[2:0]==MCONTR_PHY_16BIT_EXTRA);
assign control_status_we= phy_16bit_we && (phy_16bit_addr[2:0]==MCONTR_PHY_STATUS_CNTRL);
assign contral_status_data= phy_16bit_data[7:0];
always @ (posedge mclk or posedge rst) begin
if (rst) begin
dqm_pattern <=DFLT_DQM_PATTERN;
dqs_pattern <=DFLT_DQS_PATTERN;
end else if (set_patterns) begin
dqm_pattern <= phy_16bit_data[15:8];
dqs_pattern <= phy_16bit_data[7:0];
end
if (rst) begin
dqs_tri_off_pattern[3:0] <= DFLT_DQS_TRI_OFF_PATTERN;
dqs_tri_on_pattern[3:0] <= DFLT_DQS_TRI_ON_PATTERN;
dq_tri_off_pattern[3:0] <= DFLT_DQ_TRI_OFF_PATTERN;
dq_tri_on_pattern[3:0] <= DFLT_DQ_TRI_ON_PATTERN;
end else if (set_patterns_tri) begin
dqs_tri_off_pattern[3:0] <= phy_16bit_data[15:12];
dqs_tri_on_pattern[3:0] <= phy_16bit_data[11: 8];
dq_tri_off_pattern[3:0] <= phy_16bit_data[ 7: 4];
dq_tri_on_pattern[3:0] <= phy_16bit_data[ 3: 0];
end
if (rst) wbuf_delay <= DFLT_WBUF_DELAY;
else if (set_wbuf_delay) wbuf_delay <= phy_16bit_data[ 3: 0];
if (rst) inv_clk_div <= DFLT_INV_CLK_DIV;
else if (set_extra) inv_clk_div <= phy_16bit_data[0];
end
// TODO: status
assign locked=locked_mmcm && locked_pll;
assign status_data={dly_ready,dci_ready, locked_mmcm, locked_pll, run_busy,locked,ps_rdy,ps_out[7:0]};
status_generate #(
.STATUS_REG_ADDR (MCONTR_PHY_STATUS_REG_ADDR),
.PAYLOAD_BITS (15)
) status_generate_i (
.rst (rst), // input
.clk (mclk), // input
.we (control_status_we), // input
.wd (contral_status_data), // input[7:0]
.status (status_data), // input[25:0]
.ad (status_ad), // output[7:0]
.rq (status_rq), // output
.start (status_start) // input
);
always @ (posedge mclk or posedge rst) begin
if (rst) cmd_busy <= 0;
// else if (sequence_done) cmd_busy <= 0;
else if (ddr_rst) cmd_busy <= 0; // *************** reset sequencer with DDR reset
else if (sequence_done && cmd_busy[2]) cmd_busy <= 0;
else cmd_busy <= {cmd_busy[1:0],run_seq | cmd_busy[0]};
// Pause counter
if (rst) pause_cntr <= 0;
else if (!cmd_busy[1]) pause_cntr <= 0; // not needed?
else if (cmd_fetch && phy_cmd_nop) pause_cntr <= pause_len;
else if (pause_cntr!=0) pause_cntr <= pause_cntr-1; //SuppressThisWarning ISExst Result of 32-bit expression is truncated to fit in 10-bit target.
// Fetch - command data valid
if (rst) cmd_fetch <= 0;
else cmd_fetch <= cmd_busy[0] && !pause;
if (rst) add_pause <= 0;
else add_pause <= cmd_fetch && phy_cmd_add_pause;
// Command read address
if (rst) cmd_addr <= 0;
else if (run_seq) cmd_addr <= run_addr[9:0];
else if (cmd_busy[0] && !pause) cmd_addr <= cmd_addr + 1; //SuppressThisWarning ISExst Result of 11-bit expression is truncated to fit in 10-bit target.
// command bank select (0 - "manual" (software programmed sequences), 1 - "auto" (normal block r/w)
if (rst) cmd_sel <= 0;
else if (run_seq) cmd_sel <= run_addr[10];
if (rst) buf_raddr <= 7'h0;
else if (run_seq_d) buf_raddr <= 7'h0;
else if (buf_wr || buf_rd) buf_raddr <= buf_raddr +1; // Separate read/write address? read address re-registered @ negedge //SuppressThisWarning ISExst Result of 10-bit expression is truncated to fit in 9-bit target.
if (rst) run_chn_d <= 0;
else if (run_seq) run_chn_d <= run_chn;
if (rst) run_seq_d <= 0;
else run_seq_d <= run_seq;
end
// re-register buffer write address to match DDR3 data
always @ (negedge mclk) begin
buf_waddr_negedge <= buf_raddr;
buf_wr_negedge <= buf_wr;
buf_wdata_negedge <= buf_wdata;
run_chn_d_negedge <= run_chn_d;
//TODO: add write channel number?
end
// Command sequence memories:
// Command sequence memory 0 ("manual"):
wire ren0=!cmd_sel && cmd_busy[0] && !pause; // cmd_busy - multibit
wire ren1= cmd_sel && cmd_busy[0] && !pause;
ram_1kx32_1kx32 #(
.REGISTERS(1) // (0) // register output
) cmd0_buf_i (
.rclk (mclk), // input
.raddr (cmd_addr), // input[9:0]
.ren (ren0), // input TODO: verify cmd_busy[0] is correct (was cmd_busy )
.regen (ren0), // input
.data_out (phy_cmd0_word), // output[31:0]
.wclk (cmd0_clk), // input
.waddr (cmd0_addr), // input[9:0]
.we (cmd0_we), // input
.web (4'hf), // input[3:0]
.data_in (cmd0_data) // input[31:0]
);
// Command sequence memory 0 ("manual"):
ram_1kx32_1kx32 #(
.REGISTERS(1) // (0) // register output
) cmd1_buf_i (
.rclk (mclk), // input
.raddr (cmd_addr), // input[9:0]
.ren ( ren1), // input
.regen ( ren1), // input
.data_out (phy_cmd1_word), // output[31:0]
.wclk (cmd1_clk), // input
.waddr (cmd1_addr), // input[9:0]
.we (cmd1_we), // input
.web (4'hf), // input[3:0]
.data_in (cmd1_data) // input[31:0]
);
phy_cmd #(
.ADDRESS_NUMBER (ADDRESS_NUMBER),
.PHASE_WIDTH (PHASE_WIDTH),
.SLEW_DQ (SLEW_DQ),
.SLEW_DQS (SLEW_DQS),
.SLEW_CMDA (SLEW_CMDA),
.SLEW_CLK (SLEW_CLK),
.IBUF_LOW_PWR (IBUF_LOW_PWR),
.REFCLK_FREQUENCY (REFCLK_FREQUENCY),
.HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
.CLKIN_PERIOD (CLKIN_PERIOD),
.CLKFBOUT_MULT (CLKFBOUT_MULT),
.CLKFBOUT_MULT_REF (CLKFBOUT_MULT_REF),
.CLKFBOUT_DIV_REF (CLKFBOUT_DIV_REF),
.DIVCLK_DIVIDE (DIVCLK_DIVIDE),
.CLKFBOUT_PHASE (CLKFBOUT_PHASE),
.SDCLK_PHASE (SDCLK_PHASE),/// debugging
.CLK_PHASE (CLK_PHASE),
.CLK_DIV_PHASE (CLK_DIV_PHASE),
.MCLK_PHASE (MCLK_PHASE),
.REF_JITTER1 (REF_JITTER1),
.SS_EN (SS_EN),
.SS_MODE (SS_MODE),
.SS_MOD_PERIOD (SS_MOD_PERIOD),
.CMD_PAUSE_BITS (CMD_PAUSE_BITS), // numer of (address) bits to encode pause
.CMD_DONE_BIT (CMD_DONE_BIT) // bit number (address) to signal sequence done
) phy_cmd_i (
.SDRST (SDRST), // output
.SDCLK (SDCLK), // output
.SDNCLK (SDNCLK), // output
.SDA (SDA[ADDRESS_NUMBER-1:0]), // output[14:0]
.SDBA (SDBA[2:0]), // output[2:0]
.SDWE (SDWE), // output
.SDRAS (SDRAS), // output
.SDCAS (SDCAS), // output
.SDCKE (SDCKE), // output
.SDODT (SDODT), // output
.SDD (SDD[15:0]), // inout[15:0]
.SDDML (SDDML), // inout
.DQSL (DQSL), // inout
.NDQSL (NDQSL), // inout
.SDDMU (SDDMU), // inout
.DQSU (DQSU), // inout
.NDQSU (NDQSU), // inout
.clk_in (clk_in), // input
.rst_in (rst_in), // input
.mclk (mclk), // output
.dly_data (dly_data[7:0]), // input[7:0]
.dly_addr (dly_addr[6:0]), // input[6:0]
.ld_delay (ld_delay), // input
.set (set), // input
// .locked (locked), // output
.locked_mmcm (locked_mmcm), // output
.locked_pll (locked_pll), // output
.dly_ready (dly_ready), // output
.dci_ready (dci_ready), // output
.phy_locked_mmcm (phy_locked_mmcm), // output
.phy_locked_pll (phy_locked_pll), // output
.phy_dly_ready (phy_dly_ready), // output
.phy_dci_ready (phy_dci_ready), // output
.tmp_debug (tmp_debug_a[7:0]),
.ps_rdy (ps_rdy), // output
.ps_out (ps_out[7:0]), // output[7:0]
.phy_cmd_word (phy_cmd_word[31:0]), // input[31:0]
.phy_cmd_nop (phy_cmd_nop), // output
.phy_cmd_add_pause (phy_cmd_add_pause), // one pause cycle (for 8-bursts)
.add_pause (add_pause),
.pause_len (pause_len), // output [CMD_PAUSE_BITS-1:0]
.sequence_done (sequence_done), // output
.buf_wdata (buf_wdata[63:0]), // output[63:0]
.buf_rdata (buf_rdata[63:0]), // input[63:0]
.buf_wr (buf_wr_ndly), // output
.buf_rd (buf_rd), // output
.cmda_en (cmda_en), // input
.ddr_rst (ddr_rst), // input
.dci_rst (dci_rst), // input
.dly_rst (dly_rst), // input
.ddr_cke (ddr_cke), // input
.inv_clk_div (inv_clk_div), // input
.dqs_pattern (dqs_pattern), // input[7:0]
.dqm_pattern (dqm_pattern), // input[7:0]
.dq_tri_on_pattern (dq_tri_on_pattern[3:0]), // input[3:0]
.dq_tri_off_pattern (dq_tri_off_pattern[3:0]), // input[3:0]
.dqs_tri_on_pattern (dqs_tri_on_pattern[3:0]), // input[3:0]
.dqs_tri_off_pattern (dqs_tri_off_pattern[3:0]) // input[3:0]
);
// delay buf_wr by 1-16 cycles to compensate for DDR and HDL code latency (~7 cycles?)
dly01_16 buf_wr_dly_i (
.clk(mclk), // input
.rst(1'b0), // input
.dly(wbuf_delay[3:0]), // input[3:0]
.din(buf_wr_ndly), // input
.dout(buf_wr) // output reg
);
endmodule
......@@ -32,7 +32,7 @@ module status_read#(
parameter STATUS_ADDR = 'h1400, // AXI write address of status read registers
parameter STATUS_ADDR_MASK = 'h1400, // AXI write address of status registers
parameter AXI_RD_ADDR_BITS = 13,
parameter integer DATA_DEPTH= 8 // 256 cells, maybe just 16..64 are enough?
parameter integer STATUS_DEPTH= 8 // 256 cells, maybe just 16..64 are enough?
)(
input rst,
input clk,
......@@ -44,10 +44,10 @@ module status_read#(
input rq, // request from sources to transfer status data
output start // acknowledge receiving of first byte (address), currently always ready
);
localparam integer DATA_2DEPTH=(1<<DATA_DEPTH)-1;
localparam integer DATA_2DEPTH=(1<<STATUS_DEPTH)-1;
reg [31:0] ram [0:DATA_2DEPTH];
reg [DATA_DEPTH-1:0] waddr;
wire [DATA_DEPTH-1:0] raddr;
reg [STATUS_DEPTH-1:0] waddr;
wire [STATUS_DEPTH-1:0] raddr;
reg we;
wire re;
reg [31: 0] wdata;
......@@ -55,7 +55,7 @@ module status_read#(
reg [3:0] dstb;
assign re= pre_stb && (((axi_pre_addr ^ STATUS_ADDR) & STATUS_ADDR_MASK) == 0);
assign raddr=axi_pre_addr[DATA_DEPTH-1:0];
assign raddr=axi_pre_addr[STATUS_DEPTH-1:0];
assign start=rq && !rq_r;
always @ (posedge rst or posedge clk) begin
......@@ -70,7 +70,7 @@ module status_read#(
else dstb <= {dstb[2:0],~rq_r};
// byte 0 - address
if (rst) waddr <= 0;
else if (start) waddr <= ad[DATA_DEPTH-1:0];
else if (start) waddr <= ad[STATUS_DEPTH-1:0];
// byte 1 - 2 payload bits and sequence number
// 6 bits of the sequence number will go to bits 26.. 31
......
/*******************************************************************************
* Module: mcont_from_chnbuf_reg
* Date:2015-01-19
* Author: andrey
* Description: Registering data from channel buffer to memory controller
*
* Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
* mcont_from_chnbuf_reg.v is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* mcont_from_chnbuf_reg.v is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*******************************************************************************/
`timescale 1ns/1ps
module mcont_from_chnbuf_reg #(
parameter CHN_NUMBER=0,
parameter CHN_LATENCY=0 // 0 - no extra latency in extrenal BRAM - data available next cycle after re (but prev. data)
)(
input rst,
input clk,
input ext_buf_rd,
input [6:0] ext_buf_raddr, // valid with ext_buf_rd, 2 page MSB to be generated externally
input [3:0] ext_buf_rchn, // ==run_chn_d valid 1 cycle ahead opf ext_buf_rd!, maybe not needed - will be generated externally
output reg [63:0] ext_buf_rdata, // Latency of ram_1kx32w_512x64r plus 2
output reg buf_rd_chn,
output reg [6:0] buf_raddr_chn,
input [63:0] buf_rdata_chn
);
reg buf_chn_sel;
reg [CHN_LATENCY:0] latency_reg=0;
always @ (posedge rst or posedge clk) begin
if (rst) buf_chn_sel <= 0;
else buf_chn_sel <= (ext_buf_rchn==CHN_NUMBER);
if (rst) buf_rd_chn <= 0;
else buf_rd_chn <= buf_chn_sel && ext_buf_rd;
if (rst) latency_reg<= 0;
else latency_reg <= buf_rd_chn | (latency_reg << 1);
end
always @ (posedge clk) if (buf_chn_sel && ext_buf_rd) buf_raddr_chn <= ext_buf_raddr;
always @ (posedge clk) if (latency_reg[CHN_LATENCY]) ext_buf_rdata <= buf_rdata_chn;
endmodule
/*******************************************************************************
* Module: mcont_to_chnbuf_reg
* Date:2015-01-19
* Author: andrey
* Description: Registering data from memory controller to channel buffer
*
* Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
* mcont_to_chnbuf_reg.v is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* mcont_to_chnbuf_reg.v is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*******************************************************************************/
`timescale 1ns/1ps
module mcont_to_chnbuf_reg #(
parameter CHN_NUMBER=0
)(
input rst,
input clk,
input ext_buf_wr,
input [6:0] ext_buf_waddr, // valid with ext_buf_wr
input [3:0] ext_buf_wchn, // ==run_chn_d valid 1 cycle ahead opf ext_buf_wr!, maybe not needed - will be generated externally
input [63:0] ext_buf_wdata, // valid with ext_buf_wr
output reg buf_wr_chn,
output reg [6:0] buf_waddr_chn,
output reg [63:0] buf_wdata_chn
);
reg buf_chn_sel;
always @ (posedge rst or negedge clk) begin
if (rst) buf_chn_sel <= 0;
else buf_chn_sel <= (ext_buf_wchn==CHN_NUMBER);
if (rst) buf_wr_chn <= 0;
else buf_wr_chn <= buf_chn_sel && ext_buf_wr;
end
always @ (negedge clk) if (buf_chn_sel && ext_buf_wr) begin
buf_waddr_chn <= ext_buf_waddr;
buf_wdata_chn <= ext_buf_wdata;
end
endmodule
......@@ -39,7 +39,7 @@ module status_generate #(
*/
localparam NUM_BYTES=(PAYLOAD_BITS+21)>>3;
localparam ALIGNED_STATUS_WIDTH=((NUM_BYTES-2)<<3)+2; // 2 ->2,
// ugly solution to avoid warnings in unused branch
// ugly solution to avoid warnings in unused "if" branch
localparam ALIGNED_STATUS_BIT_2=(ALIGNED_STATUS_WIDTH>2)?2:0;
reg [1:0] mode;
reg [5:0] seq;
......
......@@ -20,7 +20,8 @@
*******************************************************************************/
`timescale 1ns/1ps
`define use200Mhz 1
`define DEBUG_FIFO 1
`define DEBUG_FIFO 1
`include ".editor_defines"
module x393 #(
parameter PHASE_WIDTH = 8,
parameter SLEW_DQ = "SLOW",
......@@ -55,6 +56,11 @@ module x393 #(
parameter SS_MOD_PERIOD = 10000,
parameter CMD_PAUSE_BITS= 10,
parameter CMD_DONE_BIT= 10,
parameter STATUS_ADDR = 'h1400, // AXI write address of status read registers
parameter STATUS_ADDR_MASK = 'h1400, // AXI write address of status registers
parameter STATUS_DEPTH= 8, // 256 cells, maybe just 16..64 are enough?
parameter AXI_WR_ADDR_BITS = 13,
parameter AXI_RD_ADDR_BITS = 13,
parameter CONTROL_ADDR = 'h1000, // AXI write address of control write registers
......@@ -78,10 +84,10 @@ module x393 #(
parameter NUM_CYCLES_14 = 6, //
parameter NUM_CYCLES_15 = 6, //
parameter STATUS_ADDR = 'h1400, // AXI write address of status read registers
parameter STATUS_ADDR_MASK = 'h1400, // AXI write address of status registers
parameter BUSY_WR_ADDR = 'h1800, // AXI write address to generate busy
parameter BUSY_WR_ADDR_MASK = 'h1c00, // AXI write address mask to generate busy
// parameter STATUS_ADDR = 'h1400, // AXI write address of status read registers
// parameter STATUS_ADDR_MASK = 'h1400, // AXI write address of status registers
// parameter BUSY_WR_ADDR = 'h1800, // AXI write address to generate busy
// parameter BUSY_WR_ADDR_MASK = 'h1c00, // AXI write address mask to generate busy
parameter CMD0_ADDR = 'h0800, // AXI write to command sequence memory
parameter CMD0_ADDR_MASK = 'h1800, // AXI read address mask for the command sequence memory
parameter PORT0_RD_ADDR = 'h0000, // AXI read address to generate busy
......@@ -228,6 +234,7 @@ module x393 #(
wire [31:0] axird_bram_rdata; // .data_out(rdata[31:0]), // data out
wire [31:0] port0_rdata; //
wire [31:0] status_rdata; //
wire status_valid;
wire mclk;
wire en_cmd0_wr;
......@@ -382,14 +389,26 @@ end
// ddrc_status () was here
// ddrc_sequencer() was here - move to module memctrl16
wire [AXI_WR_ADDR_BITS-1:0] cseq_waddr; // command sequencer write address (output to command multiplexer)
wire cseq_wr_en; // command sequencer write enable (output to command multiplexer) - keep until cseq_ackn received
wire [31:0] cseq_wdata; // command sequencer write data (output to command multiplexer)
wire cseq_ackn; // ackn to command sequencer, command sequencer should de-assert cseq_wr_en
wire [AXI_WR_ADDR_BITS-1:0] par_waddr; // multiplexed address (full, parallel) to slave devices
wire [31:0] par_data; // multiplexed data (full, parallel) to slave devices
wire [7:0] byte_ad; // multiplexed byte-wide serialized address/data to salve devices (AL-AH-D0-D1-D2-D3), may contain less cycles
wire ad_stb; // strobe marking the first of 1-6 a/d bytes and also data valid for par_waddr and par_data
wire [AXI_WR_ADDR_BITS-1:0] cseq_waddr; // command sequencer write address (output to command multiplexer)
wire cseq_wr_en; // command sequencer write enable (output to command multiplexer) - keep until cseq_ackn received
wire [31:0] cseq_wdata; // command sequencer write data (output to command multiplexer)
wire cseq_ackn; // ackn to command sequencer, command sequencer should de-assert cseq_wr_en
wire [AXI_WR_ADDR_BITS-1:0] par_waddr; // multiplexed address (full, parallel) to slave devices
wire [31:0] par_data; // multiplexed data (full, parallel) to slave devices
wire [7:0] cmd_root_ad; // multiplexed byte-wide serialized address/data to salve devices (AL-AH-D0-D1-D2-D3), may contain less cycles
wire cmd_root_stb; // strobe marking the first of 1-6 a/d bytes and also data valid for par_waddr and par_data
wire [7:0] status_root_ad; // Root status byte-wide address/data
wire status_root_rq; // Root status request
wire status_root_start; // Root status packet transfer start (currently with 0 latency from status_root_rq)
wire [7:0] status_mcontr_ad; // Memory contyroller status byte-wide address/data
wire status_mcontr_rq; // Memory contyroller status request
wire status_mcontr_start; // Memory contyroller status packet transfer start (currently with 0 latency from status_root_rq)
wire [7:0] status_other_ad; // Other status byte-wide address/data
wire status_other_rq; // Other status request
wire status_other_start; // Other status packet transfer start (currently with 0 latency from status_root_rq)
cmd_mux #(
.AXI_WR_ADDR_BITS (AXI_WR_ADDR_BITS),
......@@ -429,10 +448,150 @@ end
.par_waddr (par_waddr), // output[12:0]
.par_data (par_data), // output[31:0]
// registers may be inserted before byte_ad and ad_stb
.byte_ad (byte_ad), // output[7:0]
.ad_stb (ad_stb) // output
.byte_ad (cmd_root_ad), // output[7:0]
.ad_stb (cmd_root_stb) // output
);
status_read #(
.STATUS_ADDR(STATUS_ADDR),
.STATUS_ADDR_MASK(STATUS_ADDR_MASK),
.AXI_RD_ADDR_BITS(AXI_RD_ADDR_BITS),
.STATUS_DEPTH(STATUS_DEPTH)
) status_read_i (
.rst (axi_rst), // input
.clk (mclk), // input
.axi_pre_addr (axird_pre_araddr), // input[12:0]
.pre_stb (axird_start_burst), // input
.axi_status_rdata (status_rdata[31:0]), // output[31:0] reg
.data_valid (status_valid), // output reg
.ad (status_root_ad), // input[7:0]
.rq (status_root_rq), // input
.start (status_root_start) // output
);
// Insert register layer if needed
wire [7:0] cmd_mcontr_ad;
wire cmd_mcontr_stb;
assign cmd_mcontr_ad= cmd_root_ad;
assign cmd_mcontr_stb=cmd_root_stb;
// mux status info from the memory controller and other modules
status_router2 status_router2_top_i (
.rst (axi_rst), // input
.clk (mclk), // input
.db_in0 (status_mcontr_ad), // input[7:0]
.rq_in0 (status_mcontr_rq), // input
.start_in0 (status_mcontr_start), // output
.db_in1 (status_other_ad), // input[7:0]
.rq_in1 (status_other_rq), // input
.start_in1 (status_other_start), // output
.db_out (status_root_ad), // output[7:0]
.rq_out (status_root_rq), // output
.start_out (status_root_start) // input
);
// Memory controller signals
wire [15:0] mem_want; // to mcontr
wire [15:0] mem_need; // to mcontr
wire [15:0] mem_pgm_chn; // from mcontr
wire [511:0] mem_seq_data; // to mcontr
wire [15:0] mem_seq_wr; // to mcontr
wire [15:0] mem_seq_done; // to mcontr
memctrl16 #(
.ADDRESS_NUMBER (ADDRESS_NUMBER),
.PHASE_WIDTH (PHASE_WIDTH),
.SLEW_DQ (SLEW_DQ),
.SLEW_DQS (SLEW_DQS),
.SLEW_CMDA (SLEW_CMDA),
.SLEW_CLK (SLEW_CLK),
.IBUF_LOW_PWR (IBUF_LOW_PWR),
.REFCLK_FREQUENCY (REFCLK_FREQUENCY),
.HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
.CLKIN_PERIOD (CLKIN_PERIOD),
.CLKFBOUT_MULT (CLKFBOUT_MULT),
.CLKFBOUT_MULT_REF (CLKFBOUT_MULT_REF),
.CLKFBOUT_DIV_REF (CLKFBOUT_DIV_REF),
.DIVCLK_DIVIDE (DIVCLK_DIVIDE),
.CLKFBOUT_PHASE (CLKFBOUT_PHASE),
.SDCLK_PHASE (SDCLK_PHASE),
.CLK_PHASE (CLK_PHASE),
.CLK_DIV_PHASE (CLK_DIV_PHASE),
.MCLK_PHASE (MCLK_PHASE),
.REF_JITTER1 (REF_JITTER1),
.SS_EN (SS_EN),
.SS_MODE (SS_MODE),
.SS_MOD_PERIOD (SS_MOD_PERIOD),
.CMD_PAUSE_BITS (CMD_PAUSE_BITS),
.CMD_DONE_BIT (CMD_DONE_BIT),
.DLY_LD_REL (DLY_LD_REL),
.DLY_LD_REL_MASK (DLY_LD_REL_MASK),
.DLY_SET_REL (DLY_SET_REL),
.DLY_SET_REL_MASK (DLY_SET_REL_MASK),
.RUN_CHN_REL (RUN_CHN_REL),
.RUN_CHN_REL_MASK (RUN_CHN_REL_MASK),
.PATTERNS_REL (PATTERNS_REL),
.PATTERNS_REL_MASK (PATTERNS_REL_MASK),
.PATTERNS_TRI_REL (PATTERNS_TRI_REL),
.PATTERNS_TRI_REL_MASK (PATTERNS_TRI_REL_MASK),
.WBUF_DELAY_REL (WBUF_DELAY_REL),
.WBUF_DELAY_REL_MASK (WBUF_DELAY_REL_MASK),
.PAGES_REL (PAGES_REL),
.PAGES_REL_MASK (PAGES_REL_MASK),
.CMDA_EN_REL (CMDA_EN_REL),
.CMDA_EN_REL_MASK (CMDA_EN_REL_MASK),
.SDRST_ACT_REL (SDRST_ACT_REL),
.SDRST_ACT_REL_MASK (SDRST_ACT_REL_MASK),
.CKE_EN_REL (CKE_EN_REL),
.CKE_EN_REL_MASK (CKE_EN_REL_MASK),
.DCI_RST_REL (DCI_RST_REL),
.DCI_RST_REL_MASK (DCI_RST_REL_MASK),
.DLY_RST_REL (DLY_RST_REL),
.DLY_RST_REL_MASK (DLY_RST_REL_MASK),
.EXTRA_REL (EXTRA_REL),
.EXTRA_REL_MASK (EXTRA_REL_MASK),
.REFRESH_EN_REL (REFRESH_EN_REL),
.REFRESH_EN_REL_MASK (REFRESH_EN_REL_MASK),
.REFRESH_PER_REL (REFRESH_PER_REL),
.REFRESH_PER_REL_MASK (REFRESH_PER_REL_MASK),
.REFRESH_ADDR_REL (REFRESH_ADDR_REL),
.REFRESH_ADDR_REL_MASK (REFRESH_ADDR_REL_MASK)
) memctrl16_i (
// TODO: Add some other clock i/o?
.rst (axi_rst), // input
.clk (mclk), // input
.want_rq (mem_want[15:0]), // input[15:0]
.need_rq (mem_need[15:0]), // input[15:0]
.channel_pgm_en (mem_pgm_chn[15:0]), // output[15:0]
.seq_data (mem_seq_data[511:0]), // input[511:0]
.seq_wr (mem_seq_wr[15:0]), // input[15:0]
.seq_done (mem_seq_done), // input[15:0]
.cmd_ad (cmd_mcontr_ad[7:0]), // input[7:0]
.cmd_stb (cmd_mcontr_stb), // input
.status_ad (status_mcontr_ad[7:0]), // output[7:0]
.status_rq (status_mcontr_rq), // input request to send status downstream
.status_start (status_mcontr_start), // Acknowledge of the first status packet byte (address)
.SDRST (SDRST), // output
.SDCLK (SDCLK), // output
.SDNCLK (SDNCLK), // output
.SDA (SDA), // output[14:0]
.SDBA (SDBA), // output[2:0]
.SDWE (SDWE), // output
.SDRAS (SDRAS), // output
.SDCAS (SDCAS), // output
.SDCKE (SDCKE), // output
.SDODT (SDODT), // output
.SDD (SDD), // inout[15:0]
.SDDML (SDDML), // output
.DQSL (DQSL), // inout
.NDQSL (NDQSL), // inout
.SDDMU (SDDMU), // output
.DQSU (DQSU), // inout
.NDQSU (NDQSU) // inout
);
//MEMCLK
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment