VHDL 1-bit ALU - behavioral - vhdl

I just wrote this code of a 1-bit ALU with behavioral way.The code contains an overflow check. Can someone explain me if the code is correct ?
Here is the code:
entity ALU_VHDL is
port
(
a, b: in std_logic_vector(1 downto 0);
Operation : in std_logic_vector(2 downto 0);
Carry_Out : out std_logic;
Flag : out std_logic;
Result : out std_logic_vector(1 downto 0)
);
end entity ALU_VHDL;
architecture Behavioral of ALU_VHDL is
signal Temp: std_logic_vector(2 downto 0);
begin
process(a, b, Operation, temp) is
begin
Flag <= '0';
case Operation is
when "000" => -- resu = a + b, flag = carry = overflow
Temp <= std_logic_vector((unsigned("0" & a) + unsigned(b)));
Result <= temp(1 downto 0);
Carry_Out <= temp(2);
when "001" => -- resu = |a - b|, flag = 1 iff a > b
if (a >= b) then
Result <= std_logic_vector(unsigned(a) - unsigned(b));
Flag <= '0';
else
Result <= std_logic_vector(unsigned(a) - unsigned(b));
Flag <= '1';
end if;
when "010" =>
Result <= a and b;
when "011" =>
Result <= a or b;
when "100" =>
Result <= a xor b;
when "101" =>
Result <= not a;
when "110" =>
Result <= not b;
when others => -- resu = a + not b + 1, flag = 0
Temp <= std_logic_vector((unsigned("0" & Nibble1) + unsigned(not Nibble2)) + 1);
Result <= temp(1 downto 0);
Flag <= temp(2);
end case;
end process;
end architecture Behavioral;
I am new in VHDL so any advice is appreciated. Thanks in advance.

Related

Flags for ALU in VHDL not updating when running simulation

