How can I add two std_logic_vectors that have been concatenated in VHDL? - 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';

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;

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

VHDL Test Bench working but incorrect results when run on FPGA

I am trying to write a program to detect if a given input is a prime number or not. When I run the test bench I get correct results however when I run it on the FPGA it only recognizes numbers that are divisible 3 or even as not prime. Any number such as 25 which is divisible by 5 will result in isPrime being 1. What could be causing this inconsistent result?
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
USE IEEE.std_logic_unsigned.all;
USE IEEE.numeric_std.all;
entity PrimeNumber is
Port ( clk: in std_logic;
rst : in std_logic;
input: in std_logic_vector(15 downto 0);
isPrime: out std_logic:= '0';
testOut: out std_logic_vector(31 downto 0)
);
end PrimeNumber;
architecture Behavioral of PrimeNumber is
SIGNAL current_state: std_logic_vector(2 downto 0);
signal next_state: std_logic_vector(2 downto 0):= "000";
signal max: integer;
signal temp: integer;
signal x: integer;
signal nextX:integer;
signal localPrime : std_logic:= '0';
signal current : integer;
signal update: std_logic := '0';
begin
nextX <= x +2;
process(current_state,input)
begin
case (current_state) is
when "000" => --Initial State
update <= '0';
localPrime <= '0';
if(input < x"0004")then
next_state <= "111";
else
max <= to_integer(unsigned(input(15 downto 1)));
current <=to_integer(unsigned(input));
if(input(0) = '0')then
next_state <= "110";
else
next_state <= "001";
end if;
end if;
when "001" => -- Computation State
localPrime <= '0';
temp <= current mod x;
if(x > max) then
next_state <= "111";
else
next_state <= "010";
end if;
update <= '1';
when "010" => -- Checking State
update <= '0';
localPrime <= '0';
if(temp = 0) then
next_state <= "110";
else
next_state <= "001";
end if;
when "110" =>
localPrime <= '0'; -- Not Prime State
next_state <= "110";
when "111" =>
update <= '0';
localPrime <= '1'; --Prime State
next_state <= "111";
when others =>
temp <= 0;
localPrime <= '0';
next_state <= "000";
end case;
end process;
Update_Registers: process(clk)
begin
if(clk'event and clk = '1') then
if ( rst = '1') then
current_state <= "000";
isPrime <= '0';
x<=3;
else
if(update = '1') then
x <= nextX;
end if;
current_state <= next_state;
isPrime <= localPrime;
end if;
end if;
end process;
end Behavioral;
To quickly check sim/syn mismatch, with the visibility you need outside of HW: output the mod result to a port, sim, should still "work"... syn, compile your (hopefully, verilog) netlist for TB, point to compiled netlist, sim, check the mod result against RTL/expected results.

4-Bit ALU to BCD display

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).

FSM model of FIR filter

