Generating 2 clock pulses in VHDL - vhdl

How do I generate two clock pulses based on a trigger signal. I have found this code (which works very well) here in stackoverflow :
get_data:process(clk, reset)
variable idle : boolean;
begin
if reset = '1' then
idle := true;
elsif rising_edge(clk) then
clr_flag <= '0'; -- default action
if idle then
if flag = '1' then
clr_flag <= '1'; -- overrides default FOR THIS CYCLE ONLY
idle <= false;
end if;
else
if flag = '0' then
idle := true;
end if;
end if;
end if;
end process;
I was wondering if someone can help me in generating a flag that lasts 2 clock pulses instead of one.

I would just do this:
signal s_flag, s_flag_1z : std_logic := '0';
begin
get_data:process(clk, reset)
variable idle : boolean;
begin
if reset = '1' then
idle := true;
s_flag <= '0';
s_flag_1z <= '0';
elsif rising_edge(clk) then
s_flag <= '0'; -- default action
s_flag_1z <= s_flag;
if idle then
if flag = '1' then
s_flag <= '1'; -- overrides default FOR THIS CYCLE ONLY
idle <= false;
end if;
else
if flag = '0' then
idle := true;
end if;
end if;
end if;
end process;
cl_flag <= '1' when (s_flag & s_flag_1) /= "00" else '0';
Now the flag will be 2 clock cycles high and only a small addition was required.
/Ben