So far everything works as intended except for the Cout (carryout) and V (overflow) when I simulate in the testbench. I get constant Us when performing addition and subtraction. I performed some of the calculations I'm testing by hand so I know which should have a carry value and overflow value.
entity ALU is
Port ( Cin : in STD_LOGIC_VECTOR ( 0 downto 0);
ALUCntrl : in STD_LOGIC_VECTOR ( 3 downto 0);
A, B : in STD_LOGIC_VECTOR (31 downto 0);
ALUout : out STD_LOGIC_VECTOR (31 downto 0);
Cout, Z, V : out STD_LOGIC );
end ALU;
architecture Behavioral of ALU is
SIGNAL result : STD_LOGIC_VECTOR (32 downto 0);
SIGNAL bCout, bZ, bV : STD_LOGIC;
begin
WITH ALUCntrl SELECT
result(31 downto 0) <= A and B when "0000",
A or B when "0001",
A xor B when "0011",
std_logic_vector(unsigned(A) + unsigned(B) + unsigned(Cin)) WHEN "0010",
std_logic_vector(unsigned(A) - unsigned(B)) WHEN "0110",
A xnor B WHEN "1100",
A xnor B WHEN "1111",
"00000000000000000000000000000000" WHEN OTHERS;
WITH result(31 downto 0) SELECT
bZ <= '1' WHEN "00000000000000000000000000000000",
'0' WHEN OTHERS;
WITH ALUCntrl SELECT
bCout <= result(32) WHEN "0010",
result(32) WHEN "0110",
'0' WHEN OTHERS;
PROCESS(ALUCntrl)
BEGIN
CASE ALUCntrl IS
WHEN "0010" =>-- Addition Overflow
IF ((A(31) = '1') and (B(31) = '1') and (result(31) = '0')) THEN
bV <= '1';
ELSIF ((A(31) = '0') and (B(31) = '0') and (result(31) = '1')) THEN
bV <= '1';
ELSE
bV <= '0';
END IF;
WHEN "0110" => -- Subtraction overflow
IF ((A(31) = '0') and (B(31) ='1') and (result(31) = '1')) THEN
bV <= '1';
ELSIF ((A(31) = '1') and (B(31) = '0') and (result(31) = '0')) THEN
bV <= '1';
ELSE
bV <= '0';
END IF;
WHEN OTHERS =>
bV <= '0';
END CASE;
END PROCESS;
ALUout <= result(31 downto 0);
Cout <= bCout;
Z <= bZ;
V <= bV;
end Behavioral;
TEST-BENCH
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity ALU_tb is
-- Port ( );
end ALU_tb;
architecture Behavioral of ALU_tb is
-- INPUTS
signal Cin : STD_LOGIC_VECTOR ( 0 downto 0);
signal A, B : STD_LOGIC_VECTOR (31 downto 0);
signal ALUCntrl : STD_LOGIC_VECTOR ( 3 downto 0);
-- OUTPUTS
signal ALUout : STD_LOGIC_VECTOR (31 downto 0);
signal Cout, Z, V : STD_LOGIC;
component ALU is
port(
Cin : in STD_LOGIC_VECTOR ( 0 downto 0);
A, B : in STD_LOGIC_VECTOR (31 downto 0);
ALUCntrl : in STD_LOGIC_VECTOR ( 3 downto 0);
ALUout : out STD_LOGIC_VECTOR (31 downto 0);
Cout, Z, V : out STD_LOGIC );
end component ALU;
begin
design_ALU: ALU
port map(
Cin => Cin,
A => A,
B => B,
ALUCntrl => ALUCntrl,
ALUout => ALUout,
Cout => Cout,
Z => Z,
V => V
);
tb : PROCESS
BEGIN
ALUCntrl <= "0000"; -- AND
Cin <= "00";
A <= "11111111111111111111111111111111";
B <= "00000000000000000000000000000000";
wait for 250ns;
ALUCntrl <= "0001"; -- OR
A <= "10011000100110001001100010011000";
B <= "10001001100010011000100110001001";
wait for 250ns;
ALUCntrl <= "0011"; -- XOR
A <= "00000001000000010000000100000001";
B <= "00010000000100000001000000010000";
wait for 250ns;
ALUCntrl <= "0010"; -- ADD
A <= "00000000000000000000000000000001";
B <= "11111111111111111111111111111111";
wait for 250ns;
ALUCntrl <= "0010"; -- ADD
A <= "01100011100010010111010101001111";
B <= "10101101010101100010010011100110";
wait for 250ns;
ALUCntrl <= "0010"; -- ADD
Cin <= "01";
A <= "00000000000000000000000000000001";
B <= "11111111111111111111111111111111";
wait for 250ns;
ALUCntrl <= "0010"; -- ADD
A <= "01100011100010010111010101001111";
B <= "10101101010101100010010011100110";
wait for 250ns;
ALUCntrl <= "0010"; -- ADD
A <= "11111111111111111111111111111111";
B <= "11111111111111111111111111111111";
wait for 250ns;
ALUCntrl <= "0110"; -- SUB
A <= "00000000000000000000000000000000";
B <= "00000000000000000000000000000001";
wait for 250ns;
ALUCntrl <= "0110"; -- SUB
A <= "11111001011010000100011110000011";
B <= "11111001100110001101010101100010";
wait for 250ns;
ALUCntrl <= "0110"; -- SUB
A <= "10000000000000000000000000000000";
B <= "00000001000000000000000000000000";
wait for 250ns;
ALUCntrl <= "1100"; -- NOR
A <= "10011010101111001101111011011111";
B <= "10011010101111001101111011111101";
wait for 250ns;
ALUCntrl <= "1111"; -- XNOR
A <= "10001001101111001101111000110100";
B <= "11000101001110111101011010000111";
wait;
END PROCESS tb;
end Behavioral;

VHDL Getting a simulation fatal error in the loading design in modelsim

