Question

I'm in the process of writing the VHDL code for Salsa20 stream cipher. Its main function is the 'quarterround' which I have successfully written. I want to test it in Modelsim before moving on but I am encountering difficulties. I understand I have to 'stimulate' the inputs to observe the outputs. All attempts I've made have resulted in the output, z, not giving any values. The code for the Quarterround (which is top level):

LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;

ENTITY quarter_round is 
    GENERIC(l:integer:=9);
    PORT(y : in unsigned(127 downto 0);
    z : out unsigned( 127 downto 0)
    );
END quarter_round;

ARCHITECTURE quarter_round_arch of quarter_round is

COMPONENT left is                                               
    GENERIC(l:integer);                                     
    PORT( a: in unsigned( 31 downto 0);
    b: out unsigned( 31 downto 0));
    end COMPONENT;
    signal i1,i2,i3,i4 :unsigned( 31 downto 0);
    signal j1,j2,j3,j4 :unsigned( 31 downto 0);
    signal z0,z1,z2,z3 :unsigned( 31 downto 0);
    signal y0 : unsigned( 31 downto 0);                 
    signal y1 : unsigned( 31 downto 0);                 
    signal y2 : unsigned( 31 downto 0);
    signal y3 : unsigned( 31 downto 0);

BEGIN                                                                   
    y0 <=y(127 downto 96);                                  
    y1 <=y(95 downto 64);                                   
    y2 <=y(63 downto 32);
    y3 <=y(31 downto 0);
    i1<=y0+y3;
    a1:left generic map(7) port map(i1,j1);         
    z1<=j1 xor y1;                                              
    i2<=z1+y0;
    a2:left generic map(9) port map(i2,j2); 
    z2<=j2 xor y2;
    i3<=z2+z1;
    a3:left generic map(13) port map(i3,j3);
    z3<=j3 xor y3;
    i4<=z3+z2;
    a4:left generic map(18) port map(i4,j4);
    z0<=j4 xor y0;
    z<=z0&z1&z2&z3;
END quarter_round_arch;

The COMPONENT left:

LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;

ENTITY left is
GENERIC (l:integer:=7);
PORT( n: in unsigned( 31 downto 0);
m: out unsigned( 31 downto 0));
END left;

ARCHITECTURE dataflow of left is
    begin
    m<=n(31-l downto 0)& n(31 downto 31-l+1);
END dataflow;

The testbench I'm trying to write will be assigned a value for y (128 bits), process the function and z should output the correct answer in Modelsim. I realize this is a basic VHDL question, but it's driving me nuts!

This code is failing Modelsim:

LIBRARY ieee;                                               
USE ieee.std_logic_1164.all;                                
USE ieee.numeric_std.all;

ENTITY quarter_round_vhd_tst IS
END quarter_round_vhd_tst;

ARCHITECTURE test of quarter_round_vhd_tst IS

COMPONENT quarter_round
PORT (
    y : IN STD_LOGIC_VECTOR(127 DOWNTO 0);
    z : OUT STD_LOGIC_VECTOR(127 DOWNTO 0)
    );
    END COMPONENT;
    SIGNAL clk : std_logic := '0';
    SIGNAL reset : std_logic := '0';                                       
    SIGNAL y : STD_LOGIC_VECTOR(127 DOWNTO 0);
    SIGNAL z : STD_LOGIC_VECTOR(127 DOWNTO 0);                               
    BEGIN
   DUT : quarter_round
    PORT MAP (
    y => y,
    z => z
    );

    y  <= x"201f1e1d1c1b1a191817161514131211"; 

PROCESS
BEGIN
    clk <= '0' ;
    wait for 10 ns;
    z <= y ;
    clk <= '1';
    wait for 10 ns;
    END PROCESS;
    END test;

Edit: this is latest attempt. Code is compiling but Modelsim giving errors saying types do not match.. Any ideas appreciated. CT

Was it helpful?

Solution

david_koontz@Macbook: ghdl -a quarter_round.vhdl
david_koontz@Macbook: ghdl -e quarter_round_vhd_tst
quarter_round.vhdl:100:1: type of signal interface "y" from component "quarter_round" and port "y" from entity "quarter_round" are not compatible for an association quarter_round.vhdl:100:1: type of signal interface "z" from component "quarter_round" and port "z" from entity "quarter_round" are not compatible for an association ghdl: compilation error

So the problem you describe after the edit shows up during elaboration. Note the type in the component declaration and the entity quarter_round don't match.

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

entity quarter_round_vhd_tst is
end quarter_round_vhd_tst;

architecture test of quarter_round_vhd_tst is

    component quarter_round
        port (
            y: in  unsigned(127 downto 0);
            z: out unsigned(127 downto 0)
        );
    end component;

    signal clk : std_logic := '0';
    signal reset : std_logic := '0';
    signal y : unsigned(127 downto 0);
    signal z : unsigned(127 downto 0);
begin
DUT: quarter_round
        port map (
            y => y,
            z => z
        );

CLOCK:
    process
    begin
        wait for 10 ns;    
        clk <= not clk;
        if Now > 30 ns then
            wait;
        end if;
    end process;

STIMULUS:
    process
    begin
        wait for 10 ns;
         y  <= x"201f1e1d1c1b1a191817161514131211";
        wait for 10 ns;
        -- z <= y ;
        wait;  
    end process;
end test;

The changes are for a separate process for clock, likely you'll need it once you add more in. You originally tried to assign z in the testbench, z is an output of quarter_round.

I moved the y assignment into the stimulus process. If the reset gets used you can put that in there too.

The idea behind using wait statements without arguments is to stop processes from repeating endlessly. As long as you assign signals they'd go until Time'HIGH. The comparison for Now in process CLOCK can be changed for multiple stimulus or length of time to execute. Likewise you can introduce a signal used to stop the clock that is assigned in a process (e.g. STIMULUS) that is used instead of Now to stop the clock, if there's something coming out of the (eventual) model that signals end of simulation.

Without the DUT relying on clock (or reset) as soon as y is assigned, z is assigned with the result. (This is why I put the delay before the y assignment, to demonstrate this).

I used the quarter_round and left I corrected yesterday, so mine has a and b instead of m and n.

quarter_round_vhd_test

So does the result look right?

Once over the hurtle of getting something back, then sequential (clocked) processes and you should start making good progress.

And you can use type conversions in the port map for quarter round:

    signal y : std_logic_vector(127 downto 0);
    signal z : std_logic_vector(127 downto 0);
begin
DUT: quarter_round
        port map (
            y => unsigned(y),
            std_logic_vector(z)=> z
        );

But the component declaration still needs to match the entity declaration for quarter_round.

And if you're sure you'll never need to configure quarter_round in the testbench you can use direct entity instantiation, eliminating the component declaration:

    -- component quarter_round
    --     port (
    --         y: in  unsigned(127 downto 0);
    --         z: out unsigned(127 downto 0)
    --     );
    -- end component;
    ...

begin
DUT: -- quarter_round
    entity work.quarter_round
        port map (
            y => unsigned(y),
            std_logic_vector(z)=> z
        );

It's generally useful to have a valid component declaration or to at least use formal association (instead of positional, the above shows formal). That way someone reading the code doesn't have to count arguments while looking somewhere else.

Notice the directly instantiated entity is specified with a selected name specifying the library the entity is found in.

OTHER TIPS

You must have overlooked the compilation errors relating to "left.vhd". Signals "a" and "b" are undeclared.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top