質問

I have a vector A that's 64bits long and I want the output B to equal 3 while A is 30-35 and zero elsewhere. I can't figure out the testbench to loop through the vector A as a bit. I've tried several different ways but only got 1/5 of the array to give any output at all. This is as far as I could get without syntax/compile errors.

Main code

library IEEE;
use IEEE.STD_LOGIC_1164.all;     
use IEEE.NUMERIC_STD.ALL;

entity ent is
port(A:in std_logic_vector(5 downto 0);
     B:out std_logic_vector(3 downto 0));
end ent;

architecture arch_ent of ent is
begin               
with A select
B <= "0011" when "011110",
      "0011" when "011111", 
      "0011" when "100000",
      "0011" when "100001",
      "0011" when "100010",
      "0011" when "100011",
      "0000" when others;       
end arch_ent;

Testbench

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity tb is
end tb;

architecture arch_tb of tb is

component ent 
port(A:in std_logic_vector(5 downto 0);
B:out std_logic_vector(3 downto 0));
end component;

signal A_tb: std_logic_vector(5 downto 0);
signal B_tb: std_logic_vector(3 downto 0);

begin
uut: entity ent port map(A=>A_tb, B=>B_tb);
tb: process 
constant period: time := 20ns;
begin
for i in A_tb'range loop
    A_tb <= std_logic_vector(to_unsigned(i,6));
    wait for period;
    assert (B_tb = "0011") 
    report "test failed" severity error; 
end loop;   
wait;
end process;  
end arch_tb;

In the end I'm trying to plot out the waveform like this: http://i10.photobucket.com/albums/a142/blargonblop/wave.png

where A will go to 63 and each output is its correct value from 30-35 and 0 elsewhere

役に立ちましたか?

解決

The loop parameter you use to specify the number of 'tests' is A_tb'range, which happens to be 5 downto 0, or six tests, i is assigned 5,4,3,2,1 and 0 successively.

You want to specify i in 0 to 2**A-tb'length-1 or i in 0 to 63 to get all 64 possible A_tb 'binary' values.

(A_tb'length = 6, 2**6-1 = 63, where ** is the exponentiation operator, 2 to the 6th power minus 1 equals 63)

I found two syntax errors in your test bench, 20ns where the standard requires a space between 20 and ns:

    constant period: time := 20 ns;

And entity ent where that should either be just ent (you have a component declaration ent) or entity work.ent and no need for a component declaration:

uut: ent port map(A=>A_tb, B=>B_tb);

or

uut: entity work.ent port map(A=>A_tb, B=>B_tb);

And in keeping with Russell's answer there is no implied logic replication in a loop other than through synthesis which unravels loop iterations by paralleling logic (the replication). Not all loop statements are intended as synthesis targets.

Test benches are generally not synthesized and are used to write tests (as in your case) for a VHDL model that might be used as a synthesis target.

他のヒント

First, loops are just fine, and common, in testbenches. @Russell's comment applies to RTL code. You can adapt his approach for this problem and make it work. You would need to use 64 as a sentinel (ending) value and do your end of test checks then. Keep in mind though that the most important thing you do is code for readability. Test cases generally run from top to bottom of a process one time.

You loop has some issues in addition to the recommendations @DavidKoontz gave. Specifically,

  • Your assertion is should not be checked when you expect B to be 0.
  • Using numeric_std_unsigned (requires VHDL-2008 compile switch) will simplify your conversions.
  • Keep an error count so you can report pass or failed at the end.
  • Keep your constants in the architecture or a package

So the modified code is:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.numeric_std_unsigned.all;

entity tb is
end tb;

architecture arch_tb of tb is
  constant period: time := 20 ns;
...
begin
...

tb: process 
  variable ErrorCount : 
begin
  for i in i in 0 to 2**A-tb'length-1
    A_tb <= to_slv(i,6);
    wait for period;
    if i >= 30 and i <= 35 then 
      if B_tb /= 3 then 
        ErrorCount := Error Count + 1 ; 
        report "B_tb = " & to_string(B_tb) & "  Expecting: 0011" severity ERROR ; 
      end if; 
    else 
      if B_tb /= 0 then 
        ErrorCount := Error Count + 1 ; 
        report "B_tb = " & to_string(B_tb) & "  Expecting: 0000" severity ERROR ; 
      end if; 
  end loop;   
  if ErrorCount = 0 then 
    report "Test Passed" severity NOTE ; 
  else
    report "Test FAILED.  There were " & to_string(ErrorCount) & " Errors " severity NOTE; 
  end if; 
  std.env.stop(0) ; -- testbench stops here
end process; 

Note that the rules about using (or forbidding usage of) numeric_std_unsigned do not apply to testbenches.

You really should not be using a for loop for this. For loops in VHDL are used to REPLICATE LOGIC, not to do something some number of times. Try something like this in your test bench:

signal r_CLOCK : std_logic := '0';
signal r_INDEX : unsigned(5 downto 0) := (others => '0');

begin

  r_CLOCK <= not r_CLOCK after period/2;

  process (r_CLOCK)
  begin
    if rising_edge(r_CLOCK) then
      r_INDEX <= r_INDEX + 1;
    end if;
  end process;

Now simply cast r_INDEX as std_logic_vector and pass it to your ent component.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top