As part of an assignment, I'm expected to write a process that spans over a certain amount of time. However, we are not allowed to use neither wait for nor after statements.
Since I've been given a clock that has a period of 250ms, I have tried to create a counter that adds 1 each time the clock completes a full period, and then multiply it by 250 to get the time in miliseconds but when testing, the values for a and b are the ones defined at the beginning of the process, instead of updating at all.
The clock starts at 1, hence why I start the counter at -1.
process_1: process
variable t1: integer := 3000;
variable t2: integer := 10000;
variable t3: integer := 13000;
variable t4: integer := 23000;
variable counter: integer := -1;
begin
a <= "001";
b <= "100";
if (sensor = '1' and clk = '1' and clk'event) then
while (250*counter < t4) loop
--updates the counter
if (clk = '1') then counter := counter+1; end if;
--0 to 3000 ms
if (250*counter < t1) then
a <= "010";
b <= "100";
--3000 to 10000 ms
elsif (250*counter < t2) then
a <= "100";
b <= "001";
--10000 to 13000 ms
elsif (250*counter < t3) then
a <= "100";
b <= "010";
--13000 to 23000 ms
else
a <= "001";
b <= "100";
end if;
end loop;
end if;
wait until (sensor = '1');
end process;
Any ideas? How do I put a process through time intervals without using wait for?
Related
Please understand my very low skill-set on the code. I am trying to learn to be better.
Using DE0 Nano board, I am trying to write VHDL to simulate all available LEDs on the board (8 of them)
I labeled them LED0 ~ LED7. Using 50 MHZ and 1/2 s counter, I wanted to operate individual LEDs in order.
For example, if these individual bits represents on and off of the LEDs.
1|0|0|0|0|0|0|0 -> 0|1|0|0|0|0|0|0 -> 0|0|1|0|0|0|0|0 and so on. At the end, counter would reset back to 0 to repeat the sequence again.
Please view my code below with these questions/issues.
1) I get one 1/2 s pause after 8th LED. Why? How do I fix this?
2) Even if i put the variable counter as 8, it repeats as 16 thus I had to implement the reset of the counter to 0. (marked as question 2 in the code)
3) Is there any better way to write these codes? It is completely messy. Could you give tips on any other function or method I can use to shorten this codes?
Please let me know if any questions!
THANKS A LOT FOR THE HELP.
entity ledtest is
port(
clk_50mhz : in std_logic ;
reset_btn : in std_logic;
green_led : out std_logic_vector(7 downto 0)
);
end entity;
architecture behave of ledtest is
signal clk_1hz : std_logic ;
signal scaler : integer range 0 to 25000000 ;
signal counter : integer range 0 to 8;
signal LED : std_logic_vector(7 downto 0);
begin
clk_1hz_process : process( clk_50mhz , reset_btn )
begin
if (reset_btn = '0') then
clk_1hz <= '0';
scaler <= 0;
counter <= 0;
elsif(rising_edge(clk_50mhz)) then
if (scaler < 25000000) then
scaler <= scaler + 1 ;
clk_1hz <= '0';
else
scaler <= 0;
clk_1hz <= '1';
counter <= counter + 1;
if (counter >= 8) then --------question 2
counter <= 0;
end if;
end if;
end if;
end process clk_1hz_process;
blinking_process : process (clk_1hz,reset_btn)
begin
if (reset_btn = '0') then
LED(0) <= '0';
elsif rising_edge(clk_1hz) AND counter = 1 then
LED(0) <= not LED(0) ;
LED(7) <= '0' ;
elsif rising_edge(clk_1hz) AND counter = 2 then
LED(1) <= not LED(1) ;
LED(0) <= not LED(0) ;
elsif rising_edge(clk_1hz) AND counter = 3 then
LED(2) <= not LED(2) ;
LED(1) <= not LED(1) ;
elsif rising_edge(clk_1hz) AND counter = 4 then
LED(3) <= not LED(3) ;
LED(2) <= not LED(2) ;
elsif rising_edge(clk_1hz) AND counter = 5 then
LED(4) <= not LED(4) ;
LED(3) <= not LED(3) ;
elsif rising_edge(clk_1hz) AND counter = 6 then
LED(5) <= not LED(5) ;
LED(4) <= not LED(4) ;
elsif rising_edge(clk_1hz) AND counter = 7 then
LED(6) <= not LED(6) ;
LED(5) <= not LED(5) ;
elsif rising_edge(clk_1hz) AND counter = 8 then
LED(7) <= not LED(7) ;
LED(6) <= not LED(6) ;
end if;
end process blinking_process;
green_led(0) <= LED(0);
green_led(1) <= LED(1);
green_led(2) <= LED(2);
green_led(3) <= LED(3);
green_led(4) <= LED(4);
green_led(5) <= LED(5);
green_led(6) <= LED(6);
green_led(7) <= LED(7);
end behave;
If your readers squint real hard they can treat the original post as one question and two issues. (A questions is singular.)
Please view my code below with these questions/issues.
1) I get one 1/2 s pause after 8th LED. Why? How do I fix this?
There are 9 counter values (0 to 8) and only 8 LEDs (7 downto 0). No assignments occur in the half second between assigning counter to 0 and incrementing by 1 again.
2) Even if i put the variable counter as 8, it repeats as 16 thus I had to implement the reset of the counter to 0. (marked as question 2 in the code)
This issue is tied in with 1). The requirement for evaluating counter greater than or equal to 8 is caused by assigning counter to 8, again there are 9 values and only 8 LEDs. Note that's a synchronous load to 0 and not an asynchronous reset.
3) Is there any better way to write these codes? It is completely messy. Could you give tips on any other function or method I can use to shorten this codes?
Because you're attempting to go directly to FPGA instead of simulating the focus on tips should relate to the question 1) and how to fix it. There are also some synthesis issues, here gating clocks by adding enables to the conditions in if statement elsif alternatives. There's also the issue of design specification complexity and the amount of debugging effort associated with the number of lines of code.
First there are flip flops for all LED elements as well a counter. We can reduce the number of flip flops to one for each LED element by using a ring counter (not to be confused with a Johnson counter).
Assignments to green_led (the std_logic_vector) can be from LED (the std_logic_vector) instead of element by element. There's a one to one correspondence between element indices on both side of the assignment(s).
Also to allow simulation you could virtualize the time interval of a half second loaded into scalar. This has the effect of having fewer clocks represent a half second. The idea is simulation doesn't have to take the 10+ seconds of 100 million clock transitions per second (rising and falling edges).
Throw all these together and the code is changed to look like:
library ieee;
use ieee.std_logic_1164.all;
entity ledtest is
generic (half_second: integer := 24999999); -- zero identity
-- the generic allows fewer clocks per second for simulation
port (
clk_50mhz: in std_logic;
reset_btn: in std_logic;
green_led: out std_logic_vector(7 downto 0)
);
end entity;
architecture behave of ledtest is
signal clk_1hz: std_logic;
signal scaler: integer range 0 to half_second;
-- signal counter: integer range 0 to 8; -- DELETED
signal ring_counter: std_logic_vector (7 downto 0); -- ADDED
signal LED: std_logic_vector (7 downto 0);
signal LED0I: std_logic; -- ADDED
begin
LED0I <= '1' when LED = "00000000" else
'0';
clk_1hz_process:
process (clk_50mhz, reset_btn)
begin
if reset_btn = '0' then
clk_1hz <= '0';
scaler <= 0;
-- counter <= 0;
elsif rising_edge(clk_50mhz) then
if scaler /= half_second then
scaler <= scaler + 1;
clk_1hz <= '0';
else
scaler <= 0;
clk_1hz <= '1';
-- counter <= counter + 1;
-- if counter >= 8 then --------question 2
-- counter <= 0;
-- end if;
end if;
end if;
end process clk_1hz_process;
blinking_process:
process (clk_1hz, reset_btn)
begin
if reset_btn = '0' then
LED <= (others => '0');
-- LED(0) <= '0';
elsif rising_edge(clk_1hz) then
LED <= LED(6 downto 0) & (LED(7) or LED0I);
-- ring counter with a roulette ball lauch after reset
-- elsif rising_edge(clk_1hz) AND counter = 1 then
-- LED(0) <= not LED(0);
-- LED(7) <= '0';
-- elsif rising_edge(clk_1hz) AND counter = 2 then
-- LED(1) <= not LED(1);
-- LED(0) <= not LED(0);
-- elsif rising_edge(clk_1hz) AND counter = 3 then
-- LED(2) <= not LED(2);
-- LED(1) <= not LED(1);
-- elsif rising_edge(clk_1hz) AND counter = 4 then
-- LED(3) <= not LED(3);
-- LED(2) <= not LED(2);
-- elsif rising_edge(clk_1hz) AND counter = 5 then
-- LED(4) <= not LED(4);
-- LED(3) <= not LED(3);
-- elsif rising_edge(clk_1hz) AND counter = 6 then
-- LED(5) <= not LED(5);
-- LED(4) <= not LED(4);
-- elsif rising_edge(clk_1hz) AND counter = 7 then
-- LED(6) <= not LED(6);
-- LED(5) <= not LED(5);
-- elsif rising_edge(clk_1hz) AND counter = 8 then
-- LED(7) <= not LED(7);
-- LED(6) <= not LED(6);
end if;
end process blinking_process;
green_led <= led;
-- green_led(0) <= LED(0);
-- green_led(1) <= LED(1);
-- green_led(2) <= LED(2);
-- green_led(3) <= LED(3);
-- green_led(4) <= LED(4);
-- green_led(5) <= LED(5);
-- green_led(6) <= LED(6);
-- green_led(7) <= LED(7);
end architecture behave;
(Also note the default generic value scalar is reset and loaded to has been decremented to include the unity 0 in the 250,000,000 clocks be half second. The equality test for half_second is simpler than using magnitude comparison.)
Using a ring counter reduces complexity and side steps the issue of a counter range of 9.
The ring counter has a flourish added, the reset value is all '0's which are detected by signal LED0I which is used to start the ring counter after reset. It prevents all the LEDs from being lit during reset.
You can use a testbench with the number of clocks comprising a half second to a much smaller number allowing fast simulation with small waveform dump files:
library ieee;
use ieee.std_logic_1164.all;
entity ledtest_tb is
end entity;
architecture foo of ledtest_tb is
signal clk: std_logic := '0';
signal reset_btn: std_logic := '1';
signal green_led: std_logic_vector (7 downto 0);
begin
DUT:
entity work.ledtest
generic map (half_second => 7)
port map (
clk_50mhz => clk,
reset_btn => reset_btn,
green_led => green_led
);
CLOCK:
process
begin
wait for 0.5 sec / 7;
clk <= not clk;
if now > 19 sec then
wait;
end if;
end process;
STIMULUS:
process
begin
wait for 0.5 sec;
reset_btn <= '0';
wait for 0.5 sec;
reset_btn <= '1';
wait;
end process;
end architecture;
And that gives:
You could eliminate the generic map in the testbench instantiation of ledtest to demonstrate the difference in simulation time and dump file size inherent with simulating every clock transition with a 50 MHz clock. The idea here is it's easier to troubleshoot a simulation than it is to guess from what you can see (here the LEDs). Because the code description was simplified there was debugging required using the original code as a starting point. It did rely on a knowledge of digital electronics and VHDL.
The simulation was done with ghdl and gtkwave.
I'm trying to write vhdl code for a spartan-6 xc6slx45t for generating multiple frequencies in single channel.. That is:
242.72khz with 20 cycles
23.6khz with 1 cycle
243.90khz with 6 cycles
then 23.4 khz with 386 cycles
all in single output. I just tried with one frequency here and got some issues with delays in codes..
I mentioned each states with different no.of cycles here.. But what I need is for example: when state S0 =>242.72khz with 20 cycles and then a delay in between two states, and next state S1 => 23.6khz with one cycle and then again a delay and next state and so on..)
Here i attached my code. Please help me with developing the code..
Thanks in advance...
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY FSM_Example IS
PORT (
clk, reset, en : IN std_logic;
output : INOUT std_logic
);
END FSM_Example;
ARCHITECTURE Behavioral OF FSM_Example IS
TYPE state_type IS (S0, S1, S2, S3);
SIGNAL cur_state, next_state : state_type;
SIGNAL count : INTEGER RANGE 0 TO 5000;
SIGNAL i : INTEGER RANGE 0 TO 400;
SIGNAL cnt : INTEGER RANGE 0 TO 400;
BEGIN
state_memory : PROCESS (clk, reset)
BEGIN
IF (reset = '1') THEN
cur_state <= S0;
ELSIF (clk = '1' AND clk'event) THEN
IF (count = 4240 - 1) THEN
count <= 0;
cur_state <= next_state;
ELSE
count <= count + 1;
END IF;
END IF;
END PROCESS state_memory;
PROCESS (count)
BEGIN
IF (count < 1480) THEN
output <= '1';
ELSE
output <= '0';
END IF;
END PROCESS count;
PROCESS (en, cur_state)
BEGIN
CASE cur_state IS
WHEN S0 =>
loop0 : FOR i IN 0 TO 6 LOOP
EXIT loop0 WHEN i = 7;
cnt(i + 1) <= cnt(i) + 1;
IF (en = '1' AND en'event) THEN
ELSIF (i < 6) THEN
next_state <= S1;
ELSE
next_state <= S0;
END IF;
END LOOP;
WHEN S1 =>
loop1 : FOR i IN 0 TO 1 LOOP
EXIT loop1 WHEN i = 2;
i <= i + 1;
IF (en = '1' AND en'event) THEN
ELSIF (i < 1) THEN
next_state <= S2;
ELSE
next_state <= S1;
END IF;
END LOOP;
WHEN S2 =>
loop2 : FOR i IN 0 TO 20 LOOP
EXIT loop2 WHEN i = 21;
i <= i + 1;
IF (en = '1' AND en'event) THEN
ELSIF (i < 20) THEN
next_state <= S3;
ELSE
next_state <= S2;
END IF;
END LOOP;
WHEN S3 =>
loop3 : FOR i IN 0 TO 386 LOOP
EXIT loop3 WHEN i = 387;
i <= i + 1;
IF (en = '1' AND en'event) THEN
ELSIF (i < 386) THEN
next_state <= S0;
ELSE
next_state <= S3;
END IF;
END LOOP;
END CASE;
END PROCESS;
END Behavioral;
You are trying to write synthesize code. Then you cannot use wait for x ns. The FPGA does not know how to wait for x nanoseconds. It does not know what a nanosecond is.
But more of your code does not seem synthesizable. You should read-up on how to write VHDL for synthesis on FPGAs
What an FPGA does have (normally) is a clock crystal input and also . From the frequency of the clock input, you can derive how many clock cycles would be in a time period. Then you should implement a counter and insert intermediate wait-states, where the fsm waits until a specific value of the counter is reached.
E.g. If the clock input is 100 MHz, each clock pulse is 10 ns long ==> 10 clock pulses is 100 ns long. If you need smaller time step, you need to increase the clock frequency using a PLL/DCM/MMCM/etc. but you cannot do this indefinitely, as the FPGA does not support very high clock frequencies.
line 62: Signal s 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;
entity clock is
Port ( start : in STD_LOGIC;
reset : in STD_LOGIC;
CLOCK : in STD_LOGIC;
setH, setM, setS : in STD_LOGIC;
alarmH, alarmM, alarmS : in STD_LOGIC;
Alarm_On : in STD_LOGIC;
Buzzer_Stop : in STD_LOGIC;
BUZZER : out STD_LOGIC;
hh, mm, ss : out INTEGER);
end clock;
architecture Behavioral of clock is
signal h, m, s : INTEGER range 0 to 60 := 0;
signal hA, mA, sA : INTEGER range 0 to 60 := 0;
signal clk : std_logic :='0';
signal count : integer :=1;
begin
Frequency_Reducer : process(CLOCK) --Reducing Frequency From 40MHz to 1Hz
begin
if rising_edge(CLOCK) then
count <= count + 1;
if(count = 20000000) then
clk <= not clk;
count <=1;
end if;
end if;
end process;
Clock_Logic : process(start, reset, clk)
begin
if reset = '1' then
h <= 00;
m <= 00;
s <= 0;
end if;
if start = '1' then
if rising_edge(clk) then --Clock Logic Start
s <= s + 1;
end if;
end if;
if s = 60 then
s <= 0;
m <= m + 1;
end if;
if m = 60 then
m <= 0;
h <= h + 1;
end if;
if h = 24 then
h <= 0;
end if; --Clock Logic End
if setH = '1' then --Set Time Logic Start
h <= h + 1;
end if;
if setM = '1' then
m <= m + 1;
end if;
if setS = '1' then
s <= s + 1;
end if; -- Set Time Logic End
end process;
hh <= h;
mm <= m;
ss <= s;
end Behavioral;
Let's take a look at the assignments of signal s only:
Clock_Logic : process(start, reset, clk)
begin
if reset = '1' then
s <= 0;
end if;
if start = '1' then
if rising_edge(clk) then --Clock Logic Start
s <= s + 1;
end if;
end if;
if s = 60 then
s <= 0;
end if;
if setS = '1' then
s <= s + 1;
end if; -- Set Time Logic End
end process;
In the last assignment, you are requesting that s is incremented when setS is high and the process is executed (resumed). The process is executed initially after system startup and every time when one of the signals in the sensitivity list changes. Thus, you are requesting flipf-flops clocked on both edges of three signals start, reset and clock. I suspect, that this increment should be done only on the rising edge of the clock:
if rising_edge(clk) then --Clock Logic Start
if setS = '1' then
s <= s + 1;
end if; -- Set Time Logic End
end if;
The asynchronous reset of s when s reaches 60 is possible, but error prone due to glitches. s is is multi-bit signal in hardware. Thus, when it is incremented it could be equal to 60 for short moments in time even when the final value is below 60! You should reset it synchronously to 0, when current value is 59.
The increment of s when start is high and a rising-edge on the clock occur is ok, but synthesis tool often request to re-arrange this so that the outer if block checks for the rising edge:
if rising_edge(clk) then --Clock Logic Start
if start = '1' then
s <= s + 1;
end if;
end if;
Finally, the asynchronous reset (or set) inputs on flip-flops have always a higher priority then the synchronous data inputs. Thus, you must arrange it either this way:
Clock_Logic : process(reset, clk)
begin
if reset = '1' then
-- asynchronous part
s <= 0;
elsif rising_edge(clk) then
-- synchronous part (add more conditions if required)
s <= s + 1;
end if;
end process;
or this way:
Clock_Logic : process(reset, clk)
begin
if rising_edge(clk) then
-- synchronous part (add more conditions if required)
s <= s + 1;
end if;
if reset = '1' then
-- asynchronous part
s <= 0;
end if;
end process;
The synchronous assignments can be more complex. For example, if you want to synchronously reset a counter when it reaches 59 and to increment it otherwise when the signal setS is high:
Clock_Logic : process(reset, clk)
begin
if reset = '1' then
-- asynchronous part
s <= 0;
elsif rising_edge(clk) then
-- synchronous part
if s = 59 then
s <= 0;
elsif setS = '1' then
s <= s + 1;
end if;
end if;
end process;
I have searched about this problem but it all seemed Greek to me so I came here as last effort.I have the following VHDL code that I want to be implemented on an fpga.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.std_logic_arith.all;
use work.conversions.all;
entity counter is
port ( clk_in: in std_logic; --new clock
target : in std_logic_vector(7 downto 1); --Set the target with the switches (SW7-SW1)
start : in std_logic; --Start/pause (SW0)
rst : in std_logic; --Reset (BT0)
LD : out std_logic_vector(7 downto 1); --Leds show the target at binary (LD7-LD1)
LD0 : out std_logic; --LD0 indicates thw the limit has been reached
seg : out std_logic_vector(7 downto 0); --7 segment display
digit : out std_logic_vector(3 downto 0)
);
end counter;
architecture Behavioral of counter is
begin
process(clk_in,target,rst)
variable timer : natural := 0;
variable counter : natural := 0;
variable display_counter : natural range 0 to 4 := 0;
begin
LD0 <= '0';
LD <= target; --Show the target at the leds
digit <= "1110"; --Last digit active
seg <= "00000011"; --Show zero
<--->if(rst='1') then --Reset counter
counter := 0;
timer := 0;
digit <= "1110"; --Last digit active
seg <= "00000011"; --Show zero
LD0 <= '0';
elsif rising_edge(clk_in) then
if(start = '0') then --Pause
--counter := counter;
elsif(counter = conv_integer(unsigned(target))) then --timer limit has been reached
LD0 <= '1';
else
counter := counter + 1;
display_counter := display_counter + 1;
if(counter rem 10 = 0) then --one second has elapsed (10Hz cycle)
timer := timer + 1; --increase timer
end if;
case display_counter is --Select which digits are gonna be activated and with what
when 1 =>
seg <= int2led(timer/1000);
if(int2led(timer/1000) = "00000000") then
digit(3) <= '1';
else
digit(3) <= '0';
end if;
when 2 =>
seg <= int2led((timer/100) mod 10);
if(int2led((timer/100) mod 10) = "00000000") then
digit(2) <= '1';
else
digit(2) <= '0';
end if;
when 3 =>
seg <= int2led((timer/10) mod 10);
if(int2led((timer/10) mod 10) = "00000000") then
digit(1) <= '1';
else
digit(1) <= '0';
end if;
when others =>
seg <= int2led(timer/10);
if(int2led(timer/10) = "00000000") then
digit(1) <= '1';
else
digit(1) <= '0';
end if;
end case;
if (display_counter = 4) then --reset the display counter from time to time
display_counter := 0;
else
display_counter := display_counter;
end if;
end if;
end if;
end process;
end Behavioral;
The problem is at if(rst='1') then. Can anyone explain to me in plain English why is this happening and a solution to it so I won't have the same kind problems again? Thanks in advance
You have default signal assignments before the if rst='1' then clause.
That means, when rst returns to 0 (in simulation) these default assignments will execute, and delete the reset values of those signals.
XST is telling you that the hardware can't actually do that.
The solution is to delete those default assignments, which will restore this process to a standard form. Then think carefully about what they were for and how to keep their functionality if you need to.
The traditional place for such assignments is immediately after the elsif rising_edge(clk) then clause, where they will be executed on every clock edge (provided Rst is low) then overridden by any other assignments that are executed yb the process.
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;