(Yes I know there's an easier way, yes my professor is asking for the long way.)
The following is the code for my 1 bit adder/subtractor.
library ieee;
use ieee.std_logic_1164.all;
entity FA1Bit is
port(x,y,Cin: in std_logic;
op: in std_logic;
S, Cout: out std_logic);
end FA1Bit;
architecture FA1Bit_arch of FA1Bit is
begin
behavior : PROCESS(op,x,y,Cin)
begin
if op = '0' then --if we're adding the bits;
if Cin = '0' then
if x = y then
S <= '0';
if (x= '1' and y = '1') then
Cout <= '1';
else --if x = 0 and y = 0;
Cout <= '0';
end if;
else --if x not equal to y;
S <= '1';
Cout <= '0';
end if;
else --if Cin = 1 then;
if x = y then
S <= '1';
if (x= '1' and y = '1') then
Cout <= '1';
else --if x = 0 and y = 0;
Cout <= '0';
end if;
else --if x not equal to y;
S <= '0';
Cout <= '1';
end if;
end if;
else -- if we're subtracting bits (op = 1);
if Cin = '0' then
if x = y then
Cout <= '0';
S <= '0';
elsif (x ='1' and y = '0') then
Cout <= '0';
S <= '1';
else --if x not equal to y;
S <= '1';
Cout <= '1';
end if;
else --if Cin = 1 then;
if x = y then
Cout <= '1';
S <= '1';
elsif (x ='1' and y = '0') then
Cout <= '0';
S <= '0';
else --if x not equal to y;
S <= '0';
Cout <= '1';
end if;
end if;
end if;
end PROCESS;
end FA1Bit_arch;
Now I use this component in my 4 bit adder/subtractor in this code:
library IEEE;
use IEEE.std_logic_1164.all;
entity FA4Bit is
port (
X : in STD_LOGIC_VECTOR(3 downto 0);
Y : in STD_LOGIC_VECTOR(3 downto 0);
C0: in STD_LOGIC;
S : out STD_LOGIC_VECTOR(3 downto 0);
C4: out STD_LOGIC;
OP1: in STD_LOGIC_VECTOR(3 DOWNTO 0));
end FA4Bit;
architecture FA4Bit_arch of FA4Bit is
component FA1bit
port ( X: in STD_LOGIC; Y: in STD_LOGIC; CIN : in STD_LOGIC;
SI : out STD_LOGIC; COUT: out STD_LOGIC;
OPA : in STD_LOGIC);
end component;
signal C : std_logic_vector(1 to 3);
begin
U1: FA1bit port map (X=>X(0), Y=>Y(0), CIN=> C0, SI=>S(0), COUT=>C(1), OPA => OP1(0));
U2: FA1bit port map (X=>X(1), Y=>Y(1), CIN=> C(1), SI=>S(1), COUT=>C(2), OPA => OP1(1));
U3: FA1bit port map (X=>X(2), Y=>Y(2), CIN=> C(2), SI=>S(2), COUT=>C(3), OPA => OP1(2));
U4: FA1bit port map (X=>X(3), Y=>Y(3), CIN=> C(3), SI=>S(3), COUT=>C4, OPA => OP1(3));
end FA4Bit_arch;
Everything compiles perfectly same goes for the following testbench.
library ieee;
use ieee.std_logic_1164.all;
entity FA4Bit_tb is
end ;
architecture arch of FA4Bit_tb is
component FA4Bit
port ( X1 : in std_logic_vector(3 downto 0);
Y : in std_logic_vector(3 downto 0);
C0 : in std_logic;
S : out std_logic_vector(3 downto 0);
C4 : out std_logic;
OP1: in std_logic_vector(3 downto 0));
end component;
signal X : std_logic_vector(3 downto 0) := "0000";
signal Y : std_logic_vector(3 downto 0) := "0000";
signal C0 : std_logic := '0';
signal opa: std_logic_vector(3 downto 0) := (others=>'0');
signal S : std_logic_vector(3 downto 0);
signal C4 : std_logic;
begin
UUT : FA4Bit
port map (X1 => X, Y => Y, C0 => C0, S => S, C4 => C4, OP1=> opa);
X <= not X after 5 ns;
Y <= not Y after 7 ns;
opa <= not opa after 9 ns;
end arch;
However, I'm receiving a FATAL ERROR in the loading design.
# ** Fatal: (vsim-3817) Port "X" of entity "fa4bit" is not in the component being instantiated.
# Time: 0 ns Iteration: 0 Instance: /fa4bit_tb/UUT File: C:/Users/Omar/Desktop/320 PROJECT 3ANJAD HAL MARRA/FA4Bit.vhd Line: 5
# FATAL ERROR while loading design
# Error loading design
This is one reason why I hate component instantiations. In your component instantiation, the port is called X1, not X. Renaming to X should fix this issue. Then you have a couple of similar ones to fix (OP and S on FA1bit).
If you use entity instantiations, then a lot of problems like this go away.

Carry/Borrow in VHDL ALU

I am making a generic N-bit ALU in VHDL. I am having trouble assigning the value for the carry for addition, or borrow for subtraction. I have tried the following:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity alu is
generic(n: integer :=1); --Default to 1
port (
a : in std_logic_vector(n-1 downto 0);
b : in std_logic_vector(n-1 downto 0);
op : in std_logic_vector(1 downto 0);
output : out std_logic_vector(n-1 downto 0);
carryborrow: out std_logic
);
end alu;
architecture Behavioral of alu is
signal result: std_logic_vector(n downto 0);
begin
process( a, b, op )
begin
case op is
when "00" =>
result(n) <= '0';
result(n-1 downto 0) <= a and b; --and gate
output <= result(n-1 downto 0);
carryborrow <= '0';
when "01" =>
result(n) <= '0';
result(n-1 downto 0) <= a or b; --or gate
output <= result(n-1 downto 0);
carryborrow <= '0';
when "10" =>
result(n) <= '0';
result(n-1 downto 0) <= std_logic_vector(signed(a) + signed(b)); --addition
output <= result(n-1 downto 0);
carryborrow <= result(n);
when "11" =>
result(n) <= '0';
result(n-1 downto 0) <= std_logic_vector(signed(a) - signed(b)); --subtraction
output <= result(n-1 downto 0);
carryborrow <= result(n);
when others =>
NULL;
end case;
end process;
end Behavioral;
This seems to set the carryborrow bit to always be 0. How can I assign it to what it should be without type errors?
There are bugs in your code:
i) You have not taken into account the fact that signals are not updated immediately. Consequently, the following lines will not do as I think you are expecting:
result(n) <= '0';
result(n-1 downto 0) <= a and b; --and gate
output <= result(n-1 downto 0);
Instead, you need to take the lines driving output and carryborrow outside the combinational process, as you can see below.
ii) Assuming you wish this code to be synthesisable, simply putting NULL in your always branch will result in latches being inferred. You need to drive result in the others branch, too.
So, making an assumption about how your carry output is to behave with the and and or operations, this is how I would have written your code:
architecture Behavioral of alu is
signal result: std_logic_vector(n downto 0);
begin
process( a, b, op )
begin
case op is
when "00" =>
result <= '0' & (a and b); --and gate
when "01" =>
result <= '0' & (a or b); --or gate
when "10" =>
result <= std_logic_vector(resize(signed(a), n+1) + resize(signed(b), n+1)); --addition
when "11" =>
result <= std_logic_vector(resize(signed(a), n+1) - resize(signed(b), n+1)); --subtraction
when others =>
result <= (others => 'X');
end case;
end process;
output <= result(n-1 downto 0);
carryborrow <= result(n);
end Behavioral;
I normally do this:
result <= std_logic_vector(signed(a(n-1) & a) + signed(b(n-1) & b));
result <= std_logic_vector(signed(a(n-1) & a) - signed(b(n-1) & b));
Sign extend and then do the operation to take care of overflow, when the result is one extra bit long.
Hmm, consider this in a 4 bit environment, say a="0101" and b="1001". Adding them shall give the output="1110", with NO carry.
However, sign extending with resize(signed(a), n+1) and resize(signed(b), n+1) will set a="00101" and b="11001" and hence result="11110" and carryborrow='1', which is wrong!
By sign extending vectors a and b, the numeral range has increased to 5 bits, and thus result needs to be 6 bits to be able to hold carry, and we're back to square one.
Vectors a and b should only be zero extended, that is '0' & a and '0' & b before adding them to result, and then carryborrow, as MSB(Most Significant Bit) of result, will get the correct value.

