I'm new at VHDL. I'm trying to realize the block diagram in the following picture: The code which realize the Z^1 block (which is just a delay) is the following:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity DFF is
generic (N : INTEGER:=16);
port(
D : in signed(N-1 downto 0); -- Data input
clk : in std_logic; -- Clock input
reset : in std_logic; -- Reset input
Q : out signed(N-1 downto 0)); -- Data output
end DFF;
architecture Behavioral of DFF is
begin
DFF:process(clk)
begin
IF (clk'EVENT AND clk='1') THEN
FOR i IN 0 TO N-1 LOOP
Q(i) <= reset AND D(i);
END LOOP;
END IF;
END process DFF;
end Behavioral;
The code which realize the entire block diagram is the following:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity fir is
generic (N : INTEGER:=16);
port(
Clk : in std_logic; --clock signal
reset : in std_logic;
Xin : in signed(N-1 downto 0); --input signal
Yout : out signed(N-1 downto 0) --filter output
);
end fir;
architecture fir_struct of fir is
component dff is
generic (N : INTEGER:=16);
port(
D : in signed(N-1 downto 0);
clk : in std_logic;
reset : in std_logic;
Q : out signed(N-1 downto 0));
END component;
signal y_delayed, add2_in1, add2_in2, y_temp : signed(N-1 downto 0) := (others => '0');
-- add2_in1 is the first input of the adder (The input of the block diagram)
-- add2_in2 is the delayed output of the adder
-- y_temp is the output of the adder
-- y_delayed is the output of the delay operation
begin
add2_in1 <= Xin;
y_temp <= add2_in1 + add2_in2; -- this line is giving me troubles
DELAY1: dff port map(y_temp, Clk, reset, y_delayed);
Yout <= y_temp;
add2_in2 <= y_delayed;
end fir_struct;
I highlighted the line which gives me troubles. I tried to remove it and to put as first parameter of DELAY1 my input Xin (just to try if it works or the problem was in another line) and it works (of course it doesn't do what I want, but the waveform behave as I expeted). The testbench is the following:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY iir_wav_tb IS
END iir_wav_tb;
ARCHITECTURE behavior OF iir_wav_tb IS
signal Clk : std_logic := '0';
signal reset : std_logic := '1';
signal Xin : signed(15 downto 0) := (others => '0');
signal Yout : signed(15 downto 0) := (others => '0');
constant Clk_period : time := 10 ns;
begin
-- Instantiate the Unit Under Test (UUT)
uut: entity work.fir PORT MAP (
Clk => Clk,
reset => reset,
Xin => Xin,
Yout => Yout);
-- Clock process definitions
Clk_process :process
begin
Clk <= '0';
wait for Clk_period/2;
Clk <= '1';
wait for Clk_period/2;
end process;
-- Stimulus process
stim_proc: process
begin
Xin <= to_signed(1,16);
wait for clk_period*1;
Xin <= to_signed(23,16);
wait for clk_period*1;
end process;
end
The waveform which I obtain is the following:
The problem is that when the add operation occurs, the value of y_temp become '?' (the components of this 16bits signal are all 'X'). I think is a problem of inizialization, as passing Xin directly without adding anything won't rise the problem. Could anyone help me?
Before start with your code, you need to remember that VHDL is to create hardware and it's not a software language. So, every process is executed in parallel by simulator. Only variables are executed immediately.
Second thing, don't initialize signals that don't need initialization.
So, I propose this changes:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity DFF is
generic (N : INTEGER:=16);
port(
D : in signed(N-1 downto 0); -- Data input
clk : in std_logic; -- Clock input
reset : in std_logic; -- Reset input
Q : out signed(N-1 downto 0)) -- Data output
end DFF;
architecture Behavioral of DFF is
begin
DFF:process(clk,reset)
begin
IF (reset = '0') then
Q <= (others => '0');
elsif (clk'EVENT AND clk='1') THEN
Q <= D;
END IF;
END process DFF;
end Behavioral;
Doing so, you initialize add2_in2 inside the flip-flop (it's necessary that the reset at the begin going from 0 to 1). You don't need a loop to assign every bit.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity fir is
generic (N : INTEGER:=16);
port(
Clk : in std_logic; --clock signal
reset : in std_logic;
Xin : in signed(N-1 downto 0); --input signal
Yout : out signed(N-1 downto 0) --filter output
);
end fir;
architecture fir_struct of fir is
component dff is
generic (N : INTEGER:=16);
port(
D : in signed(N-1 downto 0);
clk : in std_logic;
reset : in std_logic;
Q : out signed(N-1 downto 0));
END component;
signal y_delayed, y_temp : signed(N-1 downto 0);
-- add2_in1 is the first input of the adder (The input of the block diagram)
-- add2_in2 is the delayed output of the adder
-- y_temp is the output of the adder
-- y_delayed is the output of the delay operation
begin
y_temp <= Xin + y_delayed;
DELAY1: dff port map(y_temp, Clk, reset, y_delayed);
Yout <= y_temp;
end fir_struct;
I think that so your adder will work. You need to update your test-bench:
signal reset : std_logic;
process
begin
reset <= '0';
wait for 5 ns;
reset <= '1';
wait;
end process;
If I forgot something, please ask me.