This code works except for the add and subtract operations denoted by opcode 010 and 110 respectively. When I try to add the numbers the result looks as though a and b are being XOR'd and subtracting does A XNOR B. I have no idea why this is happening pls help. Also I am not allowed to use arithmetic plus or minus in my code the point of it is to add logically.
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_arith.ALL;
USE ieee.std_logic_unsigned.ALL;
USE ieee.numeric_std.ALL;
ENTITY Lab3ALU IS
PORT(
opcode :IN STD_LOGIC_VECTOR(2 DOWNTO 0);--INPUT
a :IN STD_LOGIC_VECTOR(31 DOWNTO 0);--INPUT
b :IN STD_LOGIC_VECTOR(31 DOWNTO 0);--INPUT
Cout :OUT STD_LOGIC;
Zero :OUT STD_LOGIC;
q :OUT STD_LOGIC_VECTOR(31 DOWNTO 0));--OUTPUT
END Lab3ALU;
ARCHITECTURE description of Lab3ALU IS
SIGNAL Reg1, Reg2, Reg3, Result : STD_LOGIC_VECTOR(31 DOWNTO 0);
SIGNAL Cin, Sum, Carry : STD_LOGIC;
BEGIN
-- Update the register output on the clock's rising edge
process (a,b, opcode)
begin
Cin <= opcode(2);
Reg1 <= a;--temporarirly store A in Reg1 local variable
Reg2 <= b;--temporarily store B in Reg2 local variable
Reg3 <= NOT b;
case opcode is
When "000" => Result <= Reg1 AND Reg2;--AND
When "001" => Result <= Reg1 OR Reg2;--OR
When "010" =>
addloop: for i in 0 to 31 loop
Result(i) <= ((Reg1(i) XOR Reg2(i)) XOR Cin);
Cin <= (((Reg1(i) XOR Reg2(i))AND Cin)OR (Reg1(i) AND Reg2(i)));
end loop addloop;
When "110" =>
subloop: for i in 0 to 31 loop
Result(i) <= ((Reg1(i) XOR Reg3(i)) XOR Cin);
Cin <= (((Reg1(i) XOR Reg3(i))AND Cin)OR (Reg1(i) AND Reg3(i)));
end loop subloop;
When "100" => Result(31 downto 1) <= reg1(30 downto 0);
Result(0) <= '0';
Cin <= '0';
When "101" => Result(30 downto 0) <= reg1(31 downto 1);
Result(31) <= '0';
Cin <= '0';
When others => Result <= "00000000000000000000000000000000";
end case;
if Result = "00000000000000000000000000000000" then
Zero <= '1';
else
Zero <= '0';
end if;
q<= Result;
Cout<= Cin;
end process;
END description;```
Related
I'm working on an ALU using a certain set of functions. I figured that the addition and bitshift portions would be a lot easier if I used an extra bit to store the carry out. I'm trying to concatenate an extra bit to two 8 bit long 'std_logic_vector's. The extra bit would hold the carry out in the addition.
However when I go to run the simulation after some debugging it doesn't look like the lines I used to give s_a and s_b their values are doing anything. If I were to take out the default values they come out empty.
I'm sure the error is something silly, I'm not to familiar with how concatenation works in vhdl, maybe theres a better way of storing the carry out, any help would be appreciated.
CODE:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
entity ALU is
Port (
A : in std_logic_vector(7 downto 0);
B : in std_logic_vector(7 downto 0);
SEL : in std_logic_vector(3 downto 0);
Cin : in std_logic;
Result : out std_logic_vector(7 downto 0);
C : out std_logic;
Z : out std_logic);
end ALU;
architecture Behavioral of ALU is
signal s_result: unsigned(8 downto 0) := "000000000";
signal s_cin: unsigned(8 downto 0) := "000000000";
signal s_a: unsigned(8 downto 0) := "000000000";
signal s_b: unsigned(8 downto 0) := "000000000";
signal s_exempt: std_logic := '0';
begin
s1: process(A, B, SEL, CIN)
begin
s_a <= ('0' & unsigned(A));
s_b <= ('0' & unsigned(B));
s_cin(0) <= Cin;
s_exempt <= '0';
case SEL is
when "0000" =>
s_result <= s_a + s_b;
C <= s_result(8);
when "0001" => --ADDc Add with carry
s_result <= s_a + s_b + s_cin;
C <= s_result(8);
when "0010" => --SUB
if(s_a > s_b) then
s_result <= s_a - s_b;
C <= '0';
else
s_result <= s_b - s_a;
C <= '1';
end if;
when "0011" => --SUBc Subtract with carry
if(s_a > (s_b + s_cin)) then
s_result <= s_a - s_b - s_cin;
C <= '0';
else
s_result <= s_b - s_a - s_cin;
C <= '1';
end if;
when "0100" => --CMP Compare both values
if(s_a > s_b) then
C <= '0';
Z <= '0';
elsif(s_a = s_b) then
Z <= '1';
C <= '0';
else
C <= '1';
Z <= '1';
end if;
s_exempt <= '1';
when "0101" => --AND
s_result <= s_a AND s_b;
C <= '0';
when "0110" => Z<= '1'; --OR
s_result <= s_a OR s_b;
C <= '0';
when "0111" => --EXOR
s_result <= s_a XOR s_b;
C <= '0';
when "1000" => --TEST, comparator, flag change ONLY
if((s_a AND s_b) = "000000000")
then
C <= '0';
Z <= '1';
else
C <= '0';
Z <= '0';
end if;
when "1001" => --LSL Left shift
s_result <= s_a sll 1;
C <= s_result(8);
when "1010" => --LSR RIght shift
C <= s_a(0);
s_result <= s_a srl 1;
when "1011" => Z<= '1'; --ROL Rotate Left
s_result <= s_a sll 1;
C <= s_result(8);
s_result(0) <= s_result(8);
when "1100" => Z<= '1'; --ROR Rotate Right
C <= s_a(0);
s_result <= s_a srl 1;
s_result(0) <= s_a(0);
when "1101" => --ASR Arithemetic Roation
C <= s_a(0);
s_result <= s_a srl 1;
s_result(8) <= s_a(7);
when "1110" => --MOV Moves data into result
s_result <= s_b;
s_exempt <= '1';
when others =>
s_result <= "000000000";
s_exempt <= '1';
Z <= '0';
C <= '0';
end case;
if(s_exempt = '0') -- Checks Result for 0 if hasn't been found
then
if(s_result(7 downto 0) = "00000000")
then
Z <= '1';
else Z <= '0';
end if;
end if;
Result <= std_logic_vector(s_result(7 downto 0));
end process;
end Behavioral;
TESTBENCH:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
entity simulation is
end simulation;
architecture Behavioral of simulation is
COMPONENT ALU
Port (
A : in std_logic_vector(7 downto 0);
B : in std_logic_vector(7 downto 0);
SEL : in std_logic_vector(3 downto 0);
Cin : in std_logic;
Result : out std_logic_vector(7 downto 0);
C : out std_logic;
Z : out std_logic
);
END COMPONENT;
signal A : std_logic_vector(7 downto 0) := "00000000";
signal B : std_logic_vector(7 downto 0) := "00000000";
signal SEL : std_logic_vector(3 downto 0) := "0000";
signal Cin : std_logic;
signal Result : std_logic_vector(7 downto 0) := "00000000";
signal C: std_logic := '0';
signal Z: std_logic := '0';
begin
uut: ALU PORT MAP (
A => A,
B => B,
SEL => SEL,
Cin => Cin,
Result => Result,
C => C,
Z => Z
);
stim_proc: process
begin
A <= "00000001";
B <= "00100001";
SEL <= "0000";
Cin <= '1';
wait for 10ns;
wait;
end process;
end Behavioral;
Any signal assigned in a process in VHDL is not updated until the process suspends. So, for example, the value of s_result from this line:
s_result <= s_a + s_b + s_cin;
will not be updated by the time that this line is executed:
C <= s_result(8);
You need to find out about delta delays, then once you have, you will need to rewrite your code.
VHDL is a hardware description language. You are designing hardware, not writing software. For example, your initialisation of all your signals will not be implemented in hardware, meaning that your simulation may well behave differently to your hardware:
signal s_result: unsigned(8 downto 0) := "000000000";
signal s_cin: unsigned(8 downto 0) := "000000000";
signal s_a: unsigned(8 downto 0) := "000000000";
signal s_b: unsigned(8 downto 0) := "000000000";
signal s_exempt: std_logic := '0';
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.
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
I want to make a 4-Bit Adder and Subtractor with VHDL
I have created 1-Bit Full-Adder , XOR Gate ( for Subtract ) and a 4-Bit Adder as shown below :
Full-Adder :
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY FullAdder_1_Bit IS
PORT(
X, Y : IN STD_LOGIC;
CIn : IN STD_LOGIC;
Sum : OUT STD_LOGIC;
COut : OUT STD_LOGIC
);
END FullAdder_1_Bit;
ARCHITECTURE Behavier OF FullAdder_1_Bit IS
BEGIN
Sum <= X XOR Y XOR CIn;
COut <= (X AND Y) OR (X AND CIn) OR (Y AND CIn);
END Behavier;
XOR Gate :
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY XORGate IS
PORT(
X1, X2 : IN STD_LOGIC;
Y : OUT STD_LOGIC
);
END XORGate;
ARCHITECTURE Declare OF XORGate IS
BEGIN
Y <= X1 XOR X2;
END Declare;
4-Bit Adder :
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY Adder_4_Bit IS
PORT(
A, B : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
Mode : IN STD_LOGIC;
Sum : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
COut : OUT STD_LOGIC
);
END Adder_4_Bit;
ARCHITECTURE Structure OF Adder_4_Bit IS
COMPONENT FullAdder_1_Bit IS
PORT(
X, Y : IN STD_LOGIC;
CIn : IN STD_LOGIC;
Sum : OUT STD_LOGIC;
COut : OUT STD_LOGIC
);
END COMPONENT;
COMPONENT XORGate IS
PORT(
X1, X2 : IN STD_LOGIC;
Y : OUT STD_LOGIC
);
END COMPONENT;
SIGNAL COut_Temp : STD_LOGIC_VECTOR(2 DOWNTO 0);
SIGNAL XB : STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
B_0 : XORGate PORT MAP(Mode, B(0), XB(0));
B_1 : XORGate PORT MAP(Mode, B(1), XB(1));
B_2 : XORGate PORT MAP(Mode, B(2), XB(2));
B_3 : XORGate PORT MAP(Mode, B(3), XB(3));
SUM_0 : FullAdder_1_Bit
PORT MAP (A(0), XB(0), Mode, Sum(0), COut_Temp(0));
SUM_1 : FullAdder_1_Bit
PORT MAP (A(1), XB(1), COut_Temp(0), Sum(1), COut_Temp(1));
SUM_2 : FullAdder_1_Bit
PORT MAP (A(2), XB(2), COut_Temp(1), Sum(2), COut_Temp(2));
SUM_3 : FullAdder_1_Bit
PORT MAP (A(3), XB(3), COut_Temp(2), Sum(3), COut);
END;
and in my Main Codes , i have used those ( like Test-Bench ! ) :
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.ALL;
ENTITY Add_AND_Sub IS
END Add_AND_Sub;
ARCHITECTURE Declare OF Add_AND_Sub IS
COMPONENT Adder_4_Bit IS
PORT(
A, B : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
Mode : IN STD_LOGIC;
Sum : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
COut : OUT STD_LOGIC
);
END COMPONENT;
SIGNAL A, B : STD_LOGIC_VECTOR(4 DOWNTO 0);
SIGNAL Mode : STD_LOGIC;
SIGNAL As, Bs, E, AVF : STD_LOGIC;
SIGNAL XA, XB, Sum : STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
Add : Adder_4_Bit
PORT MAP(XA, XB, Mode, Sum, E);
PROCESS(A, B, Mode)
BEGIN
As <= A(4);
Bs <= B(4);
XA <= A(3 DOWNTO 0);
XB <= B(3 DOWNTO 0);
CASE Mode IS
WHEN '0' =>
IF ((As XOR Bs) = '1') THEN
Mode <= '1';
XA <= Sum;
AVF <= '0';
IF (E = '1') THEN
IF (XA = "0000") THEN
As <= '0';
END IF;
ELSE
XA <= (NOT XA) + "0001";
As <= NOT As;
END IF;
ELSE
XA <= Sum;
END IF;
WHEN '1' =>
IF ((As XOR Bs) = '1') THEN
Mode <= '0';
XA <= Sum;
AVF <= E;
ELSE
AVF <= '0';
XA <= Sum;
IF (E = '1') THEN
IF (XA = "0000") THEN
As <= '0';
END IF;
ELSE
XA <= (NOT XA) + "0001";
As <= NOT As;
END IF;
END IF;
WHEN Others =>
--
END CASE;
END PROCESS;
END Declare;
The main scenario is to Model this algorithm :
but now i want to have output in XA and As
I Should use registers shown in algorithm such as "E" and "AVF"
there is one question :
we know port maps are continuously connected , so when i change Mode Value , Result ( Sum ) must change , is it True ?!
I have tried this code but i cant get output in XA , and there is no True result for sum values , i know there is some problem in my main code ( Process ) , but i cant find problems
please check that codes and tell me what goes wrong !
Edit :
Im using ModelSim and its simulation for testing my code , first i force values of "A", "B" and "Mode" then run to get result and wave
thanks ...
Your testbench add_and_sub makes no assignments to it's a and b, they're default values are all 'U's.
What do you expect when your inputs to adder_4_bit are undefined?
Look at the not_table, or_table, and_table and xor_table in the body of the std_logic_1164 package.
Also to be a Minimal, Complete, and Verifiable example your readers need both expected and actual results.
If you're actually simulating the testbench I'd expect it consume no simulation time and after some number of delta cycles during initialization show sum and e chock full of 'U's.
I haven't personally modified your testbench to determine if your adder_4_bit works, but if you provide it with valid stimulus you can debug it. It can be helpful to consume simulation time and use different input values.
Adding a monitor process to add_and_sub:
MONITOR:
process (sum)
function to_string(inp: std_logic_vector) return string is
variable image_str: string (1 to inp'length);
alias input_str: std_logic_vector (1 to inp'length) is inp;
begin
for i in input_str'range loop
image_str(i) := character'VALUE(std_ulogic'IMAGE(input_str(i)));
end loop;
-- report "image_str = " & image_str;
return image_str;
end;
begin
report "sum = " & to_string(sum);
end process;
gives:
fourbitadder.vhdl:174:10:#0ms:(report note): sum = uuuu
one event on sum.
Add a process to cause events on a and 'b`:
STIMULUS:
process
begin
a <= "00000" after 10 ns;
b <= "00000" after 10 ns;
wait for 20 ns;
wait;
end process;
and we get:
(clickable)
We find we get an event on a and b but sum didn't change.
And the reason why is apparent in the case statement in the process. The default value of mode is 'U', and the case statement has choices for 0, 1 and:
when others =>
--
end case;
And the others choice results in no new value in mode.
Why nothing works can be discovered by reading the source of the body for package std_logic_1164, the xor_table, and_table, or_table. With mode = 'U' all your combinatorial outputs will be 'U'.
And to fix this you can assign a default value to mode where it is declared in the testbench:
signal mode : std_logic := '0';
With mode defined as a valid choice resulting in some action we note xa is now never defined causing the same issue:
(clickable)
And this is a problem in the process:
process(a, b, mode)
begin
as <= a(4);
bs <= b(4);
xa <= a(3 downto 0);
xb <= b(3 downto 0);
case mode is
when '0' =>
if ((as xor bs) = '1') then
mode <= '1';
xa <= sum;
avf <= '0';
if (e = '1') then
if (xa = "0000") then
as <= '0';
end if;
else
xa <= std_logic_vector(unsigned(not xa) + unsigned'("0001"));
as <= not as;
end if;
else
xa <= sum;
end if;
when '1' =>
if ((as xor bs) = '1') then
mode <= '0';
xa <= sum;
avf <= e;
else
avf <= '0';
xa <= sum;
if (e = '1') then
if (xa = "0000") then
as <= '0';
end if;
else
xa <= std_logic_vector(unsigned(not xa) + unsigned'("0001"));
as <= not as;
end if;
end if;
when others =>
--
end case;
Notice there are three places where xa is assigned, with no simulation time between them. There's only one projected output waveform value for any simulation time. A later assignment in the same process will result in the later value being assigned, in this case sum, which is all 'U's.
So how do you solve this conundrum? There are two possibilities. First you could not try and do algorithmic stimulus generation, assigning input to add explicitly with wait statements between successive assignments of different values. You can also insert delays between successive assignments to the same signal in the existing process, which requires a substantial re-write.
On a positive note the adder_4_bit and full_adder_1bit look like they should work. The problem appears to be all in the testbench.
I made some changes
I made a ALU unit as :
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;
USE ieee.std_logic_unsigned.ALL;
ENTITY ALU IS
PORT(
--Clk : IN STD_LOGIC;
A, B : IN STD_LOGIC_VECTOR(4 DOWNTO 0);
Sel : IN STD_LOGIC;
AOut : OUT STD_LOGIC_VECTOR(4 DOWNTO 0);
AsO : OUT STD_LOGIC
);
END ALU;
ARCHITECTURE Declare OF ALU IS
COMPONENT Adder_4_Bit IS
PORT(
A, B : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
Mode : IN STD_LOGIC;
Sum : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
COut : OUT STD_LOGIC
);
END COMPONENT;
SIGNAL As, Bs, E, AVF : STD_LOGIC;
SIGNAL XA, XB, Sum : STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL Mode : STD_LOGIC;
BEGIN
Add : Adder_4_Bit
PORT MAP(XA, XB, Mode, Sum, E);
PROCESS
BEGIN
As <= A(4);
Bs <= B(4);
XA <= A(3 DOWNTO 0);
XB <= B(3 DOWNTO 0);
CASE Sel IS
WHEN '0' =>
IF ((As XOR Bs) = '1') THEN
Mode <= '1';
AVF <= '0';
WAIT ON Sum;
IF (E = '1') THEN
IF (Sum = "0000") THEN
As <= '0';
END IF;
ELSE
Sum <= (NOT Sum) + "0001";
As <= NOT As;
END IF;
ELSE
Mode <= '0';
WAIT ON Sum;
END IF;
AOut <= Sum;
AsO <= As;
WHEN '1' =>
IF ((As XOR Bs) = '1') THEN
Mode <= '0';
WAIT ON Sum;
AVF <= E;
ELSE
Mode <= '1';
WAIT ON Sum;
AVF <= '0';
IF (E = '1') THEN
IF (Sum = "0000") THEN
As <= '0';
END IF;
ELSE
Sum <= (NOT Sum) + "0001";
As <= NOT As;
END IF;
END IF;
AOut <= Sum;
AsO <= As;
WHEN Others =>
--
END CASE;
END PROCESS;
END Declare;
and A Test Bench like this :
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;
USE ieee.std_logic_unsigned.ALL;
ENTITY ALU_Test_Bench IS
END ALU_Test_Bench;
ARCHITECTURE Declare OF ALU_Test_Bench IS
COMPONENT ALU IS
PORT(
--Clk : IN STD_LOGIC;
A, B : IN STD_LOGIC_VECTOR(4 DOWNTO 0);
Sel : IN STD_LOGIC;
AOut : OUT STD_LOGIC_VECTOR(4 DOWNTO 0);
AsO : OUT STD_LOGIC
);
END COMPONENT;
SIGNAL Xs, S : STD_LOGIC;
SIGNAL X, Y, O : STD_LOGIC_VECTOR(4 DOWNTO 0);
BEGIN
ALU_PM : ALU PORT MAP(X, Y, S, O, Xs);
Main_Process : PROCESS
BEGIN
WAIT FOR 100 ns;
X <= "00010";
Y <= "11011";
S <= '0';
WAIT FOR 30 ns;
S <= '1';
WAIT FOR 30 ns;
WAIT FOR 100 ns;
X <= "01110";
Y <= "10011";
S <= '0';
WAIT FOR 30 ns;
S <= '1';
WAIT FOR 30 ns;
WAIT FOR 100 ns;
X <= "10011";
Y <= "11111";
S <= '0';
WAIT FOR 30 ns;
S <= '1';
WAIT FOR 30 ns;
END PROCESS;
END Declare;
As i say , i want to model the algorithm i posted in first post
there is some problem ...
for example when i simulate and run test bench , there is no output value in O and Xs !
I know the problem is in ALU and Test Bench
I changed ALU many times and tested many ways but all times some things goes wrong !
If you want to code that algorithm , which units you will create or at all what will you create ?! and how will you code that ?!
thanks for your help ...
I have to make a 8-bit ALU which is connected to a shift register. I think this is the code for a ALU but what is the best way to connect it too 8-bit shift register with a reset and clock? Im not sure how to use an internal signal to connect these two components, should they both have separate
library IEEE;
use IEEE.STD_LOGIC_1164.ALL; -- Calling libary's to be used
use IEEE.NUMERIC_STD.ALL;
entity lu is
port( Clk : in std_logic; -- The clock signal
A : in signed(7 downto 0); -- The A Input
B : in signed(7 downto 0); -- The B Input
OPCODE : in unsigned(2 downto 0); -- Op code entered into ALU
RES :in std_logic; -- The reset pin
Q : out signed(7 downto 0) -- The Output of LU
);
end lu; -- End Entity
architecture Behavioral of lu is
signal Reg1,Reg2,Reg3 : signed(7 downto 0) := (others => '0'); --The signal declaration
begin
Reg1 <= A; -- Linking Reg1 Signal to Input A
Reg2 <= B; -- Linking Reg2 Signal to Input B
Q <= Reg3; -- Linking Output Q to Signal Reg3
process(Clk)
begin
if(rising_edge(Clk)) then -- Calculate at the positive edge of clk
case OPCODE is
when "000" =>
Reg3 <= Reg1 + Reg2; -- Output is = to addition
when "001" =>
Reg3 <= Reg1 - Reg2; -- Output is = to subtraction
when "010" =>
Reg3 <= not Reg1; -- Output is = to NOT gate
when "011" =>
Reg3 <= Reg1 nand Reg2; -- Output is = to NAND gate
when "100" =>
Reg3 <= Reg1 nor Reg2; -- Output is = to NOR gate
when "101" =>
Reg3 <= Reg1 and Reg2; -- Output is = to AND gate
when "110" =>
Reg3 <= Reg1 or Reg2; -- Output is = to OR gate
when "111" =>
Reg3 <= Reg1 xor Reg2; -- Output is = to XOR gate
when others => -- If anyother Input Outputs nothing
NULL;
end case;
end if;
end process;
end Behavioral;
Assuming you mean to add logical operations to the ALU code provided, you need to make two changes:
1) In the ports list, increase the width of your opcode signal so that you can add new opcode values:
OPCODE: in unsigned(3 downto 0); -- Operation selection for the ALU
2) In your case statement, simply add the new conditions and the code to perform the logical operations:
case OPCODE is
...
when "1000" =>
Reg3 <= Reg1 srl to_integer(Reg2); -- Reg3 <= Reg1 shifted Reg2 bits to the right
when "1001" =>
Reg3 <= Reg1 sll to_integer(Reg2); -- Reg3 <= Reg1 shifted Reg2 bits to the left
when "1010" =>
Reg3 <= Reg1 ror to_integer(Reg2); -- Reg3 <= Reg1 rotated Reg2 bits to the right
when "1011" =>
Reg3 <= Reg1 rol to_integer(Reg2); -- Reg3 <= Reg1 rotated Reg2 bits to the right
when others =>
Reg3 <= (others => '0');
end case;