Type of expression is ambiguous - "st_ulogic" or "bit" are two possible matches VHDL

Using the gezel software, I created a vhdl file from this fdl code:
dp delay_collatz_rev (
in start : ns(1) ; in x0 : ns(16) ;
out done : ns(1) ; out delay : ns(16))
{ reg r : ns(32) ;
reg d : ns(16) ;
reg stop : ns(1) ;
sig x : ns(32) ;
sig d0, dd : ns(16) ;
always { x = start ? x0 : r ;
r = x[0] ? x + (x >> 1) + 1 : x >> 1 ;
done = ( x == 1 ) | ( stop & ~start ) ;
stop = done ;
dd = 1 + x[0] ;
d0 = start ? 0 : d ;
d = done ? d0 : d0 + dd ;
delay = d ;
} }
But when I try to compile this code on the Quartus software, I am getting this error on line 124, which is "sig_10 <= unsigned('1') + unsigned(x(0));"
Error (10647): VHDL type inferencing error at delay_collatz_rev.vhd(124): type of expression is ambiguous - "std_ulogic" or "bit" are two possible matches
library ieee;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
library work;
--use work.std_logic_arithext.all;
-- datapath entity
entity delay_collatz_rev is
port(
start : in std_logic;
x0 : in std_logic_vector(15 downto 0);
done : out std_logic;
delay : out std_logic_vector(15 downto 0);
RST : in std_logic;
CLK : in std_logic
);
end delay_collatz_rev;
architecture RTL of delay_collatz_rev is
-- signal declaration
signal r : std_logic_vector(31 downto 0);
signal r_wire : std_logic_vector(31 downto 0);
signal d : std_logic_vector(15 downto 0);
signal d_wire : std_logic_vector(15 downto 0);
signal stop : std_logic;
signal stop_wire : std_logic;
signal x : std_logic_vector(31 downto 0);
signal d0 : std_logic_vector(15 downto 0);
signal dd : std_logic_vector(15 downto 0);
signal sig_0 : std_logic_vector(31 downto 0);
signal sig_1 : std_logic_vector(31 downto 0);
signal sig_2 : std_logic_vector(31 downto 0);
signal sig_3 : std_logic_vector(31 downto 0);
signal sig_4 : std_logic_vector(31 downto 0);
signal sig_5 : std_logic_vector(31 downto 0);
signal sig_6 : std_logic;
signal sig_7 : std_logic;
signal sig_8 : std_logic;
signal sig_9 : std_logic;
signal sig_10 : std_logic;
signal sig_11 : std_logic_vector(15 downto 0);
signal sig_12 : std_logic_vector(15 downto 0);
signal sig_13 : std_logic_vector(15 downto 0);
signal done_int : std_logic;
signal delay_int : std_logic_vector(15 downto 0);
-- state register & states
begin
-- register updates
dpREG: process (CLK, RST)
begin
if (RST = '1') then
r <= (others => '0');
d <= (others => '0');
stop <= '0';
elsif CLK' event and CLK = '1' then
r <= r_wire;
d <= d_wire;
stop <= stop_wire;
end if;
end process dpREG;
-- combinational logics
dpCMB: process (r, d, stop, x, d0, dd, sig_0, sig_1, sig_2, sig_3
, sig_4, sig_5, sig_6, sig_7, sig_8, sig_9, sig_10, sig_11, sig_12, sig_13
, done_int, delay_int, start, x0)
begin
r_wire <= r;
d_wire <= d;
stop_wire <= stop;
x <= (others => '0');
d0 <= (others => '0');
dd <= (others => '0');
sig_0 <= (others => '0');
sig_1 <= (others => '0');
sig_2 <= (others => '0');
sig_3 <= (others => '0');
sig_4 <= (others => '0');
sig_5 <= (others => '0');
sig_6 <= '0';
sig_7 <= '0';
sig_8 <= '0';
sig_9 <= '0';
sig_10 <= '0';
sig_11 <= (others => '0');
sig_12 <= (others => '0');
sig_13 <= (others => '0');
done_int <= '0';
delay_int <= (others => '0');
done <= '0';
delay <= (others => '0');
if (start = '1') then
sig_0 <= std_logic_vector(resize(unsigned(x0), 32));
else
sig_0 <= r;
end if;
x <= sig_0;
sig_1 <= std_logic_vector(shift_right(unsigned(x), 1));
sig_2 <= std_logic_vector(unsigned(x) + unsigned(sig_1));
sig_3 <= std_logic_vector(unsigned(sig_2) + unsigned(std_logic_vector(to_unsigned(1, 32))));
sig_4 <= std_logic_vector(shift_right(unsigned(x), 1));
if (x(0) = '1') then
sig_5 <= sig_3;
else
sig_5 <= sig_4;
end if;
if (unsigned(x) = 1) then
sig_6 <= '1';
else
sig_6 <= '0';
end if;
sig_7 <= not start;
sig_8 <= stop and sig_7;
sig_9 <= sig_6 or sig_8;
done <= done_int;
sig_10 <= unsigned('1') + unsigned(x(0));
--sig_10 <= std_logic_unsigned(unsigned(unsigned('1')+unsigned(x(0))));
dd <= logic_zero_ext(sig_10, 16);
if (start = '1') then
sig_11 <= std_logic_vector(to_unsigned(0, 16));
else
sig_11 <= d;
end if;
d0 <= sig_11;
sig_12 <= std_logic_vector(unsigned(d0) + unsigned(dd));
if (done_int = '1') then
sig_13 <= d0;
else
sig_13 <= sig_12;
end if;
delay <= delay_int;
done_int <= sig_9;
delay_int <= d;
r_wire <= sig_5;
stop_wire <= done_int;
d_wire <= sig_13;
end process dpCMB;
end RTL;
I am pretty new with Gezel and VHDL, what am I missing?
The Gezel to VHDL generator does not create valid VHDL code, since the used packages does not support addition with target in std_logic as in sig_10 <= unsigned('1') + unsigned(x(0));.
I guess that the problem is due to selection of a single bit in x as x[0], and maybe you can work around this if creating a temporary one bit for x[0], and the assign this with x[0] before making the addition:
sig temp_x_0 : ns(1) ;
...
temp_x_0 = x[0];
dd = 1 + temp_x_0;
But I must admit that I am not that much into Gezel.

