D-latch with both asynchro and synchro resetting in VHDL - vhdl

I have to implement a D-latch that follows asynchronnous resetting when aclrn=0 and synchronnous when sclrn=0. The implementation should be able to follow both methods of resetting.
Here's what I came up with in VHDL (I only include the process) based on basic D-latches.
process(aclrn,clock)
begin
if (aclrn='0') then
q <= '0';
elsif (rising_edge(clock)) then
if (sclrn='0') then
q <= '0';
else
q <= d;
end if;
end if;
end process;
where
clock, d, aclrn, sclrn : in std_logic; q : out std_logic
Am I correct that the process doesn't need to take in sclrn as an argument, but only aclrn and clock? Are there any other inconsistencies?
Thank you in advance.

You say D-latch but coded flipflop. Do you really need a D-latch or you are just using latch instead of register carelessly?
if you really need a flipflop, you have done it right.
You have put aclrn and clock in sensitivity list which is right. You don't need to put sclrn in list because it is synchronous.
Xilinx XST tutorial example for Flip-Flop With Positive-Edge Clock and Synchronous Set
architecture archi of registers_3 is
begin
process (C)
begin
if (C'event and C='1') then
if (S='1') then
Q <= '1';
else
Q <= D;
end if;
end if;
end process;
end archi;
and XST coding example for Flip-Flop With Positive-Edge Clock and Asynchronous Reset
architecture archi of registers_2 is
begin
process (C, CLR)
begin
if (CLR = '1')then
Q <= '0';
elsif (C'event and C='1')then
Q <= D;
end if;
end process;
end archi;
By mixing these two you get your answer. I see nothing wrong with your code. best way to know if you've code what you are asked is to simulate it.
If you need latch, notice that latches are sensitive to levels instead of edges. this is an example of LATCH with positive gate and async reset
architecture archi of latches_2 is
begin
process (CLR, D, G)
begin
if (CLR='1') then
Q <= '0';
elsif (G='1') then
Q <= D;
end if;
end process;
end archi;

Related

VHDL error "Process clocking is too complex."

Hello everyone I recently started coding in VHDL(code here is of T flip flop) and I'm having an error which says "Process clocking is too complex", and this is with the first code attached below and surprisingly I the solution too. But I don't know how it worked, code without error is Second code. I googled about the error for half hour but couldn't find the satisfying reason. Please help.
First code:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY t_ff IS
PORT(t,clk,rst:IN STD_LOGIC;
q,q_bar:OUT STD_LOGIC);
END t_ff;
ARCHITECTURE t_ff OF t_ff IS
SIGNAL temp: STD_LOGIC;
BEGIN
PROCESS(clk,rst)
BEGIN
IF(clk='1' AND clk'event)THEN
IF(t='1')THEN temp<= NOT temp;
END IF;
ELSIF(rst='1')THEN temp<='0';
END IF;
q<= temp;
q_bar<= NOT temp;
END PROCESS;
END t_ff;
Second code:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY t_ff IS
PORT(t,clk,rst:IN STD_LOGIC;
q,q_bar:OUT STD_LOGIC);
END t_ff;
ARCHITECTURE t_ff OF t_ff IS
SIGNAL temp: STD_LOGIC;
BEGIN
PROCESS(clk,rst)
BEGIN
IF(rst='1')THEN temp<='0';
ELSIF(clk='1' AND clk'event)THEN
IF(t='1')THEN temp<= NOT temp;
END IF;
END IF;
q<= temp;
q_bar<= NOT temp;
END PROCESS;
END t_ff;
The reason is quite simple. But first we need to change your code:
Neither version describes the behaviour of a T flip-flop; both describe the behaviour of at least 2, if not 3 flip-flops. This is because
every signal assignment in a clocked process infers a flip-flop
There are 3 signal assignments in each process - to temp, q and q_bar - so you will get 3 flip-flops (though 1 is redundant and so may be optimised away by your synthesiser). So, first, if you want to guarantee that you only have one flip-flop, you need to rewrite each process so that there is only one signal assignment contained within it.
There's no point in re-writing the first process, because it's wrong for other reasons - see later. The second process should be rewritten to something like this:
PROCESS(clk,rst)
BEGIN
IF (rst='1') THEN temp<='0';
ELSIF (clk='1' AND clk'event) THEN
IF (t='1') THEN temp <= NOT temp;
END IF;
END IF;
END PROCESS;
q <= temp;
q_bar <= NOT temp;
In other words, you need to move the assignments to q and q_bar outside the process. This new version of your second version describes the behaviour of a T-type flip-flop with an asynchronous reset:
if the reset is asserted then reset the flip-flop; otherwise, if the T
input is asserted at the rising edge of the clock, then invert the
flip-flop
Had I rewritten your first version, it would describe the behaviour of some electronic component that doesn't exist, so it would not be able to be synthesised. There is no such flip-flop with this behaviour:
if the T
input is asserted at the rising edge of the clock, then invert the
flip-flop; otherwise, if the reset is asserted then reset the flip-flop
You could have described a T type flip-flop with a synchronous reset:
at the rising edge of the clock: if the reset is asserted then reset
the flip-flop, otherwise, if the T input is asserted at the rising
edge of the clock, then invert the flip-flop
like this
PROCESS(clk)
BEGIN
IF (clk='1' AND clk'event) THEN
IF (rst='1') THEN temp<='0';
ELSIF (t='1') THEN temp <= NOT temp;
END IF;
END IF;
END PROCESS;
q <= temp;
q_bar <= NOT temp;
Finally, you are using a rather old-fashioned coding style. I would recommend the use of the rising_edge function. Also your brackets are redundant. An experienced VHDL code would write your second version like this:
PROCESS(clk,rst)
BEGIN
IF rst='1' THEN temp<='0';
ELSIF rising_edge(clk) THEN
IF t='1' THEN temp<= NOT temp;
END IF;
END IF;
END PROCESS;
q <= temp;
q_bar <= NOT temp;

Signal temp2 cannot be synthesized, bad synchronous description

entity timer is
Port ( click : in STD_LOGIC;
clear : out STD_LOGIC;
t_unlock : out STD_LOGIC);
end timer;
architecture Behavioral of timer is
signal temp2 : integer range 0 to 20 := 0;
begin
process
begin
if rising_edge(click) then
temp2<=0;
clear<='0';
t_unlock<='0';
else
temp2<=temp2+1 after 15 ns;
end if;
if temp2=6 then
clear<='1';
elsif temp2=20 then
t_unlock<='1';
end if;
end process;
end Behavioral;
I have writted this code.And the complier say:
Signal temp2 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.
I have searched on stackoverflow.They say The error 'bad synchronous description' usually means that you have described a register (clocked element) that does not exist in the hardware.But I don't know how to solve my problem.
The VHDL has to follow some synthesis tool specific coding guidelines, for the tool to be able to translate the VHDL code into the FPGA implementation. For implementation to a flip-flop with asynchronous reset, the style can be:
process (clk, rst) is
begin
-- Clock
if rising_edge(clk) then
... -- Update at clock
end if;
-- Asynchronous reset
if rst = '1' then
... -- Update at reset
end if;
end process;
In the case of your code it looks like you are not using the asynchronous reset, thus the template may be reduced to:
process (clk) is
begin
if rising_edge(clk) then
... -- Update at clock
end if;
end process;
The exercise is now for you to fit your code into that template, and unfortunately it is pretty hard to determine the exact intention based on the provided code.
Your code seems to mix concepts of HDL and "software" languages. I'm not sure what it's supposed to do, but I would refactor it into the code below
architecture Behavioral of timer is
constant COUNTER_VALUE_TO_REACH_15ns : integer := <some value>;
signal temp2 : integer range 0 to 20 := 0;
signal divider : std_logic_vector(7 downto 0) := (others => '0');
begin
process
begin
-- Everything happens when the clock ticks, except for reset
if rising_edge(click) then
temp2 <= 0;
clear <= '0';
t_unlock <= '0';
-- Count how many cycles until we need to increment temp2
if divider = COUNTER_VALUE_TO_REACH_15ns then
temp2 <= temp2 + 1;
divider <= (others => '0'); -- Reset the counter when we reach the required amount of time
else
divider <= divider + 1;
end if;
if temp2 = 6 then
clear <= '1';
elsif temp2 = 20 then
t_unlock <= '1';
end if;
else
end if;
end process;
end Behavioral;

how to avoid delay in the output of simple process statement in VHDL

i am a beginner in VHDL. i want ot know why there is a delay of one cycle in the following code.and how to avoid it..at the same time in verilog the statement always #(posedge clk) dont have any delay.. how to do the same in VHDL
library IEEE;
use IEEE.std_logic_1164.all;
-- entity
entity t_ff_s is
port ( T,S,CLK : in std_logic;
Q : out std_logic);
end t_ff_s;
-- entity
architecture my_t_ff_s of t_ff_s is
signal t_tmp : std_logic; -- intermediate signal declaration
begin
tff: process (S,rising_edge(clk))
begin
if (S = '0') then
t_tmp <= '1';
--elsif (rising_edge(CLK)) then
else
t_tmp <= T XOR t_tmp; -- temp output assignment
end if;
end process tff;
Q <= t_tmp; -- final output assignment
end my_t_ff_s;
Sensitivity lists in VHDL don't take an edge specification like in Verilog. VHDL is more flexible in that you can freely use the 'event signal attribute anywhere within a process to implement edge triggered behavior. You can mix level and edge sensitive logic without resorting to split blocks/processes or hacks like negedge for resets. Function calls like rising_edge(clk) (which implements a test for clk'event) are not permitted in a sensitivity list. It only contains signal names. Your code won't compile as is.
If some other syntactically correct version of your code compiles cleanly, the delays you see are artifacts of the simulation model or having a broken sensitivity list. If you want a synchronous clock driven process then you only need the clock signal and possibly an asynchronous reset in the sensitivity list.
Consider the following process:
tff: process(S, clk)
begin
if S = '0' then -- Asynchronous reset (level sensitive)
t_tmp <= '1';
elsif rising_edge(clk) then -- Synchronous logic (edge sensitive)
t_tmp <= T xor t_tmp;
end if;
end process;
Q <= t_tmp;
This process executes when an event occurs on S or clk. If S is '0' then the reset condition is executed with priority over the elsif clause (clk is a don't-care). The assignment to t_tmp takes effect on the next delta cycle which is still the same as the current simulation time. Otherwise, if rising_edge(clk) evaluates to true then an event occurred on clk and it's state changed from '0' (or 'L') to '1' (or 'H') indicating that the event was a rising edge. The synchronous assignment takes place and the new xored t_tmp takes effect on the next delta cycle. Changes in T don't cause the process to execute since it isn't (and shouldn't be) in the sensitivity list.
Because there is no unconditional else clause the t_tmp signal retains its last assigned value if both of the two if conditions are false. It will change the next time there is an event on S or clk that causes a new assignment to t_tmp. This will either be the next clock edge or a re-application of asynchronous reset.
The assignment to Q is continuous and is effectively the same as a process with t_tmp in its sensitivity list. As a consequence, the assignment to Q takes place a delta cycle after events on t_tmp which is two delta cycles after the rising edge. If Q is feeding into logic that updates earlier than the second delta cycle of an edge, it will appear to take an extra clock cycle for it to propagate.
The behavior surrounding delta cycles can sometimes create confusing results when inspecting waveforms. You may have a rising edge that should capture a data input that appears to transition simultaneously on the same time step when, in fact, the data is transitioning on a later delta cycle and will only be captured on the next clock edge.
Similarly, if you construct a simple gated clock without any time delay, its edges will occur at the same time but on later delta cycles than the ungated version of the clock. Data driven from the "earlier" ungated clock will be captured by the gated logic a clock cycle earlier than expected as a result. Data driven the other direction will appear to have an unexpected delay by a clock cycle.
It isn't clear what is causing the problem you see without more information on how you're driving the S, T, and clk signals but it is likely connected to the delta cycle behavior of the simulation engine in some way.
The problem
A little more succinctly than Kevin, rising_edge is an expression and not a signal, a sensitivity list requires a named signal, a transaction on which you resume execution of a suspended process. Put the elsif back in and have only S and clk in the sensitivity list.
Note that because t_tmp isn't in the sensitivity list, you won't see Q follow t_tmp until the next clock event causing the delay you noted.
The fixed syntax process:
tff: process (S,clk) -- was (S, risingedge(CLK)), a syntax error)
begin
if (S = '0') then
t_tmp <= '1';
elsif (rising_edge(CLK)) then -- put back
-- else
t_tmp <= T XOR t_tmp; -- temp output assignment
end if;
Q <= t_tmp; -- final output assignment
end process tff;
Which shows the delay between t_tmp and Q:
(clickable)
Fix it by making Q a concurrent signal assignment
To cure the half clock delay you could make the assignment to Q a concurrent signal assignment statement (move it outside of the process).
tff:
process (S, clk)
begin
if S = '0' then
t_tmp <= '1';
elsif rising_edge(clk) then
t_tmp <= T xor t_tmp;
end if;
end process;
Q <= t_tmp; -- concurrent signal assignment
Which gives:
(clickable)
And you can see above that t_tmp and Q are now in phase.
Fix it by making t_tmp a variable
You could also declare t_tmp as a variable in process dff instead of a signal and switching assignments to it as variable assignments will also cure the one clock delay between t_tmp and Q.
tff:
process (S, clk)
variable t_tmp: std_logic;
begin
if S = '0' then
t_tmp := '1';
elsif rising_edge(clk) then
t_tmp := T xor t_tmp;
end if;
Q <= t_tmp;
end process;
Which shows:
(clickable)
And ghdl using gtkwave doesn't output variables or show delta cycles. You can see Q occurs on the rising edge of the clock.
Making t_tmp a variable also has the effect of eliminating a delta cycle between a transaction on t_tmp and a transaction on Q.
Eliminating delta cycles makes your model execute faster (while occurring at the current simulation time). Signal assignments don't take effect while any process is executing and variable assignments take effect immediately.
Fix it by adding t_tmp to the sensitivity list
And alternatively you could just add t_tmp to the sensitivity list (along with S and clk).
tff:
process (S, clk, t_tmp)
begin
if S = '0' then
t_tmp <= '1';
elsif rising_edge(clk) then
t_tmp <= T xor t_tmp;
end if;
Q <= t_tmp;
end process;
(clickable)
And this is slower than all the rest of the fixes because the if statement is executed each time t_tmp has an event as well as S or CLK. rising_edge is a function call which dynamically elaborates it's interface list, a significant simulator performance penalty particularly if you use a lot of these primitives.
These were done with a test bench:
library IEEE;
use IEEE.std_logic_1164.all;
-- entity
entity t_ff_s is
port ( T,S,CLK : in std_logic;
Q : out std_logic);
end entity t_ff_s;
architecture my_t_ff_s of t_ff_s is
signal t_tmp : std_logic; -- intermediate signal declaration
begin
tff: process (S,clk) -- was (S, risingedge(CLK)), a syntax error)
begin
if (S = '0') then
t_tmp <= '1';
elsif (rising_edge(CLK)) then -- put back
-- else
t_tmp <= T XOR t_tmp; -- temp output assignment
end if;
Q <= t_tmp; -- final output assignment
end process tff;
end my_t_ff_s;
architecture foe of t_ff_s is
signal t_tmp: std_logic;
begin
tff:
process (S, clk)
begin
if S = '0' then
t_tmp <= '1';
elsif rising_edge(clk) then
t_tmp <= T xor t_tmp;
end if;
end process;
Q <= t_tmp; -- concurrent signal assignment
end architecture;
architecture fie of t_ff_s is
begin
tff:
process (S, clk)
variable t_tmp: std_logic;
begin
if S = '0' then
t_tmp := '1';
elsif rising_edge(clk) then
t_tmp := T xor t_tmp;
end if;
Q <= t_tmp;
end process;
end architecture;
architecture fee of t_ff_s is
signal t_tmp: std_logic;
begin
tff:
process (S, clk, t_tmp)
begin
if S = '0' then
t_tmp <= '1';
elsif rising_edge(clk) then
t_tmp <= T xor t_tmp;
end if;
Q <= t_tmp;
end process;
end architecture;
library ieee;
use ieee.std_logic_1164.all;
entity test_tff is
end entity;
architecture foo of test_tff is
signal CLK: std_logic := '0';
signal T: std_logic := '0';
signal S: std_logic := '0';
signal Q: std_logic;
component t_ff_s is
port (
signal CLK: in std_logic;
signal T: in std_logic;
signal S: in std_logic;
signal Q: out std_logic
);
end component;
begin
DUT:
t_ff_s
port map (
T => T,
S => S,
CLK => CLK,
Q => Q
);
CLOCK:
process
begin
wait for 10 ns;
CLK <= not CLK;
if Now > 250 ns then
wait;
end if;
end process;
SET:
process
begin
S <= '0';
wait for 20 ns;
S <= '1';
wait;
end process;
TOGGLE:
process
begin
wait for 20 ns;
T <= '1';
wait for 60 ns;
T <= '0';
wait for 40 ns;
T <= '1';
wait;
end process;
end architecture;
configuration my_t_ff_s_config of test_tff is
for foo
for DUT: t_ff_s
use entity work.t_ff_s(my_t_ff_s);
end for;
end for;
end configuration;
configuration concurrent_config of test_tff is
for foo
for DUT: t_ff_s
use entity work.t_ff_s(foe);
end for;
end for;
end configuration;
configuration variable_config of test_tff is
for foo
for DUT: t_ff_s
use entity work.t_ff_s(fie);
end for;
end for;
end configuration;
configuration sensitivity_config of test_tff is
for foo
for DUT: t_ff_s
use entity work.t_ff_s(fee);
end for;
end for;
end configuration;
note the use of configuration
Using VHDL's configuration declarations to allow the use of multiple architectures. (my_t_ff_s - the original, foe - with concurrent assignment to Q, fie - with t_tmp as a variable and fee - with t_tmp in the sensitivity list).
And amazingly enough ghdl's analyzer was quite helpful getting the configuration declarations syntax right. Once you get the first one, the others are easy.
We tend to get rusty using configuration, it wasn't generally supported historically by synthesis tools. But then again, this is simulation for verification.
And for those with ghdl and gtkwave this is how it was done:
ghdl -a t_ff.vhdl
ghdl -e my_t_ff_s_config
ghdl -e concurrent_config
ghdl -e concurrent_config
ghdl -e sensitivity_config
ghdl -r my_t_ff_s_config --wave=test_tff_my_t_ff_s.ghw
ghdl -r concurrent_config --wave=test_tff_foe.ghw
ghdl -r variable_config --wave=test_tff_fie.ghw
ghdl -r sensitivity_config --wave=test_tff_fee.ghw
GHW is ghdl's native waveform dump file format, understood by gtkwave.
In gtkwave:
open t_ff_s.gtkw (reads in test_tff_my_t_ff_s.ghw)
(otherwise read in test_tff_my_t_ff_s.ghw and add signals to
waveform display, format the window, save save file to t_ff_s.gtkw)
new tab open test_tff_foe.ghw
read save file open t_ff_s.gtkw
new tab open test_tff_fie.ghw
read save file open t_ff_s.gtkw
new tab open test_tff_fee.ghw
read save file open t_ff_s.gtkw
Note ghdl doesn't save variable state or delta cycles, t_tmp won't show up in the waveform for test_ff_fie.ghw.

Place and route timing strategy

This sounds very naive, but i would like your expert comments on the below pseudo-code. Which of the 2 methods below can achieve minimal place & route timing when implemented in hardware.
Method:1
control_proc: process(clk)
begin
if(clk'event and clk=='1') then
if sig_delay == 1 then
sig_ctrl <= '1';
else
sig_ctrl <= '0';
end if;
end if;
end process
delay_proc: process(clk)
begin
if(clk'event and clk=='1') then
if <some-condition> then
sig_delay <= '1';
else
sig_delay <= '0';
end if;
end if;
end process
Method:2
control_single_proc: process(clk)
begin
if(clk'event and clk=='1') then
if <some-condition> then
sig_delay <= '1';
else
sig_delay <= '0';
end if;
if sig_delay == 1 then
sig_ctrl <= '1';
else
sig_ctrl <= '0';
end if;
end if;
end process
Note:
sig_ctrl is used as a CE (chip enable) for another component in the hierarchy, which is kind of bit serialiser.
Your two methods are equivalent. Any good synthesis tool will be able to perform the same optimisations on both cases.
The sorts of things that might prevent a synthesis tool from optimising logically equivalent hardware are entity hierarchy / design partition boundaries, however most tools flatten the netlist before optimisation anyway.
Method 2 may perform marginally better in simulation since there are fewer processes to schedule.

Understanding this T Flip-Flop example?

I'm reading a VHDL book and having trouble understanding an example they gave.
The code given:
-------------------------------------------------------------------
-- RET T Flip-flop model with active-low asynchronous set input. --
-------------------------------------------------------------------
-- library declaration
library IEEE;
use IEEE.std_logic_1164.all;
-- entity
entity t_ff_s is
port ( T,S,CLK : in std_logic;
Q : out std_logic);
end t_ff_s;
-- entity
architecture my_t_ff_s of t_ff_s is
signal t_tmp : std_logic; -- intermediate signal declaration
begin
tff: process (S,CLK)
begin
if (S = '0') then
Q <= '1';
elsif (rising_edge(CLK)) then
t_tmp <= T XOR t_tmp; -- temp output assignment
end if;
end process tff;
Q <= t_tmp; -- final output assignment
end my_t_ff_s;
What I don't understand is how they assign multiple signals to Q. Outside of the process statement, it's Q <= t_tmp but inside the process if S='0' then Q <= '1'. How exactly does this work? It looks wrong to me with my limited understanding of VHDL. Basically, this looks the same to me as if writing:
Q <= '0';
Q <= '1';
Can anyone help me better understand this example better?
You're right to question the example. It's broken.
Q <= '1';
should be
t_tmp <= '1';
Somebody realised they couldn't read an output, introduced t_tmp and only changed half the code.

Resources