Add mem_ctrl Level 0 Test 1

mem_ctrl fixed and testbench implemented
This commit is contained in:
Greek 2021-02-17 14:01:49 +01:00
parent 7244fffacd
commit 52bd4053d1
3 changed files with 317 additions and 20 deletions

51
sim/L0_mem_ctrl_test1.do Normal file
View File

@ -0,0 +1,51 @@
onerror {resume}
quietly WaveActivateNextPane {} 0
add wave -noupdate -divider SYSTEM
add wave -noupdate /l0_mem_ctrl_test1/uut/clk
add wave -noupdate /l0_mem_ctrl_test1/uut/reset
add wave -noupdate -divider INPUT
add wave -noupdate /l0_mem_ctrl_test1/uut/ready_in
add wave -noupdate /l0_mem_ctrl_test1/uut/valid_in
add wave -noupdate -radix unsigned /l0_mem_ctrl_test1/uut/addr
add wave -noupdate -radix hexadecimal /l0_mem_ctrl_test1/uut/data_in
add wave -noupdate /l0_mem_ctrl_test1/uut/read
add wave -noupdate -divider MEMORY
add wave -noupdate -expand -group MEMORY -radix unsigned /l0_mem_ctrl_test1/uut/ram_inst/addr
add wave -noupdate -expand -group MEMORY -radix hexadecimal /l0_mem_ctrl_test1/uut/ram_inst/rd_data
add wave -noupdate -expand -group MEMORY /l0_mem_ctrl_test1/uut/ram_inst/ren
add wave -noupdate -expand -group MEMORY /l0_mem_ctrl_test1/uut/ram_inst/wen
add wave -noupdate -expand -group MEMORY -radix hexadecimal /l0_mem_ctrl_test1/uut/ram_inst/wr_data
add wave -noupdate -divider OUTPUT
add wave -noupdate /l0_mem_ctrl_test1/uut/ready_out
add wave -noupdate -radix hexadecimal /l0_mem_ctrl_test1/uut/data_out
add wave -noupdate /l0_mem_ctrl_test1/uut/valid_out
add wave -noupdate -divider MISC
add wave -noupdate /l0_mem_ctrl_test1/uut/delay_line
add wave -noupdate -radix unsigned /l0_mem_ctrl_test1/uut/delay_cnt
add wave -noupdate /l0_mem_ctrl_test1/uut/burst_fifo_inst/free
add wave -noupdate -divider FIFO
add wave -noupdate -group FIFO -radix hexadecimal /l0_mem_ctrl_test1/uut/burst_fifo_inst/data_in
add wave -noupdate -group FIFO /l0_mem_ctrl_test1/uut/burst_fifo_inst/read
add wave -noupdate -group FIFO /l0_mem_ctrl_test1/uut/burst_fifo_inst/write
add wave -noupdate -group FIFO -radix hexadecimal /l0_mem_ctrl_test1/uut/burst_fifo_inst/data_out
add wave -noupdate -group FIFO /l0_mem_ctrl_test1/uut/burst_fifo_inst/empty
add wave -noupdate -group FIFO /l0_mem_ctrl_test1/uut/burst_fifo_inst/free
add wave -noupdate -group FIFO /l0_mem_ctrl_test1/uut/burst_fifo_inst/full
TreeUpdate [SetDefaultTree]
WaveRestoreCursors {{Cursor 1} {574535 ps} 0}
quietly wave cursor active 1
configure wave -namecolwidth 149
configure wave -valuecolwidth 144
configure wave -justifyvalue left
configure wave -signalnamewidth 1
configure wave -snapdistance 10
configure wave -datasetprefix 0
configure wave -rowmargin 4
configure wave -childrowmargin 2
configure wave -gridoffset 0
configure wave -gridperiod 1
configure wave -griddelta 40
configure wave -timeline 0
configure wave -timelineunits ps
update
WaveRestoreZoom {0 ps} {1148342 ps}

View File