VHDL code error

I have this code for a Serial Adder in VHDL. I am trying to get it to work, but I keep on getting an error that says:
Errors found in VHDL File -
Line : 17, Error : Index constraint expected in the subtype indication
This error is referring to the line:
signal state, next_state : integer range 0 to 3;
I'm not sure why this is happening. Any help? Please find the full code below.
library ieee;
use ieee.std_logic_1164.all;
entity adder is
port(
start : in std_logic;
clk : in std_logic;
a_out : out std_logic_vector(3 downto 0)
);
end adder;
architecture behave of adder is
signal a, b : std_logic_vector(3 downto 0);
signal shift : std_logic;
signal Cin, Cout : std_logic;
signal sum_in : std_logic;
signal state, next_state : integer range 0 to 3;
begin
sum_in <= a(0) xor b(0) xor Cin;
Cout <= (Cin and a(0))or(Cin and b(0))or(a(0) and b(0));
a_out <= a;
process(state, start)
begin
case state is
when 0 =>
if start = '1' then shift <= '1'; next_state <= 1;
else shift <= '0'; next_state <= 2; end if;
when 1 => shift <= '1'; next_state <= 2;
when 2 => shift <= '1'; next_state <= 3;
when 3 => shift <= '1'; next_state <= 0;
end case;
end process;
process(clk)
begin
if clk'event and clk = '0' then
state <= next_state;
if shift = '1' then
a <= sum_in & a(3 downto 1);
b <= b(0) & b(3 downto 1);
Cin <= Cout;
end if;
end if;
end process;
end behave;
Try to replace your line in which you are getting error by:
signal state, next_state : integer is range 0 to 3;
If you are specifying range then you should use is range instead of range

Resources