delay in VHDL register - vhdl

I have simple register which stores value as std_logic_vector. In simulation behavior, the output is delayed by 1 cycle. What is the reason behind that? Is it behavior due to clock'event? How to solve this issue?
Here is the code:
entity fault_reg is
port (
clk : in std_logic;
rst : in std_logic;
reg_in : in std_logic_vector(NUM_PORTS - 1 downto 0);
reg_out : out std_logic_vector(NUM_PORTS - 1 downto 0));
end fault_reg;
architecture Behavioral of fault_reg is
begin
reg_impl : process(clk, rst)
begin
if rst = '1' then
reg_out <= (others => '0');
elsif clk'event and clk='1' then
reg_out <= reg_in;
end if;
end process reg_impl;
end Behavioral;
Here is the waveform:

The process you written is a synchronous process, which is sensitive to the clk and rst signals; the process only "wakes up" to evaluate/update outputs when clk or rst changes. So even though reg_in may change, reg_out will only update on the next rising clock edge (clk'event and clk='1') or reset is asserted (rst = '1').
The timeline breaks down like this:
Rising clock edge.
reg_in changes soon after event #1.
Rising clock edge.
reg_out changes soon after event #3, with the value of reg_in that was present at event #3, which was the value that it changed to in event #2.

Related

Reset from Port to internal components connection

I have a Module consisting from another module. e.g.
entity Layer is
port (
CLK: IN std_logic; -- Clock
DIN: IN std_logic;
RST: IN std_logic -- Reset
); -- Data
end Layer;
architecture Behavioral Layer is
component MVM
port (
CLK: IN std_logic; -- Clock
DIN: IN std_logic; -- Data
RST: IN std_logic -- Reset
);
end component;
signal MVM_RST: std_logic;
port MAP( DIN => DIN, CLK => CLK, RST => MVM_RST);
process(CLK) is
begin
if rising_edge(CLK) then
IF RST='1' then
MVM_RST <= '1';
ELSE
MVM_RST <= '0';
END IF;
END IF;
END PROCESS;
end Behavioral;
The logic behind this is I have several other modules connected to reset (not shown in this example) and want them to reset at different time steps but all at the beginning
(i dont know if this is runable, because i wrote it only as a minimin example)
my module 'MVM' is something like
IF RST='1' THEN
MVM_RESULT <= '0';
ELSE
MVM_RESULT <= DIN;
END IF;
The In port of the top module (the layer) is getting new data every clock cycle except for the first one. The first clock cycle is reserved for a high impulse of the reset signal. It starts with clock 0 to get a 0->1 transition
When I am looking at my simulation, the module receives data from the 3th cycle (or?). but so I am loosing 2 cycles instead of 1 cycle
The problem behind this is the part
if rising_edge(CLK) then
IF RST='1' then
MVM_RST <= '1';
ELSE
MVM_RST <= '0';
END IF;
As far as I understand, it means in the first cycle MVM_Res is seted to 1 (which is correct), at the second clock cycle is set to 0, this means for me it can receive data from the 3th cycle (or?)
How to avoid the delay of two cycles. I only want a maximum of 1 cycle delay. I also dont want to directly connect my top module-reset to the component-reset
Here is my testbench (I converted the values to std_logic instead std_logic_vectors to have a minimum example)
entity tb_Layer is
end tb_Layer;
architecture TEST of tb_Layer is
component Layer is
port(
CLK,DIN, RST: IN std_logic;
);
end component;
signal CLK, DIN, RST: std_logic;
BEGIN
uut: Layer PORT MAP(
CLK=> CLK, DIN => DIN, RST=> RST);
tb: process
BEGIN
CLK <= '0';
RST <= '1';
DIN <= '0';
wait for 100ns;
CLK <= '1';
wait for 100ns;
RST <= '0';
CLK <= '0';
DIN <= '1';
wait for 100ns;
CLK <= '1';
wait for 100ns;
CLK <= '0';
DIN <= '0';
wait for 100ns;
CLK <= '1';
wait for 100ns;
END PROCESS;
end TEST;
What the component sees:
The problem is that the first edge it transmits the RST high. SO the component sees after half a cycle too late the Reset high. But because of this the component sees a half cycle the 'u' and so the issue occurs.
You still have the same reason as in your other question, the synchronous reset. In that question, you left the stimulating signals undefined in the first clock cycle, and wondered why the result occurred one clock cycle later than you expected. The suggested change removed the first problem, but not your current issue.
BTW, the shown wave diagram does not match the code of the test bench. Therefore, I respond to the wave diagram, because it seems that this is you problem.
Again, the synchronous nature of the internally generated reset signal delays the reset of the component MVM by one cycle:
At the first rising edge of CLK the signal MVM_RST latches the 'U', as this is the value of RST.
At the second rising edge of CLK the signal MVM_RST latches the '1' of RST and resets MVM_RESULT to all zeroes.
At the third rising edge of CLK the signal MVM_RST latches the '0' of RST and let MVM_RESULT take the value of DIN.
If you had evaluated and simulated the shown test bench, it would go like this:
At the first rising edge of CLK the signal MVM_RST latches the '1' of RST and resets MVM_RESULT to all zeroes.
At the second rising edge of CLK the signal MVM_RST latches the '0' of RST and let MVM_RESULT take the value of DIN.
You might want to learn how to display waves of internal signals with your simulator. Then you can look at MVM_RST to see when it is active.

Encoder Debounce VHDL

For practice, I attempted to make a VHDL code to run Rotary encoder hardware. It was full with debounce, quadrature decoder and an up/down counter codes.
Unfortunately, when running simulation with a testbench, my results were disappointing so I decided that each block needs to be analysed separately. For the debounce code, I created a symbol file and produced the circuit below
(clickable)
While attempting to debounce the testbench signal in simulation, I found out that my results were terrible so I believe I am missing something.
(clickable)
The VHDL code for the encoder block can be found here :
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;
ENTITY debounce_a IS
GENERIC( counter_size : INTEGER := 8); --counter size (8 bits gives 51.6 us with 5MHz clock)
PORT(
clk : IN STD_LOGIC; --input clock
bounce_a : IN STD_LOGIC; --input signal to be debounced
result : OUT STD_LOGIC); --debounced signal
END debounce_a;
ARCHITECTURE logic OF debounce_a IS
SIGNAL flipflops : STD_LOGIC_VECTOR(1 DOWNTO 0); --input flip flops
SIGNAL counter_set : STD_LOGIC; --sync reset to zero
SIGNAL counter_out : STD_LOGIC_VECTOR(counter_size DOWNTO 0) := (OTHERS => '0'); --counter output
BEGIN
counter_set <= flipflops(0) xor flipflops(1); --determine when to start/reset counter
PROCESS(clk) -- occurs within a clock event
BEGIN
IF(clk'EVENT and clk = '1') THEN -- can be rising_edge(clk)
flipflops(0) <= bounce_a; -- adresses the signal as a set value
flipflops(1) <= flipflops(0);
If(counter_set = '1') THEN --reset counter because input is changing
counter_out <= (OTHERS => '0'); --set all bits to '0'
ELSIF(counter_out(counter_size) = '0') THEN --stable input time is not yet met
counter_out <= counter_out + 1;
ELSE --stable input time is met
result <= flipflops(1);
END IF;
END IF;
END PROCESS;
END logic;
It could be filled to the brim with unwanted logic because I had a limited idea of what I was doing and I took a friends general debounce code and edited it to try and fit my specific needs.
If anything extra is needed I am willing to provide. I feel like it's a pretty basic error but I just need any sort of help.
Here is a look on the testbench code that I used if that helps identify toggling properties :
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY decodeblock_vhd_tst IS
END decodeblock_vhd_tst;
ARCHITECTURE decodeblock_arch OF decodeblock_vhd_tst IS
-- constants
CONSTANT clk_period : TIME := 20 ns;
CONSTANT num_clk_cycles : INTEGER := 100;
-- signals
SIGNAL b_Input : STD_LOGIC;
SIGNAL b_output : STD_LOGIC;
SIGNAL CLOCK_50 : STD_LOGIC := '0';
COMPONENT decodeblock
PORT (
b_Input : IN STD_LOGIC;
b_output : OUT STD_LOGIC;
CLOCK_50 : IN STD_LOGIC
);
END COMPONENT;
BEGIN
i1 : decodeblock
PORT MAP (
-- list connections between master ports and signals
b_Input => b_Input,
b_output => b_output,
CLOCK_50 => CLOCK_50
);
init : PROCESS
-- variable declarations
BEGIN
b_input <= '0',
'1' after 1.1 ns,
'0' after 2.9 ns,
'1' after 5.1 ns,
'0' after 7.6 ns,
'1' after 9.9 ns,
'0' after 12.5 ns,
'1' after 15.4 ns,
'0' after 18.6 ns,
'1' after 22.1 ns,
'0' after 25.9 ns,
'1' after 29.7 ns,
'0' after 33.8 ns,
'1' after 38.2 ns;
-- variable declarations
for i in 1 to num_clk_cycles loop
CLOCK_50 <= not CLOCK_50;
wait for clk_period/2;
CLOCK_50 <= not CLOCK_50;
wait for clk_period/2;
end loop;
WAIT;
END PROCESS init;
always : PROCESS
-- optional sensitivity list
-- ( )
-- variable declarations
BEGIN
-- code executes for every event on sensitivity list
WAIT;
END PROCESS always;
END decodeblock_arch;

Unexpected behavior of simple VHDL circuit

What the cause of different delays of signals Q_VLD1 and Q_VLD2 in simulator?
Result of simulation. Is it expected behaviour of simulator or not?
I use Xilinx Isim.
There is the code and testbench for it:
entity assign_test is
port(CLK : in STD_LOGIC;
D_VLD : in STD_LOGIC;
Q_VLD1 : out STD_LOGIC;
Q_VLD2 : out STD_LOGIC
);
end assign_test;
architecture Behavioral of assign_test is
signal D_VLD_i : std_logic;
signal d_vld_dly1 : std_logic;
signal d_vld_dly2 : std_logic;
begin
D_VLD_i <= D_VLD;
process (clk) is
begin
if rising_edge(clk) then
d_vld_dly1 <= D_VLD;
d_vld_dly2 <= D_VLD_i;
end if;
end process ;
Q_VLD1 <= d_vld_dly1;
Q_VLD2 <= d_vld_dly2;
end Behavioral;
ENTITY tb_assign_test IS
END tb_assign_test;
ARCHITECTURE behavior OF tb_assign_test IS
COMPONENT assign_test
PORT(
CLK : IN std_logic;
D_VLD : IN std_logic;
Q_VLD1 : OUT std_logic;
Q_VLD2 : OUT std_logic
);
END COMPONENT;
--Inputs
signal CLK : std_logic := '0';
signal D_VLD : std_logic := '0';
--Outputs
signal Q_VLD1 : std_logic;
signal Q_VLD2 : std_logic;
constant CLK_period : time := 10 ns;
BEGIN
uut: assign_test PORT MAP (
CLK => CLK,
D_VLD => D_VLD,
Q_VLD1 => Q_VLD1,
Q_VLD2 => Q_VLD2
);
CLK_process :process
begin
CLK <= '0';
wait for CLK_period/2;
CLK <= '1';
wait for CLK_period/2;
end process;
stim_proc: process
begin
wait for 100 ns;
wait for 5 ns;
wait for CLK_period*10;
D_VLD <= '1';
wait for CLK_period*3;
D_VLD <= '0';
wait;
end process;
END;
So if you look at the internal signals in the assign_test module, based on simulation time only, it may look as in figure below (d_vld_dly* is before assign to Q_VLD*).
But the figure is misleading, since that figure does not show the VHDL concept of delta delay. If the waveform is expanded to show delta delays (using ModelSim in this case), it looks like below.
So this reveals that the D_VLD_i <= D_VLD; in the assign_test actually delays the D_VLD_i a delta delay, whereby the new value is not seen at the clock until next rising clock edge.
The reason for this problem, is that the test bench does not generate input data as a cause of the clock, which would make data one delta delay after the clock, but independently and at the same simulation time and same delta delay as the clock.
The test bench can be updated to generate data as a cause of the clock, if wait for clock is changed from:
wait for CLK_period*10;
to:
for i in 1 to 10 loop
wait until rising_edge(CLK);
end loop;
which will then give a waveform as:
So based on this, a rule for good test bench design is to generate stimuli the same way as generating data in synthesized modules, so the stimuli from the test bench is like data between modules in general, in order to get expected and reliable and test bench behavior.

Why does incrementing a std_logic_vector give unknown value?

I'm attempting to write a I2C bus master in VHDL - and thoroughly test it to ensure it works etc. In doing so, I've written the module and a subsequent test-bench to test it under different stimuli - namely changing addresses and data input after each sending cycle (which is when the busy goes low).
To do this, I first attempted to increment the value in the data bus and decrement the values in the address bus, using the techniques described in this question here. However, when I did this, rather than the address bus taking the new value, it takes an uninitialised value and the assignment statement doesnt seem to execute.
I then attempted to use an intermediate integer signal, however this produced the same results, however this means that the address & data buses take the correct value for the first cycle - but then don't increment and instead take a unknown state!
Ultimately my question is why do these errors occur - and how do I fix/avoid them?
My code for the I2C master module can be found here and the code for the I2CBus (testbench) can be found here. Any other information I can provide to help please just say!
Thanks very much,
David
-----Code using intermediate signals------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
ENTITY I2CBus IS
END I2CBus;
ARCHITECTURE behavior OF I2CBus IS
COMPONENT IIC_Master
PORT(
CLOCK : IN std_logic;
RESET_N : IN std_logic;
ENA : IN std_logic;
ADR : IN std_logic_vector(6 downto 0);
RW : IN std_logic;
DAT_WR : IN std_logic_vector(7 downto 0);
DAT_RD : OUT std_logic_vector(7 downto 0);
BUSY : OUT std_logic;
SCL : INOUT std_logic;
SDA : INOUT std_logic;
ACK_ERR : BUFFER std_logic
);
END COMPONENT;
--Inputs
signal CLOCK : std_logic := '0';
signal RESET_N : std_logic; --active high
signal ENA : std_logic; --active high
signal ADR : std_logic_vector(6 downto 0);
signal RW : std_logic; --read high write low
signal DAT_WR : std_logic_vector(7 downto 0);
--BiDirs
signal SCL : std_logic;
signal SDA : std_logic;
--Outputs
signal DAT_RD : std_logic_vector(7 downto 0);
signal BUSY : std_logic;
signal ACK_ERR : std_logic;
-- Clock period definitions
constant CLOCK_period : time := 5 ns;
--Signals to vary
signal address : integer := 127;
signal input_data : integer := 0;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut : IIC_Master PORT MAP(
CLOCK => CLOCK,
RESET_N => RESET_N,
ENA => ENA,
ADR => ADR,
RW => RW,
DAT_WR => DAT_WR,
DAT_RD => DAT_RD,
BUSY => BUSY,
SCL => SCL,
SDA => SDA,
ACK_ERR => ACK_ERR
);
-- Clock process definitions
CLOCK_process : process
begin
CLOCK <= '0';
wait for CLOCK_period / 2;
CLOCK <= '1';
wait for CLOCK_period / 2;
end process;
-- Reset process
reset : process
begin
reset_n <= '0';
ADR <= "1111111"; --This doesn't seem to happen the first time?
DAT_WR <= "00000000"; --Nor does this?
RW <= '0';
wait for 50 ns;
reset_n <= '1';
ENA <= '1';
wait;
end process;
stim_proc : process
begin
DAT_WR <= std_logic_vector(to_unsigned(input_data, 8));
ADR <= std_logic_vector(to_unsigned(address, 7));
if input_data < 127 then
address <= address - 1;
input_data <= input_data + 1;
wait until BUSY = '0' and RESET_N = '1';
elsif unsigned(DAT_WR) > 126 then
wait;
end if;
end process;
end behavior;
------1st Stimulus Process w/out intermediate signals
stim_proc : process
begin
if input_data < 127 then
wait until BUSY = '0' and RESET_N = '1';
ADR <= std_logic_vector(unsigned(ADR) + 1);
DAT_WR <= std_logic_vector(unsigned(DAT_WR) + 1);
elsif unsigned(DAT_WR) > 126 then
wait;
end if;
end process;
Results from second simulation using intermediate signals
The usual cause of this is the resolution of multiple assignments to signals like ADR in several different processes. In hardware terms. this is equivalent to short circuiting together the output of several different ICs. (It doesn't work without special care, and can destroy your ICs).
So check that you are assigning ADR and similar signals in only one process, and if necessary, rewrite to combine those processes into one process.
If you need to connect several outputs together, there are 2 ways that work successfully, though I don't think it's the right approach here.
Wired-OR outputs (or Wired-AND). In Wired-OR scheme the signal is permanently pulled weakly low by an assignment like ADR <= (others -> 'L'); and this can be overridden by each output driving either 'Z' for low or '1' for high. This works because multiple outputs can safely drive the signal at once.
Tri-state outputs, with arbitration to make sure only one process drives the output at any time. The others all drive 'Z' or (others => 'Z') onto the same signal, to signify they are inactive.
The answer from Brian Drummond is correct. I just wand to explain in at your example. At time 0, both the reset as well as the stim_proc process assign the same value:
reset : process
begin
...
ADR <= "1111111";
...
end process;
and
stim_proc : process
begin
ADR <= std_logic_vector(to_unsigned(address, 7)); -- with address = 127
...
end process;
So, the result for ADR is "1111111". But after decrementing address (in original code with intermediate version), the stim_proc process assigns a different value (than the reset process) after it starts over. You see this in the waveform. When address gets 126, which is "1111110", only the lowest bit of ADR gets X because only this bit differs from "1111111" assigned in the reset process.
Solution 1
If you just want to initialize a signal, assign the initialization value at the signal declaration. (I think, this is what you want according to your VHDL comment.) That is:
signal ADR : std_logic_vector(6 downto 0) := (others => '1');
Solution 2
If you (really) want to assign "1111111" only for the first 50 ns seconds from the reset process, then you have to assign (others => 'Z') (tri-state), (others => 'Z') (weak pull-down) or (others => 'H') (weak pull-up) afterwards in this process to allow an "overriding" by the stim_proc process, e.g.:
reset : process
begin
ADR <= "1111111";
wait for 50 ns;
ADR <= (others => 'Z');
wait;
end process;

Signal led cannot be synthesized, bad synchronous description?

I have created a frequency divider, and I want to test it using a FPGA board. To test it I want to make a led flicker with the divided frequency, if a switch is on. The problem is that I do't know how to change the value of the led if clock is not on rising edge.
Here is the exact error I get:
line 51: Signal led cannot be synthesized, bad synchronous description. The description style you are using to describe a synchronous element (register, memory, etc.) is not supported in the current software release.
-->
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity divizor1 is
Port (clk : in STD_LOGIC;
--clk_out : out STD_LOGIC;
btn : in STD_LOGIC;
led : out STD_LOGIC
);
end entity divizor1;
architecture divizor_frecv of divizor1 is
signal cnt : std_logic_vector (24 downto 0);
signal clock :std_logic;
signal bec : std_logic;
begin
process(clk)
begin
if rising_edge(clk) then
cnt<=cnt +1;
end if;
if (cnt = "1111111111111111111111111") then
--clk_out <= '1';
clock <= '1';
else
-- clk_out <= '0';
clock <= '0';
end if;
end process;
process (clock, btn)
begin
if btn = '1' then
if clock'event and clock = '1' then
led <= '1';
else
led <= '0';
end if;
end if;
end process;
end divizor_frecv;
The error message appears to be complaining that you are using the output of the cnt counter as a clock.
Instead you could use it as a toggle enable and clk as the clock:
--process (clock, btn)
process (clk, btn)
begin
-- if btn = '0' then
if btn = '1' then -- reset led
led <= '0'; -- or '1' which ever turns it off
-- if clock'event and clock = '1' then
elsif clock = '1' and rising_edge(clk) then -- clock as enable
-- led <= '1';
led <= not led;
-- else
-- led <= '0';
end if;
-- end if;
end process;
The state of btn made a convenient reset to provide an initial value for led to be able to use not led. This either requires the port signal led be made mode inout or you need a proxy variable or signal which is assigned to led so the not led works (so led can be read). A default value for cnt would also help simulation.
I cheated and made your counter cnt shorter and set the clock to 4 MHz to illustrate:
The simulation was done using ghdl and gtkwave.
process (clock, btn)
begin
if btn = '1' then
if clock'event and clock = '1' then
led <= '1';
else
led <= '0';
end if;
end if;
end process;
At a first glance, I would have guessed the button was a clock enable here. However, the else part is connected to the clock. So you've asked for led to go high at the rising clock edge and low at all other times; given that the clock edge is an instant, this doesn't make much sense (it would always be low). I expect you want to update led based on some other state on the clock edge, for instance:
process (clock)
begin
if clock'event and clock = '1' then
led <= btn;
end if;
end process;
If all you wanted was for the LED to indicate the clock pulses (which may well be too fast to detect) you could just route clock directly to led. Your divider is already producing very short pulses (usually we aim for 50% duty cycle, this has 0.000003%).

Resources