4-Bit ALU to BCD display - vhdl

I have a mega-assignment and the last part(for extra marks) is to display the output of a designed ALU using two 7-seg displays. These should display the result of the operations performed in the ALU. I am performing logical and arithmetic operations and I can only use the lower display for logical operations. For the arithmetic operations I need to use BCD code to display the answers. My ALU is working fine, I am finding it hard to do the decoder part. I don't even know if I am on the right track. Help!
CODE
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_unsigned.ALL;
entity codeALU is
Port ( A : in STD_LOGIC_VECTOR (3 downto 0);
B : in STD_LOGIC_VECTOR (3 downto 0);
Cin : in STD_LOGIC;
S0 : in STD_LOGIC;
S1 : in STD_LOGIC;
M : in STD_LOGIC;
Cout : out STD_LOGIC;
Z : out STD_LOGIC;
F : out STD_LOGIC_VECTOR (3 downto 0);
bcd1 : out STD_LOGIC_VECTOR (6 downto 0);
bcd2 : out STD_LOGIC_VECTOR (6 downto 0));
end codeALU;
architecture Behavioral of codeALU is
begin
process(A, B, M, Cin, S1, S0)
variable temp : STD_LOGIC_VECTOR (4 downto 0);
variable Fx : STD_LOGIC_VECTOR (3 downto 0);
variable Cx, Zx : STD_LOGIC;
variable Sel : STD_LOGIC_VECTOR (2 downto 0);
begin
Sel := S1 & S0 & Cin;
Cx := '0';
Zx := '0';
if M = '0' then
Z <= '0';
case Sel(2 downto 1) is
when "00" =>
Fx := A AND B;
Zx := '0';
when "01" =>
Fx := A XOR B;
when "10" =>
Fx := A OR B;
when "11" =>
Fx := A XNOR B;
when others =>
null;
end case;
case Fx is
when "0000"=> bcd1 <="0000001"; -- '0'
when "0001"=> bcd1 <="1001111"; -- '1'
when "0010"=> bcd1 <="0010010"; -- '2'
when "0011"=> bcd1 <="0000110"; -- '3'
when "0100"=> bcd1 <="1001100"; -- '4'
when "0101"=> bcd1 <="0100100"; -- '5'
when "0110"=> bcd1 <="0100000"; -- '6'
when "0111"=> bcd1 <="0001111"; -- '7'
when "1000"=> bcd1 <="0000000"; -- '8'
when "1001"=> bcd1 <="0000100"; -- '9'
when others=> bcd1 <="1111111";
end case;
else
case Sel is
when "000" =>
temp := (B(3)&B(3 downto 1) + ('0'&A));
Fx := temp(3 downto 0);
Cx := temp(4);
when "001" =>
temp := (A(3)&A(3 downto 1) + ('0'&B));
Fx := temp(3 downto 0);
Cx := temp(4);
when "010" =>
temp := ('0'&A) + ('0'&B);
Fx := temp(3 downto 0);
Cx := temp(4);
when "011" =>
temp := ('0'&A) + ('0'&B) + ('0'&Cin);
Fx := temp(3 downto 0);
Cx := temp(4);
when "100" =>
temp := ('0'&A) + (not B);
Fx := temp(3 downto 0);
Cx := temp(4);
when "101" =>
temp := (not B) + ('0'&A) + 1;
Fx := temp(3 downto 0);
Cx := temp(4);
when "110" =>
temp := ('0'&A) + ('0'&B(3 downto 1));
Fx := temp(3 downto 0);
Cx := temp(4);
when "111" =>
temp := ('0'&B) + ('0'&A(3 downto 1));
Fx := temp(3 downto 0);
Cx := temp(4);
when others =>
null;
end case;
case Fx is
when "0000"=> bcd2 <="0000001"; -- '0'
when "0001"=> bcd2 <="1001111"; -- '1'
when "0010"=> bcd2 <="0010010"; -- '2'
when "0011"=> bcd2 <="0000110"; -- '3'
when "0100"=> bcd2 <="1001100"; -- '4'
when "0101"=> bcd2 <="0100100"; -- '5'
when "0110"=> bcd2 <="0100000"; -- '6'
when "0111"=> bcd2 <="0001111"; -- '7'
when "1000"=> bcd2 <="0000000"; -- '8'
when "1001"=> bcd2 <="0000100"; -- '9'
when others=> bcd2 <="1111111";
end case;
for i in 0 to 3 loop
Zx := Zx or Fx(i);
end loop;
Z <= not Zx;
end if;
F <= Fx;
Cout <= Cx;
end process;
end Behavioral;
Test Bench
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
use ieee.std_logic_arith.all;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--USE ieee.numeric_std.ALL;
ENTITY test4ALU IS
END test4ALU;
ARCHITECTURE behavior OF test4ALU IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT codeALU
PORT(
A : IN std_logic_vector(3 downto 0);
B : IN std_logic_vector(3 downto 0);
Cin : IN std_logic;
S0 : IN std_logic;
S1 : IN std_logic;
M : IN std_logic;
Cout : OUT std_logic;
Z : OUT std_logic;
F : OUT std_logic_vector(3 downto 0);
bcd1 : OUT std_logic_vector(6 downto 0);
bcd2 : OUT std_logic_vector(6 downto 0)
);
END COMPONENT;
--Inputs
signal A : std_logic_vector(3 downto 0) := (others => '0');
signal B : std_logic_vector(3 downto 0) := (others => '0');
signal Cin : std_logic := '0';
signal S0 : std_logic := '0';
signal S1 : std_logic := '0';
signal M : std_logic := '0';
--Outputs
signal Cout : std_logic;
signal Z : std_logic;
signal F : std_logic_vector(3 downto 0) := (others => '0');
signal bcd1 : std_logic_vector(6 downto 0);
signal bcd2 : std_logic_vector(6 downto 0);
-- No clocks detected in port list. Replace <clock> below with
-- appropriate port name
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: codeALU PORT MAP (
A => A,
B => B,
Cin => Cin,
S0 => S0,
S1 => S1,
M => M,
Cout => Cout,
Z => Z,
F => F,
bcd1 => bcd1,
bcd2 => bcd2
);
-- Stimulus process
stim_proc: process
begin
-- hold reset state for 100 ns.
wait for 100 ns;
A <= "1001";
B <= "1111";
M <= '0';
wait for 50 ns;
S1 <= '0';
S0 <= '0';
wait for 50 ns;
S1 <= '0';
S0 <= '1';
wait for 50 ns;
S1 <= '1';
S0 <= '0';
wait for 50 ns;
S1 <= '1';
S0 <= '1';
wait for 50 ns;
M <= '1';
S1 <= '0';
S0 <= '0';
Cin <= '0';
wait for 50 ns;
S1 <= '0';
S0 <= '0';
Cin <= '1';
wait for 50 ns;
S1 <= '0';
S0 <= '1';
Cin <= '0';
wait for 50 ns;
S1 <= '0';
S0 <= '1';
Cin <= '1';
wait for 50 ns;
S1 <= '1';
S0 <= '0';
Cin <= '0';
wait for 50 ns;
S1 <= '1';
S0 <= '0';
Cin <= '1';
wait for 50 ns;
S1 <= '1';
S0 <= '1';
Cin <= '0';
wait for 50 ns;
S1 <= '1';
S0 <= '1';
Cin <= '1';
wait;
end process;
process
begin
for i in 0 to 9 loop
F <= conv_std_logic_vector(i,4);
wait for 50 ns;
end loop;
end process;
END;