A variable length pulse is cleanest and easiest with a tap at the top of a shift register
get_data:process(clk, reset) --make sure you really want asynchronous reset
variable pulse_line : std_logic_vector(1 downto 0); --set the width to how many clocks you want the pulse
begin
if reset = '1' then --again make sure you really want asynchronous reset
pulse_line := (others => '1');
elsif rising_edge(clk) then
if flag = '1' then
pulse_line := (others => '1'); --reset the shift register
else
pulse_line := pulse_line(pulse_line'high-1 downto 0) & '0'; --push a 0 onto bottom of the shift register
end if;
clr_flag <= pulse_line(pulse_line'high); --tap out the top of the shift register
end if;
end process;

Related

VHDL state machine is skipping states

I am developing a state machine in VHDL and it doesn't' seem to be functioning properly. The design is shown below:
SHARED VARIABLE XM_INDEX : NATURAL RANGE 0 TO 99 := 0;
SIGNAL XM_STATE_INDICATOR : STD_LOGIC_VECTOR (7 DOWNTO 0) := "00000000";
TYPE XM_STATE_TYPE IS (EMPTY, IDLE, POWER_UP, POWER_UP_CONFIRM,
CHANNEL_SELECT, CHANNEL_SELECT_CONFIRM, VOLUME_CHANGE,
VOLUME_CHANGE_CONFIRM, TRANSMIT_CHAR, TRANSMIT_CHAR_CONFIRM,
COMPLETED);
SIGNAL XM_CURRENT_STATE : XM_STATE_TYPE := EMPTY;
SIGNAL XM_NEXT_STATE : XM_STATE_TYPE := EMPTY;
XMStateMachineClock: PROCESS (CLK25, SYS_RST) IS
BEGIN
IF (SYS_RST = '1') THEN
XM_CURRENT_STATE <= EMPTY;
ELSIF (RISING_EDGE(CLK25)) THEN
XM_CURRENT_STATE <= XM_NEXT_STATE;
END IF;
END PROCESS XMStateMachineClock;
XMStateMachine: PROCESS (XM_CURRENT_STATE) IS
BEGIN
-- Pend on current XM state
CASE XM_CURRENT_STATE IS
-- Empty: Debug only
WHEN EMPTY =>
XM_NEXT_STATE <= IDLE;
XM_STATE_INDICATOR <= "00000001";
-- Idle: Idle state
WHEN IDLE =>
IF XM_POWER_UP = '1' THEN
XM_INDEX := 0;
XM_NEXT_STATE <= POWER_UP;
XM_STATE_INDICATOR <= "00000010";
ELSE
-- Remain in idle
XM_NEXT_STATE <= IDLE;
XM_STATE_INDICATOR <= "00000001";
END IF;
WHEN POWER_UP =>
XM_NEXT_STATE <= TRANSMIT_CHAR;
XM_STATE_INDICATOR <= "00000100";
WHEN TRANSMIT_CHAR =>
IF (XM_INDEX < 11) THEN
XM_NEXT_STATE <= TRANSMIT_CHAR_CONFIRM;
XM_STATE_INDICATOR <= "00001000";
ELSE
XM_NEXT_STATE <= COMPLETED;
XM_STATE_INDICATOR <= "00000000";
END IF;
WHEN TRANSMIT_CHAR_CONFIRM =>
XM_INDEX := XM_INDEX + 1;
XM_NEXT_STATE <= TRANSMIT_CHAR;
XM_STATE_INDICATOR <= "00000100";
WHEN COMPLETED =>
XM_NEXT_STATE <= COMPLETED;
XM_STATE_INDICATOR <= "00000000";
-- Default
WHEN OTHERS =>
END CASE;
END PROCESS XMStateMachine;
The state machine is being clocked at 25 MHz. Per my understanding, my state machine should progress between the states as follows:
However, what I see when I hook up my logic analyzer is the following:
It seems as if the state machine is only alternating between the transmit and transmit confirm states once, as opposed to the 11 times that is should, and I cannot figure out why.
If you make XM_INDEX a signal have an XM_INDEX_NEXT that is latched in your XMStateMachineClock process and then change XM_INDEX := XM_INDEX + 1 to XM_INDEX_NEXT <= XM_INDEX + 1. I believe that this will fix your issue. XMStateMachine will also need to be sensitive to XM_INDEX.
The example code isn't compete and there's some chance chaning xm_index from a shared variable might upset some plans for it's use, should more than one process write to it. You could note that the user is responsible for controlling exclusive access in -1993 shared variables.
Creating a MCVE by providing a complete entity and architecture pair:
library ieee;
use ieee.std_logic_1164.all;
entity xm_sm is
port (
clk25: in std_logic;
sys_rst: in std_logic;
xm_power_up: in std_logic
);
end entity;
architecture foo of xm_sm is
-- shared variable xm_index: natural range 0 to 99 := 0;
signal xm_index: natural range 0 to 99 := 0; -- CHANGED to SIGNAL
signal xm_index_nxt: natural range 0 to 99; -- ADDED
signal xm_state_indicator: std_logic_vector (7 downto 0) := "00000000";
type xm_state_type is (EMPTY, IDLE, POWER_UP, POWER_UP_CONFIRM,
CHANNEL_SELECT, CHANNEL_SELECT_CONFIRM,
VOLUME_CHANGE, VOLUME_CHANGE_CONFIRM,
TRANSMIT_CHAR, TRANSMIT_CHAR_CONFIRM,
COMPLETED);
signal xm_current_state: xm_state_type := EMPTY;
signal xm_next_state: xm_state_type := EMPTY;
begin
xmstatemachineclock:
process (clk25, sys_rst) is
begin
if sys_rst = '1' then
xm_current_state <= EMPTY;
xm_index <= 0; -- ADDED
elsif rising_edge(clk25) then
xm_current_state <= xm_next_state;
xm_index <= xm_index_nxt; -- ADDED
end if;
end process xmstatemachineclock;
xmstatemachine:
process (xm_current_state, xm_power_up) is
begin
-- pend on current xm state
case xm_current_state is
-- empty: debug only
when EMPTY =>
xm_next_state <= IDLE;
xm_state_indicator <= "00000001";
-- idle: idle state
when IDLE =>
if xm_power_up = '1' then
xm_index_nxt <= 0;
xm_next_state <= POWER_UP;
xm_state_indicator <= "00000010";
else
-- remain in idle
xm_next_state <= IDLE;
xm_state_indicator <= "00000001";
end if;
when POWER_UP =>
xm_next_state <= TRANSMIT_CHAR;
xm_state_indicator <= "00000100";
when TRANSMIT_CHAR =>
if xm_index < 11 then
xm_next_state <= TRANSMIT_CHAR_CONFIRM;
xm_state_indicator <= "00001000";
else
xm_next_state <= COMPLETED;
xm_state_indicator <= "00000000";
end if;
when TRANSMIT_CHAR_CONFIRM =>
if xm_index = 99 then -- protect again overflow -- ADDED
xm_index_nxt <= 0;
else
xm_index_nxt <= xm_index + 1; -- CHANGED
end if;
-- xm_index_nxt <= xm_index + 1;
xm_next_state <= TRANSMIT_CHAR;
xm_state_indicator <= "00000100";
when COMPLETED =>
xm_next_state <= COMPLETED;
xm_state_indicator <= "00000000";
-- default
when others =>
end case;
end process xmstatemachine;
end architecture;
This changes xm_index to a signal and including a next value as suggested by Alden in his answer. This works as long as there's only one process that writes to it. xm_index is also now set to 0 during reset. Additionally in the TRANSMIT_CHAR_CONFIRM of the xm_currrent_state case statement xm_index is protected against overflow as a matter of course. The range of xm_index (0 to 99) can be limited to the maximum value (11). It raises suspicions that we're not seeing all of the design.
Adding a test bench:
library ieee;
use ieee.std_logic_1164.all;
entity xm_sm_tb is
end entity;
architecture foo of xm_sm_tb is
signal clk25: std_logic := '0';
signal sys_rst: std_logic := '0';
signal xm_power_up: std_logic := '0';
begin
DUT:
entity work.xm_sm
port map (
clk25 => clk25,
sys_rst => sys_rst,
xm_power_up => xm_power_up
);
CLOCK:
process
begin
wait for 50 ns;
clk25 <= not clk25;
if now > 3.1 us then
wait;
end if;
end process;
STIMULI:
process
begin
wait for 100 ns;
sys_rst <= '1';
wait for 100 ns;
sys_rst <= '0';
wait for 200 ns;
xm_power_up <= '1';
wait for 100 ns;
xm_power_up <= '0';
wait;
end process;
end architecture;
and we get:
Where we see we go through all the index values before finishing.
The original code successfully simulated but appears to have not synthesized to a working design due to the combinatorical loop:
XM_INDEX := XM_INDEX + 1;
where xm_loop is latched by a presumably one hot state representation for state TRANSMIT_CHAR_CONFIRM as a latch enable.
In simulation the sensitivity list being devoid of xm_index would prevent the adder from ripple incrementing xm_index. If xm_index had been in the process sensitivity list it would caused a bounds check violation on assignment after reaching 100. (Integer types aren't modular, they don't wrap and aren't proofed against overflow).
In synthesis without seeing the console output we might presume that the ripply time is sufficient to push the value of xm_index above 11 reliably in one clock time without wrapping to less than 11.

ERROR:Xst:827 = Signal count cannot be synthesized, bad synchronous description

I am trying to simulate an elevator and as a result i get the error
ERROR:Xst:827 = Signal count cannot be synthesized, bad synchronous description
I am following the code from this source [https://www.youtube.com/watch?v=i03_-NMwmDs] since mine is very similar,(i have 7 floors and two more elevators). At first i am working with the code mentioned on the video and later i am going to implement two more elevators to work together in this simulation.
Thanks in advance.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity elevator is
port (clk: in std_logic;
sensors1: out std_logic:='0'; --sensors at each level for elevator 1
a1, a2, a3, a4, a5, a6, a7: out std_logic; -- for LED display at FPGA
insideopendoor, in1, in2, in3, in4, in5, in1up, in2up, in3up, in4up, in5up, in5down, in4down, in3down, in2down, in1down: std_logic; -- input request for each floor
opendoor: out std_logic; -- from inside elevator
closedoor: out std_logic); -- from inside elevator
end elevator;
architecture sequence of elevator is
constant timedoorclose: integer := 3;
constant timedoorclosed: integer := 2;
constant time_nx_state: integer :=4;
signal demand: std_logic_vector(0 to 4) := "00000";
signal direction_of_elevator : integer range 0 to 2 := 0;
signal updownpassenger : std_logic := '0';
signal signalstatus: std_logic := '1';
type status is (L1, L2, L3, L4, L5);
signal pr_state, nx_state: status;
begin
main: process (clk, insideopendoor, in1, in2, in3, in4, in5, in1up, in2up, in3up, in4up, in5up, in5down, in4down, in3down, in2down, in1down)
variable digit1 : std_logic_vector (6 downto 0);
variable count : integer range 0 to (time_nx_state + timedoorclose + timedoorclosed);
variable bufferopendoor : std_logic;
variable position : integer range 0 to 4;
variable tempup : integer range 1 to 2 := 1;
variable tempdown : integer range -4 to 4;
begin
if (clk'event and clk='1') then
demand(0) <= demand(0) or in1 or in1up or in1down;
demand(1) <= demand(1) or in2 or in2up or in2down;
demand(2) <= demand(2) or in3 or in3up or in3down;
demand(3) <= demand(3) or in4 or in4up or in4down;
demand(4) <= demand(4) or in5 or in5up or in5down;
case pr_state is
when L1 => position := 0;
when L2 => position := 1;
when L3 => position := 2;
when L4 => position := 3;
when L5 => position := 4;
end case;
for i in 1 to 4 loop
if demand(i) ='1' then
tempup := i - position;
else null;
end if;
end loop;
for i in 3 downto 0 loop
bufferopendoor := '1';
closedoor <= '0';
count := 0;
end loop; --
elsif (updownpassenger = '1') then
if (count < timedoorclose) then
opendoor <= '1';
bufferopendoor := '1';
elsif count < (timedoorclose + timedoorclosed) then
opendoor <= '0';
bufferopendoor := '0';
else
closedoor <= '0';
end if;
--else null; ------
--end if; ------
-----------part main-----------------
count := count +1;
if insideopendoor = '1' then
opendoor<='1';
bufferopendoor :='1';
closedoor <= '0';
count := 0;
elsif (updownpassenger ='1') then
if (count < timedoorclose) then
opendoor <= '1';
bufferopendoor := '1';
closedoor <= '0';
elsif (count < (timedoorclose + timedoorclosed)) then
opendoor <= '0';
bufferopendoor := '0';
closedoor <= '1';
else
closedoor <= '0';
pr_state <= nx_state;
if signalstatus = '1' then
signalstatus <= '0';
else
signalstatus <= '1';
end if;
count := 0;
end if;
else null; --
end if;--
case nx_state is
when L1 =>
digit1 := "1111001";
if demand(0) = '1' then
demand(0) <= '0';
else null;
end if;
when L2 =>
digit1 := "0100100";
if demand(1) = '1' then
demand(1) <= '0';
else null;
end if;
when L3 =>
digit1 := "0110000";
if demand(3) = '1' then
demand(3) <= '0';
else null;
end if;
when L4 =>
digit1 := "0011001";
if demand(3) = '1' then
demand(3) <= '0';
else null;
end if;
when L5 =>
digit1 := "0010010";
if demand(4) = '1' then
demand(4) <= '0';
else null;
end if;
when others => null;
end case;
a1 <= digit1(0);
a2 <= digit1(1);
a3 <= digit1(2);
a4 <= digit1(3);
a5 <= digit1(4);
a6 <= digit1(5);
a7 <= digit1(6);
end if;
end process main;
step: process (pr_state, signalstatus)
begin
case pr_state is
--end if;
when L1 =>
if (demand(0)='1') then
nx_state <= pr_state;
updownpassenger <= '1';
else
updownpassenger <= '0';
if direction_of_elevator = 1 then
nx_state <=L2;
elsif direction_of_elevator = 2 then
nx_state <= pr_state;
else
nx_state <= pr_state;
end if;
end if;
when L2 =>
if (demand(1)= '1') then
nx_state <= pr_state;
updownpassenger <= '1';
else
updownpassenger <= '0';
if direction_of_elevator = 1 then
nx_state <= L3;
elsif direction_of_elevator = 2 then
nx_state <= L1;
else
nx_state <= pr_state;
end if;
end if;
when L3 =>
if (demand(2)= '1') then
nx_state <= pr_state;
updownpassenger <= '1';
else
updownpassenger <= '0';
if direction_of_elevator = 1 then
nx_state <= L4;
elsif direction_of_elevator = 2 then
updownpassenger <= '1';
else
updownpassenger <= '0';
if direction_of_elevator = 1 then
nx_state <= L5;
elsif direction_of_elevator = 2 then
end if;
end if;
end if;
when L5 =>
if (demand(4)='1') then
nx_state <= pr_state;
updownpassenger <= '1';
else
updownpassenger <= '0';
if direction_of_elevator = 1 then
nx_state <= L4;
elsif direction_of_elevator = 2 then
nx_state <= L1;
else
nx_state <= pr_state;
end if;
end if;
when others => null;
end case;
end process step;
end sequence;
Your code seems very mixed up. There is a specific reason why it won't synthesise: think carefully when the code immediately following this line here
elsif (updownpassenger = '1') then
will be executed. It will be executed following a positive edge or negative edge on any input in the sensitivity list, apart from clk where it will be executed only following a negative edge. How would you design logic with such behaviour? Well, your synthesiser can't do it, either.
Basically, you need to refactor your code. You need to split it into sequential and combinational processes. (Combinational logic is logic whose output depends only on it's input and thus is logic that contains no latches or flip-flops. Sequential logic is logic that contains latches or flip-flops, but will also usually contain some gates too. Do not use latches - they are not synchronous design.) Whilst there are many ways to code such processes, it is wise to be consistent by sticking to a template. Here are three templates, which if followed, will give you everything you need and will keep your VHDL coding life simple:
Here is the template for sequential logic with an asynchronous reset, which all synthesis tools should understand:
process(clock, async_reset) -- nothing else should go in the sensitivity list
begin
-- never put anything here
if async_reset ='1' then -- or '0' for an active low reset
-- set/reset the flip-flops here
-- ie drive the signals to their initial values
elsif rising_edge(clock) then -- or falling_edge(clock) or clk'event and clk='1' or clk'event and clk='0'
-- put the synchronous stuff here
-- ie the stuff that happens on the rising or falling edge of the clock
end if;
-- never put anything here
end process;
Here is the template for sequential logic without an asynchronous reset:
process(clock) -- nothing else should go in the sensitivity list
begin
-- never put anything here
if rising_edge(clock) then -- or falling_edge(clock) or clk'event and clk='1' or clk'event and clk='0'
-- put the synchronous stuff here
-- ie the stuff that happens on the rising or falling edge of the clock
end if;
-- never put anything here
end process;
And here is the corresponding template for a combinational process:
process(all inputs in the sensitivity list) -- an 'input' is a signal either on the LHS of an assignment or a signal that is tested
begin
-- combinational logic (with complete assignment and no feedback)
end process;

Simplifying A State Machine To Reduce Logic Levels and Meet Timing

My design at the moment isn't meeting timing. I've tried putting it on a slower clock and pipelining the inputs/outputs. The problem is always the same - too many levels of logic. Have any of you got any tips on making this logic more clock friendly?
signal ctr : std_logic_vector(9 downto 0);
signal sig_bit_shift : std_logic_vector (15 downto 0);
begin
process(clk_p)
begin
if rising_edge(clk_p) then
if rst_i = '1' or nuke = '1' then
ctr <= (others => '0');
state <= ST_IDLE;
elsif unsigned(event_settings) < 1 then -- disables
state <= ST_IDLE;
elsif unsigned(event_settings) = 1 then -- always on
state <= ST_ENABLE;
else
case state is
when ST_IDLE =>
if ctr = (unsigned(event)-2) then
state <= ST_ENABLE;
elsif unsigned(ctr) = 1 and sig = '0' then --catches first word
state <= ST_ENABLE;
elsif sig = '1' then
ctr <= ctr + 1;
end if;
when ST_ENABLE =>
if s_sig = '1' then
state <= ST_IDLE;
if unsigned(s_evt) > 1 then
ctr <= (others => '0');
end if;
end if;
end case;
end if;
end if;
end process;
UPDATE:
process(clk_p)
begin
if rising_edge(clk_p) then
if rst_i = '1' or nuke = '1' then
ctr <= x"00" & "10";
state <= ST_IDLE;
elsif settings = '1' then
case state is
when ST_IDLE =>
if ctr = (unsigned(event)) then
state <= ST_ENABLE;
elsif unsigned(ctr) = 1 and sig = '0' then --catches first word -- this is the part which when added, fails timing
state <= ST_ENABLE;
elsif sig = '1' then
ctr <= ctr + 1;
end if;
when ST_ENABLE =>
if s_sig = '1' then
state <= ST_IDLE;
if unsigned(s_evt) > 1 then
ctr <= X"00" & "10";
end if;
end if;
end case;
end if;
end if;
end process;
I think too it's slowed down by where the signal comes from:
sig <= sig_token when unsigned(SIG_DELAY) < 1 else (sig_bit_shift(to_integer(unsigned(SIG_DELAY)-1)));
process(clk_p) -- delays sig
begin
if rising_edge(clk_p) then
if rst = '1' then
sig_bit_shift <= (others => '0');
else
sig_bit_shift <= l1a_bit_shift(sig_bit_shift'high-1 downto 0) & sig_token;
end if;
end if;
end process;
UPDATE 2 :
Seems like half the routing went into the above delay so i'm going to try and fix with this:
signal sig_del_en : std_logic;
signal sig_del_sel : integer;
begin
process(clk_p)
begin
if rising_edge(clk_p) then
if unsigned(SIG_DELAY) = 0 then
sig_del_en <= '0';
else
sig_del_en <= '1';
end if;
sig_del_sel <= to_integer(unsigned(SIG_DELAY)-1);
end if;
end process;
sig <= sig_token when sig_del_en = '0' else (sig_bit_shift(sig_del_sel));
Some of the "slow" operations are array = which requires compare over all bits in the argument, and < and > which requires subtraction over all bits in the argument. So you may improve timing in a cycle, if there is sufficient time in the previous cycle to generate the compare result up front as a std_logic. It may be relevant for these:
unsigned(event_settings) < 1
unsigned(event_settings) = 1
ctr = (unsigned(event)-2)
unsigned(ctr) = 1
unsigned(s_evt) > 1
The code to generate the different std_logic values depends on the way the related signal is generated, but an example can be:
process (clk) is
variable event_settings_v : event_settings'range;
begin
if rising_edge(clk) then
...
event_settings_v := ... code for generating event_settings; -- Variable with value
event_settings <= event_settings_v; -- Signal drive from variable
if unsigned(event_settings_v) < 1 then
unsigned_event_settings_tl_1 <= '1';
else
unsigned_event_settings_tl_1 <= '0';
end if;
end if;
end process;
The code unsigned(event_settings) < 1 in the state machine can then be changed to unsigned_event_settings_tl_1 = '1', which may improve timing if this compare is in the critical path.
Using the asynchronous reset typically available on the the flip-flop for rst_i = '1' may also improve timing, since it removes logic from the synchronous part. It is unlikely to give a significant improvement, but it's typically a good design practice in order to maximize the time for synchronous logic. The asynchronous reset is used through coding style like:
process (rst_i, clk_p) is
begin
if rst_i = '1' then
... Apply asynchronous reset value to signals
elsif rising_edge(clk_p) then
... Synchronous update of signals

VHDL Clock divider

I am using the following VHDL to take a 100 Mhz clock and put out a 25 Mhz clock. :
process(clk, reset)
variable count : integer range 0 to 2;
begin
if (reset = '1') then
clock_25MHz <= '0';
count := 0;
elsif rising_edge(clk) then
count := count+1;
if(count >= 2) then
clock_25MHz <= not clock_25MHz;
count := 0;
end if;
end if;
end process;
It is giving me this warning:
"WARNING:Xst:1293 - FF/Latch count_1 has a constant value of 0 in block . This FF/Latch will be trimmed during the optimization process."
I don't understand why its happening. Can anyone shed some light on this for me? Thanks!
You don't need 2 bits of count. A single flip flop is enough.
If you add an integer signal CNT that's assigned count (allowing me to see it on a waveform with ghdl):
library ieee;
use ieee.std_logic_1164.all;
entity clk_div is
end entity;
architecture foo of clk_div is
signal clk: std_logic := '0';
signal reset: std_logic := '1';
signal clock_25MHz: std_logic;
signal CNT: integer;
begin
CLKDIV:
process(clk,reset)
variable count: integer range 0 to 2;
begin
if (reset = '1') then
clock_25MHz <= '0';
count:=0;
elsif rising_edge(clk) then
count:=count+1;
if(count>=2) then
clock_25MHz <= not clock_25MHz;
count:=0;
end if;
end if;
CNT <= count;
end process;
CLOCK:
process
begin
wait for 5 ns;
clk <= not clk;
if Now > 200 ns then
wait;
end if;
end process;
UNRESET:
process
begin
wait for 20 ns;
reset <= '0';
wait;
end process;
end architecture;
You find:
The count always shows up as either 0 or 1 and not 2 or 3, because you assign it to 0 when ever its 2 or greater. It never shows up as 2 on a clock edge.
Is that correct? Why yes it is. If you clock at the waveform with clock_25MHz lasting 4 100 Mhz clocks it works perfectly. You're process is doing something that's not necessary, count doesn't need a range of 0 to 2, (requiring two flip flops).
Change the evaluation order for count so clock_25MHz is toggled when count = 1, then toggle count. Change the range of count to 0 to 1 or better still make it type std_logic.
-- signal CNT: integer;
signal toggle_ff: std_logic;
begin
CLKDIV:
process(clk,reset)
--variable count: integer range 0 to 2;
variable toggle: std_logic;
begin
if (reset = '1') then
clock_25MHz <= '0';
-- count:=0;
toggle := '0';
elsif rising_edge(clk) then
-- count:=count+1;
-- if(count>=2) then
if toggle = '1' then
clock_25MHz <= not clock_25MHz;
-- count:=0;
end if;
toggle := not toggle;
end if;
-- CNT <= count;
toggle_ff <= toggle;
end process;
Which gives:
You could also use a signal in the process statement instead of a variable. In my example code rename toggle_ff to toggle, remove the variable toggle declaration and remove the signal assignment statement to toggle_ff. The reason this will work seamlessly is because you evaluate the output of the toogle FF before it is toggled.
The warning occurs since the state in count implemented as FF/Latch by Xilinx
goes 0, 1, 0, 1, ..., and only an internal combinatorial value of count ever
gets the value 2, thus any bit 1 in the count state will always be 0, as the
warning says "FF/Latch count_1 has a constant value of 0 in block".
You can also see this since the code can be rewritten with reduced ´count´
range as 0 to 1, if the count increment is placed inside the if like:
process(clk, reset)
variable count : integer range 0 to 1;
begin
if (reset = '1') then
clock_25MHz <= '0';
count := 0;
elsif rising_edge(clk) then
if (count = 1) then
clock_25MHz <= not clock_25MHz;
count := 0;
else
count := count + 1;
end if;
end if;
end process;
But based on the specific requirement of doing a division by 4 from a 100 MHz
to a 25 MHz clock, it may be more obvious creating an intermediate 50 MHz clock
instead of count, with code like:
process(clk, reset)
variable clock_50MHz : std_logic;
begin
if (reset = '1') then
clock_25MHz <= '0';
clock_50MHz := '0';
elsif rising_edge(clk) then
clock_50MHz := not clock_50MHz;
if clock_50MHz = '1' then
clock_25MHz <= not clock_25MHz;
end if;
end if;
end process;

VHDL edge detection

I want to detect the edges on the serial data signal (din). I have written the following code in VHDL which is running successfully but the edges are detected with one clock period delay i.e change output is generated with one clk_50mhz period delay at each edge. Could anyone please help me to detect edges without delay. Thank you.
process (clk_50mhz)
begin
if clk_50mhz'event and clk_50mhz = '1' then
if (rst = '0') then
shift_reg <= (others => '0');
else
shift_reg(1) <= shift_reg(0);
shift_reg(0) <= din;
end if;
end if;
end process;
process (clk_50mhz)
begin
if clk_50mhz'event and clk_50mhz = '1' then
if rst = '0' then
change <= '0' ;
elsif(clk_enable_2mhz = '1') then
change <= shift_reg(0) xor shift_reg(1);
end if ;
end if ;
end process ;
When I changed my code to following I am able to detect the edges
process (clk_50mhz)
begin
if clk_50mhz'event and clk_50mhz = '1' then
if (RST = '0') then
shift_reg <= (others=>'0');
else
shift_reg(1) <= shift_reg(0);
shift_reg(0) <= din;
end if;
end if;
end process;
change <= shift_reg(1) xor din;
Here you go
library ieee;
use ieee.std_logic_1164.all;
entity double_edge_detector is
port (
clk_50mhz : in std_logic;
rst : in std_logic;
din : in std_logic;
change : out std_logic
);
end double_edge_detector;
architecture bhv of double_edge_detector is
signal din_delayed1 :std_logic;
begin
process(clk_50mhz)
begin
if rising_edge(clk_50mhz) then
if rst = '1' then
din_delayed1 <= '0';
else
din_delayed1 <= din;
end if;
end if;
end process;
change <= (din_delayed1 xor din); --rising or falling edge (0 -> 1 xor 1 -> 0)
end bhv;
You have to use a combinatorial process to detect the difference without incurring extra clock cycle delays. (You will still need one register to delay the input as well.)
DELAY: process(clk_50mhz)
begin
if clk_50mhz'event and clk_50mhz = '1' then
din_reg <= din;
end if;
end process;
change <= din xor din_reg;

Resources