0
\$\begingroup\$

I need to connect an ALU with a two-port data memory, but I can only implement this far, and I don't know what is missing, plus I am a bit confused as to what to write for the testbench code epsecially when it come to what time intervals I should put, can someone please help?

Here is the VHDL code:

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;

entity micro is
    port( alu: in signed (31 downto 0);
          rom: in unsigned (4 downto 0);
          c: out std_logic));
end entity micro;

architecture comb of micro is
    signal romalucon: std_logic_vector (31 downto 0);
begin
    g1: entity.work.rom(comb)
        port ( data_out1 => romalucon, data_out2 => romalucon);
    g2: entity.work.alu(comb)
        port ( a => roamlucon, b => romalucon);
end architecture comb; 

And the testbench, so far:

library IEEE;
use IEEE.std_logic_1164.all;

entity micro_test is
end entity micro_test;

architecture end_product of micro_test is
    signal alu_input: std_logic_vector (31 downto 0);
    signal rom_input: std_logic_vector (4 downto 0);
    signal c_output: std_logic;
    
begin
    g3: entity.work.micro(comb)
        port map ( alu => alu_input, rom => rom_input, c => c_output );

Additionally, here is the VHDL code for the ALU:

library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_signed.ALL; --In this case signed arithmetic is used due to the fact that one of the variable operations utilised in this code is the absolute value function which only exists for signed values, therefore the values in this code need to be signed numbers.

entity alu is port ( A, B: in std_logic_vector(31 downto 0); opcode: in std_logic_vector(5 downto 0); Result: out std_logic_vector(31 downto 0));
end entity alu;

architecture dataoperations of alu is begin Result <= A + B when opcode="001010" else A - B when opcode="001000" else abs(A) when opcode="001011" else -A when opcode="001101" else abs(B) when opcode="000001" else -B when opcode="001001" else A or B when opcode="000110" else not A when opcode="001111" else not B when opcode="000101" else A and B when opcode="001100" else A xor B when opcode="000010"; end architecture dataoperations;

The testbench for ALU:

library IEEE;
use IEEE.std_logic_1164.all;

entity alu_test is
end entity alu_test;

architecture test of alu_test is
    signal in1, in2, out1: std_logic_vector (31 downto 0);
    signal in3: std_logic_vector (5 downto 0);
begin
    g1: entity work.alu(dataoperations)
        port map ( A => in1, B => in2, opcode => in3, Result => out1 );
   
    in1 (6) <= '0';
    in1 (5 downto 0) <= x"000000",
                        x"000001" after 10 ns,
                        x"2" after 20 ns,
                        x"3" after 30 ns,
                        x"4" after 40 ns,
                        x"5" after 50 ns;    
    in2 (6) <= '0';
    in2 (5 downto 0) <= x"6",
                        x"7" after 60 ns,
                        x"8" after 70 ns,
                        x"9" after 80 ns,
                        x"A" after 90 ns,
                        x"B" after 100 ns;                                        
    in3 <= "000000";
end architecture test;

The VHDL code for the 5-bit input, 32-bit output ROM:

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all; --The reason why unsigned arithmetic is used here is because we will need to convert the hexadecimal inputs to integers, and by using unsigned we allow ourselves to get values within the number the number range requested in line 11 of the code, ie from 0 to 31. If we didn't use unsigned, then except from positive value, we would also probably get neagtive addr values, which would not fall within our request.

entity rom is
    port ( addr1, addr2: in std_logic_vector(4 downto 0);
      data_out1, data_out2: out std_logic_vector(31 downto 0));
end entity rom;

architecture dataflow of rom is
    type rom_array is array (0 to 31) 
                    of std_logic_vector (31 downto 0);
    signal rom_data: rom_array := 
                    (x"00000000", x"00000000", x"000005E4", x"0000EE7C", x"000175FE", x"00000BAE", x"0000E4E0", x"00000F20", x"00013CE3", x"000072B0", x"000075BE", x"00005974", x"0000DC71", x"00009064", x"0000D246", x"00017CE1", x"00015275", x"00011CD8",x"000131F3", x"00013B3F", x"00000149", x"000124D5",                    x"000051CD", x"00015A16", x"00016EAE", x"0000A312", x"00007F96", x"000161A4", x"0001673C", x"00005E6F", x"000154B5", x"00000000");
