diff --git a/vhdl/testbenches/ddr_ram_model.vhd b/vhdl/testbenches/ddr_ram_model.vhd index b556fe3..6878079 100644 --- a/vhdl/testbenches/ddr_ram_model.vhd +++ b/vhdl/testbenches/ddr_ram_model.vhd @@ -4,22 +4,7 @@ LIBRARY IEEE; LIBRARY work; -PACKAGE ddr_ram_model_pkg IS - -- DDR RAM timing constants - - CONSTANT TRFC_MIN : TIME := 105000 ps; -- refresh to refresh command minimum value - CONSTANT TRFC_MAX : TIME := 70000000 ps; -- refresh to refresh command maximum value - CONSTANT TRP : TIME := 13125 ps; -- precharge period - CONSTANT TRPA : TIME := 13125 ps; -- precharge all period - CONSTANT TRC : TIME := 54000 ps; -- activate to activate/auto refresh command time - CONSTANT TRAS_MIN : TIME := 40000 ps; -- minimum active to precharge command time - CONSTANT TRAS_MAX : TIME := 70000000 ps; -- maximum active to precharge command time - CONSTANT TRRD : TIME := 10000 ps; -- tRRD: active bank to active bank command time - CONSTANT TFAW : TIME := 45000 ps; -- four bank activate window - CONSTANT TWR : TIME := 15000 ps; -- write recovery time - - CONSTANT RANDOM_SEED : INTEGER := 711689044; -- seed value for random generator - +PACKAGE ddr_ram_model_pkg IS COMPONENT ddr_ram_model IS GENERIC ( @@ -27,31 +12,33 @@ PACKAGE ddr_ram_model_pkg IS CLOCK_TICK : TIME := (1000000 / 132000) * 1 ps; -- time for one clock tick - BA_BITS : INTEGER := 2; -- number of banks - ADDR_BITS : INTEGER := 13; -- number of address bits - DM_BITS : INTEGER := 2; -- number of data mask bits - DQ_BITS : INTEGER := 16; -- number of data bits - DQS_BITS : INTEGER := 2 -- number of data strobes + NBANK : INTEGER := 4; + ADDRTOP : INTEGER := 12; + A10_LESS : BOOLEAN := TRUE; -- top column address is less than A10 + B : INTEGER := 16; -- number of bit (x16) + NCOL : INTEGER := 10; -- top column address is CA9 (NCOL- 1) + PAGEDEPTH : INTEGER := 1024; + NDM : INTEGER := 2; + NDQS : INTEGER := 2 ); PORT ( - ck : IN STD_LOGIC; - ck_n : IN STD_LOGIC; + dqi : INOUT STD_LOGIC_VECTOR (B - 1 DOWNTO 0); + ba : IN UNSIGNED (NBANK / 2 - 1 DOWNTO 0); + ad : IN STD_LOGIC_VECTOR (ADDRTOP DOWNTO 0); + rasb : IN STD_LOGIC; + casb : IN STD_LOGIC; + web : IN STD_LOGIC; + clk : IN STD_LOGIC; + clkb : IN STD_LOGIC; cke : IN STD_LOGIC; - cs_n : IN STD_LOGIC; - ras_n : IN STD_LOGIC; - cas_n : IN STD_LOGIC; - we_n : IN STD_LOGIC; - dm_rdqs : INOUT UNSIGNED (DM_BITS - 1 DOWNTO 0); - ba : IN UNSIGNED (BA_BITS - 1 DOWNTO 0); - addr : IN UNSIGNED (ADDR_BITS - 1 DOWNTO 0); - dq : INOUT UNSIGNED (DQ_BITS - 1 DOWNTO 0); - dqs : INOUT UNSIGNED (DQS_BITS - 1 DOWNTO 0); - dqs_n : INOUT UNSIGNED (DQS_BITS - 1 DOWNTO 0); - rdqs_n : OUT UNSIGNED (DQS_BITS - 1 DOWNTO 0); - odt : IN STD_LOGIC + csb : IN STD_LOGIC; + dm : IN UNSIGNED (NDM - 1 DOWNTO 0); + dqs : INOUT STD_LOGIC_VECTOR (NDQS - 1 DOWNTO 0); + qfc : OUT STD_LOGIC ); END COMPONENT; + END PACKAGE; PACKAGE BODY ddr_ram_model_pkg IS @@ -69,716 +56,90 @@ LIBRARY work; ENTITY ddr_ram_model IS GENERIC ( - VERBOSE : BOOLEAN := TRUE; -- define if you want additional debug output + VERBOSE : BOOLEAN := TRUE; -- define if you want additional debug output + CLOCK_TICK : TIME := (1000000 / 132000) * 1 ps; -- time for one clock tick - - BA_BITS : INTEGER := 2; -- number of banks - ADDR_BITS : INTEGER := 13; -- number of address bits - DM_BITS : INTEGER := 2; -- number of data mask bits - DQ_BITS : INTEGER := 8; -- number of data bits - DQS_BITS : INTEGER := 2 -- number of data strobes + + NBANK : INTEGER := 4; + ADDRTOP : INTEGER := 12; + A10_LESS : BOOLEAN := TRUE; -- top column address is less than A10 + B : INTEGER := 16; -- number of bit (x16) + NCOL : INTEGER := 10; -- top column address is CA9 (NCOL- 1) + PAGEDEPTH : INTEGER := 1024; + NDM : INTEGER := 2; + NDQS : INTEGER := 2 ); PORT ( - ck : IN STD_LOGIC; - ck_n : IN STD_LOGIC; - cke : IN STD_LOGIC; - cs_n : IN STD_LOGIC; - ras_n : IN STD_LOGIC; - cas_n : IN STD_LOGIC; - we_n : IN STD_LOGIC; - dm_rdqs : INOUT UNSIGNED (DM_BITS - 1 DOWNTO 0); - ba : IN UNSIGNED (BA_BITS - 1 DOWNTO 0); - addr : IN UNSIGNED (ADDR_BITS - 1 DOWNTO 0); - dq : INOUT UNSIGNED (DQ_BITS - 1 DOWNTO 0); - dqs : INOUT UNSIGNED (DQS_BITS - 1 DOWNTO 0); - dqs_n : INOUT UNSIGNED (DQS_BITS - 1 DOWNTO 0); - rdqs_n : OUT UNSIGNED (DQS_BITS - 1 DOWNTO 0); - odt : IN STD_LOGIC - ); + dqi : INOUT STD_LOGIC_VECTOR (B - 1 DOWNTO 0); + ba : IN UNSIGNED (NBANK / 2 - 1 DOWNTO 0); + ad : IN STD_LOGIC_VECTOR (ADDRTOP DOWNTO 0); + rasb : IN STD_LOGIC; + casb : IN STD_LOGIC; + web : IN STD_LOGIC; + clk : IN STD_LOGIC; + clkb : IN STD_LOGIC; + cke : IN STD_LOGIC; + csb : IN STD_LOGIC; + dm : IN UNSIGNED (NDM - 1 DOWNTO 0); + dqs : INOUT STD_LOGIC_VECTOR (NDQS - 1 DOWNTO 0); + qfc : OUT STD_LOGIC + ); END ENTITY ddr_ram_model; ARCHITECTURE rtl OF ddr_ram_model IS - -- DDR RAM size constants - CONSTANT MEM_BITS : INTEGER := 10; -- number of write data bursts can be stored in memory. The default is 2 ** 10 = 1024 - CONSTANT AP : INTEGER := 10; -- the address bit that controls auto-precharge and precharge-all - CONSTANT TDLLK : INTEGER := 200; - CONSTANT BANKS : INTEGER := TO_INTEGER(SHIFT_LEFT(TO_UNSIGNED(1, 32), BA_BITS)); - CONSTANT ROW_BITS : INTEGER := 13; - CONSTANT COL_BITS : INTEGER := 10; - CONSTANT BL_BITS : INTEGER := 3; -- the number of bits required to count to MAX_BL - CONSTANT BL_MAX : INTEGER := 8; - CONSTANT BO_BITS : INTEGER := 2; -- the number of burst order bits - CONSTANT MAX_BITS : INTEGER := BA_BITS + ROW_BITS + COL_BITS - BL_BITS; + -- DDR RAM timing constants + CONSTANT TRC : TIME := 65 ps; -- row cycle time (min) + CONSTANT TRFC : TIME := 115 ps; -- Refresh Row cycle time (min) + CONSTANT TRASMIN : TIME := 45 ps; -- Row active minimum time + CONSTANT TRASMAX : TIME := 120000 ps; -- Row active maximum time + CONSTANT TRCD : TIME := 20 ps; -- Ras to cas delay (min) + CONSTANT TRP : TIME := 20 ps; -- Row precharge time (min) + CONSTANT TRRD : TIME := 15 ps; -- Row to row delay (min) + + CONSTANT TCCD : TIME := CLOCK_TICK; -- Col. address to col. address delay: 1 clk + + CONSTANT TCKMIN : TIME := 7.5 ps; -- Clock minimum cycle time + CONSTANT TCKMAX : TIME := 12 ps; -- Clock maximum cycle time + CONSTANT TCK15 : TIME := 10 ps; -- Clock minimum cycle time at cas latency=1.5 + CONSTANT TCK2 : TIME := 10 ps; -- Clock minimum cycle time at cas latency=2 + CONSTANT TCK25 : TIME := 7.5 ps; -- Clock minimum cycle time at cas latency=2.5 + CONSTANT TCK3 : TIME := 7.5 ps; -- Clock minimum cycle time at cas latency=3 + CONSTANT TCHMIN : TIME := 0.45 ps; -- Clock high pulse width (min. 0.45 tCK, max: 0.55 tCK) + CONSTANT TCHMAX : TIME := 0.55 ps; + CONSTANT TCLMIN : TIME := 0.45 ps; -- Clock low pulse width (min. 0.45 tCK, max: 0.55 tCK) + CONSTANT TCLMAX : TIME := 0.55 ps; + CONSTANT TIS : TIME := 0.9 ps; -- input setup time (old Tss) + CONSTANT TIH : TIME := 0.9 ps; -- input hold time (old Tsh) + CONSTANT TWR : TIME := 15 ps; -- write recovery time + CONSTANT TDS : TIME := 0.5 ps; -- Data in & DQM setup time + CONSTANT TDH : TIME := 0.5 ps; -- Data in & DQM hold time + CONSTANT TDQSH : TIME := 0.6 ps; -- DQS-in high level width (min. 0.4 tCK, max. 0.6 tCK) + CONSTANT TDQSL : TIME := 0.6 ps; -- + CONSTANT TDSC : TIME := 1 ps; -- DQS-in cycle time tCIC changed following tDSC + CONSTANT TPDEX : TIME := 7.5 ps; -- Power down exit time + CONSTANT TSREX : TIME := 200 ps; -- Self refresh exit time : 200 clk + CONSTANT THZQ : TIME := 0.75 ps; -- Data out active to High-Z (min:-0.75, max: +0.75) + CONSTANT TDQSCK : TIME := 0.75 ps; -- DQS out edge to clock edge + CONSTANT TAC : TIME := 0.75 ps; -- Output data access time from CK/CKB (min: -0.75, max: +0.75) + CONSTANT TQCSW : TIME := 3.5 ps; -- Delay from the clock edge of write command to QFC out on writes (max: 4ns) + CONSTANT TQCHW : TIME := 0.5 ps; -- QFC hold time on writes (min 1.25 ns, max: 0.5 tCK) + CONSTANT TQCH : TIME := 0.4 ps; -- QFC hold time on reads (min 0.4 tCK, max 0.6 tCK) + CONSTANT TQCS : TIME := 0.9 ps; -- QFC setup time on reads (min: 0.9 tCK, max 1.1 tCK) - -- time constants - CONSTANT BUS_DELAY : TIME := 0 ps; + CONSTANT K1 : INTEGER := 1024; + CONSTANT M1 : INTEGER := 1048576; + CONSTANT BYTE : INTEGER := 8; - -- time constants (in tCK's) - CONSTANT TMRD : INTEGER := 2; -- load mode register command cycle time - CONSTANT TCCD : INTEGER := 2; -- CAS to CAS command delay + CONSTANT TBITS : INTEGER := 512 * M1; - CONSTANT DQ_PER_DQS : INTEGER := DQ_BITS / DQS_BITS; - CONSTANT MAX_SIZE : INTEGER := TO_INTEGER(SHIFT_LEFT(TO_UNSIGNED(1, 32), BA_BITS + ROW_BITS + COL_BITS - BL_BITS)); - CONSTANT MEM_SIZE : INTEGER := TO_INTEGER(SHIFT_LEFT(TO_UNSIGNED(1, 32), MEM_BITS)); - CONSTANT AL_MAX : INTEGER := 6; - CONSTANT CL_MAX : INTEGER := 7; - CONSTANT MAX_PIPE : INTEGER := 2 * (AL_MAX + CL_MAX); - - TYPE time_array_t IS ARRAY (NATURAL RANGE <>) OF TIME; - - -- clock jitter - SIGNAL tck_avg : REAL; - SIGNAL tck_sample : time_array_t (TDLLK - 1 DOWNTO 0); - SIGNAL tch_sample : time_array_t (TDLLK - 1 DOWNTO 0); - SIGNAL tcl_sample : time_array_t (TDLLK - 1 DOWNTO 0); - SIGNAL tck_i : TIME; - SIGNAL tch_i : TIME; - SIGNAL tcl_i : TIME; - SIGNAL tch_avg : REAL; - SIGNAL tcl_avg : REAL; - SIGNAL tm_ck_pos : TIME; - SIGNAL tm_ck_neg : TIME; - SIGNAL tjit_per_rtime : REAL; - SIGNAL tjit_cc_time : INTEGER; - SIGNAL terr_nper_rtime : REAL; - - -- clock skew - SIGNAL out_delay : REAL; - SIGNAL dqsck : UNSIGNED (DQS_BITS - 1 DOWNTO 0); - SIGNAL dqsck_min : INTEGER; - SIGNAL dqsck_max : INTEGER; - SIGNAL dqsq_min : INTEGER; - SIGNAL dqsq_max : INTEGER; - SIGNAL seed : INTEGER; - - -- mode registers - SIGNAL burst_order : STD_LOGIC; - SIGNAL burst_length : UNSIGNED (BL_BITS DOWNTO 0); - SIGNAL cas_latency : INTEGER; - SIGNAL additive_latency : INTEGER; - SIGNAL dll_reset : STD_LOGIC; - SIGNAL dll_locked : STD_LOGIC; - SIGNAL dll_en : STD_LOGIC; - SIGNAL write_recovery : INTEGER; - SIGNAL low_power : STD_LOGIC; - SIGNAL odt_rtt : UNSIGNED (1 DOWNTO 0); - SIGNAL odt_en : STD_LOGIC; - SIGNAL ocd : UNSIGNED (2 DOWNTO 0); - SIGNAL dqs_n_en : STD_LOGIC; - SIGNAL rdqs_en : STD_LOGIC; - SIGNAL out_en : STD_LOGIC; - SIGNAL read_latency : INTEGER; - SIGNAL write_latency : INTEGER; - - TYPE cmd_type_t IS (LOAD_MODE, REFRESH, PRECHARGE, ACTIVATE, WRITE_CMD, READ_CMD, NOP, PWR_DOWN, SELF_REF); - TYPE cmd_type_encoding_array_t IS ARRAY(cmd_type_t) OF UNSIGNED(3 DOWNTO 0); - CONSTANT cmd_type_encoding : cmd_type_encoding_array_t := - ( - "0000", "0001", "0010", "0011", - "0100", "0101", "0111", "1000", - "1001" - ); - - TYPE cmd_string_array_t IS ARRAY (INTEGER RANGE <>) OF STRING(1 TO 9); - CONSTANT cmd_string : cmd_string_array_t(1 TO 9) := - ( "Load Mode", - "Refresh ", - "Precharge", - "Activate ", - "Write ", - "Read ", - "No OP ", - "Pwr Down ", - "Self Ref " - ); - - -- command state - SIGNAL active_bank : UNSIGNED (BANKS - 1 DOWNTO 0); - SIGNAL auto_precharge_bank : UNSIGNED (BANKS - 1 DOWNTO 0); - SIGNAL write_precharge_bank : UNSIGNED (BANKS - 1 DOWNTO 0); - SIGNAL read_precharge_bank : UNSIGNED (BANKS - 1 DOWNTO 0); - - TYPE row_array_t IS ARRAY (INTEGER RANGE <>) OF UNSIGNED (BANKS - 1 DOWNTO 0); - SIGNAL active_row : row_array_t (ROW_BITS - 1 DOWNTO 0); - SIGNAL in_power_down : STD_LOGIC; - SIGNAL in_self_refresh : STD_LOGIC; - SIGNAL init_mode_reg : UNSIGNED (3 DOWNTO 0); - SIGNAL init_done : STD_LOGIC; - SIGNAL init_step : INTEGER; - SIGNAL er_trfc_max : STD_LOGIC; - SIGNAL odt_state : STD_LOGIC; - SIGNAL pref_odt : STD_LOGIC; - - -- cmd timers/counters - SIGNAL ref_cntr : INTEGER; - SIGNAL ck_cntr : INTEGER; - SIGNAL ck_load_mode : INTEGER; - SIGNAL ck_write : INTEGER; - SIGNAL ck_read : INTEGER; - SIGNAL ck_write_ap : INTEGER; - SIGNAL ck_power_down : INTEGER; - SIGNAL ck_slow_exit_pd : INTEGER; - SIGNAL ck_self_refresh : INTEGER; - SIGNAL ck_cke : INTEGER; - SIGNAL ck_odt : INTEGER; - SIGNAL ck_dll_reset : INTEGER; - - TYPE ck_bank_array_t IS ARRAY (NATURAL RANGE <>) OF INTEGER; - SIGNAL ck_bank_write : ck_bank_array_t (BANKS - 1 DOWNTO 0); - SIGNAL ck_bank_read : ck_bank_array_t (BANKS - 1 DOWNTO 0); - - SIGNAL tm_refresh : TIME; - SIGNAL tm_precharge : TIME; - SIGNAL tm_precharge_all : TIME; - SIGNAL tm_activate : TIME; - SIGNAL tm_write_end : TIME; - SIGNAL tm_self_refresh : TIME; - SIGNAL tm_odt_en : TIME; - SIGNAL tm_bank_precharge : time_array_t (BANKS - 1 DOWNTO 0); - SIGNAL tm_bank_activate : time_array_t (BANKS - 1 DOWNTO 0); - SIGNAL tm_bank_write_end : time_array_t (BANKS - 1 DOWNTO 0); - SIGNAL tm_bank_read_end : time_array_t (BANKS - 1 DOWNTO 0); - - -- pipelines - SIGNAL al_pipeline : UNSIGNED (MAX_PIPE DOWNTO 0); - SIGNAL wr_pipeline : UNSIGNED (MAX_PIPE DOWNTO 0); - SIGNAL rd_pipeline : UNSIGNED (MAX_PIPE DOWNTO 0); - SIGNAL odt_pipeline : UNSIGNED (MAX_PIPE DOWNTO 0); - - TYPE ba_pipeline_t IS ARRAY (NATURAL RANGE <>) OF UNSIGNED (BA_BITS - 1 DOWNTO 0); - SIGNAL ba_pipeline : ba_pipeline_t (MAX_PIPE DOWNTO 0); - - TYPE row_pipeline_t IS ARRAY (NATURAL RANGE <>) OF UNSIGNED (ROW_BITS - 1 DOWNTO 0); - SIGNAL row_pipeline : row_pipeline_t (MAX_PIPE DOWNTO 0); - - TYPE col_pipeline_t IS ARRAY (NATURAL RANGE <>) OF UNSIGNED (COL_BITS - 1 DOWNTO 0); - SIGNAL col_pipeline : col_pipeline_t (MAX_PIPE DOWNTO 0); - - SIGNAL prev_cke : STD_LOGIC; - - -- data state - SIGNAL memory_data : UNSIGNED (BL_MAX * DQ_BITS - 1 DOWNTO 0); - SIGNAL bit_mask : UNSIGNED (BL_MAX * DQ_BITS - 1 DOWNTO 0); - SIGNAL burst_position : UNSIGNED (BL_BITS - 1 DOWNTO 0); - SIGNAL burst_cntr : UNSIGNED (BL_BITS DOWNTO 0); - SIGNAL dq_temp : UNSIGNED (DQ_BITS - 1 DOWNTO 0); - SIGNAL check_write_postamble: UNSIGNED (35 DOWNTO 0); - SIGNAL check_write_preamble : UNSIGNED (35 DOWNTO 0); - SIGNAL check_write_dqs_high : UNSIGNED (35 DOWNTO 0); - SIGNAL check_write_dqs_low : UNSIGNED (35 DOWNTO 0); - SIGNAL check_dm_tdipw : UNSIGNED (17 DOWNTO 0); - SIGNAL check_dq_tdipw : UNSIGNED (17 DOWNTO 0); - - -- data timers/counters - SIGNAL tm_cke : TIME; - SIGNAL tm_odt : TIME; - SIGNAL tm_tdqss : TIME; - SIGNAL tm_dm : time_array_t (17 DOWNTO 0); - SIGNAL tm_dqs : time_array_t (17 DOWNTO 0); - SIGNAL tm_dqs_pos : time_array_t (35 DOWNTO 0); - SIGNAL tm_dqss_pos : time_array_t (35 DOWNTO 0); - SIGNAL tm_dqss_neg : time_array_t (35 DOWNTO 0); - SIGNAL tm_dq : time_array_t (71 DOWNTO 0); - SIGNAL tm_cmd_addr : time_array_t (22 DOWNTO 0); - - TYPE cmd_addr_array_t IS ARRAY (INTEGER RANGE <>) OF STRING(1 TO 8); - CONSTANT cmd_addr_string : cmd_addr_array_t(22 DOWNTO 0) := - ( - "CS_N ", - "RAS_N ", - "CAS_N ", - "WE_N ", - "BA 0 ", - "BA 1 ", - "BA 2 ", - "ADDR 0", - "ADDR 1", - "ADDR 2", - "ADDR 3", - "ADDR 4", - "ADDR 5", - "ADDR 6", - "ADDR 7", - "ADDR 8", - "ADDR 9", - "ADDR 10", - "ADDR 11", - "ADDR 12", - "ADDR 13", - "ADDR 14", - "ADDR 15" - ); - - TYPE dqs_string_t IS ARRAY (INTEGER RANGE <>) OF STRING (1 TO 5); - CONSTANT dqs_string : dqs_string_t (1 DOWNTO 0) := - ( - "DQS ", - "DQS_N" - ); + --SIGNAL BITs : UNSIGNED (B - 1 DOWNTO 0); + SIGNAL BIT_C : UNSIGNED (NCOL - 1 DOWNTO 0); + CONSTANT NWORD : INTEGER := TBITS / B / NBANK; + SIGNAL BIT_T : UNSIGNED (NCOL + ADDRTOP DOWNTO 0); + SIGNAL WORD : UNSIGNED (NWORD - 1 DOWNTO 0); - -- memory storage - TYPE mem_t IS ARRAY (INTEGER RANGE <>) OF UNSIGNED (BL_MAX * DQ_BITS - 1 DOWNTO 0); - SIGNAL memory : mem_t(0 TO MEM_SIZE - 1); - TYPE adr_t IS ARRAY (INTEGER RANGE <>) OF UNSIGNED (MAX_BITS - 1 DOWNTO 0); - SIGNAL address : adr_t(0 TO MEM_SIZE - 1); - SIGNAL memory_index : UNSIGNED(MEM_BITS DOWNTO 0); - SIGNAL memory_used : UNSIGNED(MEM_BITS DOWNTO 0); - - SIGNAL ck_in : STD_LOGIC; - SIGNAL ck_n_in : STD_LOGIC; - SIGNAL cke_in : STD_LOGIC; - SIGNAL cs_n_in : STD_LOGIC; - SIGNAL ras_n_in : STD_LOGIC; - SIGNAL cas_n_in : STD_LOGIC; - SIGNAL we_n_in : STD_LOGIC; - SIGNAL dm_in : UNSIGNED (17 DOWNTO 0); - SIGNAL ba_in : UNSIGNED (2 DOWNTO 0); - SIGNAL addr_in : UNSIGNED (15 DOWNTO 0); - SIGNAL dq_in : UNSIGNED (71 DOWNTO 0); - SIGNAL dqs_in : UNSIGNED (35 DOWNTO 0); - SIGNAL odt_in : STD_LOGIC; - - SIGNAL dm_in_pos : UNSIGNED (17 DOWNTO 0); - SIGNAL dm_in_neg : UNSIGNED (17 DOWNTO 0); - SIGNAL dq_in_pos : UNSIGNED (71 DOWNTO 0); - SIGNAL dq_in_neg : UNSIGNED (71 DOWNTO 0); - SIGNAL dq_in_valid : STD_LOGIC; - SIGNAL dqs_in_valid : STD_LOGIC; - SIGNAL wdqs_cntr : INTEGER; - SIGNAL wdq_cntr : INTEGER; - - TYPE integer_array_t IS ARRAY (NATURAL RANGE <>) OF INTEGER; - SIGNAL wdqs_pos_cntr : integer_array_t(35 DOWNTO 0); - - SIGNAL b2b_write : STD_LOGIC; - SIGNAL prev_dqs_in : UNSIGNED (35 DOWNTO 0); - SIGNAL diff_ck : STD_LOGIC; - - SIGNAL dqs_even : UNSIGNED (17 DOWNTO 0); - SIGNAL dqs_odd : UNSIGNED (17 DOWNTO 0); - SIGNAL cmd_n_in : UNSIGNED (3 DOWNTO 0); - - -- transmit - SIGNAL dqs_out_en : STD_LOGIC; - SIGNAL dqs_out_en_dly : UNSIGNED (DQS_BITS - 1 DOWNTO 0); - SIGNAL dqs_out : STD_LOGIC; - SIGNAL dqs_out_dly : UNSIGNED (DQS_BITS - 1 DOWNTO 0); - SIGNAL dq_out_en : STD_LOGIC; - SIGNAL dq_out_en_dly : UNSIGNED (DQ_BITS - 1 DOWNTO 0); - SIGNAL dq_out : UNSIGNED (DQ_BITS - 1 DOWNTO 0); - SIGNAL dq_out_dly : UNSIGNED (DQ_BITS - 1 DOWNTO 0); - SIGNAL rdqsen_cntr : INTEGER; - SIGNAL rdqs_cntr : INTEGER; - SIGNAL rdqen_cntr : INTEGER; - SIGNAL rdq_cntr : INTEGER; - - SIGNAL r : STD_LOGIC := '0'; - - PROCEDURE memory_write( - SIGNAL bank : IN UNSIGNED (BA_BITS - 1 DOWNTO 0); - SIGNAL row : IN UNSIGNED (ROW_BITS - 1 DOWNTO 0); - SIGNAL col : IN UNSIGNED (COL_BITS - 1 DOWNTO 0); - SIGNAL data : IN UNSIGNED (BL_MAX * DQ_BITS - 1 DOWNTO 0); - SIGNAL addr : INOUT UNSIGNED (MAX_BITS - 1 DOWNTO 0)) IS - BEGIN - addr <= (bank & row & col) / BL_MAX; - -- TODO: only the MAX_MEM defined functionality available here - -- memory(addr) <= data; - END memory_write; - - PROCEDURE memory_read( - SIGNAL bank : IN UNSIGNED (BA_BITS - 1 DOWNTO 0); - SIGNAL row : IN UNSIGNED (ROW_BITS - 1 DOWNTO 0); - SIGNAL col : IN UNSIGNED (COL_BITS - 1 DOWNTO 0); - SIGNAL data : OUT UNSIGNED (BL_MAX * DQ_BITS - 1 DOWNTO 0); - SIGNAL addr : INOUT UNSIGNED (MAX_BITS - 1 DOWNTO 0)) IS - BEGIN - -- chop off the lowest address bits - addr <= (bank & row & col) / BL_MAX; - -- TODO: only the MAX_MEM defined functionality defined yet - -- data <= memory(addr); - END memory_read; - - PROCEDURE cmd_task( - cke : IN STD_LOGIC; - cmd : IN UNSIGNED (3 DOWNTO 0); - bank : IN UNSIGNED (BA_BITS - 1 DOWNTO 0); - addr : IN UNSIGNED (ADDR_BITS - 1 DOWNTO 0)) IS - - VARIABLE i : UNSIGNED (BANKS DOWNTO 0); - VARIABLE j : INTEGER; - VARIABLE tfaw_cntr : UNSIGNED (BANKS DOWNTO 0); - VARIABLE col : UNSIGNED (COL_BITS - 1 DOWNTO 0); - BEGIN - END cmd_task; - - - PROCEDURE initialize( - SIGNAL mode_reg0 : IN UNSIGNED (ADDR_BITS - 1 DOWNTO 0); - SIGNAL mode_reg1 : IN UNSIGNED (ADDR_BITS - 1 DOWNTO 0); - SIGNAL mode_reg2 : IN UNSIGNED (ADDR_BITS - 1 DOWNTO 0); - SIGNAL mode_reg3 : IN UNSIGNED (ADDR_BITS - 1 DOWNTO 0)) IS - - CONSTANT AP_BIT : UNSIGNED (ADDR_BITS - 1 DOWNTO 0) := TO_UNSIGNED(2 ** AP, ADDR_BITS); - BEGIN - REPORT("at time " & TIME'IMAGE(NOW) & "INFO: performing initialization sequence"); - - cmd_task('1', cmd_type_encoding(NOP), (OTHERS => 'X'), (OTHERS => 'X')); - cmd_task('1', cmd_type_encoding(PRECHARGE), (OTHERS => 'X'), AP_BIT); - cmd_task('1', cmd_type_encoding(LOAD_MODE), RESIZE(2D"3", BA_BITS), mode_reg3); - cmd_task('1', cmd_type_encoding(LOAD_MODE), RESIZE(2D"2", BA_BITS), mode_reg2); - cmd_task('1', cmd_type_encoding(LOAD_MODE), RESIZE(2D"1", BA_BITS), mode_reg1); - cmd_task('1', cmd_type_encoding(LOAD_MODE), (OTHERS => '0'), mode_reg0 OR "100"); -- DLL reset - cmd_task('1', cmd_type_encoding(PRECHARGE), (OTHERS => 'X'), AP_BIT); -- Precharge all - cmd_task('1', cmd_type_encoding(REFRESH), (OTHERS => 'X'), (OTHERS => 'X')); - cmd_task('1', cmd_type_encoding(REFRESH), (OTHERS => 'X'), (OTHERS => 'X')); - cmd_task('1', cmd_type_encoding(LOAD_MODE), (OTHERS => '0'), mode_reg0); - cmd_task('1', cmd_type_encoding(LOAD_MODE), RESIZE(2D"1", BA_BITS), mode_reg1 OR x"380"); -- OCD default - cmd_task('1', cmd_type_encoding(LOAD_MODE), RESIZE(2D"1", BA_BITS), mode_reg1); - cmd_task('1', cmd_type_encoding(NOP), (OTHERS => 'X'), (OTHERS => 'X')); - END initialize; - - FUNCTION abs_value(SIGNAL arg : IN REAL) RETURN REAL IS - BEGIN - IF arg < 0.0 THEN - RETURN -1.0 * arg; - END IF; - - RETURN arg; - END abs_value; - -BEGIN - PROCESS (ck) - BEGIN - ck_in <= ck AFTER BUS_DELAY; - END PROCESS; - - PROCESS (ck_n) - BEGIN - ck_n_in <= ck_n AFTER BUS_DELAY; - END PROCESS; - - PROCESS (cke) - BEGIN - cke_in <= cke AFTER BUS_DELAY; - END PROCESS; - - PROCESS (cs_n) - BEGIN - cs_n_in <= cs_n AFTER BUS_DELAY; - END PROCESS; - - PROCESS (ras_n) - BEGIN - ras_n_in <= ras_n AFTER BUS_DELAY; - END PROCESS; - - PROCESS (cas_n) - BEGIN - cas_n_in <= cas_n AFTER BUS_DELAY; - END PROCESS; - - PROCESS (we_n) - BEGIN - we_n_in <= we_n AFTER BUS_DELAY; - END PROCESS; - - PROCESS (dm_rdqs) - BEGIN - dm_in <= RESIZE(dm_rdqs, dm_in'LENGTH) AFTER BUS_DELAY; - END PROCESS; - - PROCESS (ba) - BEGIN - ba_in <= RESIZE(ba, ba_in'LENGTH) AFTER BUS_DELAY; - END PROCESS; - - PROCESS (addr) - BEGIN - addr_in <= RESIZE(addr, addr_in'LENGTH) AFTER BUS_DELAY; - END PROCESS; - - PROCESS (dq) - BEGIN - dq_in <= RESIZE(dq, dq_in'LENGTH) AFTER BUS_DELAY; - END PROCESS; - - PROCESS (dqs, dqs_n) - BEGIN - dqs_in <= SHIFT_LEFT(RESIZE(dqs_n, dqs_in'LENGTH), 18) OR RESIZE(dqs, dqs_in'LENGTH); - END PROCESS; - - PROCESS (odt) - BEGIN - odt_in <= odt AFTER BUS_DELAY; - END PROCESS; - - -- create internal clock - PROCESS - BEGIN - WAIT UNTIL RISING_EDGE(ck_in); - diff_ck <= ck_in; - END PROCESS; - - PROCESS - BEGIN - WAIT UNTIL RISING_EDGE(ck_n_in); - diff_ck <= NOT ck_n_in; - END PROCESS; - - dqs_even <= dqs_in (17 DOWNTO 0); - dqs_odd <= dqs_in (35 DOWNTO 18) WHEN dqs_n_en = '1' ELSE NOT(dqs_in (17 DOWNTO 0)); - cmd_n_in <= '0' & ras_n_in & cas_n_in & we_n_in WHEN NOT(cs_n_in) ELSE cmd_type_encoding(NOP); - - -- bufif1 buf_dqs - dqs <= dqs_out_dly WHEN (dqs_out_en_dly AND UNSIGNED'(0 TO DQS_BITS - 1 => out_en)) /= x"0" ELSE (OTHERS => 'Z'); - - -- bufif1 buf_dm - dm_rdqs <= dqs_out_dly WHEN (dqs_out_en_dly AND - UNSIGNED'(0 TO DM_BITS - 1 => out_en) AND - UNSIGNED'(0 TO DM_BITS - 1 => rdqs_en)) /= x"0" ELSE (OTHERS => 'Z'); - -- bufif1 buf_dqs_n - dqs_n <= NOT dqs_out_dly WHEN (dqs_out_en_dly AND - UNSIGNED'(0 TO DQS_BITS - 1 => out_en) AND - UNSIGNED'(0 TO DQS_BITS - 1 => dqs_n_en)) /= x"0" ELSE (OTHERS => 'Z'); - -- bufif1 buf_rdqs_n - rdqs_n <= NOT dqs_out_dly WHEN (dqs_out_en_dly AND - UNSIGNED'(0 TO DQS_BITS - 1 => out_en) AND - UNSIGNED'(0 to DQS_BITS - 1 => dqs_n_en) AND - UNSIGNED'(0 TO DQS_BITS - 1 => rdqs_en)) /= x"0" ELSE (OTHERS => 'Z'); - - -- bufif1 buf_dq - dq <= dq_out_dly WHEN (dq_out_en_dly AND - UNSIGNED'(0 TO DQ_BITS - 1 => out_en)) /= x"0" ELSE (OTHERS => 'Z'); - - -- initial block - init : PROCESS - BEGIN - IF BL_MAX < 2 THEN - REPORT("ERROR: BL_MAX parameter must be >= 2. BL_MAX=" & INTEGER'IMAGE(BL_MAX)); - END IF; - - IF 2 ** BO_BITS > BL_MAX THEN - REPORT("ERROR: 2**BO_BITS cannot be greater than BL_MAX parameter"); - END IF; - seed <= RANDOM_SEED; - ck_cntr <= 0; - - WAIT; - END PROCESS; - - -- ugly kludge: encapsulate reset_task PROCEDURE into a process to make ModelSim happy - reset : PROCESS - PROCEDURE reset_task IS - -- VARIABLE i : INTEGER; - BEGIN - -- disable inputs - dq_in_valid <= '0'; - dqs_in_valid <= '0'; - wdqs_cntr <= 0; - wdq_cntr <= 0; - - FOR i IN 0 TO 35 LOOP - wdqs_pos_cntr(i) <= 0; - END LOOP; - - b2b_write <= '0'; - - -- disable outputs - out_en <= '0'; - dqs_n_en <= '0'; - rdqs_en <= '0'; - dq_out_en <= '0'; - rdq_cntr <= 0; - dqs_out_en <= '0'; - rdqs_cntr <= 0; - - -- disable ODT - odt_en <= '0'; - odt_state <= '0'; - - -- reset bank state - active_bank <= (OTHERS => '1'); - auto_precharge_bank <= (OTHERS =>'0'); - read_precharge_bank <= (OTHERS => '0'); - write_precharge_bank <= (OTHERS =>'0'); - - -- require initialization sequence - init_done <= '0'; - init_step <= 0; - init_mode_reg <= (OTHERS => '0'); - - -- reset DLL - dll_en <= '0'; - dll_reset <= '0'; - dll_locked <= '0'; - ocd <= (OTHERS => '0'); - - -- exit power down and self refresh - in_power_down <= '0'; - in_self_refresh <= '0'; - - -- clear pipelines - al_pipeline <= (OTHERS => '0'); - wr_pipeline <= (OTHERS => '0'); - rd_pipeline <= (OTHERS => '0'); - odt_pipeline <= (OTHERS => '0'); - - -- clear memory - FOR i IN 0 TO MAX_SIZE LOOP - memory(i) <= (OTHERS => 'X'); - END LOOP; - - -- clear maximum timing checks - tm_refresh <= 0 ns; - FOR i IN 0 TO BANKS - 1 LOOP - tm_bank_activate(i) <= 0 ns; - END LOOP; - END reset_task; - BEGIN - WAIT UNTIL rising_edge(ck); - IF r /= '0' THEN - reset_task; - r <= '0'; - END IF; - END PROCESS; -- reset - - err : PROCESS - PROCEDURE chk_err( - samebank : IN UNSIGNED (0 DOWNTO 0); - bank : IN UNSIGNED (BA_BITS - 1 DOWNTO 0); - fromcmd : IN UNSIGNED (3 DOWNTO 0); - cmd : IN UNSIGNED (3 DOWNTO 0) - ) IS - - VARIABLE err : STD_LOGIC; - BEGIN - -- all matching case expression will be evaluated - - CASE? (samebank & fromcmd & cmd) IS - WHEN "0" & cmd_type_encoding(LOAD_MODE) & "0---" => - IF ck_cntr - ck_load_mode < TMRD THEN - REPORT("at time " & TIME'IMAGE(NOW) & " ERROR: tMRD violation during " & cmd_string(TO_INTEGER(cmd))); - END IF; - - WHEN "0" & cmd_type_encoding(LOAD_MODE) & "100-" => - IF ck_cntr - ck_load_mode < TMRD THEN - REPORT("at time " & TIME'IMAGE(NOW) & " INFO: Load Mode to Reset Condition"); - END IF; - - WHEN "0" & cmd_type_encoding(REFRESH) & "0---" => - IF NOW - tm_refresh < TRFC_MIN THEN - REPORT("tRFC violation during " & cmd_string(TO_INTEGER(cmd))); - END IF; - - WHEN "0" & cmd_type_encoding(REFRESH) & cmd_type_encoding(PWR_DOWN) => - NULL; -- 1 tCK_avg - - WHEN "0" & cmd_type_encoding(REFRESH) & cmd_type_encoding(SELF_REF) => - IF NOW - tm_refresh < TRFC_MIN THEN - REPORT("at time " & TIME'IMAGE(NOW) & "INFO: Refresh to Reset condition"); - END IF; - init_done <= '0'; - - WHEN "0" & cmd_type_encoding(PRECHARGE) & "000-" => - IF NOW - tm_precharge_all < TRPA THEN - REPORT("at time " & TIME'IMAGE(NOW) & " ERROR: tRPA violation during " & cmd_string(TO_INTEGER(cmd))); - END IF; - IF NOW - tm_precharge < TRP THEN - REPORT("at time " & TIME'IMAGE(NOW) & " ERROR: tRP violation during " & cmd_string(TO_INTEGER(cmd))); - END IF; - - WHEN "1" & cmd_type_encoding(PRECHARGE) & cmd_type_encoding(PRECHARGE) => - IF VERBOSE = TRUE AND NOW - tm_precharge_all < TRPA THEN - REPORT("at time " & TIME'IMAGE(NOW) & " INFO: Precharge All interruption during " & cmd_string(TO_INTEGER(cmd))); - END IF; - IF VERBOSE = TRUE AND NOW - tm_bank_precharge(TO_INTEGER(bank)) < TRP THEN - REPORT("at time " & TIME'IMAGE(NOW) & " INFO: Precharge Bank " & INTEGER'IMAGE(TO_INTEGER(bank)) & " interruption during " - & cmd_string(TO_INTEGER(cmd))); - END IF; - - WHEN "1" & cmd_type_encoding(PRECHARGE) & cmd_type_encoding(ACTIVATE) => - IF NOW - tm_precharge_all < TRPA THEN - REPORT("at time " & TIME'IMAGE(NOW) & " ERROR: tRPA violation during " & cmd_string(TO_INTEGER(cmd))); - END IF; - IF NOW - tm_bank_precharge(TO_INTEGER(bank)) < TRP THEN - REPORT("at time " & TIME'IMAGE(NOW) & " tRP violation during " & cmd_string(TO_INTEGER(cmd)) & " to bank " - & INTEGER'IMAGE(TO_INTEGER(bank))); - END IF; - - WHEN "0" & cmd_type_encoding(PRECHARGE) & cmd_type_encoding(PWR_DOWN) => - -- 1 tCK, can be concurrent with auto precharge - - WHEN "0" & cmd_type_encoding(PRECHARGE) & cmd_type_encoding(SELF_REF) => - IF NOW - tm_precharge_all < TRPA OR NOW - tm_precharge < TRP THEN - REPORT("at time " & TIME'IMAGE(NOW) & " INFO: Precharge to reset condition"); - init_done <= '0'; - END IF; - - WHEN "0" & cmd_type_encoding(ACTIVATE) & cmd_type_encoding(REFRESH) => - IF NOW - tm_activate < TRC THEN - REPORT("at time " & TIME'IMAGE(NOW) & " ERROR: tRC violation during " & cmd_string(TO_INTEGER(cmd))); - END IF; - - WHEN "1" & cmd_type_encoding(ACTIVATE) & cmd_type_encoding(PRECHARGE) => - IF NOW - tm_bank_activate(TO_INTEGER(bank)) > TRAS_MAX AND active_bank(TO_INTEGER(bank)) = '1' THEN - REPORT("at time " & TIME'IMAGE(NOW) & " ERROR: tRAS maximum violation during " & cmd_string(TO_INTEGER(cmd)) & - " to bank " & INTEGER'IMAGE(TO_INTEGER(bank))); - END IF; - IF NOW - tm_bank_activate(TO_INTEGER(bank)) < TRAS_MIN THEN - REPORT("at time " & TIME'IMAGE(NOW) & " ERROR: tRAS minimum violation during " & cmd_string(TO_INTEGER(cmd)) & - " to bank " & INTEGER'IMAGE(TO_INTEGER(bank))); - END IF; - - WHEN "0" & cmd_type_encoding(ACTIVATE) & cmd_type_encoding(ACTIVATE) => - IF NOW - tm_activate < TRRD THEN - REPORT("at time " & TIME'IMAGE(NOW) & " ERROR: tRRD violation during " & cmd_string(TO_INTEGER(cmd)) & - " to bank " & INTEGER'IMAGE(TO_INTEGER(bank))); - END IF; - - WHEN "1" & cmd_type_encoding(ACTIVATE) & cmd_type_encoding(ACTIVATE) => - IF NOW - tm_bank_activate(TO_INTEGER(bank)) < TRC THEN - REPORT("at time " & TIME'IMAGE(NOW) & " ERROR: tRC violation during " & cmd_string(TO_INTEGER(cmd)) & " to bank " & - INTEGER'IMAGE(TO_INTEGER(bank))); - END IF; - - WHEN "1" & cmd_type_encoding(ACTIVATE) & "010-" => - NULL; -- tRCD is checked outside this task - - WHEN "1" & cmd_type_encoding(ACTIVATE) & cmd_type_encoding(PWR_DOWN) => - NULL; -- 1 tCK - - WHEN "1" & cmd_type_encoding(WRITE_CMD) & cmd_type_encoding(PRECHARGE) => - IF ck_cntr - ck_bank_write(TO_INTEGER(bank)) - <= write_latency + TO_INTEGER(burst_length) + 2 OR - NOW - tm_bank_write_end(TO_INTEGER(bank)) < TWR THEN - REPORT("at time " & TIME'IMAGE(NOW) & " ERROR: tWR violation during " & cmd_string(TO_INTEGER(cmd)) & - " to bank " & INTEGER'IMAGE(TO_INTEGER(bank))); - END IF; - - WHEN "0" & cmd_type_encoding(WRITE_CMD) & cmd_type_encoding(WRITE_CMD) => - IF ck_cntr - ck_write < TCCD THEN - REPORT("at time " & TIME'IMAGE(NOW) & " ERROR: tCCD violation during " & cmd_string(TO_INTEGER(cmd)) & - " to bank " & INTEGER'IMAGE(TO_INTEGER(bank))); - END IF; - - WHEN "0" & cmd_type_encoding(WRITE_CMD) & cmd_type_encoding(READ_CMD) => - IF ck_load_mode < ck_write AND ck_cntr - ck_write < write_latency + TO_INTEGER(burst_length) / 2 + 2 - additive_latency THEN - REPORT("at time " & TIME'IMAGE(NOW) & " ERROR: tWTR violation during " & cmd_string(TO_INTEGER(cmd)) & - " to bank " & INTEGER'IMAGE(TO_INTEGER(bank))); - END IF; - - WHEN "0" & cmd_type_encoding(WRITE_CMD) & cmd_type_encoding(PWR_DOWN) => - - - WHEN OTHERS => - NULL; -- do nothing - - END CASE?; - END; - BEGIN - WAIT UNTIL RISING_EDGE(ck); - END PROCESS; -- err + CONSTANT HB : INTEGER := B / 2; +BEGIN END rtl; diff --git a/vhdl/testbenches/firebee_tb.vhd b/vhdl/testbenches/firebee_tb.vhd index e1d71d3..02b9576 100644 --- a/vhdl/testbenches/firebee_tb.vhd +++ b/vhdl/testbenches/firebee_tb.vhd @@ -469,15 +469,17 @@ BEGIN I_DDR_1 : ddr_ram_model PORT MAP ( - ck => clk_ddr_out, - ck_n => clk_ddr_out_n, + clk => clk_ddr_out, + clkb => clk_ddr_out_n, cke => vcke, - cs_n => vcs_n, - ras_n => vras_n, - cas_n => vcas_n, - we_n => vwe_n, + csb => vcs_n, + rasb => vras_n, + casb => vcas_n, + web => vwe_n, ba => UNSIGNED(ba), - addr => UNSIGNED(va), - odt => '1' + ad => va (12 DOWNTO 0), + dqi => vd (30 DOWNTO 15), + dm => UNSIGNED(vdm (3 DOWNTO 2)), + dqs => vd_qs (3 DOWNTO 2) ); END beh; \ No newline at end of file