@ -0,0 +1,233 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library osvvm; -- Utility Library
context osvvm.OsvvmContext;
use work.rtps_test_package.all;
entity L0_mem_ctrl_test1 is
end entity;
architecture testbench of L0_mem_ctrl_test1 is
-- *CONSTANT DECLARATION*
constant WORD_WIDTH : natural := 32;
constant ADDR_WIDTH : natural := 3;
constant MEMORY_DEPTH : natural := 2**ADDR_WIDTH;
constant BURST_LENGTH : natural := MEMORY_DEPTH;
-- *TYPE DECLARATION*
type TEST_ARRAY_TYPE is array (0 to MEMORY_DEPTH-1) of std_logic_vector(WORD_WIDTH-1 downto 0);
-- *SIGNAL DECLARATION*
signal clk, read, ready_in, valid_in, ready_out, valid_out : std_logic := '0';
signal data_in, data_out : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0');
signal addr : std_logic_vector(ADDR_WIDTH-1 downto 0) := (others => '0');
signal reset : std_logic := '1';
shared variable SB : osvvm.ScoreBoardPkg_slv.ScoreBoardPType;
begin
-- Unit Under Test
uut : entity work.mem_ctrl(arch)
generic map (
ADDR_WIDTH => ADDR_WIDTH,
DATA_WIDTH => WORD_WIDTH,
MEMORY_DEPTH => MEMORY_DEPTH,
MAX_BURST_LENGTH => BURST_LENGTH
)
port map (
clk => clk,
reset => reset,
addr => addr,
read => read,
ready_in => ready_in,
valid_in => valid_in,
data_in => data_in,
ready_out => ready_out,
valid_out => valid_out,
data_out => data_out
);
stimulus_prc : process
variable RV : RandomPType;
variable test_array : TEST_ARRAY_TYPE := (others => (others => '0'));
variable tmp : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0');
begin
SetAlertLogName("mem_ctrl - Level 0 - Generic");
SetAlertEnable(FAILURE, TRUE);
SetAlertEnable(ERROR, TRUE);
SetAlertEnable(WARNING, TRUE);
SetLogEnable(DEBUG, FALSE);
SetLogEnable(PASSED, FALSE);
SetLogEnable(INFO, TRUE);
RV.InitSeed(RV'instance_name);
Log("Initiating Test", INFO);
valid_in <= '0';
data_in <= (others => '0');
reset <= '1';
wait until rising_edge(clk);
wait until rising_edge(clk);
reset <= '0';
Log("Test Write Burst", INFO);
AffirmIf(valid_out = '0', "Read output without Read request");
-- Write entire Memory with random data
for i in 0 to MEMORY_DEPTH-1 loop
valid_in <= '1';
addr <= std_logic_vector(to_unsigned(i, ADDR_WIDTH));
tmp := RV.RandSlv(WORD_WIDTH);
test_array(i) := tmp;
data_in <= tmp;
if (ready_in = '0') then
wait until ready_in = '1';
end if;
wait until rising_edge(clk);
end loop;
valid_in <= '0';
addr <= (others => '0');
data_in <= (others => '0');
wait until rising_edge(clk);
Log("Test Single Read", INFO);
-- Read one element from memory
AffirmIf(valid_out = '0', "Read output without Read request");
valid_in <= '1';
addr <= std_logic_vector(to_unsigned(0, ADDR_WIDTH));
read <= '1';
SB.Push(test_array(0));
wait until rising_edge(clk);
valid_in <= '0';
addr <= (others => '0');
read <= '0';
wait until rising_edge(clk);
wait until rising_edge(clk);
Log("Test Read Burst", INFO);
-- Fill Read Burst
for i in MEMORY_DEPTH-1 downto 0 loop
valid_in <= '1';
addr <= std_logic_vector(to_unsigned(i, ADDR_WIDTH));
read <= '1';
SB.Push(test_array(i));
if (ready_in = '0') then
wait until ready_in = '1';
end if;
wait until rising_edge(clk);
end loop;
valid_in <= '0';
addr <= (others => '0');
read <= '0';
wait until rising_edge(clk);
wait until rising_edge(clk);
Log("Test Concurrent Request/Read Operation", INFO);
-- Request
valid_in <= '1';
addr <= std_logic_vector(to_unsigned(0, ADDR_WIDTH));
read <= '1';
SB.Push(test_array(0));
if (ready_in = '0') then
wait until ready_in = '1';
end if;
wait until rising_edge(clk);
valid_in <= '0';
addr <= (others => '0');
read <= '0';
-- Read and Request
if (valid_out /= '1') then
wait until valid_out = '1';
end if;
valid_in <= '1';
addr <= std_logic_vector(to_unsigned(1, ADDR_WIDTH));
read <= '1';
SB.Push(test_array(1));
AlertIf(ready_in /= '1', "Precondition for concurrent operation not met");
wait until rising_edge(clk);
valid_in <= '0';
addr <= (others => '0');
read <= '0';
-- Read
wait until rising_edge(clk);
wait until rising_edge(clk);
Log("Test Operation Order", INFO);
-- Request Address 0
valid_in <= '1';
addr <= std_logic_vector(to_unsigned(0, ADDR_WIDTH));
read <= '1';
SB.Push(test_array(0));
if (ready_in = '0') then
wait until ready_in = '1';
end if;
wait until rising_edge(clk);
-- Write Address 0
read <= '0';
data_in <= test_array(MEMORY_DEPTH-1);
if (ready_in = '0') then
wait until ready_in = '1';
end if;
wait until rising_edge(clk);
-- Request Address 0
read <= '1';
SB.Push(test_array(7));
data_in <= (others => '0');
if (ready_in = '0') then
wait until ready_in = '1';
end if;
wait until rising_edge(clk);
valid_in <= '0';
addr <= (others => '0');
read <= '0';
wait until rising_edge(clk);
wait until rising_edge(clk);
-- Wait until test Completion
if (not SB.empty) then
wait until SB.empty;
end if;
TranscriptOpen(RESULTS_FILE, APPEND_MODE);
SetTranscriptMirror;
ReportAlerts;
TranscriptClose;
std.env.stop;
wait;
end process;
output_check_prc : process(all)
begin
if falling_edge(clk) then
if (valid_out = '1') then
ready_out <= '1';
SB.Check(data_out);
else
ready_out <= '0';
end if;
end if;
end process;
clock_prc : process
begin
clk <= '0';
wait for 25 ns;
clk <= '1';
wait for 25 ns;
end process;
watchdog : process
begin
wait for 1 ms;
Alert("Test timeout", FAILURE);
std.env.stop;
end process;
end architecture;

View File

@ -32,10 +32,11 @@ architecture arch of mem_ctrl is
-- *SIGNAL DECLARATION* -- *SIGNAL DECLARATION*
signal mem_read_data : std_logic_vector(DATA_WIDTH-1 downto 0); signal mem_read_data : std_logic_vector(DATA_WIDTH-1 downto 0);
signal delay_line : std_logic_vector(READ_LATENCY downto 0) := (others => '0'); signal delay_line : std_logic_vector(READ_LATENCY-1 downto 0) := (others => '0');
signal fifo_empty : std_logic := '0'; signal fifo_empty : std_logic := '0';
signal fifo_cnt : natural 0 to MAX_BURST_LENGTH := 0; signal fifo_cnt : natural range 0 to MAX_BURST_LENGTH := 0;
signal delay_cnt : natural 0 to READ_LATENCY := 0; signal delay_cnt : natural range 0 to READ_LATENCY := 0;
signal ready_in_sig, valid_out_sig : std_logic := '0';
begin begin
@ -49,27 +50,43 @@ begin
port map ( port map (
clk => clk, clk => clk,
addr => addr, addr => addr,
wen => not read, wen => ready_in_sig and valid_in and (not read),
ren => read, ren => ready_in_sig and valid_in and read,
wr_data => data_in, wr_data => data_in,
rd_data => mem_read_data rd_data => mem_read_data
); );
ready_in_sig <= '0' when (fifo_cnt - delay_cnt = 0) else '1';
ready_in <= ready_in_sig;
valid_out_sig <= not fifo_empty;
valid_out <= valid_out_sig;
delay_line_prc : process(clk) delay_line_prc : process(clk)
begin begin
if rising_edge(clk) then if rising_edge(clk) then
if (reset = '1') then if (reset = '1') then
delay_line <= (others => '0'); delay_line <= (others => '0');
delay_cnt <= 0; delay_cnt <= 0;
else else
-- Shift Right -- Shift Right
delay_line(READ_LATENCY-1 downto 0) <= delay_line(READ_LATENCY downto 1); if (READ_LATENCY > 1) then
delay_line(READ_LATENCY) <= read; delay_line(READ_LATENCY-2 downto 0) <= delay_line(READ_LATENCY-1 downto 1);
delay_line(READ_LATENCY-1) <= ready_in_sig and valid_in and read;
if (read = '1' and delay_line(1) = '0') then
delay_cnt <= delay_cnt + 1; if ((ready_in_sig and valid_in and read) = '1' and delay_line(1) = '0') then
elsif (read = '0' and delay_line(1) = '1') then delay_cnt <= delay_cnt + 1;
delay_cnt <= delay_cnt - 1; elsif ((ready_in_sig and valid_in and read) = '0' and delay_line(1) = '1') then
delay_cnt <= delay_cnt - 1;
end if;
else
delay_line(0) <= ready_in_sig and valid_in and read;
if ((ready_in_sig and valid_in and read) = '1' and delay_line(0) = '0') then
delay_cnt <= delay_cnt + 1;
elsif ((ready_in_sig and valid_in and read) = '0' and delay_line(0) = '1') then
delay_cnt <= delay_cnt - 1;
end if;
end if; end if;
end if; end if;
end if; end if;
@ -85,14 +102,10 @@ begin
reset => reset, reset => reset,
data_in => mem_read_data, data_in => mem_read_data,
write => delay_line(0), write => delay_line(0),
read => ready_out, read => ready_out and valid_out_sig,
data_out => data_out, data_out => data_out,
empty => fifo_empty, empty => fifo_empty,
full => open, full => open,
free => fifo_cnt, free => fifo_cnt
); );
ready_in <= '0' when (fifo_cnt + delay_cnt = MAX_BURST_LENGTH) else '1';
valid_out <= not fifo_empty;
end architecture; end architecture;