---------------------------------------------------------------------------------- --EE 552 -- dram_test_simm.vhd --Project : Porta-AMP --Author : Kevin Mlazgar -- --Created on : Dec 4, 1999 -- -- Program Functional Description -- -- A Test Bench based in hardware. -- -- A count is used to limit the amount of memory tested. -- The count is padded with zeros to 16 bits to generate the -- test vector that will be written to the address location. -- The count is padded with zeros to 22 bits to generate the -- address to write and read from. -- -- An initial loop writes all the vectors to their respective -- addresses. A second loop then reads from those addresses -- and verifies that the result is that expected. If an error -- is detected the address location is displayed on the 7 segment -- display. Sixteen bit values are displayed on the two 7 segment -- displays by displaying first the two high order HEX digits then -- the two low order HEX digits. When the high order HEX digits are -- being displayed, the decimal points will be turned on. -- At the end of the memory test the total count of errors is -- displayed on the 7 segment display (it will blink at twice the -- rate of that when the bad addresses are being displayed.) -- -- -- -- Max Speed: 28.98 MHz -- Optimized for speed... -- --Chip/ Input Output Bidir Memory Memory LCs --POF Device Pins Pins Pins Bits % Utilized LCs % Utilized -- --dram_test_simm -- EPF10K20RC240-4 2 32 16 0 0 % 290 24 % -- -- library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; library work; use work.sdram_package.all; use work.seg_decode_pkg.all; --use work.mem_mgmt_cont_pkg.all; use work.dram_int_pkg.all; entity dram_test_simm is port ( clock : in std_logic; reset : in std_logic; -- 7 segment display display1 : out std_logic_vector(6 downto 0); display2 : out std_logic_vector(6 downto 0); dec_pt1 : out std_logic; dec_pt2 : out std_logic; -- DRAM external lines -- -- RAS lines to DRAM -- acts as bank select rasn : out std_logic_vector(3 downto 0); -- CASN line to common CASN line on DRAM DIMM casn : out std_logic; -- write enable line to DRAM -- '1' indicates a READ from DRAM -- '0' indicates a WRITE to DRAM wen : out std_logic; -- data path to DRAM dram_datapath : inout std_logic_vector(15 downto 0); -- address path to DRAM (time multiplexed address lines) dram_addresspath : out std_logic_vector(9 downto 0) ); end entity dram_test_simm; architecture mixed of dram_test_simm is type state_type is (write_check, write_check_for_ack, write_wait1, write_wait2, increment_write_vector, check_if_done_write, end_write, read_check, read_check_for_ack, read_wait_for_valid_data1, read_wait_for_valid_data2, output_bad_addr_15_8, output_bad_addr_15_8_again, output_bad_addr_7_0, output_bad_addr_7_0_again, check_result, increment_read_vector, check_if_done_read, increment_error_count, output_result_7_0, output_result_15_8 ); signal state : state_type; signal display_data1 : std_logic_vector(3 downto 0); signal display_data2 : std_logic_vector(3 downto 0); signal test_vector, test_vector_out : std_logic_vector(15 downto 0); alias test_vector_3_0 : std_logic_vector(3 downto 0) is test_vector(3 downto 0); alias test_vector_7_4 : std_logic_vector(3 downto 0) is test_vector(7 downto 4); alias test_vector_11_8 : std_logic_vector(3 downto 0) is test_vector(11 downto 8); alias test_vector_15_12 : std_logic_vector(3 downto 0) is test_vector(15 downto 12); -- count of errors detected in DRAM signal error_count : std_logic_vector(15 downto 0); alias error_count_3_0 : std_logic_vector(3 downto 0) is error_count(3 downto 0); alias error_count_7_4 : std_logic_vector(3 downto 0) is error_count(7 downto 4); alias error_count_11_8 : std_logic_vector(3 downto 0) is error_count(11 downto 8); alias error_count_15_12 : std_logic_vector(3 downto 0) is error_count(15 downto 12); signal mmc_dram_address_in_int : std_logic_vector(21 downto 0); signal mmc_ram_ready_int : std_logic; signal mmc_ram_enable_int : std_logic; signal mmc_ram_read_write_int : std_logic; signal mmc_cmd_ack_int : std_logic; -- widen this vector to test more of memory signal count, count_end : std_logic_vector(9 downto 0); -- padding for 22 bit address with width of above vector signal addr_pad : std_logic_vector(11 downto 0); -- padding for the test vector (16 bits wide) if the count -- vector is smaller than 16 bits wide.... signal test_pad : std_logic_vector(5 downto 0); -- delay so can see bad address locations and error count result -- on the 7 segment display signal delay_count, delay_end : std_logic_vector(21 downto 0); signal delay_done : std_logic; begin count_end <= (others => '1'); delay_end <= (others => '1'); -- various options that can be used as test vectors... test_pad <= (others => '0'); test_vector <= test_pad & count; --test_vector <= count; --test_vector <= count(15 downto 0); --test_vector <= (others => '1'); --test_vector <= (others => '0'); --test_vector <= "1010101010101010"; -- address is the same as the test_vector but padded with -- more zeros... addr_pad <= (others => '0'); -- for a different bank --mmc_dram_address_in_int <= '1' & addr_pad & count; mmc_dram_address_in_int <= addr_pad & count; dram_simm : dram_int generic map ( datawidth => 16, -- addresswidth = framewidth + offsetwidth addresswidth => 22, bank_addrwidth => 2, -- don't change this... -- dram_addrwidth = (addresswidth - bank_addrwidth)/2 dram_addrwidth => 10, -- for an 8 MB SIMM -- delay embedded in commands to DRAM -- increase this to have more delays in accesses... access_delay => 6 ) port map ( -- clock dram_int_clk => clock, -- reset dram_int_reset => reset, -- **************************** -- ** DRAM Interface Signals ** -- RAS lines to DRAM -- acts as bank select rasn => rasn, -- CASN line to common CASN line on DRAM DIMM casn => casn, -- write enable line to DRAM -- '1' indicates a READ to DRAM -- '0' indicates a WRITE from DRAM wen => wen, -- data path to DRAM dram_datapath => dram_datapath, -- address path to DRAM (time multiplexed address lines) dram_addresspath => dram_addresspath, -- ****************************** -- ** Porta-AMP Direct Signals ** -- This signal should be checked immediately after a command is -- issued to the DRAM interface to ensure that the command -- has not been prempted by the refresh. -- If it has been the command must be resent... mmc_cmd_ack => mmc_cmd_ack_int, -- signal to the master indicating that the interface is ready for -- a command. -- The master should NEVER address the dram interface if this -- signal is low. -- If a read or write had been issued or a refresh is in progress this -- signal will go low during the access. When it goes high again there -- is valid data available on the mc_datapath_out for a read, -- or the write is done. mmc_ram_ready => mmc_ram_ready_int, -- client active-high Chip Select signal is asserted when cpu is addressing -- the memory management controller. -- The data will be loaded into the write_data register of -- the primary data path if a write is also being issued... mmc_ram_enable => mmc_ram_enable_int, -- client read/writen line -- '1' indicates a READ -- '0' indicates a WRITE -- A 1 clock period latency is required to switch between these. -- i.e. wait a period before asserting mmc_ram_enable! -- While doing a read or a write hold this signal at its value and -- assert mmc_ram_enable to do another read or write. Once this signal -- is changed a further read or write will occur at the start of memory. mmc_ram_read_write => mmc_ram_read_write_int, -- address path from memory mgmt cont mmc_dram_address_in => mmc_dram_address_in_int, -- data path to memory mgmt cont mmc_datapath_in => test_vector, mmc_datapath_out => test_vector_out ); -- The decimal points will light up on the 7 seg display -- when the most significant HEX digits are displaying with state select dec_pt1 <= '0' when output_bad_addr_15_8, '0' when output_bad_addr_15_8_again, '0' when output_result_15_8, '1' when others; -- The decimal points will light up on the 7 seg display -- when the most significant HEX digits are displaying with state select dec_pt2 <= '0' when output_bad_addr_15_8, '0' when output_bad_addr_15_8_again, '0' when output_result_15_8, '1' when others; with state select display_data1 <= "0111" when write_check, test_vector_15_12 when output_bad_addr_15_8, test_vector_15_12 when output_bad_addr_15_8_again, test_vector_7_4 when output_bad_addr_7_0, test_vector_7_4 when output_bad_addr_7_0_again, error_count_7_4 when output_result_7_0, error_count_15_12 when output_result_15_8, display_data1 when others; seg7_dec1 : seg_decode port map ( value => display_data1, decode => display1 ); with state select display_data2 <= test_vector_11_8 when output_bad_addr_15_8, test_vector_11_8 when output_bad_addr_15_8_again, test_vector_3_0 when output_bad_addr_7_0, test_vector_3_0 when output_bad_addr_7_0_again, error_count_3_0 when output_result_7_0, error_count_11_8 when output_result_15_8, display_data2 when others; seg7_dec2 : seg_decode port map ( value => display_data2, decode => display2 ); -- test vector to be written to memory -- Acts as test vector, address, and number of times to write -- to memory... test_vector_count : process(reset, clock) begin if reset = '0' then count <= (others => '0'); elsif rising_edge(clock) then if state = end_write then count <= (others => '0'); elsif state = increment_write_vector or state = increment_read_vector then count <= count + 1; else count <= count; end if; end if; end process test_vector_count; -- counter of errors in memory error_counter : process(reset, clock) begin if reset = '0' then error_count <= (others => '0'); elsif rising_edge(clock) then if state = increment_error_count then error_count <= error_count + 1; else error_count <= error_count; end if; end if; end process error_counter; -- delay counter so can see result on 7 seg display delay_counter : process(reset, clock) begin if reset = '0' then delay_count <= (others => '0'); delay_done <= '0'; elsif rising_edge(clock) then if state = output_bad_addr_15_8 or state = output_bad_addr_15_8_again or state = output_bad_addr_7_0 or state = output_bad_addr_7_0_again or state = output_result_15_8 or state = output_result_7_0 then delay_count <= delay_count + 1; if delay_count = delay_end then delay_done <= '1'; else delay_done <= '0'; end if; else delay_count <= (others => '0'); end if; end if; end process delay_counter; with state select mmc_ram_enable_int <= '1' when write_check, '1' when read_check, '0' when others; with state select mmc_ram_read_write_int <= '0' when write_check, '0' when write_check_for_ack, '0' when write_wait1, '0' when write_wait2, '0' when increment_write_vector, '0' when check_if_done_write, '1' when end_write, '1' when others; StateLogic : process (reset, clock) begin if reset = '0' then state <= write_check; elsif rising_edge(clock) then case state is -- check if dram is ready -- assert mc_ram_enable high and mc_ram_read_write low when write_check => if mmc_ram_ready_int = '1' then state <= write_check_for_ack; else state <= write_check; end if; -- detect if dram interface was leaving state to do a refresh -- at the same time that a write was issued... when write_check_for_ack => if mmc_cmd_ack_int = '1' then -- no refresh in progress state <= write_wait1; else -- refresh in progress state <= write_check; end if; when write_wait1 => if mmc_ram_ready_int = '0' then state <= write_wait2; else state <= write_wait1; -- should NEVER occur end if; when write_wait2 => if mmc_ram_ready_int = '1' then state <= increment_write_vector; else state <= write_wait2; end if; -- increment data to be written to memory when increment_write_vector => state <= check_if_done_write; -- when check_if_done_write => if count = count_end then state <= end_write; else state <= write_check; end if; -- indicate to DRAM that the write is over -- by deasserting the mc_ram_read_write to high -- reset the test vector when end_write => state <= read_check; -- check if dram is ready -- assert mc_ram_enable high and mc_ram_read_write high -- to start a read as soon as is ready... when read_check => if mmc_ram_ready_int = '1' then state <= read_check_for_ack; else state <= read_check; end if; -- detect if dram interface was leaving state to do a refresh -- at the same time that a read was issued... when read_check_for_ack => if mmc_cmd_ack_int = '1' then -- no refresh in progress state <= read_wait_for_valid_data1; else -- refresh in progress, so try again... state <= read_check; end if; -- verify request being serviced when read_wait_for_valid_data1 => if mmc_ram_ready_int = '0' then state <= read_wait_for_valid_data2; else state <= read_wait_for_valid_data1; end if; -- data out should be valid after here when read_wait_for_valid_data2 => if mmc_ram_ready_int = '1' then state <= check_result; else state <= read_wait_for_valid_data2; end if; when check_result => if test_vector_out = test_vector then -- this word of memory OK, go to next state <= increment_read_vector; else -- this word of memory BAD, go on to next state <= increment_error_count; end if; -- increment the error count when increment_error_count => state <= output_bad_addr_15_8; when output_bad_addr_15_8 => if delay_done = '1' then state <= output_bad_addr_15_8_again; else state <= output_bad_addr_15_8; end if; when output_bad_addr_15_8_again => if delay_done = '1' then state <= output_bad_addr_7_0; else state <= output_bad_addr_15_8_again; end if; when output_bad_addr_7_0 => if delay_done = '1' then state <= output_bad_addr_7_0_again; else state <= output_bad_addr_7_0; end if; when output_bad_addr_7_0_again => if delay_done = '1' then state <= increment_read_vector; else state <= output_bad_addr_7_0_again; end if; -- increment the test vector when increment_read_vector => state <= check_if_done_read; -- check if are at end of testing sequence when check_if_done_read => if count = count_end then state <= output_result_15_8; else state <= read_check; end if; when output_result_15_8 => if delay_done = '1' then state <= output_result_7_0; else state <= output_result_15_8; end if; when output_result_7_0 => if delay_done = '1' then state <= output_result_15_8; else state <= output_result_7_0; end if; end case; end if; end process StateLogic; end mixed;