I'm very new to VHDL and am required to modify this ALU with an additional eight operations, which aren't relevant themselves but from the testing in GTKwave I see that the clk(clock) and r(result) discontinue simulating after the first eight operations it seems, although the op waveform acknowledges them. Both source and test bench compile fine with no errors, resulting what seems to be incorrect waveforms. Waveforms/Testing
I tried to fix this by going back into the test bench code and changing the ‘exit L1 when i >10;
’ loop from 10 to 20(or any other over 10) and then recompiling, but this resulted in a “bound check failure” error which stumped me. I also tried changing modifying to make it 16-bit, but that didn't compile - definitely not the solution I imagine.
Ignore the mixed up operational comments.
Any help would be much appreciated, I'm assume it's a very novice overlook.
Initial code derived from http://vhdlguru.blogspot.co.uk/2011/06/vhdl-code-for-simple-alu.html
SOURCE CODE
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity Ex8 is
port( Clk : in std_logic; --clock signal
A,B : in signed(7 downto 0); --input operands
Op : in unsigned(3 downto 0); --Operation to be performed -- 2 to 3
R : out signed(7 downto 0) --output of ALU
);
end Ex8;
architecture Behavioral of Ex8 is
--temporary signal declaration.
signal Reg1,Reg2,Reg3 : signed(7 downto 0) := (others => '0');
begin
Reg1 <= A;
Reg2 <= B;
R <= Reg3;
process(Clk)
begin
if(rising_edge(Clk)) then --Do the calculation at the positive edge of clock cycle.
case Op is
when "0000" =>
Reg3 <= Reg1 + Reg2; --addition
when "0001" =>
Reg3 <= Reg1 - Reg2; --subtraction
when "0010" =>
Reg3 <= not Reg1; --NOT gate
when "0011" =>
Reg3 <= Reg1 nand Reg2; --NAND gate
when "0100" =>
Reg3 <= Reg1 nor Reg2; --NOR gate
when "0101" =>
Reg3 <= Reg1 and Reg2; --AND gate
when "0110" =>
Reg3 <= Reg1 or Reg2; --OR gate
when "0111" =>
Reg3 <= Reg1 xor Reg2; --XOR gate
when "1000" =>
Reg3 <= Reg1 / Reg2; --division
when "1001" =>
Reg3 <= Reg1 * Reg2; --multiplication
when "1010" =>
Reg3 <= Reg1 xnor Reg2; --rotate left
when "1011" =>
Reg3 <= Reg1 srl 4; --rotate right
when "1100" =>
Reg3 <= Reg1 & Reg2; --shift left logical
when "1101" =>
Reg3 <= Reg1 sll 4; --shift right logical
when "1110" =>
Reg3 <= Reg1 mod Reg2; --modulo
when "1111" =>
Reg3 <= Reg1 rem Reg2; --remainder
when others =>
NULL;
end case;
end if;
end process;
end Behavioral;
TEST BENCH
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
ENTITY Ex8_tb IS
END Ex8_tb;
ARCHITECTURE behavior OF Ex8_tb IS
signal Clk : std_logic := '0';
signal A,B,R : signed(7 downto 0) := (others => '0');
signal Op : unsigned(3 downto 0) := (others => '0');
constant Clk_period : time := 10 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: entity work.Ex8 PORT MAP (
Clk => Clk,
A => A,
B => B,
Op => Op,
R => R
);
-- Clock process definitions
Clk_process :process
variable i : POSITIVE := 1;
begin
L1: loop
Clk <= '0';
wait for Clk_period/2;
Clk <= '1';
wait for Clk_period/2;
i:= i+1;
exit L1 when i >10;
end loop L1; -- changed from failure to warning
assert false report "NONE. End of simulation." severity warning;
wait; -- added wait;
end process;
-- Stimulus process
stim_proc: process
begin
wait for Clk_period*1;
A <= "00010010"; --18 in decimal
B <= "00001010"; --10 in decimal
Op <= "0000"; wait for Clk_period; --add A and B
Op <= "0001"; wait for Clk_period; --subtract B from A.
Op <= "0010"; wait for Clk_period; --Bitwise NOT of A
Op <= "0011"; wait for Clk_period; --Bitwise NAND of A and B
Op <= "0100"; wait for Clk_period; --Bitwise NOR of A and B
Op <= "0101"; wait for Clk_period; --Bitwise AND of A and B
Op <= "0110"; wait for Clk_period; --Bitwise OR of A and B
Op <= "0111"; wait for Clk_period; --Bitwise XOR of A and B
Op <= "1000"; wait for Clk_period; --Bitwise DIV of A and B
Op <= "1001"; wait for Clk_period; --Bitwise MUL of A and B
Op <= "1010"; wait for Clk_period; --Bitwise ROL of A and B
Op <= "1011"; wait for Clk_period; --Bitwise ROR of A and B
Op <= "1100"; wait for Clk_period; --Bitwise SLL of A and B
Op <= "1101"; wait for Clk_period; --Bitwise SRL of A and B
Op <= "1110"; wait for Clk_period; --Bitwise MOD of A and B
Op <= "1111"; wait for Clk_period; --Bitwise REM of A and B
wait;
end process;
END;
You have one problem in your code that prevents it compiling; you have one that prevents it simulating (a run-time error). Both fail for the same reason: array sizes do not match.
This line might not compile:
Reg3 <= Reg1 & Reg2;
This is because reg1
, reg2
and reg3
are all the same width. &
is concatenation - the joining of two arrays to make a bigger array. The width of reg3
needs to be equal to the width of reg1
plus the width of reg2
. (I say "might not" because it gave a compile error on one simulator and a runtime error on another).
I then changed this line:
exit L1 when i >10;
to this:
exit L1 when i >20;
as you suggested and then got a run time error at this line:
Reg3 <= Reg1 * Reg2; --multiplication
This is again because reg1
, reg2
and reg3
are all the same width. The multiplication operator defined in the numeric_std
package outputs a result with width equal to the sum of the widths of the two operands, ie the width of reg1
plus the width of reg2
.
So, you need to think about the widths of your inputs and outputs or you need to do some truncation (but that would make your concatenation operation pointless).