Why doesn't my code produce output? - vhdl

I'm new to VHDL and I've just been messing around with Quartus II 9.0 and decided to make a register type component. I think my logic is right but I'm not getting any output when I run the simulation. I created a waveform to test possible situations (used node finder to list all inputs and output, generated the functional simulation netlist) but I do not get any output for Q. Not even the simple case when clr = 1 and all of Q should be set to 0.
library ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_arith.ALL;
USE ieee.std_logic_unsigned.ALL;
ENTITY Register32 IS PORT (
d : IN STD_LOGIC_VECTOR(31 DOWNTO 0); -- input.
ld : IN STD_LOGIC; -- load/enable.
clr : IN STD_LOGIC; -- async. clear.
clk : IN STD_LOGIC; -- clock.
Q : OUT STD_LOGIC_VECTOR (31 DOWNTO 0)); -- output.
END Register32;
ARCHITECTURE description OF Register32 IS
BEGIN
process (clk) begin
if (clr = '1') then
Q <= (others => '0');
else
if (rising_edge(clk)) then
if (ld = '1') then
Q <= d;
end if;
end if;
end if;
end process;
END description;

When the clr is asynchronous, then it must be included in the process
sensitivity list, since update of Q should react immediately on changes to
clr. Quartus II has probably given you a warning about this, if you dive
into the warnings.
The clr missing in the sensitivity list is not that visible if clk is
running, but if your current test bench only tries clr so far, it may be the
reason that you do not see any changes of Q.

Related

Signal value won't be initialized during simulation

We've a project for college where we have to simulate a MAC unit for DSP.
For the simulation, I'm using Aldec Riviera Pro 2014.06 through EDA playground.
The problem is that even though I initialized a 32-bit signed signal named add_res, at the simulation its value will be shown as XXXX_XXXX the whole time.
Here's the simulation's result.
Here's the code of the design.vhd
LIBRARY IEEE;
USE IEEE.std_logic_1164.all;
USE IEEE.numeric_std.all;
-----------------------------
ENTITY mac IS
PORT (B, C : IN SIGNED (15 DOWNTO 0);
clk : IN STD_LOGIC;
A : OUT SIGNED (31 DOWNTO 0));
END mac;
-----------------------------
ARCHITECTURE mac_rtl OF mac IS
SIGNAL mul_res: SIGNED (31 DOWNTO 0);
SIGNAL add_res: SIGNED (31 DOWNTO 0) := (others => '0');
BEGIN
mul_res <= B * C;
PROCESS (clk)
BEGIN
A <= mul_res + add_res;
add_res <= A;
END PROCESS;
END mac_rtl;
And here's the code of the testbench.vhd
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity testbench is
end entity testbench;
architecture BENCH of testbench is
component mac is
port (B, C : in SIGNED (15 DOWNTO 0);
clk : in STD_LOGIC;
A : out SIGNED (31 DOWNTO 0));
end component;
signal StopClock : BOOLEAN;
signal clk : STD_LOGIC;
signal B, C : SIGNED (15 DOWNTO 0);
signal A : SIGNED (31 DOWNTO 0);
begin
ClockGenerator: process
begin
clk <= '0';
wait for 2 ns;
while not StopClock loop
clk <= '0';
wait for 1 ns;
clk <= '1';
wait for 1 ns;
end loop;
wait;
end process ClockGenerator;
Stimulus: process
begin
B <= "0000000000000010";
C <= "0000000000001000";
wait;
end process Stimulus;
DUT : entity work.mac
port map (B, C, clk, A);
end architecture BENCH;
I've searched here and in Google in general for others having the same problem, but the solutions given didn't help.
I've tried and with a Reset variable from testbench, but nothing. It's like it won't be initialized at all, while everything else work normally.
The issue is that the value of add_res and mul_res have to be known at the time add_res is loaded into a register.
Note that the process is sensitive to clk but doesn't use an edge nor qualify with a value of clk.
I modified your architecture to qualify add_res update to the rising edge of clk. There's a built in assumption you have non-metavalue values on mult_res at that time. That can be dealt with in part by defining a default initial value.
Also the new value of A is not available until signals are update, which doesn't occur while there are any processes pending to be resumed in the current simulation cycle. This means you need to assign to add_res (which holds the accumulated value anyway) and assign to A outside the process:
ARCHITECTURE mac_rtl OF mac IS
SIGNAL mul_res: SIGNED (31 DOWNTO 0) := (others => '0'); -- added init val
SIGNAL add_res: SIGNED (31 DOWNTO 0) := (others => '0');
BEGIN
mul_res <= B * C;
PROCESS (clk)
BEGIN
if rising_edge(clk) then -- ADDED
-- A <= mul_res + add_res; CHANGED
add_res <= mul_res + add_res;
-- add_res <= A; CHANGED
end if; -- ADDED
END PROCESS;
A <= add_res;
END mac_rtl;
And this gives:
You could note there is no need to try to collapse A and add_res. For simulation purposes delta cycles caused by signal assignments that take effect after 0 simulation time has passed do not take simulation time.
Scheduled signal updates and delta cycles are used to emulate concurrency in signals that are inherently assigned sequentially. (And yes in the modified architecture the assignment to A will occur one delta cycle later than add_res).
(And yes I put a StopClock transaction at the tail end of the stimuli in process Stimulus in the testbench).