You've issue in your test bench:
Within codeALU entity is F defined as out signal. Within you test bench signal F is used to map F out from component codeALU. In the name less process below in test bench the signal F gets value: F <= conv_std_logic_vector(i,4);
It's unusable behavior. You see it in modelsim as red X's (not defined).

Related

Undefined Initial Signals VHDL

I have to implement a mini-router in VHDL. The design requirements for this are:
I've written the implementation, and a testbench. However, looking at the simulation waveform, some of my initial signals are undefined and I'm not sure why.
This is the source code:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
use IEEE.numeric_std.all;
entity mini_router is
port (
clk : in std_logic;
reset : in std_logic; -- synchronous negative reset
data1 : in std_logic_vector(9 downto 0);
req1 : in std_logic;
grant1 : out std_logic;
data2 : in std_logic_vector(9 downto 0);
req2 : in std_logic;
grant2 : out std_logic;
data_out : out std_logic_vector(7 downto 0);
valid : out std_logic
);
end entity;
architecture arch of mini_router is
signal aux : std_logic_vector(9 downto 0);
signal aux1 : std_logic_vector(1 downto 0);
signal aux2 : std_logic_vector(1 downto 0);
signal aux_valid : std_logic;
signal aux_grant1 : std_logic;
signal aux_grant2 : std_logic;
begin
mini_router: process(clk)
variable r : std_logic:= '1';
begin
-- conta le volte in cui c'è stato data conflict
if rising_edge(clk) then -- chiuso
if reset = '0' then
aux <= (others => '0');
aux_valid <= '0';
aux_grant1 <= '0';
aux_grant2 <= '0';
elsif reset = '1' then
if (req1 xor req2) = '1' then --chiuso -- un solo req è alto
if req1 ='1' then --chiuso
aux <= data1;
aux_grant1 <= '1';
aux_grant2 <= '0';
aux_valid <= '1';
else
aux <= data2;
aux_grant1 <= '0';
aux_grant2 <= '1';
aux_valid <= '1';
end if;
----entrambi i req sono alti
elsif (req1 and req2) = '1' then -- chiuso
if ((unsigned(aux1)) > (unsigned(aux2))) then
aux <= data1;
aux_grant1 <= '1';
aux_grant2 <= '0';
aux_valid <= '1';
elsif ((unsigned(aux1)) < (unsigned(aux2))) then
aux <= data2;
aux_grant2 <= '1';
aux_grant1 <= '0';
aux_valid <= '1';
elsif ((unsigned(aux1)) = (unsigned(aux2))) then -- stesso livello di priorità -- alternativa:(aux1 xnor aux2)="11"
if r = '1' then
aux <= data1;
aux_grant1<= '1';
aux_grant2 <= '0';
aux_valid <= '1';
r := not (r);
else
aux <= data2;
aux_grant2 <= '1';
aux_grant1<= '0';
aux_valid <= '1';
r := not (r);
end if;
end if;
elsif (req1 nor req2) = '1' then
aux_valid <= '0';
aux <= (others => '0');
aux_grant1 <= '0';
aux_grant2 <= '0';
end if;
end if; -- if del reset
end if; -- if del clock
end process;
data_out <= aux(9 downto 2);
aux1 <= data1 (1 downto 0);
aux2 <= data2 (1 downto 0);
valid <= aux_valid;
grant1 <= aux_grant1;
grant2 <= aux_grant2;
end architecture;
This is the testbench:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity mini_router_tb is
end mini_router_tb;
architecture arc of mini_router_tb is
constant T_CLK : time := 10 ns; --- frequenza di clock: 125 MHz
signal clk_tb : std_logic := '1';
signal reset_tb : std_logic := '0'; -- reset attivo basso sincrono
signal data1_tb : std_logic_vector(9 downto 0) := (others => '0');
signal req1_tb : std_logic:= '0';
signal grant1_tb : std_logic;
signal data2_tb : std_logic_vector(9 downto 0) := (others => '0');
signal req2_tb : std_logic:= '0';
signal grant2_tb : std_logic;
signal data_out_tb : std_logic_vector(7 downto 0);
signal valid_tb : std_logic;
signal end_sim : std_logic := '1'; -- signal to use to stop the simulation when there is nothing else to test
component mini_router is
port (
clk : in std_logic;
reset : in std_logic; -- synchronous negative reset
data1 : in std_logic_vector(9 downto 0);
req1 : in std_logic;
grant1 : out std_logic;
data2 : in std_logic_vector(9 downto 0);
req2 : in std_logic;
grant2 : out std_logic;
data_out : out std_logic_vector(7 downto 0);
valid : out std_logic
);
end component;
begin
clk_tb <= (not(clk_tb)and(end_sim)) after T_CLK/2;
DUT : mini_router
port map (
clk => clk_tb,
reset => reset_tb,
data1 => data1_tb,
req1 => req1_tb,
grant1 => grant1_tb,
data2 => data2_tb,
req2 => req2_tb,
grant2 => grant2_tb,
data_out => data_out_tb,
valid => valid_tb
);
-- process used to make the testbench signals change synchronously with the rising edge of the clock
stimuli_process: process(clk_tb,reset_tb)
variable t : integer := 0; -- variabile che conta i cicli di clock
begin
if (rising_edge(clk_tb)) then
case (t) is
when 1 => data1_tb <= (9 downto 3 => '0') & "100"; -- data1= 4; data_out=0 per il reset
data2_tb <= (9 downto 4 => '0') & "1101";-- data2= 13;
req1_tb <= '1' ; req2_tb<= '0';
when 2 => reset_tb <= '1';
data1_tb <= (9 downto 3 => '0') & "100"; -- data1= 4; data_out=1
data2_tb <= (9 downto 4 => '0') & "1101"; -- data2= 13;
req1_tb <= '1' ; req2_tb<= '0';
when 3 => data1_tb <= (9 downto 3 => '0') & "100"; -- data1= 4;
data2_tb <= (9 downto 4 => '0') & "1101";-- data2= 13; data_out=3
req1_tb <= '0' ; req2_tb<= '1';
when 4 => data1_tb <= (9 downto 5 => '0') & "11100"; --data1=28
data2_tb <= (9 downto 4 => '0') & "1101"; -- data2= 13; data_out=3 priorità maggiore
req1_tb <= '1' ; req2_tb<= '1';
when 5 => data1_tb <= (9 downto 5 => '0') & "00111"; --data1=7; data_out=1 priorità maggiore
data2_tb <= (9 downto 5 => '0') & "11101"; -- data2= 29;
req1_tb <= '1' ; req2_tb<= '1';
when 6 => data1_tb <= (9 downto 5 => '0') & "00111"; --data1=7; data_out=1
data2_tb <= (9 downto 5 => '0') & "11111"; -- data2= 31;
req1_tb <= '1' ; req2_tb<= '1';
when 7 => data1_tb <= (9 downto 5 => '0') & "00111"; --data_out=0;
data2_tb <= (9 downto 5 => '0') & "11111";
req1_tb <= '0' ; req2_tb<= '0';
when 8 => data1_tb <= (9 downto 5 => '0') & "10111"; --data1=7; data_out non assunto=5
data2_tb <= (9 downto 5 => '0') & "11111"; -- data2= 31; data_out=7
req1_tb <= '1' ; req2_tb<= '1';
when 9 => end_sim <= '0'; -- stops the simulation when t = 10
when others => null; -- non accade nulla negli altri casi
end case;
t := t + 1;
end if;
end process;
end architecture;
Your reset logic is synchronous, because the outmost condition is rising_edge(clk). Therefore the internal signals are undefined until the first raising edge of the clock.
Change to an asynchronous reset like this (excerpt):
if reset = '0' then
-- reset statements
elsif rising_edge(clk) then
-- work statements
end if;
Please be aware that even with an asynchronous reset the signals will be undefined until reset is activated or the clock raises. This reflects the actual behavior of a real device.
The reason your signals are initially set to U or X is because the values of all signals, variables, etc. are initialized to the left hand side of the type definition.
From the IEEE 1076 code (see here):
-------------------------------------------------------------------
-- logic state system (unresolved)
-------------------------------------------------------------------
type STD_ULOGIC is ( 'U', -- Uninitialized
'X', -- Forcing Unknown
'0', -- Forcing 0
'1', -- Forcing 1
'Z', -- High Impedance
'W', -- Weak Unknown
'L', -- Weak 0
'H', -- Weak 1
'-' -- Don't care
);
--------------------------------
And std_logic is just a resolved version of std_ulogic. So any signal of type std_logic will have its default value be U, unless set otherwise.
Consider the following code:
signal A : std_logic;
signal B : std_logic := '1';
Signal A would be U until set otherwise. Signal B will be 0 until set otherwise.
This is why you are seeing U in your simulation. (As for X you see in your waveform window, many simulators that collapse vectors into a single value in the waveform view treat collections with U as X. Expand that vector and I suspect you will see several U's.)

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;

SDRAM Controller in VHDL

I have to develop a SDRAM controller for a class project in VHDL. But this is my first time working with VHDL, that has a very important learning curve.
I have downloaded a SDRAM controller from github (https://github.com/christianmiyoshi/SDRAM_Controller_VHDL/blob/master/sdram_controller.vhd) and I am trying to complete it.
I am trying to write a data in an address and later read it, but I cant read a single data. I dont know if my problem is in the writing or in the reading process.
Can anybody help me, please?
Thank you all!
library ieee;
use ieee.numeric_std.all;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity ram_controller is
port(
clk : in std_logic;
reset: in std_logic;
refresh: in std_logic;
read_write_enable: in std_logic;
write_n: in std_logic;
address: in std_logic_vector(21 downto 0);
data_in: in std_logic_vector(15 downto 0);
dqmu: in std_logic;
dqml: in std_logic;
ready: out std_logic;
done: out std_logic;
data_out: out std_logic_vector(15 downto 0);
single_burst: in std_logic; --0 single y 1 burst
SDRAM_CKE: out std_logic;
SDRAM_CS_N: out std_logic;
SDRAM_RAS_N: out std_logic;
SDRAM_CAS_N: out std_logic;
SDRAM_WE_N: out std_logic;
SDRAM_BA: out std_logic_vector(1 downto 0);
SDRAM_SA: out std_logic_vector(11 downto 0);
SDRAM_DQ: inout std_logic_vector(15 downto 0);
SDRAM_DQM: out std_logic_vector(1 downto 0)
);
end entity;
architecture behavior of ram_controller is
type state_type is (init_ckeLow, init_stableClock, init_wait, init_nopCommand, init_prechargeAll, init_refresh_1, init_mode, init_refresh_2, idle, refresh_state, activate_row, activate_rcd, read_write, ras1, ras2, precharge);
signal state: state_type := init_ckeLow;
signal ticks: std_logic_vector(7 downto 0) := (others => '0');
signal ticks_ref: integer := 0;
signal ticks_ref_refresh: integer := 0;
constant burstMode: std_logic := '0';
constant casLatency: std_logic_vector(2 downto 0) := "010";
constant burstType: std_logic := '0';
constant burstLength: std_logic_vector(2 downto 0) := "000";
--signal highz_output: std_logic:= '0';
constant MODE_REG: std_logic_vector(11 downto 0) := "00" & burstMode & "00" & casLatency & burstType & burstLength;
constant MODE_REG_BURST: std_logic_vector(11 downto 0) := "000000100111";
signal command: std_logic_vector(3 downto 0);
signal row: std_logic_vector(11 downto 0);
signal column: std_logic_vector(7 downto 0);
signal bank: std_logic_vector(1 downto 0);
signal sd_busdir_x: std_logic:='0';
-- Command truth table
-- CS_N, RAS_N, CAS_N, WE_N
constant CMD_ACTIVATE: std_logic_vector(3 downto 0) := "0011";
constant CMD_PRECHARGE: std_logic_vector(3 downto 0) := "0010";
constant CMD_WRITE: std_logic_vector(3 downto 0) := "0100";
constant CMD_READ: std_logic_vector(3 downto 0) := "0101";
constant CMD_MODE: std_logic_vector(3 downto 0) := "0000";
constant CMD_NOP: std_logic_vector(3 downto 0) := "0111";
constant CMD_REFRESH: std_logic_vector(3 downto 0) := "0001";
signal address_buffer: std_logic_vector(21 downto 0) := (others => '0');
signal data_in_buffer: std_logic_vector(15 downto 0) := (others => '0');
signal dqu_buffer: std_logic := '0';
signal dql_buffer: std_logic := '0';
signal ready_buffer: std_logic := '0';
signal done_buffer: std_logic := '0';
signal data_out_buffer: std_logic_vector(15 downto 0) := (others => '0');
signal CKE: std_logic;
signal CS_N: std_logic;
signal RAS_N: std_logic;
signal CAS_N: std_logic;
signal WE_N: std_logic;
signal BA: std_logic_vector(1 downto 0);
signal SA: std_logic_vector(11 downto 0);
signal DQ: std_logic_vector(15 downto 0);
signal DQM: std_logic_vector(1 downto 0);
signal contador : std_logic_vector(15 downto 0) := x"0000";
signal modo: std_logic := '0';
begin
(CS_N, RAS_N, CAS_N, WE_N) <= command;
SDRAM_CKE <= CKE;
SDRAM_CS_N <= CS_N;
SDRAM_RAS_N <= RAS_N;
SDRAM_CAS_N <= CAS_N;
SDRAM_WE_N <= WE_N;
SDRAM_BA <= BA;
SDRAM_SA <= SA;
--SDRAM_DQ <= DQ;
SDRAM_DQM <= DQM;
--SA <= address_buffer;
SDRAM_DQ <= data_in_buffer when sd_busdir_x = '1' else (others => 'Z');
DQM <= dqu_buffer & dql_buffer;
ready <= ready_buffer;
done <= done_buffer;
data_out <= data_out_buffer;
bank <= address(21 downto 20);
row <= address(19 downto 8);
column <= address(7 downto 0);
process(clk, reset)
begin
if reset = '0' then
state <= init_ckeLow;
ticks_ref <= 0;
elsif rising_edge(clk) then
if ticks_ref /= 0 then
ticks_ref <= ticks_ref - 1;
else
-- Micron datasheet instructions
-- Frequency = 100 Mhz => period of 10ns
-- 1: Apply Vdd and Vddq simultaneously
case state is
when init_ckeLow =>
-- 2: Assert and hold CKE ant LVTTL logic low
ticks_ref <= 10;
CKE <= '0';
state <= init_stableClock;
when init_stableClock =>
-- 3: Provide stable clock
ticks_ref <= 10;
state <= init_wait;
when init_wait=>
-- 4: Wait at least 100us
-- 5: bring cke high at some point of the period
-- with command inhibit or nop
--ticks_ref <= 10000;
ticks_ref <= 2; -- debugadd
state <= init_nopCommand;
when init_nopCommand =>
--ticks_ref <= 10000;
ticks_ref <= 2; -- debug
CKE <= '1';
command <= CMD_NOP;
state <= init_prechargeAll;
when init_prechargeAll =>
-- 6: perform precharge all
-- 7: wait at leas t_RP
command <= CMD_PRECHARGE;
BA <= "00";
SA(10) <= '1'; -- all banks
ticks_ref <= 2;
ticks_ref_refresh <= 8;
state <= init_refresh_1;
when init_refresh_1 =>
-- auto refresj period: < 64 ns
if ticks_ref_refresh = 0 then
state <= init_mode;
else
ticks_ref_refresh <= ticks_ref_refresh - 1;
command <= CMD_REFRESH;
ticks_ref <= 7;
end if;
when init_mode =>
command <= CMD_MODE;
if single_burst = '0' then
SA <= MODE_REG;
modo <= '0';
else
SA <= MODE_REG_BURST;
modo <= '1';
end if;
BA <= "00";
ticks_ref <= 2;
ticks_ref_refresh <= 8;
state <= init_refresh_2;
when init_refresh_2 =>
if ticks_ref_refresh = 0 then
state <= idle;
--done_buffer <= '1';
else
ticks_ref_refresh <= ticks_ref_refresh - 1;
command <= CMD_REFRESH;
ticks_ref <= 7;
end if;
when idle =>
done_buffer <= '0';
contador <= (others => '0');
if read_write_enable = '1' then
-- tras: active to precharge: 45 ns min, 120000ns max
state <= activate_row;
command <= CMD_ACTIVATE;
SA <= row;
BA <= bank;
--done_buffer <= '0';
elsif refresh = '1' then
state <= refresh_state;
command <= CMD_REFRESH;
ticks_ref <= 7;
--done_buffer <= '0';
end if;
when refresh_state =>
state <= idle;
--done_buffer <= '1';
when activate_row =>
--trcd 20 ns
command <= CMD_NOP;
state <= activate_rcd;
data_in_buffer <= data_in;
ticks_ref <= 1;
when activate_rcd =>
-- trcs = 20ns min
state <=read_write;
SA <= "0000" & column;
if write_n = '0' then
command <= CMD_WRITE;
dqu_buffer <= dqmu;
dql_buffer <= dqml;
sd_busdir_x <= '1';
else
command <= CMD_READ;
end if;
when read_write =>
--command <= CMD_NOP;
state <= ras1;
--if modo='0' then
--sd_busdir_x <= '0';
--end if;
when ras1 =>
state <= ras2;
command <= CMD_NOP;
when ras2 =>
-- trp = 20ns min
if modo='1' and contador <= x"00FF" then
data_in_buffer <= data_in;
state <= ras2;
contador <= contador +1;
else
contador <= (others => '0');
state <= precharge;
sd_busdir_x <= '0';
command <= CMD_PRECHARGE;
SA(10) <= '1';
data_out_buffer <= SDRAM_DQ;
ticks_ref <= 2;
end if;
when precharge =>
state <= idle;
done_buffer <= '1';
ticks_ref <= 1;
end case;
end if;
end if;
end process;
end architecture;
[enter image description here][1]
[1]: https://i.stack.imgur.com/CaqqL.png

How can I add two std_logic_vectors that have been concatenated in VHDL?

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';

ALU implementation w/ ADDER

Hello I'm trying to create a 32-bit adder with a few opcodes and I've got it working quite well except for two cases and I can't seem to find what's causing them.. Maybe you can help me?
The subtraction case always fails for some reason and the ADDC case fails to compute the correct output when it should be using the carry bit in c_reg that has been created by the ADDS operation.
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
ENTITY ALU IS
GENERIC(WIDTH : NATURAL := 32);
PORT(Clk : IN STD_LOGIC := '0';
Reset : IN STD_LOGIC := '0';
A : IN STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0) := (OTHERS => '0');
B : IN STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0) := (OTHERS => '0');
Op : IN STD_LOGIC_VECTOR(3 DOWNTO 0) := (OTHERS => '0');
Outs : OUT STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0));
END ALU;
ARCHITECTURE arch_ALU OF ALU IS
COMPONENT adder
PORT(OpA : IN STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0);
OpB : IN STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0);
Cin : IN STD_LOGIC;
Cout : OUT STD_LOGIC;
Result : OUT STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0));
END COMPONENT;
SIGNAL adder_output : STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0) := (OTHERS => '0');
SIGNAL B_neg : STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0) := (OTHERS => '0');
SIGNAL c_flag : STD_LOGIC := '0';
SIGNAL c_reg : STD_LOGIC := '0';
SIGNAL cin : STD_LOGIC := '0';
BEGIN
adder_comp : adder
PORT MAP(OpA => A,
OpB => B_neg,
Cin => cin,
Result => adder_output,
Cout => c_flag);
WITH Op SELECT
B_neg <= NOT(B) WHEN "1000",
B WHEN OTHERS;
WITH Op SELECT
cin <= '1' WHEN "1000", -- SUB
c_reg WHEN "0111", -- ADDC
'0' WHEN OTHERS; -- ADD/ADDS
ALU_Process:
PROCESS(Clk)
BEGIN
IF Reset = '0' THEN
Outs <= (OTHERS => '0');
ELSIF rising_edge(Clk) THEN
CASE Op IS
WHEN "0001" => Outs <= A AND B;
WHEN "0010" => Outs <= A OR B;
WHEN "0011" => Outs <= A NOR B;
WHEN "0100" => Outs <= A XOR B;
WHEN "0101" => Outs <= adder_output; -- ADD
WHEN "0110" => Outs <= adder_output; -- ADDS
c_reg <= c_flag;
WHEN "0111" => Outs <= adder_output; -- ADDC
WHEN "1000" => Outs <= adder_output; -- SUB
WHEN "1001" => Outs <= STD_LOGIC_VECTOR(UNSIGNED(A) SLL to_integer(UNSIGNED(B(4 DOWNTO 0))));
WHEN "1010" => Outs <= STD_LOGIC_VECTOR(unsigned(A) SRL to_integer(UNSIGNED(B(4 DOWNTO 0))));
WHEN "1011" => Outs <= STD_LOGIC_VECTOR(shift_right(SIGNED(A),to_integer(UNSIGNED(B(4 DOWNTO 0)))));
WHEN OTHERS => Outs <= (OTHERS => '0');
END CASE;
END IF;
END PROCESS;
END arch_ALU;
Only the ADDS operation should write it's carry-out to the c_reg and ADDC operation should take the c_reg into account when calculating it's output
The adder is tested and working correctly so the problem is not in the adder design.
First of all I'd like to get to know the problem of the subtraction because it is doing subtraction but the result is a little bit off.. For example:
A : h'E6A4960F
B : h'7B494E34
Op : d'1000
Outs: h'6B5B47DA while it should be h'6B5B47DB
A : h'EFDE31A3
B : h'0BCAB8FA
Op : d'1000
Out : h'E41378BB while should be h'E41378A9
Can you spot my misstake? Cause I certainly can't..
While you didn't provide a Minimal, Complete, and Verifiable example the reader can at least test the subtract portions of your design that are present:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity alu is
generic (width: natural := 32);
port (
clk: in std_logic := '0';
reset: in std_logic := '0';
a: in std_logic_vector(width - 1 downto 0) := (others => '0');
b: in std_logic_vector(width - 1 downto 0) := (others => '0');
op: in std_logic_vector(3 downto 0) := (others => '0');
outs: out std_logic_vector(width - 1 downto 0)
);
end alu;
architecture arch_alu of alu is
-- component adder
-- port (
-- opa: in std_logic_vector(width - 1 downto 0);
-- opb: in std_logic_vector(width - 1 downto 0);
-- cin: in std_logic;
-- cout: out std_logic;
-- result: out std_logic_vector(width - 1 downto 0)
-- );
-- end component;
procedure adder (
signal opa: in std_logic_vector(width - 1 downto 0);
signal opb: in std_logic_vector(width - 1 downto 0);
signal cin: in std_logic;
signal cout: out std_logic;
signal result: out std_logic_vector(width - 1 downto 0)
) is
variable sum: unsigned (width downto 0);
begin
sum := unsigned('0' & opa) + unsigned(opb) + unsigned'(""& cin);
result <= std_logic_vector(sum (width - 1 downto 0));
cout <= sum(width);
end procedure;
signal adder_output: std_logic_vector(width - 1 downto 0) := (others => '0');
signal b_neg: std_logic_vector(width - 1 downto 0) := (others => '0');
signal c_flag: std_logic := '0';
signal c_reg: std_logic := '0';
signal cin: std_logic := '0';
begin
adder_comp:
adder
-- port map (
(
opa => a,
opb => b_neg,
cin => cin,
result => adder_output,
cout => c_flag
);
with op select
b_neg <= not b when "1000",
b when others;
with op select
cin <= '1' when "1000", -- sub
c_reg when "0111", -- addc
'0' when others; -- add/adds
alu_process:
process(clk)
begin
if reset = '0' then
outs <= (others => '0');
elsif rising_edge(clk) then
case op is
when "0001" => outs <= a and b;
when "0010" => outs <= a or b;
when "0011" => outs <= a nor b;
when "0100" => outs <= a xor b;
when "0101" => outs <= adder_output; -- add
when "0110" => outs <= adder_output; -- adds
c_reg <= c_flag;
when "0111" => outs <= adder_output; -- addc
when "1000" => outs <= adder_output; -- sub
when "1001" => outs <= std_logic_vector (
unsigned(a) sll to_integer(unsigned(b(4 downto 0)))
);
when "1010" => outs <= std_logic_vector (
unsigned(a) srl to_integer(unsigned(b(4 downto 0)))
);
when "1011" => outs <= std_logic_vector (
shift_right(signed(a),to_integer(unsigned(b(4 downto 0))))
);
when others => outs <= (others => '0');
end case;
end if;
end process;
end arch_alu;
library ieee;
use ieee.std_logic_1164.all;
entity alu_tb is
end entity;
architecture foo of alu_tb is
constant width: integer := 32;
signal clk: std_logic := '0';
signal reset: std_logic := '0';
signal a: std_logic_vector(width - 1 downto 0) := (others => '0');
signal b: std_logic_vector(width - 1 downto 0) := (others => '0');
signal op: std_logic_vector(3 downto 0) := (others => '0');
signal outs: std_logic_vector(width - 1 downto 0);
begin
CLOCK:
process
begin
wait for 10 ns;
clk <= not clk;
if Now > 90 ns then
wait;
end if;
end process;
DUT:
entity work.alu
port map (
clk => clk,
reset => reset,
a => a,
b => b,
op => op,
outs => outs
);
STIMULUS:
process
begin
wait for 20 ns;
reset <= '1';
a <= x"E6A4960F";
b <= x"7B494E34";
op <= "1000";
wait for 20 ns;
a <= x"EFDE31A3";
b <= x"0BCAB8FA";
wait for 20 ns;
wait;
end process;
end architecture;
I wrote a quick and dirty procedure adder. This eliminates your adder entity/architecture and the component declaration.
I added a simple testbench for the two subtractions, this eliminates your test bench or testing procedure.
And this gives:
And as you can see the results are what you claim as correct.
So what that leaves is either your adder or your testbench (it's a stretch to blame your component declaration).
So what we get from this is that you haven't presented enough information to determine where the error is.
I did this little demonstration because the two errors don't have all the wrong bits in common. If you've tested your adder and are sure of it, it's probably the stimulus input when subtracting.

Resources