begin
    data_out1 <= rom_data (conv_integer (addr1) );
    data_out2 <= rom_data (conv_integer (addr2) );
end architecture dataflow;

And the testbench for the ROM:

library IEEE;
use IEEE.std_logic_1164.all;

entity rom_test is
end entity rom_test;

architecture dataflow of rom_test is
    signal input_address1, input_address2: std_logic_vector (4 downto 0);
    signal output_data1, output_data2: std_logic_vector (31 downto 0);
    
begin
    g1: entity work.rom(dataflow)
        port map ( addr1 => input_address1, addr2 => input_address2, data_out1 => output_data1, data_out2 => output_data2 );
        
        input_address1 (4) <= '0';
        input_address1 (3 downto 0) <= x"0",
                                        x"1" after 1 ns,
                                        x"2" after 2 ns,
                                        x"3" after 3 ns,
                                        x"4" after 4 ns,
                                        x"5" after 5 ns,
                                        x"6" after 6 ns,
                                        x"7" after 7 ns,
                                        x"8" after 8 ns,
                                        x"9" after 9 ns,
                                        x"A" after 10 ns,
                                        x"B" after 11 ns,
                                        x"C" after 12 ns,
                                        x"D" after 13 ns,
                                        x"E" after 14 ns,
                                        x"F" after 15 ns,
                                        x"10" after 16 ns,
                                        
        input_address2 (4 downto 0) <= x"11",
                                        x"12" after 17 ns,
                                        x"13" after 18 ns,
                                        x"14" after 19 ns,
                                        x"15" after 20 ns,
                                        x"16" after 21 ns,
                                        x"17" after 22 ns,
                                        x"18" after 23 ns,
                                        x"19" after 24 ns,
                                        x"1A" after 25 ns,
                                        x"1B" after 26 ns,
                                        x"1C" after 27 ns,
                                        x"1D" after 28 ns,
                                        x"1E" after 29 ns,
                                        x"1F" after 30 ns;
                                     
end architecture dataflow; 

          
\$\endgroup\$
1
  • \$\begingroup\$ Can you draw a wiring diagram of what you're trying to create? \$\endgroup\$ Commented Feb 15, 2021 at 16:23

1 Answer 1

0
\$\begingroup\$

Using std_logic_unsigned and std_logic_signed is discouraged for new code. You should use numeric_std. Its more of a pain to do conversions. Alu opcode is a different width from how it is used. And most designs use clocks, where as your design is 100% combinatorial (so far). You should have the testbench step through all of the opcodes for the alu, and all the addresses for the rom and check the results with asserts.

\$\endgroup\$
6
  • \$\begingroup\$ Thank you for your help. The point is I just realised that the opcode is 6-bit so now I don't know how to fix the time intervals on the testbench for alu. Additionally, our teachers ask us to use signed and unsigned logic for rom and alu respectively, and the clock will be added later. Also the run time is supposed to be 100 ns so how am I supposed to make the testbenches for alu and rom run through all the opcodes/addresses respectively? \$\endgroup\$
    – xxs899
    Commented Feb 15, 2021 at 16:35
  • \$\begingroup\$ Get your signed and unsigned from numeric_std. \$\endgroup\$
    – user16324
    Commented Feb 15, 2021 at 16:42
  • \$\begingroup\$ How will that help? \$\endgroup\$
    – xxs899
    Commented Feb 15, 2021 at 16:53
  • \$\begingroup\$ numeric_std is maintained by the standards community and is an IEEE standard. std_logic_arith is not maintained and is erroneously in the IEEE library as it is not an IEEE standard. \$\endgroup\$
    – Jim Lewis
    Commented Feb 15, 2021 at 16:58
  • \$\begingroup\$ @xxs899 You can do the whole simulation in under 100 ns. Just use 1 ns time intervals instead of 10 ns. To use numberic_std, you would have to do something like: Result <= std_logic_vector(signed(A) + signed(B)). Here's a link [nandland.com/vhdl/tips/… \$\endgroup\$
    – IanJ
    Commented Feb 15, 2021 at 17:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.