I want to make a FSM model of FIR, for that I need to write FIR calculation code line in FSM implementation.
Here is the actual and correct code for FIR
entity fir_4tap is
port( Clk : in std_logic; --clock signal
Clk_fast : in std_logic;
-- Xin : in signed(7 downto 0); --input signal
bit_in : in std_logic;
bit_out : out std_logic;
Yout : out signed(15 downto 0) --filter output
);
end fir_4tap;
architecture Behavioral of fir_4tap is
signal add_out3 : signed(15 downto 0) := (others => '0');
signal index : unsigned(2 downto 0) := (others =>'0');
signal counter : unsigned(3 downto 0) := (others => '0');
signal p : unsigned(1 downto 0) := (others => '0');
signal k : unsigned(1 downto 0) := (others => '0');
signal j : unsigned(1 downto 0) := (others => '0');
type array_signed is array(8 downto 0) of signed(7 downto 0);
signal z : array_signed := (others => "00000000");
type array_signed1 is array(3 downto 0) of signed(7 downto 0);
signal H : array_signed1 := (others => "00000000");
signal Xin : array_signed1 := (others => "00000000");
begin
z(0) <= to_signed(-3,8);
z(1) <= to_signed(1,8);
z(2) <= to_signed(0,8);
z(3) <= to_signed(-2,8);
z(4) <= to_signed(-1,8);
z(5) <= to_signed(4,8);
z(6) <= to_signed(-5,8);
z(7) <= to_signed(6,8);
z(8) <= to_signed(0,8);
H(0) <= to_signed(-2,8);
H(1) <= to_signed(-1,8);
H(2) <= to_signed(3,8);
H(3) <= to_signed(4,8);
process (clk)
begin
if (rising_edge(Clk)) then
index <= index +1;
if (index = "111") then
Xin(to_integer(p)) <= z(to_integer(counter)); k <= p;
p <= p + 1;
***-- This part of the code has problem, I want to write the line which is summing --up for add_out3 in a for loop.***
add_out3 <= (others => '0');
add_out3 <= Xin(to_integer(k))*H(to_integer(j)) + Xin(to_integer(k-1))*H(to_integer(j+1)) + Xin(to_integer(k-2))*H(to_integer(j+2)) + Xin(to_integer(k-3))*H(to_integer(j+3));
Yout <= add_out3;
end if;
end if;
end process;
end Behavioral;
Now Below is the FSM implementation try by me but not getting the same out sample as input can somebody tell me what could be the problem in the code?
----------------FSM implementation of the FIR filter ----------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity test is
port( Clk : in std_logic; --clock signal
Clk_fast : in std_logic;
bit_in : in std_logic;
bit_out : out std_logic;
Yout : out signed(15 downto 0) --filter output
);
end test;
architecture Behavioral of test is
signal data_buffer : signed(7 downto 0) := (others => '0');
signal index : unsigned(2 downto 0) := (others =>'0');
signal counter : unsigned(3 downto 0) := (others => '0');
type array_signed is array(8 downto 0) of signed(7 downto 0);
signal z : array_signed := (others => "00000000");
type array_signed1 is array(3 downto 0) of signed(7 downto 0);
signal H : array_signed1 := (others => "00000000");
signal input : signed(7 downto 0) := (others => '0');
type MULT_TYPE is array(3 downto 0) of signed(15 downto 0);
signal MULT_array : MULT_TYPE := (others => "0000000000000000");
type ADD_TYPE is array(3 downto 0) of signed(15 downto 0);
signal ADD_array : ADD_TYPE := (others => "0000000000000000");
constant ZERO : signed(15 downto 0) := (others => '0');
type state_type is (s0,s1,s2,s3); --type of state machine.
signal current_s : state_type := s0; --current and next state declaration.
signal next_s : state_type := s0;
signal reset : std_logic := '0';
signal go : std_logic := '0';
signal change_state : std_logic := '0' ;
signal counter_FSM_monitor : unsigned( 6 downto 0) := "0000000";
begin
z(0) <= to_signed(-3,8);
z(1) <= to_signed(1,8);
z(2) <= to_signed(0,8);
z(3) <= to_signed(-2,8);
z(4) <= to_signed(-1,8);
z(5) <= to_signed(4,8);
z(6) <= to_signed(-5,8);
z(7) <= to_signed(6,8);
z(8) <= to_signed(0,8);
H(0) <= to_signed(-2,8);
H(1) <= to_signed(-1,8);
H(2) <= to_signed(3,8);
H(3) <= to_signed(4,8);
process (Clk) is
begin
if falling_edge(Clk) then
data_buffer(to_integer(index)) <= bit_in;
index <= index +1;
if (index = "111") then
input <= z(to_integer(counter));
counter <= counter + 1;
if(counter = "1000") then
counter <= "0000";
end if;
end if;
end if;
end process;
process (clk_fast)
begin
if (falling_edge(clk_fast)) then
counter_FSM_monitor <= counter_FSM_monitor + 1;
if( to_integer(counter_FSM_monitor) = 76) then
counter_FSM_monitor <= "0000000";
end if;
case change_state is
when '1' =>
current_s <= next_s; --state change.
when '0' => --current_s <= s0;
when others =>
end case;
end if;
end process;
Process(current_s,input)
begin
if ( to_integer(counter_FSM_monitor) < 64 ) then
-- waiting for the Input
elsif (to_integer(counter_FSM_monitor) >= 64 and to_integer(counter_FSM_monitor) < 76) then
---------------------------------------------- FSM ----------------------------------------
case current_s is
when s0 =>
mult_array(0) <= input*H(3);
ADD_array(0) <= ZERO + mult_array(0);
next_s <= s1;
change_state <= '1';
when s1 =>
mult_array(1) <= input*H(2);
ADD_array(1) <= mult_array(1) + ADD_array(0);
next_s <= s2;
change_state <= '1';
when s2 =>
mult_array(2) <= input*H(1);
ADD_array(2) <= mult_array(2) + ADD_array(1);
next_s <= s3;
change_state <= '1';
when s3 =>
mult_array(3) <= input*H(0);
ADD_array(3) <= mult_array(3) + ADD_array(2);
Yout <= ADD_array(3);
next_s <= s0;
change_state <= '1';
when others =>
next_s <= s0;-- never comes here
change_state <= '1';
end case;
---------------------------------------------- FSM ----------------------------------------
end if;
end process;
end Behavioral;
How ever I am not able to receive the same output which I received by the first code.
FSM code gives the correct output for the first out but from the second out sample it gives wrong result.Can somebody tell me what I am doing wrong ?
This answer is for the initial version of the question but Now question has been changed.
Made add_out3 a variable instead of a signal.
for i in 0 to 3 loop
add_out3 := add_out3 + Xin(k-i)*H(i);
end loop;
Did the above changes in the for loop It works fine.
So the code in my question is a correct code for FIR also, works smoothly.
Learnt that one needs to be very careful while using signal or variables. All the signals get a new value at the same time i.e at the end of clock period, while in variables values gets updated as assigned within a process. Tried to run the simulation step by step and figured out the problem.

Resources