VHDL MUX Test Bench Issue

I'm trying to learn VHDL through P. Ashenden's book: Designer's Guide to VHDL. Chapter one's exercise 10 asks you to write 2-to-1 (I'm assuming 1 bit wide) MUX in VHDL and simulate it. I apologize in advance for being a complete noob. This is my first VHDL code.
My MUX didn't produce any errors or warnings in synthesis. My test bench doesn't produce errors or warnings, either. However, the simulation comes up completely blank, except for the names of the signals.
I've tried looking at a multitude of other MUX examples online (as well as a bench test example from the book), all of which gave errors when I tried sythesizing them, so I wasn't confident enough to use them as guides and didn't get much out of them. I'm not sure what I'm doing wrong here. I'd include an image of the simulation, but I don't have enough rep points :(
Also, I realize that a good MUX should also have cases for when it receives no select input/high impedance values, ect.. In this case, I'm just trying to get the toy model working.
The MUX code is:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity MUXtop is
Port (a, b, sel: in bit;
z: out bit);
end MUXtop;
architecture behav of MUXtop is
begin
choose: process is
begin
if sel = '0' then
z <= b;
else
z <= a;
end if;
end process choose;
end architecture behav;
The test bench code is:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY MUXtest IS
END MUXtest;
ARCHITECTURE behavior OF MUXtest IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT MUXtop
PORT(
a : IN bit;
b : IN bit;
sel : IN bit;
z : OUT bit
);
END COMPONENT MUXtop;
--Inputs
signal a : bit := '0';
signal b : bit := '0';
signal sel : bit := '0';
--Outputs
signal z : bit;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: MUXtop PORT MAP (
a => a,
b => b,
sel => sel,
z => z
);
-- Stimulus process
stimulus: process
begin
wait for 10 ns;
a <= '1';
wait for 10 ns;
sel <= '1';
wait for 10 ns;
b <= '1';
wait;
end process stimulus;
END architecture behavior;
You don't need a use clause for package std_logic_1164 when using type bit (declared in package standard).
Your process statement choose in MUXtop has no sensitivity clause which cause the process to continually execute in simulation. (It won't do anything until you trip over a delta cycle iteration limit which might be set to infinity).
I added a sensitivity list, commented out the superfluous use clauses in the two design units and added some more stimulus steps as well as a final wait for 10 ns; to allow the last action to be seen in your testbench:
library IEEE;
-- use IEEE.STD_LOGIC_1164.ALL;
entity MUXtop is
Port (a, b, sel: in bit;
z: out bit);
end MUXtop;
architecture behav of MUXtop is
begin
choose: process (a, b, sel) -- is
begin
if sel = '0' then
z <= b;
else
z <= a;
end if;
end process choose;
end architecture behav;
LIBRARY ieee;
-- USE ieee.std_logic_1164.ALL;
ENTITY MUXtest IS
END MUXtest;
ARCHITECTURE behavior OF MUXtest IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT MUXtop
PORT(
a : IN bit;
b : IN bit;
sel : IN bit;
z : OUT bit
);
END COMPONENT MUXtop;
--Inputs
signal a : bit := '0';
signal b : bit := '0';
signal sel : bit := '0';
--Outputs
signal z : bit;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: MUXtop PORT MAP (
a => a,
b => b,
sel => sel,
z => z
);
-- Stimulus process
stimulus: process
begin
wait for 10 ns;
a <= '1';
wait for 10 ns;
sel <= '1';
wait for 10 ns;
sel <= '0'; -- added
wait for 10 ns; -- added
b <= '1';
wait for 10 ns; -- added
wait;
end process stimulus;
END architecture behavior;
And that gives:
(clickable)

VHDL code for turning 50MHz into 38KHz doesn't work

I'm having an issue with this code. Theoretically it should turn my 50MHz sign into 36KHz but as i run the simulation it turns out that the ir_38khz doesn't get any value it is unassigned.
Can you help me where i slip?
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.NUMERIC_STD.all;
entity orajelKonverter is
Port ( clk50 : in STD_LOGIC;
rst : in STD_LOGIC;
ir_38khz : out STD_LOGIC);
end orajelKonverter;
architecture Behavioral of orajelKonverter is
signal hz38_ctr : STD_LOGIC_VECTOR(9 downto 0);
signal s38 : std_logic;
begin
clk_generator : process (clk50, rst)
begin
if rst = '1' then
s38 <= '0';
hz38_ctr <= (others => '0');
elsif clk50='1' then
if hz38_ctr = "1010010010" then
hz38_ctr <= (others => '0');
s38 <= not s38;
else
hz38_ctr <= hz38_ctr + "1";
end if;
end if;
end process clk_generator;
ir_38khz <= s38;
end Behavioral;
Here is the picture from the simulation:
You need to initialize your signals to some value OR assert your reset to initialize them in simulation. I personally prefer #1, since signal initial conditions are synthesizable, despite the relatively common misconception that they are not. As a matter of fact, I avoid resets in my designs unless I absolutely need to use them. This is actually recommended by Xilinx. So for example you can do:
signal s38 : std_logic := '0';
This will guarantee that when your simulation starts it knows what to do with the line:
s38 <= not s38;
Previously the simulator was trying to do not U which is U.

pseudorandom pattern generator, output is not changing

I am using modelsim for simulating a pseudo-random pattern generator using the below code. The problem is when i force the data_reg signal to a seed value (ex: 0001010101101111) the data_out shows the same value instead of a random value. i will really appreciate any help i cud get on this one.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity dff is
Port ( CLK : in std_logic;
RSTn : in std_logic;
D : in std_logic;
Q : out std_logic);
end dff;
architecture Behavioral of dff is
begin
process(CLK)
begin
if CLK'event and CLK='1' then
if RSTn='1' then
Q <= '1';
else
Q <= D;
end if;
end if;
end process;
end Behavioral;
VHDL CODE FOR PRBS Generator using LFSR:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity lfsr is
Port ( CLK : in STD_LOGIC;
RSTn : in STD_LOGIC;
data_out : out STD_LOGIC_VECTOR (15 downto 0));
end lfsr;
architecture Behavioral of lfsr is
component dff
Port ( CLK : in std_logic;
RSTn : in std_logic;
D : in std_logic;
Q : out std_logic);
end component;
signal data_reg : std_logic_vector(15 downto 0);
signal tap_data : std_logic;
begin
process(CLK)
begin
tap_data <= (data_reg(1) xor data_reg(2)) xor (data_reg(4) xor
data_reg(15));
end process;
stage0: dff
port map(CLK, RSTn, tap_data, data_reg(0));
g0:for i in 0 to 14 generate
stageN: dff
port map(CLK, RSTn, data_reg(i), data_reg(i+1));
end generate;
data_out <= data_reg after 3 ns;
end Behavioral;
First off. In your LFSR you have a process sensitive to CLK which should only be combinational:
process(CLK) -- Not correct
-- Change to the following (or "all" in VHDL-2008)
process(data_reg)
You could also just implement it as a continuous assignment outside of a formal process which is functionally the same in this case.
When you force data_reg to a value you are overriding the normal signal drivers instantiated in the design. In the GUI the force command defaults to "Freeze". Once that is in place, the drivers can't update data_reg because the freeze force is dominant until you cancel it. In the force dialog select the "Deposit" kind to change the state without overriding the drivers on subsequent clocks.
The Modelsim documentation has this to say about the different force kinds:
freeze -- Freezes the item at the specified value until it is forced again or until it is unforced with a noforce command.
drive -- Attaches a driver to the item and drives the specified value until the item is forced again or until it is unforced with a noforce command. This option is illegal for unresolved signals.
deposit -- Sets the item to the specified value. The value remains until there is a subsequent driver transaction, or until the item is forced again, or until it is unforced with a noforce command
Note: While a lot of instructional materials (unfortunately) demonstrate the use of the std_logic_arith and std_logic_unsigned libraries, these are not actual IEEE standards and shouldn't be used in standard conformant VHDL. Use numeric_std instead or, in your case, just eliminate them since you aren't using any arithmetic from those libraries.

Why it is necessary to use internal signal for process?

I'm learning VHDL from the root, and everything is OK except this. I found this from Internet. This is the code for a left shift register.
library ieee;
use ieee.std_logic_1164.all;
entity lsr_4 is
port(CLK, RESET, SI : in std_logic;
Q : out std_logic_vector(3 downto 0);
SO : out std_logic);
end lsr_4;
architecture sequential of lsr_4 is
signal shift : std_logic_vector(3 downto 0);
begin
process (RESET, CLK)
begin
if (RESET = '1') then
shift <= "0000";
elsif (CLK'event and (CLK = '1')) then
shift <= shift(2 downto 0) & SI;
end if;
end process;
Q <= shift;
SO <= shift(3);
end sequential;
My problem is the third line from bottom. My question is, why we need to pass the internal signal value to the output? Or in other words, what would be the problem if I write Q <= shift (2 downto 0) & SI?
In the case of the shown code, the Q output of the lsr_4 entity comes from a register (shift representing a register stage and being connected to Q). If you write the code as you proposed, the SI input is connected directly (i.e. combinationally) to the Q output. This can also work (assuming you leave the rest of the code in place), it will perform the same operation logically expect eliminate one clock cycle latency. However, it's (generally) considered good design practice to have an entity's output being registered in order to not introduce long "hidden" combinational paths which are not visible when not looking inside an entity. It usually makes designing easier and avoids running into timing problems.
First, this is just a shift register, so no combinational blocks should be inferred (except for input and output buffers, which are I/O related, not related to the circuit proper).
Second, the signal called "shift" can be eliminated altogether by specifying Q as "buffer" instead of "out" (this is needed because Q would appear on both sides of the expression; "buffer" has no side effects on the inferred circuit). A suggestion for your code follows.
Note: After compiling your code, check in the Netlist Viewers / Technology Map Viewer tool what was actually implemented.
library ieee;
use ieee.std_logic_1164.all;
entity generic_shift_register is
generic (
N: integer := 4);
port(
CLK, RESET, SI: in std_logic;
Q: buffer std_logic_vector(N-1 downto 0);
SO: out std_logic);
end entity;
architecture sequential of generic_shift_register is
begin
process (RESET, CLK)
begin
if (RESET = '1') then
Q <= (others => '0');
elsif rising_edge(CLK) then
Q <= Q(N-2 downto 0) & SI;
end if;
end process;
SO <= Q(N-1);
end architecture;

Resources