From 7c1fc341b87f2737090282618f41dff7ad832277 Mon Sep 17 00:00:00 2001 From: Ryan <> Date: Wed, 17 Sep 2025 16:06:04 -0500 Subject: [PATCH] Organize simulation library --- .../{wb_memory.vhd => dev_genericmem.vhd} | 6 +- ...s28f128j3d75.vhd => dev_js28f128j3d75.vhd} | 6 +- ...t45w8mw16bgx.vhd => dev_mt45w8mw16bgx.vhd} | 20 +- libraries/simulated/js28f128j3d75.vhd | 1142 ----------------- .../{ps2_device.vhd => proto_ps2.vhd} | 6 +- libraries/simulated/tests/test_attrs.vhd | 75 -- .../{test_simmem.vhd => test_genericmem.vhd} | 8 +- .../simulated/tests/test_js28f128j3d75.vhd | 222 ++-- .../simulated/tests/test_mt45w8mw16bgx.vhd | 10 +- .../{test_ps2_device.vhd => test_ps2.vhd} | 10 +- libraries/simulated/tests/test_simflash.vhd | 113 -- ...sewidth.vhd => util_assert_pulsewidth.vhd} | 0 ...etuphold.vhd => util_assert_setuphold.vhd} | 0 ..._vec.vhd => util_assert_setuphold_vec.vhd} | 0 ...within_t.vhd => util_changed_within_t.vhd} | 0 ..._vec.vhd => util_changed_within_t_vec.vhd} | 0 .../{delay_edges.vhd => util_delay_edges.vhd} | 0 .../{sim_utility.vhd => util_pkg.vhd} | 0 18 files changed, 109 insertions(+), 1509 deletions(-) rename libraries/simulated/{wb_memory.vhd => dev_genericmem.vhd} (92%) rename libraries/simulated/{sim_js28f128j3d75.vhd => dev_js28f128j3d75.vhd} (99%) rename libraries/simulated/{mt45w8mw16bgx.vhd => dev_mt45w8mw16bgx.vhd} (93%) delete mode 100644 libraries/simulated/js28f128j3d75.vhd rename libraries/simulated/{ps2_device.vhd => proto_ps2.vhd} (98%) delete mode 100644 libraries/simulated/tests/test_attrs.vhd rename libraries/simulated/tests/{test_simmem.vhd => test_genericmem.vhd} (89%) rename libraries/simulated/tests/{test_ps2_device.vhd => test_ps2.vhd} (92%) delete mode 100644 libraries/simulated/tests/test_simflash.vhd rename libraries/simulated/{assert_pulsewidth.vhd => util_assert_pulsewidth.vhd} (100%) rename libraries/simulated/{assert_setuphold.vhd => util_assert_setuphold.vhd} (100%) rename libraries/simulated/{assert_setuphold_vec.vhd => util_assert_setuphold_vec.vhd} (100%) rename libraries/simulated/{changed_within_t.vhd => util_changed_within_t.vhd} (100%) rename libraries/simulated/{changed_within_t_vec.vhd => util_changed_within_t_vec.vhd} (100%) rename libraries/simulated/{delay_edges.vhd => util_delay_edges.vhd} (100%) rename libraries/simulated/{sim_utility.vhd => util_pkg.vhd} (100%) diff --git a/libraries/simulated/wb_memory.vhd b/libraries/simulated/dev_genericmem.vhd similarity index 92% rename from libraries/simulated/wb_memory.vhd rename to libraries/simulated/dev_genericmem.vhd index 13a8dcc..ed5b6d9 100644 --- a/libraries/simulated/wb_memory.vhd +++ b/libraries/simulated/dev_genericmem.vhd @@ -3,7 +3,7 @@ use ieee.std_logic_1164.all; use ieee.numeric_std.all; -entity wb_memory is +entity genericmem is generic ( INIT: std_logic_vector(32*8-1 downto 0) := (others => '0') ); @@ -19,10 +19,10 @@ entity wb_memory is dat_i: in std_logic_vector(7 downto 0); dat_o: out std_logic_vector(7 downto 0) ); -end wb_memory; +end genericmem; -architecture behavioral of wb_memory is +architecture behavioral of genericmem is type mem_array_t is array(natural range <>) of std_logic_vector(7 downto 0); diff --git a/libraries/simulated/sim_js28f128j3d75.vhd b/libraries/simulated/dev_js28f128j3d75.vhd similarity index 99% rename from libraries/simulated/sim_js28f128j3d75.vhd rename to libraries/simulated/dev_js28f128j3d75.vhd index a024d7e..5a0beb3 100644 --- a/libraries/simulated/sim_js28f128j3d75.vhd +++ b/libraries/simulated/dev_js28f128j3d75.vhd @@ -6,7 +6,7 @@ library work; use work.sim_utility.all; -entity sim_js28f128j3d75 is +entity js28f128j3d75 is generic ( FILENAME: string := ""; BASEADDR: natural := 0 @@ -22,10 +22,10 @@ entity sim_js28f128j3d75 is byte_n: in std_logic; vpen: in std_logic ); -end sim_js28f128j3d75; +end js28f128j3d75; -architecture behavioral of sim_js28f128j3d75 is +architecture behavioral of js28f128j3d75 is ---------------------------------------------------------------------------- -- Timings for 128Mbit, J3D-75 parts diff --git a/libraries/simulated/mt45w8mw16bgx.vhd b/libraries/simulated/dev_mt45w8mw16bgx.vhd similarity index 93% rename from libraries/simulated/mt45w8mw16bgx.vhd rename to libraries/simulated/dev_mt45w8mw16bgx.vhd index fbcbb9c..c1e176a 100644 --- a/libraries/simulated/mt45w8mw16bgx.vhd +++ b/libraries/simulated/dev_mt45w8mw16bgx.vhd @@ -2,7 +2,7 @@ library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; -library simulated; +library work; entity mt45w8mw16bgx is @@ -116,15 +116,15 @@ begin -- Generate mask for periods of time with invalid data -- FIXME: this may break hold time - xm_addr: entity simulated.changed_within_t_vec generic map (T => T_AA, T_HOLD => T_OH) + xm_addr: entity work.changed_within_t_vec generic map (T => T_AA, T_HOLD => T_OH) port map (sig_in => a, sig_out => xmask_addr); - xm_ce: entity simulated.changed_within_t generic map (T => T_CO, T_HOLD => T_HZ) + xm_ce: entity work.changed_within_t generic map (T => T_CO, T_HOLD => T_HZ) port map (sig_in => ce_n, sig_out => xmask_ce_n); - xm_oe: entity simulated.changed_within_t generic map (T => T_OE, T_HOLD => T_OHZ) + xm_oe: entity work.changed_within_t generic map (T => T_OE, T_HOLD => T_OHZ) port map (sig_in => oe_n, sig_out => xmask_oe_n); - xm_ub: entity simulated.changed_within_t generic map (T => T_BA, T_HOLD => T_BHZ) + xm_ub: entity work.changed_within_t generic map (T => T_BA, T_HOLD => T_BHZ) port map (sig_in => ub_n, sig_out => xmask_ub_n); - xm_lb: entity simulated.changed_within_t generic map (T => T_BA, T_HOLD => T_BHZ) + xm_lb: entity work.changed_within_t generic map (T => T_BA, T_HOLD => T_BHZ) port map (sig_in => lb_n, sig_out => xmask_lb_n); xmask_hi <= xmask_addr or xmask_ce_n or xmask_oe_n or xmask_ub_n; xmask_lo <= xmask_addr or xmask_ce_n or xmask_oe_n or xmask_lb_n; @@ -134,13 +134,13 @@ begin read_word( 7 downto 0) <= (others => 'X') when xmask_lo = '1' else array_word( 7 downto 0); -- Generate mask for periods of time where data bus is high-z - zm_ce: entity simulated.delay_edges generic map (D_RISE => T_HZ, D_FALL => T_LZ) + zm_ce: entity work.delay_edges generic map (D_RISE => T_HZ, D_FALL => T_LZ) port map (sig_in => ce_n, sig_out => zmask_ce_n); - zm_oe: entity simulated.delay_edges generic map (D_RISE => T_OHZ, D_FALL => T_OLZ) + zm_oe: entity work.delay_edges generic map (D_RISE => T_OHZ, D_FALL => T_OLZ) port map (sig_in => oe_n, sig_out => zmask_oe_n); - zm_ub: entity simulated.delay_edges generic map (D_RISE => T_BHZ, D_FALL => T_BLZ) + zm_ub: entity work.delay_edges generic map (D_RISE => T_BHZ, D_FALL => T_BLZ) port map (sig_in => ub_n, sig_out => zmask_ub_n); - zm_lb: entity simulated.delay_edges generic map (D_RISE => T_BHZ, D_FALL => T_BLZ) + zm_lb: entity work.delay_edges generic map (D_RISE => T_BHZ, D_FALL => T_BLZ) port map (sig_in => lb_n, sig_out => zmask_lb_n); zmask_hi <= zmask_ce_n or zmask_oe_n or zmask_ub_n; zmask_lo <= zmask_ce_n or zmask_oe_n or zmask_lb_n; diff --git a/libraries/simulated/js28f128j3d75.vhd b/libraries/simulated/js28f128j3d75.vhd deleted file mode 100644 index c3ace7b..0000000 --- a/libraries/simulated/js28f128j3d75.vhd +++ /dev/null @@ -1,1142 +0,0 @@ --------------------------------------------------------------------------------- --- Notes: --- --- In ISim 14.7, it appears that the 'stable attribute doesn't work --- Checking if 'last_event >= T_x doesn't seem to work with no previous events --------------------------------------------------------------------------------- - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - - -entity js28f128j3d75 is - port ( - a: in std_logic_vector(23 downto 0); - d: inout std_logic_vector(15 downto 0); - ce: in std_logic_vector(2 downto 0); - rp_n: in std_logic; - oe_n: in std_logic; - we_n: in std_logic; - sts: out std_logic; -- open drain - byte_n: in std_logic; - vpen: in std_logic - ); -end js28f128j3d75; - - -architecture behavioral of js28f128j3d75 is - - -- Timings for 128Mbit, J3D-75 parts - - -- Read timings - constant T_AVAV: time := 75 ns; -- R1, Read/Write Cycle Time - constant T_AVQV: time := 75 ns; -- R2, Address to Output Delay - constant T_ELQV: time := 75 ns; -- R3, CEx to Output Delay - constant T_GLQV_NA: time := 25 ns; -- R4, OE# to Non-Array Output Delay - constant T_PHQV: time := 210 ns; -- R5, RP# High to Output Delay - constant T_ELQX: time := 0 ns; -- R6, CEx to Output Low Z - constant T_GLQX: time := 0 ns; -- R7, OE# to Output Low Z - constant T_EHQZ: time := 25 ns; -- R8, CEx High to Output in High Z - constant T_GHQZ: time := 15 ns; -- R9, OE# High to Output in High Z - constant T_OH: time := 0 ns; -- R10, Output Hold from Address, CEx, or OE# change - constant T_ELFL: time := 10 ns; -- R11, CEx Low to BYTE# High or Low - constant T_ELFH: time := 10 ns; -- R11, (Same as Above) - constant T_FLQV: time := 1 ns; -- R12, BYTE# to Output Delay - constant T_FHQV: time := 1 ns; -- R12, (Same as Above) - constant T_FLQZ: time := 1 ns; -- R13, BYTE# to Output in High Z - constant T_EHEL: time := 0 ns; -- R14, CEx High to CEx Low - constant T_APA: time := 25 ns; -- R15, Page Address Access Time - constant T_GLQV_A: time := 25 ns; -- R16, OE# to Array Output Delay - - -- Write timings - constant T_PHWL: time := 210 ns; -- W1, RP# High Recovery to WE# (CEx) Going Low - constant T_PHEL: time := 210 ns; -- W1, (Same as Above) - constant T_ELWL: time := 0 ns; -- W2, CEx (WE#) Low to WE# (CEx) Going Low - constant T_WLEL: time := 0 ns; -- W2, (Same as Above) - constant T_WP: time := 60 ns; -- W3, Write Pulse Width - constant T_DVWH: time := 50 ns; -- W4, Data Setup to WE# (CEx) Going High - constant T_DVEH: time := 50 ns; -- W4, (Same as Above) - constant T_AVWH: time := 55 ns; -- W5, Address Setup to WE# (CEx) Going High - constant T_AVEH: time := 55 ns; -- W5, (Same as Above) - constant T_WHEH: time := 0 ns; -- W6, CEx (WE#) Hold from WE# (CEx) High - constant T_EHWH: time := 0 ns; -- W6, (Same as Above) - constant T_WHDX: time := 0 ns; -- W7, Data Hold from WE# (CEx) High - constant T_EHDX: time := 0 ns; -- W7, (Same as Above) - constant T_WHAX: time := 0 ns; -- W8, Address Hold from WE# (CEx) High - constant T_EHAX: time := 0 ns; -- W8, (Same as Above) - constant T_WPH: time := 30 ns; -- W9, Write Pulse Width High - constant T_VPWH: time := 0 ns; -- W11, Vpen Setup to WE# (CEx) Going High - constant T_VPEH: time := 0 ns; -- W11, (Same as Above) - constant T_WHGL: time := 35 ns; -- W12, Write Recovery before Read - constant T_EHGL: time := 35 ns; -- W12, (Same as Above) - constant T_WHRL: time := 500 ns; -- W13, WE# (CEx) High to STS Going Low - constant T_EHRL: time := 500 ns; -- W13, (Same as Above) - constant T_QVVL: time := 0 ns; -- W15, Vpen Hold from Valid SRD, STS Going High - - -- Configuration timings - constant T_WHQV3: time := 175 us; -- W16, Byte Program Time (Using Word/Byte Program Command) - constant T_EHQV3: time := 175 us; -- W16, (Same as above) - constant T_WHQV4: time := 4 sec; -- W16, Block Erase Time - constant T_EHQV4: time := 4 sec; -- W16, (Same as above) - constant T_WHQV5: time := 60 us; -- W16, Set Lock-Bit Time - constant T_EHQV5: time := 60 us; -- W16, (Same as above) - constant T_WHQV6: time := 0.7 sec; -- W16, Clear Block Lock-Bits Time - constant T_EHQV6: time := 0.7 sec; -- W16, (Same as above) - constant T_WHRH1: time := 20 us; -- W16, Program Suspend Latency Time to Read - constant T_EHRH1: time := 20 us; -- W16, (Same as above) - constant T_WHRH: time := 20 us; -- W16, Erase Suspend Latency Time to Read - constant T_EHRH: time := 20 us; -- W16, (Same as above) - constant T_STS: time := 500 ns; -- WY, STS Pulse Width Low Time - - -- Reset timings - constant T_PLPH: time := 25 us; -- P1, RP# Pulse Low Time - constant T_PHRH: time := 100 ns; -- P2, RP# High to Reset During Block-Erase, Program, or Lock-Bit Configuration - constant T_VCCPH: time := 60 us; -- P3, Vcc Power Valid to RP# de-assertion (high) - - pure function block_index_of(address: std_logic_vector(a'high downto 0)) return integer is - begin - return to_integer(unsigned(address(address'high downto 17))); - end function; - - pure function word_index_of(address: std_logic_vector(a'high downto 0)) return integer is - begin - return to_integer(unsigned(address(16 downto 1))); - end function; - - -- Internal types - type word_array is array(natural range <>) of std_logic_vector(15 downto 0); - type block_array is array(natural range<>) of word_array(65535 downto 0); - - type cui_state is ( - C_IDLE, - C_PECR, - C_POTP, - C_STSC, - C_PROG, - C_BUF_PROG_COUNT, - C_BUF_PROG_DATA, - C_BUF_PROG_CONF, - C_ERASE, - C_LOCK - ); - type read_state is (R_ARRAY, R_ID, R_STATUS, R_CFI); - type wsm_state is (W_READY, W_PROG, W_BUF_PROG, W_ERASE, W_LOCK_PROG, W_LOCK_ERASE, W_OTP_PROG, W_RESUME); - - -- Internal signals - signal internal_ce_n: std_logic; -- Composite chip-enable from multiple CE input signals - signal internal_we_n: std_logic; -- Composite write-latch from WE# and CEx - - signal array_pre_word: std_logic_vector(15 downto 0); - signal array_word: std_logic_vector(15 downto 0); - signal cfi_pre_word: std_logic_vector(15 downto 0); - signal cfi_word: std_logic_vector(15 downto 0); - signal id_pre_word: std_logic_vector(15 downto 0); - signal id_word: std_logic_vector(15 downto 0); - signal status_pre_word: std_logic_vector(15 downto 0); - signal status_word: std_logic_vector(15 downto 0); - signal read_pre_word: std_logic_vector(15 downto 0); - signal read_word: std_logic_vector(15 downto 0); - signal last_word: std_logic_vector(15 downto 0); - - -- Delay mask signals for array reads - signal addr_hi_change_4: std_logic; - signal addr_hi_change_8: std_logic; - signal addr_hi_change: std_logic; - signal is_sensing: std_logic; - signal addr_lo_change_4: std_logic; - signal addr_lo_change_8: std_logic; - signal addr_lo_change: std_logic; - signal oe_change_array: std_logic; - - -- Delay mask signals for non-array reads - signal addr_change: std_logic; - signal oe_change_nonarray: std_logic; - - -- Delay mask signals for all reads - signal rp_change: std_logic; - signal ce_change: std_logic; - signal byte_change: std_logic; - - -- Delay mask signals for tristate logic - signal ce_n_gate: std_logic; - signal oe_n_gate: std_logic; - signal final_oe_n: std_logic; - - signal cur_cui_state: cui_state; - signal cur_read_state: read_state; - signal cur_wsm_state: wsm_state; - signal next_wsm_state: wsm_state; - signal wsm_trigger: std_logic; - - -- Status signals - signal sts_ready: std_logic := '1'; - signal sts_susp_erase: std_logic := '0'; - signal sts_error_code: std_logic_vector(1 downto 0) := "00"; - signal sts_error_volt: std_logic := '0'; - signal sts_susp_prog: std_logic := '0'; - signal sts_error_lock: std_logic := '0'; - signal sts_config: std_logic_vector(7 downto 0) := (others => '0'); - - -- Flash array data - -- Only two blocks to save the simulator - signal flash_array: block_array(1 downto 0) := (others => (others => (others => '1'))); - - -- Lock operation state - signal lock_address: std_logic_vector(a'range); - signal lock_reg: std_logic_vector(127 downto 0) := (others => '0'); - - -- Program array operation state - signal prog_count: integer; - signal prog_address: std_logic_vector(a'range); - signal prog_buf: word_array(31 downto 0); - signal prog_word: std_logic_vector(15 downto 0); - - -- Erase operation state - signal erase_address: std_logic_vector(a'range); - - -- Enhanced Configuration Register - signal ecr_reg: std_logic_vector(16 downto 0); - signal ecr_8word_page: std_logic; - - -- OTP Protection Register - signal otp_prog_offset: std_logic_vector(a'range); - signal otp_prog_data: std_logic_vector(15 downto 0); - signal plr_reg: std_logic_vector(15 downto 0) := x"FFFE"; - signal otp_reg: word_array(7 downto 0) := (others => (others => '1')); - - -- Debug - signal ce_stable: boolean; -begin - - ---------------------------------------------------------------------------- - -- Useful internal signals composed from external signals - - -- Decode multiple chip enable inputs into single chip enable signal - with ce select internal_ce_n <= - '0' when "000", - '1' when "001", - '1' when "010", - '1' when "011", - '0' when "100", - '0' when "101", - '0' when "110", - '1' when "111", - 'X' when others; - - -- Write latch is triggered by either WEx or CEx going high, whichever is first - internal_we_n <= we_n or internal_ce_n; - - -- STS signal represents the state of the WSM - sts <= 'H' when sts_ready = '1' else '0'; - - - ---------------------------------------------------------------------------- - -- Reset logic - - reset: process (rp_n) - begin - if rp_n = '0' then - -- reset all state machines - -- cur_cui_state <= C_IDLE; - -- cur_read_state <= R_ARRAY; - -- cur_wsm_state <= W_READY; - - -- reset status register and status config - --sts_ready <= '1'; - --sts_susp_erase <= '0'; - --sts_error_code <= "00"; - --sts_error_volt <= '0'; - --sts_susp_prog <= '0'; - --sts_error_lock <= '0'; - sts_config <= (others => '0'); - - -- reset ECR to 4-word page mode - ecr_reg <= (others => '0'); - - -- abort all program, erase, lock-bit operations - end if; - end process; - - - ---------------------------------------------------------------------------- - -- Read logic - - -- Look up value from flash array - array_pre_word <= flash_array(block_index_of(a))(word_index_of(a)); - - -- Generate mask signal representing sensing delay - -- ce_change is incorporated here because the datasheet says ce falling triggers sensing, - -- but the same delay also listed for all other reads, so it is incorporated again below. - addr_hi_change_4 <= '1' when (a(a'high downto 3) /= a(a'high downto 3)'delayed(T_AVQV)) or - (a(a'high downto 3)'last_event < T_AVQV) - else '0'; - addr_hi_change_8 <= '1' when (a(a'high downto 4) /= a(a'high downto 4)'delayed(T_AVQV)) or - (a(a'high downto 4)'last_event < T_AVQV) - else '0'; - with ecr_8word_page select addr_hi_change <= - addr_hi_change_8 when '1', - addr_hi_change_4 when others; - ce_change <= '1' when (internal_ce_n /= internal_ce_n'delayed(T_ELQV)) or - (internal_ce_n'last_event < T_ELQV) - else '0'; - is_sensing <= addr_hi_change or ce_change; - - -- Generate mask signal representing word select delay - addr_lo_change_4 <= '1' when (a(2 downto 0) /= a(2 downto 0)'delayed(T_APA)) or - (a(2 downto 0)'last_event < T_APA) - else '0'; - addr_lo_change_8 <= '1' when (a(3 downto 0) /= a(3 downto 0)'delayed(T_APA)) or - (a(3 downto 0)'last_event < T_APA) - else '0'; - with ecr_8word_page select addr_lo_change <= - addr_lo_change_8 when '1', - addr_lo_change_4 when others; - - -- Generate mask signal representing OE# delay for array reads - oe_change_array <= '1' when (oe_n /= oe_n'delayed(T_GLQV_A)) or - (oe_n'last_event < T_GLQV_A) - else '0'; - - array_word <= (others => 'X') when is_sensing = '1' or - addr_lo_change = '1' or - oe_change_array = '1' else array_pre_word; - - - -- Generate mask signals representing delays for non-array reads (and use ce_change from above) - -- Not sure if T_AVAV applies to non-array reads, so apply it anyway just in case - addr_change <= '1' when (a /= a'delayed(T_AVQV)) or - (a'last_event < T_AVQV) - else '0'; - oe_change_nonarray <= '1' when (oe_n /= oe_n'delayed(T_GLQV_NA)) or - (oe_n'last_event < T_GLQV_NA) - else '0'; - - -- Look up CFI query value - do_cfi_read: process (a) - begin - case a(8 downto 1) is - when x"10" => cfi_pre_word <= x"0051"; - when x"11" => cfi_pre_word <= x"0052"; - when x"12" => cfi_pre_word <= x"0059"; - when others => cfi_pre_word <= (others => '0'); - end case; - end process; - - cfi_word <= (others => 'X') when addr_change = '1' or - oe_change_nonarray = '1' else cfi_pre_word; - - -- Look up ID register value - do_id_read: process (a) - begin - case to_integer(unsigned(a(16 downto 1))) is - -- Device ID - when 16#0001# => - id_pre_word <= x"0018"; - - -- Lock bit for this block - when 16#0002# => - id_pre_word <= (others => '0'); - id_pre_word(0) <= lock_reg(to_integer(unsigned(a(a'high downto 17)))); - - -- OTP protection lock register - when 16#0080# => id_pre_word <= plr_reg; - - -- OTP register - when 16#0081# to 16#88# => - id_pre_word <= otp_reg(to_integer(unsigned(a)) - 16#81#); - - when others => id_pre_word <= (others => 'X'); - end case; - end process; - - id_word <= (others => 'X') when addr_change = '1' or - oe_change_nonarray = '1' else id_pre_word; - - -- Compute status register value - do_status: process (internal_ce_n, oe_n, - sts_ready, sts_susp_erase, sts_error_code, sts_error_volt, sts_susp_prog, sts_error_lock) - begin - -- Status register value is latched on CEx or OE# going low - if falling_edge(internal_ce_n) or (falling_edge(oe_n) and internal_ce_n = '0') then - status_pre_word(15 downto 8) <= x"00"; - status_pre_word(7) <= sts_ready; - status_pre_word(6) <= sts_susp_erase; - status_pre_word(5 downto 4) <= sts_error_code; - status_pre_word(3) <= sts_error_volt; - status_pre_word(2) <= sts_susp_prog; - status_pre_word(1) <= sts_error_lock; - status_pre_word(0) <= '0'; - end if; - end process; - - status_word <= (others => 'X') when addr_change = '1' or - oe_change_nonarray = '1' else status_pre_word; - - - -- Choose a value based on read mode - do_read: process (cur_read_state, array_word, cfi_word, id_word, status_word) - begin - case cur_read_state is - when R_ARRAY => - read_pre_word <= array_word; - when R_ID => - read_pre_word <= id_word; - when R_STATUS => - read_pre_word <= status_word; - when R_CFI => - read_pre_word <= cfi_word; - when others => - read_pre_word <= (others => 'X'); - end case; - end process; - - -- Generate mask signals for delays that apply to any read - rp_change <= '1' when (rp_n /= rp_n'delayed(T_PHQV)) or - (rp_n'last_event < T_PHQV) - else '0'; - byte_change <= '1' when (byte_n /= byte_n'delayed(T_FLQV)) or - (byte_n'last_event < T_FLQV) - else '0'; - -- ce_change from above - - -- Handle byte/word modes - byte_select: process (read_pre_word, a(0), byte_n) - begin - if byte_n = '0' then - -- Oops, extra tristating to handle here instead of in tristate logic - -- Good thing is is sim-only! - read_word(15 downto 8) <= (others => 'Z'); - if a(0) = '0' then - read_word(7 downto 0) <= read_pre_word(7 downto 0); - else - read_word(7 downto 0) <= read_pre_word(15 downto 8); - end if; - else - read_word <= read_pre_word; - end if; - end process; - - -- Equal parts gin, green chartreuse, maraschino liqueur, lime; shaken and served up - last_word <= (others => 'X') when rp_change = '1' or - byte_change = '1' else read_word; - - - -- Handle delays between CEx/OE# and transitions between low/high-Z output - -- The front and back porch have different delay specs, so to get the front porch - -- with one delay and the back porch with the other we may need to either and or - -- or the delayed signals depending on which delay is longer. - delayed_ce_n_a: if T_ELQX > T_EHQZ generate - ce_n_gate <= internal_ce_n'delayed(T_ELQX) or internal_ce_n'delayed(T_EHQZ); - end generate; - delayed_ce_n_b: if T_ELQX <= T_EHQZ generate - ce_n_gate <= internal_ce_n'delayed(T_ELQX) and internal_ce_n'delayed(T_EHQZ); - end generate; - delayed_oe_n_a: if T_GLQX > T_GHQZ generate - oe_n_gate <= oe_n'delayed(T_GLQX) or oe_n'delayed(T_GHQZ); - end generate; - delayed_oe_n_b: if T_GLQX <= T_GHQZ generate - oe_n_gate <= oe_n'delayed(T_GLQX) and oe_n'delayed(T_GHQZ); - end generate; - final_oe_n <= ce_n_gate or oe_n_gate; - d <= (others => 'Z') when rp_n = '0' or final_oe_n = '1' else last_word'delayed(T_OH); - - - ecr_8word_page <= ecr_reg(13); - - - ---------------------------------------------------------------------------- - -- Write logic - - -- Latch CUI on rising edge of we_n or ce_n - -- CUI logic is responsible for: - -- * checking sts_ready before triggering - -- * checking sts_susp_prog/erase before triggering if relevant - -- * setting sts_susp_prog/erase when suspending - -- * setting next_wsm_state and wsm_trigger to begin operations - cui: process (internal_we_n, a, d, rp_n, - sts_ready, sts_susp_prog, sts_susp_erase, cur_wsm_state) - variable prog_i: integer; - begin - if rp_n = '0' then - cur_cui_state <= C_IDLE; - cur_read_state <= R_ARRAY; - wsm_trigger <= '0'; - elsif rising_edge(internal_we_n) then - case cur_cui_state is - when C_IDLE => - wsm_trigger <= '0'; - - -- Idle, not waiting for data or confirmation commands - case d(7 downto 0) is - -- Program Enhanced Configuration Register (Setup) - --when x"60" => - -- cur_cui_state <= C_PECR; - - -- Program OTP Register (Setup) - when x"c0" => - cur_cui_state <= C_POTP; - - -- Clear Status Register - when x"50" => - -- Only clear error flags, not status - sts_error_code <= "00"; - sts_error_volt <= '0'; - sts_error_lock <= '0'; - cur_read_state <= R_STATUS; - - -- Program STS Configuration Register (Setup) - when x"b8" => - -- FIXME: enter R_STATUS? - cur_cui_state <= C_STSC; - - -- Read Array - when x"ff" => - assert sts_ready = '1' - report "Entering read-array mode while WSM is busy" - severity warning; - cur_read_state <= R_ARRAY; - - -- Read Status Register - when x"70" => - cur_read_state <= R_STATUS; - - -- Read Identifier Codes - when x"90" => - cur_read_state <= R_ID; - - -- CFI Query - when x"98" => - cur_read_state <= R_CFI; - - -- Word/Byte Program (Setup) - when x"40" | x"10" => - cur_cui_state <= C_PROG; - - -- Buffered Program (Setup) - when x"e8" => - cur_read_state <= R_STATUS; - if sts_ready = '1' then - cur_cui_state <= C_BUF_PROG_COUNT; - end if; - - -- BLock Erase (Setup) - when x"20" => - cur_cui_state <= C_ERASE; - - -- Program/Erase Suspend - when x"b0" => - if sts_ready = '1' then - -- No-op - null; - elsif cur_wsm_state = W_PROG or cur_wsm_state = W_BUF_PROG then - -- Suspend program operation - sts_susp_prog <= '1'; - elsif cur_wsm_state = W_ERASE then - -- Suspend erase operation - sts_susp_erase <= '1'; - end if; - -- Suspend does not change read mode - - -- Program/Erase Resume - when x"d0" => - next_wsm_state <= W_RESUME; - wsm_trigger <= '1'; - cur_read_state <= R_STATUS; - - -- Lock/Unlock Block (Setup) and Program Enhanced Configuration Register (Setup) - when x"60" => - cur_read_state <= R_STATUS; - cur_cui_state <= C_LOCK; - - when others => - sts_error_code <= "11"; - end case; - - -- Started Program Enhanced Configuration Register command - when C_PECR => - case d(7 downto 0) is - when x"04" => - ecr_reg <= a(ecr_reg'high downto 0); - -- Datasheet says it returns to read-array mode... - -- FIXME: Does it just not change the mode? - cur_read_state <= R_ARRAY; - - when others => - sts_error_code <= "11"; - end case; - cur_cui_state <= C_IDLE; - - -- Started Program OTP Register command - when C_POTP => - if sts_ready = '0' then - -- Not allowed while WSM is busy - sts_error_code <= "11"; - elsif sts_susp_prog = '1' or sts_susp_erase = '1' then - -- Not allowed while program/erase suspended - sts_error_code <= "11"; - else - -- Latch address and data and trigger WSM - otp_prog_offset <= a; - otp_prog_data <= d; - next_wsm_state <= W_OTP_PROG; - wsm_trigger <= '1'; - end if; - - cur_read_state <= R_STATUS; - cur_cui_state <= C_IDLE; - - -- Started Program STS Configuration Register command - when C_STSC => - if sts_ready = '0' then - -- Not allowed while WSM is busy - sts_error_code <= "11"; - elsif sts_susp_prog = '1' or sts_susp_erase = '1' then - -- Not allowed while program/erase suspended - sts_error_code <= "11"; - elsif (d and x"00fc") /= x"0000" then - -- Invalid configuration value - sts_error_code <= "11"; - else - assert d(1) = '0' and d(0) = '0' - report "TODO: STS pulse config" - severity warning; - sts_config <= d(7 downto 0); - end if; - cur_read_state <= R_STATUS; - cur_cui_state <= C_IDLE; - - -- Started Word/Byte Program command - when C_PROG => - if sts_ready = '0' then - -- Not allowed while WSM is busy - sts_error_code <= "11"; - elsif sts_susp_prog = '1' then - -- Not allowed while program suspended - sts_error_code <= "11"; - else - -- Latch address and data and trigger WSM - prog_address <= a; - prog_word <= d; - next_wsm_state <= W_PROG; - wsm_trigger <= '1'; - end if; - cur_read_state <= R_STATUS; - cur_cui_state <= C_IDLE; - - -- Started Buffer Program command - when C_BUF_PROG_COUNT => - if sts_ready = '0' then - -- sts_ready already checked in previous state, but just in case - sts_error_code <= "11"; - cur_cui_state <= C_IDLE; - elsif sts_susp_prog = '1' then - -- Do not allow while programming operation is suspended - -- Should this check have been rolled into the status check in - -- the previous state? Or should this check be done in the previous - -- state? TODO: check on hardware - sts_error_code <= "11"; - cur_cui_state <= C_IDLE; - elsif (d(7 downto 0) and x"e0") /= x"0000" then - -- Word count must be <= 31 - report "Buffer program sent with word count greater than 31" severity warning; - sts_error_code <= "11"; - cur_cui_state <= C_IDLE; - else - -- Latch start address and word count - prog_address <= a; - prog_count <= to_integer(unsigned(d)); - prog_i := to_integer(unsigned(d)); - cur_cui_state <= C_BUF_PROG_DATA; - end if; - - when C_BUF_PROG_DATA => - -- Latch data into buffer at address - prog_buf(to_integer(unsigned(a(5 downto 1)))) <= d; - if prog_i = 0 then - cur_cui_state <= C_BUF_PROG_CONF; - else - prog_i := prog_i - 1; - end if; - - when C_BUF_PROG_CONF => - if d(7 downto 0) /= x"d0" then - -- Failed to confirm write, abort - sts_error_code <= "11"; - cur_cui_state <= C_IDLE; - else - -- Trigger WSM - next_wsm_state <= W_BUF_PROG; - wsm_trigger <= '1'; - cur_cui_state <= C_IDLE; - end if; - - -- Started Block Erase command - when C_ERASE => - -- TODO: not allowed when erase or program suspended - if sts_ready = '0' then - -- Not allowed while WSM is busy - sts_error_code <= "11"; - cur_cui_state <= C_IDLE; - elsif sts_susp_prog = '1' or sts_susp_erase = '1' then - -- Not allowed while program/erase suspended - sts_error_code <= "11"; - cur_cui_state <= C_IDLE; - elsif d(7 downto 0) /= x"d0" then - -- Failed to confirm erase - sts_error_code <= "11"; - cur_cui_state <= C_IDLE; - else - -- Latch block address and trigger WSM - erase_address <= a; - next_wsm_state <= W_ERASE; - wsm_trigger <= '1'; - cur_cui_state <= C_IDLE; - end if; - - -- Started Lock/Unlock Block command - when C_LOCK => - -- Read state already set to R_STATUS in previous cycle - case d(7 downto 0) is - -- Program Enhanced Configuration Register - when x"04" => - ecr_reg <= a(ecr_reg'high downto 0); - -- Datasheet says it returns to read-array mode - cur_read_state <= R_ARRAY; - - -- Lock Block - when x"01" => - -- address in a - if sts_ready = '0' then - -- Cannot program when WSM is busy - sts_error_code <= "11"; - elsif sts_susp_erase = '1' or sts_susp_prog = '1' then - -- Cannot program when erase or program suspended - sts_error_code <= "11"; - else - lock_address <= a; - next_wsm_state <= W_LOCK_PROG; - wsm_trigger <= '1'; - end if; - - -- Unlock Blocks - when x"d0" => - if sts_ready = '0' then - -- Cannot erase when WSM is busy - sts_error_code <= "11"; - elsif sts_susp_erase = '1' or sts_susp_prog = '1' then - -- Cannot erase when erase or program suspended - sts_error_code <= "11"; - else - next_wsm_state <= W_LOCK_ERASE; - wsm_trigger <= '1'; - end if; - - when others => - sts_error_code <= "11"; - end case; - cur_cui_state <= C_IDLE; - - when others => - cur_cui_state <= C_IDLE; - end case; - end if; - end process; - - -- Write state machine is responsible for checking: - -- * Vpen state - -- * valid offset/address - -- * lock protection - -- * checking wsm_trigger and next_wsm_state to begin operations - -- * checking sts_susp_* state to suspend operations - wsm: process (rp_n, vpen, sts_susp_erase, sts_susp_prog, wsm_trigger, cur_wsm_state, next_wsm_state) - variable otp_prog_idx: integer; - variable prog_buf_addr: integer; - begin - if rp_n = '0' then - -- TODO: hold ready low for some time after reset - cur_wsm_state <= W_READY; - sts_ready <= '1'; - sts_susp_erase <= '0'; - sts_error_code <= "00"; - sts_error_volt <= '0'; - sts_susp_prog <= '0'; - sts_error_lock <= '0'; - end if; - - sts_ready <= '0'; -- Default to not-ready - - -- Process triggers from the CUI FSM - if rising_edge(wsm_trigger) then - cur_wsm_state <= next_wsm_state; - end if; - - case cur_wsm_state is - when W_READY => - sts_ready <= '1'; -- Ready status only in ready state - - when W_PROG => - -- Abort with voltage error if Vpen drops - sts_ready <= '0'; - if vpen = '0' then - sts_error_code(0) <= '1'; - sts_error_volt <= '1'; - cur_wsm_state <= W_READY after T_STS; - end if; - -- Suspend programming operation when signaled - if sts_susp_prog = '1' then - cur_wsm_state <= W_READY after T_WHRH1; -- T_EHRH1 - end if; - -- Check lock protection bit for block - if lock_reg(block_index_of(prog_address)) = '1' then - sts_error_code(0) <= '1'; - sts_error_lock <= '1'; - cur_wsm_state <= W_READY after T_STS; - end if; - flash_array(block_index_of(prog_address))(word_index_of(prog_address)) <= - flash_array(block_index_of(prog_address))(word_index_of(prog_address)) - and prog_word; - cur_wsm_state <= W_READY after T_WHQV3; -- T_EHQV3 - - when W_BUF_PROG => - -- Abort with voltage error if Vpen drops - if vpen = '0' then - sts_error_code(0) <= '1'; - sts_error_volt <= '1'; - cur_wsm_state <= W_READY after T_STS; - end if; - -- Suspend programming operation when signaled - if sts_susp_prog = '1' then - cur_wsm_state <= W_READY after T_WHRH1; -- T_EHRH1 - end if; - -- Check lock protection bit for block - if lock_reg(block_index_of(prog_address)) = '1' then - sts_error_code(0) <= '1'; - sts_error_lock <= '1'; - cur_wsm_state <= W_READY after T_STS; - end if; - -- TODO: write zeroes - prog_buf_addr := to_integer(unsigned(prog_address)); - for addr in prog_buf_addr to prog_buf_addr + prog_count + 1 loop - flash_array(block_index_of(std_logic_vector(to_unsigned(addr, 24))))(word_index_of(std_logic_vector(to_unsigned(addr, 24)))) <= - flash_array(block_index_of(std_logic_vector(to_unsigned(addr, 24))))(word_index_of(std_logic_vector(to_unsigned(addr, 24)))) - and prog_buf(addr mod 32); - end loop; - -- TODO: get correct timing - cur_wsm_state <= W_READY after T_WHQV3; -- T_EHQV3 - - when W_ERASE => - -- Abort with voltage error if Vpen drops - if vpen = '0' then - sts_error_code(1) <= '1'; - sts_error_volt <= '1'; - cur_wsm_state <= W_READY after T_STS; - end if; - -- Suspend erase operation when signaled - if sts_susp_erase = '1' then - cur_wsm_state <= W_READY after T_WHRH; -- T_EHRH - end if; - -- Check lock protection bit for block - if lock_reg(block_index_of(erase_address)) = '1' then - sts_error_code(1) <= '1'; - sts_error_lock <= '1'; - cur_wsm_state <= W_READY after T_STS; - end if; - -- Erase block and return to ready - flash_array(block_index_of(erase_address)) <= (others => (others => '1')); - cur_wsm_state <= W_READY after T_WHQV4; -- T_EHQV4 - - when W_LOCK_PROG => - -- Abort with voltage error if Vpen drops - if vpen = '0' then - sts_error_code(0) <= '1'; - sts_error_volt <= '1'; - cur_wsm_state <= W_READY after T_STS; - end if; - -- Write lock bit and return to ready - lock_reg(block_index_of(lock_address)) <= '1'; - cur_wsm_state <= W_READY after T_WHQV5; -- T_EHQV5 - - when W_LOCK_ERASE => - -- Abort with voltage error if Vpen drops - if vpen = '0' then - sts_error_code(1) <= '1'; - sts_error_volt <= '1'; - cur_wsm_state <= W_READY after T_STS; - end if; - -- Erase all lock bits and return to ready - lock_reg <= (others => '0'); - cur_wsm_state <= W_READY after T_WHQV6; -- T_EHQV6 - - when W_OTP_PROG => - -- Abort with voltage error if Vpen drops - if vpen = '0' then - sts_error_code(0) <= '1'; - sts_error_volt <= '1'; - cur_wsm_state <= W_READY after T_STS; - end if; - -- Check for out-of-range address - otp_prog_idx := to_integer(unsigned(otp_prog_offset(otp_prog_offset'high downto 1))); - if otp_prog_idx < 16#80# or otp_prog_idx > 16#88# then - sts_error_code(0) <= '1'; - cur_wsm_state <= W_READY after T_STS; - end if; - -- Check for protection bits - if otp_prog_idx >= 16#81# and otp_prog_idx <= 16#84# then - if plr_reg(0) = '0' then - sts_error_code(0) <= '1'; - sts_error_lock <= '1'; - cur_wsm_state <= W_READY after T_STS; - end if; - end if; - if otp_prog_idx >= 16#85# and otp_prog_idx <= 16#88# then - if plr_reg(1) = '0' then - sts_error_code(0) <= '1'; - sts_error_lock <= '1'; - cur_wsm_state <= W_READY after T_STS; - end if; - end if; - -- Write zeroes and return to ready - if otp_prog_idx = 16#80# then - plr_reg <= plr_reg and otp_prog_data; - else - otp_prog_idx := otp_prog_idx - 16#81#; - otp_reg(otp_prog_idx) <= otp_reg(otp_prog_idx) and otp_prog_data; - end if; - cur_wsm_state <= W_READY after T_WHQV5; -- Best guess for timing - - when W_RESUME => - if sts_susp_prog = '1' then - -- Precedence goes to resuimg programming operation - sts_susp_prog <= '0'; - cur_wsm_state <= W_PROG after T_STS; - elsif sts_susp_erase = '1' then - -- Resume erase operation if no programming operation pending - sts_susp_erase <= '0'; - cur_wsm_state <= W_ERASE after T_STS; - else - -- Nothing to resume, return to ready - cur_wsm_state <= W_READY after T_STS; - end if; - - when others => - cur_wsm_state <= W_READY after T_STS; - end case; - end process; - - - ---------------------------------------------------------------------------- - -- Check for erroneous usages - - -- Should not try to read and write at the same time - process (oe_n, we_n) - begin - assert not (oe_n = '0' and we_n = '0') - report "OE# and WE# should never be enabled simultaneously." - severity error; - end process; - - -- Address must be valid for a full read or write cycle - R1: process (oe_n, a(23 downto 4)) - begin - -- FIXME: Check more address bits if in non-array or 4-word array modes - if a(23 downto 4)'event and oe_n = '0' then - assert a(23 downto 4)'last_event >= T_AVAV; - report "T_AVAV not met (Read/Write Cycle Time)" - severity error; - end if; - end process; - - -- BYTE# cannot change more than T_ELFL/T_ELFH after CEx goes low - R11: process (byte_n, internal_ce_n) - begin - if byte_n'event and internal_ce_n = '0' then - assert internal_ce_n'last_event <= T_ELFL; - report "T_ELFL/H not met (CEx Low to BYTE# High or Low)" - severity error; - end if; - end process; - - -- WE# and CEx cannot become active less than T_PHWL/EL after RP# goes high - W1: process (rp_n, we_n, internal_ce_n) - begin - if rp_n = '1' then - if falling_edge(we_n) then - assert rp_n'last_event >= T_PHWL - report "T_PHWL not met (RP# High Recovery to WE# Going Low)" - severity error; - end if; - if falling_edge(internal_ce_n) then - assert rp_n'last_event >= T_PHEL - report "T_PHEL not met (RP# High Recovery to CEx Going Low)" - severity error; - end if; - end if; - end process; - - -- CEx and WE# may have set-up timing constraints relative to each other - W2: process (we_n, internal_ce_n) - begin - if falling_edge(we_n) and internal_ce_n = '0' then - assert internal_ce_n'last_event >= T_ELWL - report "T_ELWL not met (CEx Low to WE# Going Low)" - severity error; - end if; - if falling_edge(internal_ce_n) and we_n = '0' then - assert we_n'last_event >= T_WLEL - report "T_WLEL not met (WE# Low to CEx Going Low)" - severity error; - end if; - end process; - - -- WE# has a minimum low pulse width - W3: process (we_n) - begin - if rising_edge(we_n) then - --assert we_n'last_event >= T_WP - assert we_n'delayed(T_WP) = '0' - report "T_WP not met (Write Pulse Width)" - severity error; - end if; - end process; - - -- Data-in set-up time (no need to use internal_we_n here) - W4: process (internal_we_n, d) - begin - if rising_edge(internal_we_n) then - -- T_DVEH and T_DVWH are the same in the datasheet, so they probably - -- refer to the internal write-latch signal composed of CEx and WE#. - -- Checking against the internal signal prevents us from checking - -- timing between our own output and CEx during write cycles. - assert d'delayed'last_event >= T_DVWH -- Also T_DVEH - report "T_DVWH/T_DVEH not met (Data Setup to WE#/CEx Going High)" & time'image(d'last_event) - severity error; - end if; - --if rising_edge(we_n) then - -- assert d'last_event >= T_DVWH - -- report "T_DVWH not met (Data Setup to WE# Going High)" - -- severity error; - --end if; - --if rising_edge(internal_ce_n) then - -- -- Have seen some false-positives where d'last_event = 0 ps, but d'event = False - -- -- Delaying 1 ps will get past any event in the current simulation cycle - -- assert d'delayed(1 ps)'last_event >= T_DVEH - -- report "T_DVEH not met (Data Setup to CEx Going High)" - -- severity error; - --end if; - end process; - - -- Address set-up time (no need to use internal_we_n here) - W5: process (internal_we_n, a) - begin - if rising_edge(internal_we_n) then - -- T_AVEH and T_AVWH are the same in the datasheet, so they probably - -- refer to the internal write-latch signal composed of CEx and WE#. - -- Checking against the internal signal prevents us from checking - -- timing against CEx during read cycles. - assert a'last_event >= T_AVWH -- Also T_DVEH - report "T_AVWH/T_DVEH not met (Data Setup to WE#/CEx Going High)" - severity error; - end if; - --if rising_edge(we_n) then - -- assert a'last_event >= T_AVWH - -- report "T_AVWH not met (Address Setup to WE# Going High)" - -- severity error; - --end if; - --if rising_edge(internal_ce_n) then - -- assert a'last_event >= T_AVEH - -- report "T_AVEH not met (Address Setup to CEx Going High)" - -- severity error; - --end if; - end process; - - -- CEx and WE# may have hold timing constraints relative to each other - W6: process (we_n, internal_ce_n) - begin - if rising_edge(we_n) and internal_ce_n = '1' then - assert internal_ce_n'last_event >= T_EHWH - report "T_EHWH not met (WE# Hold from CEx High)" - severity error; - end if; - if rising_edge(internal_ce_n) and we_n = '1' then - assert we_n'last_event >= T_WHEH - report "T_WHEH not met (CEx Hold from WE# High)" - severity error; - end if; - end process; - - -- Data-in hold time - W7: process (internal_we_n, d) - begin - if d'event and internal_we_n = '1' then - assert internal_we_n'last_event >= T_WHDX -- T_EHDX - report "T_W/EHDX not met (Data Hold from WE# (CEx) High)" - severity error; - end if; - end process; - - -- Address hold time - W8: process (internal_we_n, a) - begin - if a'event and internal_we_n = '1' then - assert internal_we_n'last_event >= T_WHAX -- T_EHAX - report "T_W/EHAX not met (Address Hold from WE# (CEx) High)" - severity error; - end if; - end process; - - -- WE# has a minimum high pulse width - W9: process (we_n) - begin - if falling_edge(we_n) then - --assert we_n'last_event >= T_WPH - assert we_n'delayed(T_WPH) = '1' - report "T_WPH not met (Write Pulse Width High)" - severity error; - end if; - end process; - - -- Vpen set-up time before write latch (don't need to use internal_we_n here) - W11: process (we_n, internal_ce_n, vpen) - begin - if rising_edge(we_n) and vpen = '1' then - assert vpen'last_event >= T_VPWH - report "T_VPWH not met (Vpen Setup to WE# High)" - severity error; - end if; - if rising_edge(internal_ce_n) and vpen = '1' then - assert vpen'last_event >= T_VPEH - report "T_VPEH not met (Vpen Setup to CEx High)" - severity error; - end if; - end process; - - -- Write recovery before Read - W12: process (internal_we_n, oe_n) - begin - if falling_edge(oe_n) and internal_we_n = '1' then - assert internal_we_n'last_event >= T_WHGL -- T_EHGL - report "T_W/EHGL not met (Write Recovery before Read)" - severity error; - end if; - end process; - - -- Vpen hold time - W15: process (vpen) - begin - -- TODO: T_QVVL never shown on any waveform diagrams - end process; - - -- RP# pulse time - P1: process (rp_n) - begin - if rising_edge(rp_n) then - -- If the simulations tarts with rp_n = '0' then last_event won't work - -- assert rp_n'last_event >= T_PLPH - assert rp_n'delayed(T_PLPH) = '0' - report "T_PLPH not met (RP# Pulse Low Time)" - severity error; - end if; - end process; - -end behavioral; diff --git a/libraries/simulated/ps2_device.vhd b/libraries/simulated/proto_ps2.vhd similarity index 98% rename from libraries/simulated/ps2_device.vhd rename to libraries/simulated/proto_ps2.vhd index fe79f68..b0cffb4 100644 --- a/libraries/simulated/ps2_device.vhd +++ b/libraries/simulated/proto_ps2.vhd @@ -4,17 +4,17 @@ use ieee.numeric_std.all; use ieee.std_logic_misc.all; -entity ps2_device is +entity proto_ps2 is port ( tx_byte: in std_logic_vector(7 downto 0); ps2_clk: inout std_logic; ps2_data: inout std_logic ); -end ps2_device; +end proto_ps2; -architecture behavioral of ps2_device is +architecture behavioral of proto_ps2 is type state_t is ( S_IDLE, S_INHIBIT, diff --git a/libraries/simulated/tests/test_attrs.vhd b/libraries/simulated/tests/test_attrs.vhd deleted file mode 100644 index e651e3a..0000000 --- a/libraries/simulated/tests/test_attrs.vhd +++ /dev/null @@ -1,75 +0,0 @@ -library ieee; -use ieee.std_logic_1164.all; - - -entity test_attrs is -end test_attrs; - - -architecture behavior of test_attrs is - - constant T: time := 10 ns; - - signal sig: std_logic; - signal sig_delayed: std_logic; - signal sig_stable: boolean; - signal sig_quiet: boolean; - signal sig_last_event: time; - signal sig_last_active: time; - signal sig_last_event_2: time; - signal sig_last_active_2: time; - -begin - - test: process is - begin - - sig_last_event_2 <= sig'last_event; - sig_last_active_2 <= sig'last_active; - - sig <= '0'; - - sig_last_event_2 <= sig'last_event; - sig_last_active_2 <= sig'last_active; - wait for 30 ns; - sig_last_event_2 <= sig'last_event; - sig_last_active_2 <= sig'last_active; - - sig <= '1'; - - sig_last_event_2 <= sig'last_event; - sig_last_active_2 <= sig'last_active; - wait for 30 ns; - sig_last_event_2 <= sig'last_event; - sig_last_active_2 <= sig'last_active; - - sig <= '1'; - - sig_last_event_2 <= sig'last_event; - sig_last_active_2 <= sig'last_active; - wait for 30 ns; - sig_last_event_2 <= sig'last_event; - sig_last_active_2 <= sig'last_active; - - sig <= '0'; - - sig_last_event_2 <= sig'last_event; - sig_last_active_2 <= sig'last_active; - wait for 30 ns; - sig_last_event_2 <= sig'last_event; - sig_last_active_2 <= sig'last_active; - - wait; - - end process; - - sig_delayed <= sig'delayed(T); - sig_stable <= sig'stable(T); - sig_quiet <= sig'quiet(T); - - -- These don't work as expected! - -- This also applies to equivalent processes with sensitivity lists - sig_last_event <= sig'last_event; - sig_last_active <= sig'last_active; - -end; diff --git a/libraries/simulated/tests/test_simmem.vhd b/libraries/simulated/tests/test_genericmem.vhd similarity index 89% rename from libraries/simulated/tests/test_simmem.vhd rename to libraries/simulated/tests/test_genericmem.vhd index e00ba09..882fd2b 100644 --- a/libraries/simulated/tests/test_simmem.vhd +++ b/libraries/simulated/tests/test_genericmem.vhd @@ -5,11 +5,11 @@ use ieee.numeric_std.all; library work; -entity test_simmem is -end test_simmem; +entity test_genericmem is +end test_genericmem; -architecture behavior of test_simmem is +architecture behavior of test_genericmem is signal rst_i: std_logic; signal clk_i: std_logic; @@ -42,7 +42,7 @@ begin end process; - e_uut: entity work.wb_memory + e_uut: entity work.genericmem generic map ( INIT => x"00112233445566778899aabbccddeeff0123456789abcdeffedcba9876543210" ) diff --git a/libraries/simulated/tests/test_js28f128j3d75.vhd b/libraries/simulated/tests/test_js28f128j3d75.vhd index b84c0d1..cf65f78 100644 --- a/libraries/simulated/tests/test_js28f128j3d75.vhd +++ b/libraries/simulated/tests/test_js28f128j3d75.vhd @@ -2,180 +2,112 @@ library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; -library flash_js28f128; +library work; -entity testbench_j28f128j3d75 is -end testbench_j28f128j3d75; +entity test_js28f128j3d75 is +end test_js28f128j3d75; -architecture behavior of testbench_js28f128j3d75 is +architecture behavior of test_js28f128j3d75 is - type op is (O_NONE, O_READ_ARRAY, O_READ_STATUS, O_PROG_A, O_PROG_B, O_MODE_ARRAY); - - -- Flash signals - signal a: std_logic_vector(23 downto 0); - signal d: std_logic_vector(15 downto 0); - signal ce: std_logic_vector(2 downto 0); - signal rp_n: std_logic; - signal oe_n: std_logic; - signal we_n: std_logic; - signal sts: std_logic; + signal a: std_logic_vector(23 downto 0); + signal d: std_logic_vector(15 downto 0); + signal ce: std_logic_vector(2 downto 0); + signal rp_n: std_logic := '0'; + signal oe_n: std_logic; + signal we_n: std_logic; + signal sts: std_logic; signal byte_n: std_logic; - signal vpen: std_logic; - - -- Debug - signal cur_op: op; + signal vpen: std_logic; begin - uut: entity flash_js28f128.js28f128j3d75 port map ( - a => a, - d => d, - ce => ce, - rp_n => rp_n, - oe_n => oe_n, - we_n => we_n, - sts => sts, - byte_n => byte_n, - vpen => vpen - ); - - - tb: process + p_test: process begin - -- Initial values - cur_op <= O_NONE; - a <= (others => '0'); - d <= (others => 'Z'); - ce <= (others => '1'); - oe_n <= '1'; - we_n <= '1'; + -- Initial values and reset + a <= x"000000"; + d <= "ZZZZZZZZZZZZZZZZ"; + ce <= "111"; + rp_n <= '0'; + oe_n <= '1'; + we_n <= '1'; byte_n <= '1'; - vpen <= '1'; - - -- Reset - rp_n <= '1'; + vpen <= '1'; + wait for 10 ns; + rp_n <= '1'; wait for 1 us; - rp_n <= '0'; - wait for 25 us; - rp_n <= '1'; - wait for 210 ns; - - -- Wait for long BYTE# signal propagation time - wait for 1 ms; - -- Asynchronous array read - cur_op <= O_READ_ARRAY; - ce(0) <= '0'; - oe_n <= '0'; - a <= x"000000"; - wait for 100 ns; - a <= x"000002"; - wait for 100 ns; - a <= x"000004"; - wait for 100 ns; - a <= x"000006"; - wait for 100 ns; - a <= x"000008"; - wait for 100 ns; - a <= x"00000a"; - wait for 100 ns; - a <= x"00000c"; + -- Test a page read + ce <= "000"; + oe_n <= '0'; wait for 100 ns; - a <= x"00000e"; - wait for 100 ns; - ce(0) <= '1'; - oe_n <= '1'; - cur_op <= O_NONE; + a <= x"000002"; + wait for 50 ns; + a <= x"000004"; + wait for 50 ns; + a <= x"000006"; + wait for 50 ns; + oe_n <= '1'; + ce <= "111"; - wait for 25 ns; - - -- Program word - ce(0) <= '0'; + wait for 100 ns; - cur_op <= O_PROG_A; - a <= x"000000"; - d <= x"0040"; + -- Send the write-word command + a <= x"000008"; + d <= x"0040"; + ce <= "000"; we_n <= '0'; - wait for 60 ns; + wait for 80 ns; we_n <= '1'; - wait for 30 ns; + ce <= "111"; + wait for 35 ns; - cur_op <= O_PROG_B; - a <= x"000000"; - d <= x"abcd"; + -- Send the word to write + d <= x"1234"; + ce <= "000"; we_n <= '0'; - wait for 60 ns; + wait for 80 ns; we_n <= '1'; - wait for 30 ns; - - ce(0) <= '1'; - d <= (others => 'Z'); - cur_op <= O_NONE; - wait for 100 us; - - -- Read status during program - cur_op <= O_READ_STATUS; - ce(0) <= '0'; - oe_n <= '0'; - a <= x"000000"; - wait for 100 ns; - assert d = x"0000" - report "Status read got wrong value: " & integer'image(to_integer(unsigned(d))) - severity error; - oe_n <= '1'; - ce(0) <= '1'; - cur_op <= O_NONE; - wait for 25 ns; + ce <= "111"; + wait for 35 ns; - -- Wait for program to complete + -- Wait for the write to complete wait until sts /= '0'; - wait for 25 ns; + wait for 50 ns; - -- Read status after program - cur_op <= O_READ_STATUS; - ce(0) <= '0'; - oe_n <= '0'; - a <= x"000000"; - wait for 100 ns; - assert d = x"0080" - report "Status read got wrong value: " & integer'image(to_integer(unsigned(d))) - severity error; - oe_n <= '1'; - ce(0) <= '1'; - cur_op <= O_NONE; - wait for 25 ns; - - -- Enter read-array mode - cur_op <= O_MODE_ARRAY; - a <= x"000000"; - d <= x"00ff"; - ce(0) <= '0'; + -- Send the read-array command + d <= x"00ff"; + ce <= "000"; we_n <= '0'; - wait for 60 ns; + wait for 80 ns; we_n <= '1'; - wait for 30 ns; - ce(0) <= '1'; - d <= (others => 'Z'); - cur_op <= O_NONE; - wait for 25 ns; - - -- Read flash array value - cur_op <= O_READ_ARRAY; - ce(0) <= '0'; + ce <= "111"; + wait for 35 ns; + + -- Read back the value we wrote + d <= "ZZZZZZZZZZZZZZZZ"; + ce <= "000"; oe_n <= '0'; - a <= x"000000"; - wait for 100 ns; - assert d = x"abcd" - report "Array read got wrong value" - severity error; + wait for 80 ns; oe_n <= '1'; - ce(0) <= '1'; - cur_op <= O_NONE; - wait for 25 ns; + ce <= "111"; + wait for 35 ns; wait; end process; -end architecture; + e_dut: entity work.js28f128j3d75 + generic map (FILENAME => "/home/ryan/Dropbox/Projects/VHDL/libraries/simulated/tests/test.bin") + port map ( + a => a, + d => d, + ce => ce, + rp_n => rp_n, + oe_n => oe_n, + we_n => we_n, + sts => sts, + byte_n => byte_n, + vpen => vpen + ); +end; diff --git a/libraries/simulated/tests/test_mt45w8mw16bgx.vhd b/libraries/simulated/tests/test_mt45w8mw16bgx.vhd index d045fb1..c5d5a7a 100644 --- a/libraries/simulated/tests/test_mt45w8mw16bgx.vhd +++ b/libraries/simulated/tests/test_mt45w8mw16bgx.vhd @@ -2,14 +2,14 @@ library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; -library simulated; +library work; -entity testbench_ram is -end testbench_ram; +entity test_mt45w8mw16bgx is +end test_mt45w8mw16bgx; -architecture behavior of testbench_ram is +architecture behavior of test_mt45w8mw16bgx is signal addr: std_logic_vector(23 downto 0); -- Extra bit to allow hex literals signal data: std_logic_vector(15 downto 0); @@ -74,7 +74,7 @@ begin wait; end process; - uut: entity simulated.mt45w8mw16bgx + uut: entity work.mt45w8mw16bgx port map ( a => addr(22 downto 0), dq => data, diff --git a/libraries/simulated/tests/test_ps2_device.vhd b/libraries/simulated/tests/test_ps2.vhd similarity index 92% rename from libraries/simulated/tests/test_ps2_device.vhd rename to libraries/simulated/tests/test_ps2.vhd index 46418f7..7b0bdf9 100644 --- a/libraries/simulated/tests/test_ps2_device.vhd +++ b/libraries/simulated/tests/test_ps2.vhd @@ -2,11 +2,11 @@ library ieee; use ieee.std_logic_1164.all; -entity test_ps2_device is -end test_ps2_device; +entity test_ps2 is +end test_ps2; -architecture behavior of test_ps2_device is +architecture behavior of test_ps2 is signal tx_byte: std_logic_vector(7 downto 0) := x"00"; signal ps2_clk: std_logic; @@ -80,10 +80,8 @@ begin wait; end process; - e_ps2_device: entity work.ps2_device + e_ps2_device: entity work.proto_ps2 port map ( - fast => true, - tx_byte => tx_byte, ps2_clk => ps2_clk, diff --git a/libraries/simulated/tests/test_simflash.vhd b/libraries/simulated/tests/test_simflash.vhd deleted file mode 100644 index 6cb2456..0000000 --- a/libraries/simulated/tests/test_simflash.vhd +++ /dev/null @@ -1,113 +0,0 @@ -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -library work; - - -entity test_simflash is -end test_simflash; - - -architecture behavior of test_simflash is - - signal a: std_logic_vector(23 downto 0); - signal d: std_logic_vector(15 downto 0); - signal ce: std_logic_vector(2 downto 0); - signal rp_n: std_logic := '0'; - signal oe_n: std_logic; - signal we_n: std_logic; - signal sts: std_logic; - signal byte_n: std_logic; - signal vpen: std_logic; - -begin - - p_test: process - begin - -- Initial values and reset - a <= x"000000"; - d <= "ZZZZZZZZZZZZZZZZ"; - ce <= "111"; - rp_n <= '0'; - oe_n <= '1'; - we_n <= '1'; - byte_n <= '1'; - vpen <= '1'; - wait for 10 ns; - rp_n <= '1'; - wait for 1 us; - - -- Test a page read - ce <= "000"; - oe_n <= '0'; - wait for 100 ns; - a <= x"000002"; - wait for 50 ns; - a <= x"000004"; - wait for 50 ns; - a <= x"000006"; - wait for 50 ns; - oe_n <= '1'; - ce <= "111"; - - wait for 100 ns; - - -- Send the write-word command - a <= x"000008"; - d <= x"0040"; - ce <= "000"; - we_n <= '0'; - wait for 80 ns; - we_n <= '1'; - ce <= "111"; - wait for 35 ns; - - -- Send the word to write - d <= x"1234"; - ce <= "000"; - we_n <= '0'; - wait for 80 ns; - we_n <= '1'; - ce <= "111"; - wait for 35 ns; - - -- Wait for the write to complete - wait until sts /= '0'; - wait for 50 ns; - - -- Send the read-array command - d <= x"00ff"; - ce <= "000"; - we_n <= '0'; - wait for 80 ns; - we_n <= '1'; - ce <= "111"; - wait for 35 ns; - - -- Read back the value we wrote - d <= "ZZZZZZZZZZZZZZZZ"; - ce <= "000"; - oe_n <= '0'; - wait for 80 ns; - oe_n <= '1'; - ce <= "111"; - wait for 35 ns; - - wait; - end process; - - e_dut: entity work.sim_js28f128j3d75 - generic map (FILENAME => "/home/ryan/Dropbox/Projects/VHDL/libraries/simulated/tests/test.bin") - port map ( - a => a, - d => d, - ce => ce, - rp_n => rp_n, - oe_n => oe_n, - we_n => we_n, - sts => sts, - byte_n => byte_n, - vpen => vpen - ); -end; diff --git a/libraries/simulated/assert_pulsewidth.vhd b/libraries/simulated/util_assert_pulsewidth.vhd similarity index 100% rename from libraries/simulated/assert_pulsewidth.vhd rename to libraries/simulated/util_assert_pulsewidth.vhd diff --git a/libraries/simulated/assert_setuphold.vhd b/libraries/simulated/util_assert_setuphold.vhd similarity index 100% rename from libraries/simulated/assert_setuphold.vhd rename to libraries/simulated/util_assert_setuphold.vhd diff --git a/libraries/simulated/assert_setuphold_vec.vhd b/libraries/simulated/util_assert_setuphold_vec.vhd similarity index 100% rename from libraries/simulated/assert_setuphold_vec.vhd rename to libraries/simulated/util_assert_setuphold_vec.vhd diff --git a/libraries/simulated/changed_within_t.vhd b/libraries/simulated/util_changed_within_t.vhd similarity index 100% rename from libraries/simulated/changed_within_t.vhd rename to libraries/simulated/util_changed_within_t.vhd diff --git a/libraries/simulated/changed_within_t_vec.vhd b/libraries/simulated/util_changed_within_t_vec.vhd similarity index 100% rename from libraries/simulated/changed_within_t_vec.vhd rename to libraries/simulated/util_changed_within_t_vec.vhd diff --git a/libraries/simulated/delay_edges.vhd b/libraries/simulated/util_delay_edges.vhd similarity index 100% rename from libraries/simulated/delay_edges.vhd rename to libraries/simulated/util_delay_edges.vhd diff --git a/libraries/simulated/sim_utility.vhd b/libraries/simulated/util_pkg.vhd similarity index 100% rename from libraries/simulated/sim_utility.vhd rename to libraries/simulated/util_pkg.vhd -- 2.43.0