Synthesis: Implementing a delay signal using a counter on power-up of FPGA - vhdl

I am trying to have a delay of 20 seconds on power-up of the FPGA.
There is a clock input of 100Hz, so if a counter gets to 20,000, that should be 20 seconds worth of delay. After the delay, it should set an output pin high. However, for some reason, this out pin is going high immediately and never goes low at all on powerup. It's almost as if it is skipping the s_count <= 20000 completely.
Here is the code I have:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity delay is
port
(
pi_Clock : in std_logic;
po_Delay_Done : out std_logic
);
end entity;
architecture behavioral of delay is
begin
process(pi_Clock)
variable s_count : integer := 0;
begin
if rising_edge(pi_Clock) then
if s_count <= 20000 then
s_count := s_count + 1;
po_Delay_Done <= '0';
else
po_Delay_Done <= '1';
end if;
end if;
end process;
end architecture;
I have increased the 20000 to the max integer value, just to see if my clock was incorrect but the same result.
There is no other driver of this signal on the top level file.
Anyone see what I'm doing wrong?

For some reason, setting the initial values by the declarations seems to be the problem with this FPGA/toolset (synopsis Synplify and the FPGA is Actel A3PN250) even if it works in modelsim simulation.
The following code does what I want -- Set an output high after the FPGA is turned on for 20 seconds:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity delay is
port
(
pi_Clock : in std_logic;
pi_Reset : in std_logic;
po_Delay_Done : out std_logic
);
end entity;
architecture behavioral of delay is
begin
process(pi_Clock)
variable s_count: integer;
begin
if rising_edge(pi_Clock) then
if pi_Reset = '1' then
s_count := 0;
po_Delay_Done <= '0';
else
if s_count < 2000 then
s_count := s_count + 1;
else
po_Delay_Done <= '1';
end if;
end if;
end if;
end process;
end architecture;
The catch is that the microcontroller is now sending a reset signal (pi_Reset = '1') to the FPGA after it has been started.
Hope this helps anyone in the future, thanks to Quantum Ripple and Brian especially for suggesting the hard reset. If you had an answer I would accept it.

The code you typed has no simulation or synthesis errors and has a correct result in modelsim simulation software. (according to the above first comment "fru1tbat")
With respect to the above comments, I think if you synthesized the FPGA board correctly and the design doesn't worked (with applying a reset port to reset the output and variable parameters), the problem is related to the clock generator. Be sure about the clock generator and find the correct frequency.

Related

UART Transmitter only functions when embedded logic analyzer is running

I have been trying to implement a UART in order to communicate between my Lattice MachXO3D board and my computer. At the moment I am attempting to implement the transmission from the FPGA.
Upon testing on the hardware, I encountered a very strange issue. If run normally, it will function for a few seconds and then it will suddenly stop functioning (The CH340 connected to my computer will report it is receiving messages containing 0x0). However, if I embed a logic analyzer onto the FPGA through the Lattice Diamond software, and I run the analyzer, it will function perfectly for an extended period of time.
Sadly, I don't have a logic analyzer, so the embedded logic analyzer is my only chance at knowing what is actually being transmitted.
These are the files related to my implementation:
baud_gen
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL;
-- Generates 16 ticks per bit
ENTITY baud_gen IS
GENERIC(divider: INTEGER := 13 -- 24M/115200*16
);
PORT(
clk, reset: IN STD_LOGIC;
s_tick: OUT STD_LOGIC
);
END baud_gen;
ARCHITECTURE working OF baud_gen IS
BEGIN
PROCESS(clk)
VARIABLE counter: UNSIGNED(3 DOWNTO 0) := to_unsigned(0,4);
BEGIN
IF clk'EVENT AND clk='1' THEN
IF reset='1' THEN
s_tick <= '0';
counter := to_unsigned(0,4);
ELSIF counter=to_unsigned(divider-1,4) then
s_tick <= '1';
counter:= to_unsigned(0,4);
ELSE
s_tick <= '0';
counter := counter + 1;
END IF;
END IF;
END PROCESS;
END working;
rs232_tx
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL;
ENTITY rs232_tx IS
PORT(clk: IN std_logic;
tx: OUT std_logic;
rst: IN std_logic;
fifo_empty: IN std_logic;
fifo_RdEn, fifo_RdClock: OUT std_logic;
fifo_data: IN STD_LOGIC_VECTOR(7 DOWNTO 0);
Q: OUT STD_LOGIC_VECTOR(1 DOWNTO 0));
END rs232_tx;
ARCHITECTURE working OF rs232_tx IS
TYPE state IS (idle,start,data);
SIGNAL tx_pulse: STD_LOGIC := '1';
SIGNAL s_tick: STD_LOGIC;
SIGNAL pr_state, nx_state: state := idle;
SIGNAL data_val: std_logic_vector(7 DOWNTO 0):=(others=>'0');
SIGNAL data_count: unsigned(2 DOWNTO 0):=to_unsigned(0,3);
BEGIN
process(s_tick, rst)
VARIABLE count: unsigned(3 DOWNTO 0):= to_unsigned(0,4);
BEGIN
IF rising_edge(s_tick) THEN
count := count + to_unsigned(1,4);
IF count = to_unsigned(15,4) THEN
tx_pulse <= '1';
ELSE
tx_pulse <='0';
END IF;
END IF;
END PROCESS;
process(tx_pulse,rst)
BEGIN
IF rising_edge(tx_pulse) THEN
IF rst='1' THEN
pr_state <= idle;
data_val <= (others=>'0');
data_count <= to_unsigned(0,3);
ELSE
pr_state <= nx_state;
CASE pr_state IS
WHEN idle =>
data_count <= to_unsigned(0,3);
WHEN data =>
data_count <= data_count + to_unsigned(1,3);
WHEN start =>
data_val <= fifo_data;
WHEN OTHERS =>
END case;
END IF;
END IF;
END process;
process(fifo_empty,rst,data_count,pr_state,data_count)
BEGIN
case pr_state is
when idle =>
Q <= ('1','1');
fifo_RdEn <= '0';
tx <= '1';
IF fifo_empty='0' AND rst='0' THEN
nx_state <= start;
ELSE
nx_state <= idle;
END IF;
WHEN start =>
Q <= ('1','0');
fifo_RdEn <= '1';
tx <= '0';
nx_state <= data;
WHEN data =>
Q <= ('0','1');
fifo_RdEn <= '0';
tx <= data_val(to_integer(data_count));
if data_count=to_unsigned(7,3) then
nx_state <= idle;
ELSE
nx_state <= data;
end if;
end case;
END process;
fifo_RdClock <= tx_pulse;
baud_gen: ENTITY work.baud_gen
PORT MAP(clk,reset=>'0',s_tick=>s_tick);
END working;
testbench
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL;
ENTITY rs232_tx_test IS
GENERIC(clk_period: TIME := 41666666.7 fs;
baud_period: TIME := 8680.55556 ns);
END rs232_tx_test;
ARCHITECTURE working OF rs232_tx_test IS
SIGNAL clk: STD_LOGIC := '0';
SIGNAL tx, rst, fifo_empty, fifo_RdEn, fifo_RdClock: STD_LOGIC;
SIGNAL fifo_data: STD_LOGIC_VECTOR(7 DOWNTO 0);
BEGIN
clk <= NOT clk AFTER clk_period/2;
rst <= '1', '0' AFTER 100 ns;
PROCESS
BEGIN
fifo_empty <= '1';
WAIT FOR baud_period;
fifo_empty <= '0';
WAIT FOR baud_period*16;
END PROCESS;
fifo_data <= ('1','1','0','0','1','0','1','1') WHEN fifo_RdEn='1' ELSE (others=>'0');
dut: ENTITY work.rs232_tx
PORT MAP(clk,tx,rst,fifo_empty,fifo_RdEn,fifo_RdClock,fifo_data);
END working;
EDIT
I have tested another UART design I found online # 9600 bps and it fails in the same way. It can send a constant character, in this case 'a', to a terminal on my computer, and then it suddenly stops sending anything. However, if I start listening to the soft logic analyzer I generated in Lattice Diamond, it works without a problem and does not fail.
This smells like a classic timing issue.
In the comments, others have explained where there are weaknesses in the code that could indirectly lead to this. I'm going to concentrate on what is occurring.
As you have stated, in simulation your code works as you expect. However, that is only half the story. To create an FPGA bit stream the build tools take your code and several other files, synthesises, and conducts Place & Route. Your timing issue occurs during P&R. This is why your simulation doesn't pick up on any errors, as I'm assuming it's an RTL (pre-place & route) simulation.
During P&R the tools lay the logic in the best way to fit the timing model of the device so all paths meet their timing requirements. The path timing requirements are derived from explicit statements in a Timing Constraints file and inferred from your code (that's why your coding style matters btw).
Once P&R is complete, the tools will put the build artefact through a static timing analyser (STA) tool and report back whether the build fails to meet the timing requirements.
This leads to two questions:
Does the build report a timing error?
Do you have a Timing Constraints file - if you're unsure, the answer is no.
The way to debug your problem is to use the Timing Report generated by Lattice Diamond to see where the failures are.
If there are no reported failures it means your timing model is wrong because of a lack of appropriate timing constraints. As a minimum, you will need to constrain all IO in the design and describe all the clocks in your design.
Here is a good document to help you out:
https://www.latticesemi.com/-/media/LatticeSemi/Documents/UserManuals/RZ/Timing_Closure_Document.ashx?document_id=45588
The reason that your design works when you use the embedded Logic Analyser is that extra logic has been placed in the design, which changes the timing model. The P&R tools lay out the design differently, and by luck have placed the design in such a way as meet the real timing requirements on it.
As I often say to my Software Engineer colleagues, software languages create a set of instructions, HDL creates a set of suggestions.

Quartus II : simple counter but weird behaviour

First of all I'm sorry to bother you guys with my very noob question, but I can't find any sense to what's happening with my (ModelSim simulated) circuit.
Here's my code, simple as can be :
LIBRARY ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
ENTITY Counter IS
PORT(
enable : in std_logic;
clk : in std_logic;
count : out integer range 0 to 255);
END Counter;
ARCHITECTURE LogicFunction OF Counter IS
signal count_i : integer range 0 to 255;
begin
cnt : process(clk, enable, count_i)
begin
count <= count_i;
if (enable = '0') then
count_i <= 0;
else
count_i <= count_i + 1;
end if;
end process;
end LogicFunction;
My problem is : when I perform a timing simulation with ModelSim, with a clock signal, "enabled" is first '0' and then '1', the output ("count") stays at zero all the time. I tried a lot of different things, like setting the "count" out as a vector, doing all sorts of casts, but it still stays the same.
The increment "count_i <= count_i + 1;" seems to be the problem : I tried to replace it with something like "count_i <= 55", and then the output changes (to "55" in the previous example).
I've seen the exact same increment in the code on that webpage for example :
http://surf-vhdl.com/how-to-connect-serial-adc-fpga/
I've created a project, simulated it and... it works ! I really don't get what the guy did that I didn't, excepted for a bunch of "if" that I don't need in my code.
Any help would be greatly appreciated, I've spent like 3 hours of trial and errors...
Thanx in advance !
In addition to not using a clock edge to increment i_count you're using enable as a clear because it's both in the sensitivity list and encountered first in an if statement condition.
library ieee;
use ieee.std_logic_1164.all;
-- use ieee.numeric_std.all;
entity counter is
port(
enable : in std_logic;
clk : in std_logic;
count : out integer range 0 to 255);
end counter;
architecture logicfunction of counter is
signal count_i : integer range 0 to 255;
begin
cnt : process (clk) -- (clk, enable, count_i)
begin
-- count <= count_i; -- MOVED
-- if (enable = '0') then -- REWRITTEN
-- count_i <= 0;
-- else
-- count_i <= count_i + 1;
-- end if;
if rising_edge(clk) then
if enable = '1' then
count_i <= count_i + 1;
end if;
end if;
end process;
count <= count_i; -- MOVED TO HERE
end architecture logicfunction;
Your code is modified to using the rising edge of clk and require enable = '1' before i_count increment. The superfluous use clause referencing package numeric_std has been commented out. The only numeric operation you're performing is on an integer and those operators are predefined in package standard.
Note the replacement if statement doesn't surround it's condition with parentheses. This isn't a programming language and they aren't needed.
The count assignment is moved to a concurrent signal assignment. This removes the need of having i_count in the sensitivity list just to update count.
Throw in a testbench to complete a Miminal Complete and Verifiable Example:
library ieee;
use ieee.std_logic_1164.all;
entity counter_tb is
end entity;
architecture foo of counter_tb is
signal enable: std_logic := '0';
signal clk: std_logic := '0';
signal count: integer range 0 to 255;
begin
DUT:
entity work.counter
port map (
enable => enable,
clk => clk,
count => count
);
CLOCK:
process
begin
wait for 5 ns; -- 1/2 clock period
clk <= not clk;
if now > 540 ns then
wait;
end if;
end process;
STIMULUS:
process
begin
wait for 30 ns;
enable <= '1';
wait for 60 ns;
enable <= '0';
wait for 30 ns;
enable <= '1';
wait;
end process;
end architecture;
And that gives:
Which shows that the counter doesn't counter when enable is '0' nor does enable = '0' reset the value of i_count.
The Quartus II Handbook Volume 1 Design and Synthesis doesn't give an example using a clock edge and an enable without an asynchronous clear or load signal.
The secret here is anything inside the if statement condition specified using a clock edge will be synchronous to the clock. Any condition outside will be asynchronous.
The form of synthesis eligible sequential logic is derived from the now withdrawn IEEE Std 1076.6-2004 IEEE Standard for VHDL Register
Transfer Level (RTL) Synthesis. Using those behavioral descriptions guarantees you can produce hardware through synthesis that matches simulation.

Gated Clock in Clock Divider for a Square Wave

I recently have been designing a clock divider for my system - which I redesigned, and now has an asynchronous reset, which generates a synchronous reset for the rest of the system. To do this, I followed the answers & advice to my own question and used a clock enable to toggle an output, thus generating clock with a 50% duty cycle (which is desired).
However, this has thrown up the error when generating the bitstream of
PhysDesignRules:372 - Gated clock. Clock net ... is sourced by a combinatorial pin. This is not good design practice. Use the CE pin to control the loading of data into the flip-flop.
Reading into this question about using the clock enable, it appears when creating a clock enable is correct, however, because I need a square wave (and not just a 1/200MHz pulse), and thus using the enable to toggle another signal, it appears in this question that this is an intentional gated clock.
So my questions are; is this gated clock warning significant? Both in simulation, and on an oscilloscope it appears to function correctly (so I'm inclined to ignore it), but am I storing problems for later? Is there a way of getting a very slow 50% duty cycle pulse without a gated clock?
I've put my code below!
Thanks very much (especially to the handful of people who have collectively given a lot of time to my recent non-stop questions)
David
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
library UNISIM;
use UNISIM.VComponents.all;
ENTITY CLK_DIVIDER IS
GENERIC(INPUT_FREQ : INTEGER;
OUT1_FREQ : INTEGER;
OUT2_FREQ : INTEGER
);
PORT(SYSCLK : IN STD_LOGIC;
RESET_N : IN STD_LOGIC;
RESET_N_OUT : OUT STD_LOGIC;
OUT1 : OUT STD_LOGIC;
OUT2 : OUT STD_LOGIC);
END CLK_DIVIDER;
architecture Behavioral of Clk_Divider is
constant divider1 : integer := INPUT_FREQ / OUT1_FREQ / 2;
constant divider2 : integer := INPUT_FREQ / OUT2_FREQ / 2;
signal counter1 : integer := 0;
signal counter2 : integer := 0;
signal output1 : std_logic := '0';
signal output2 : std_logic := '0';
signal reset : boolean;
begin
reset_proc : process(RESET_N, SYSCLK)
variable cycles : integer := 0;
variable reset_counter : integer := 0;
begin
if rising_edge(SYSCLK) then
if cycles < 2 then
if reset_counter >= divider1 then
cycles := cycles + 1;
reset_counter := 0;
else
reset_counter := reset_counter + 1;
end if;
reset <= true;
else
reset <= false;
end if;
end if;
if RESET_N = '0' then
cycles := 0;
reset_counter := 0;
reset <= true;
end if;
end process;
output1_proc : process(SYSCLK)
begin
if rising_edge(SYSCLK) then
if counter1 >= divider1 - 1 then
output1 <= not output1;
counter1 <= 0;
else
counter1 <= counter1 + 1;
end if;
if RESET_N = '0' then
counter1 <= 0;
output1 <= '1';
end if;
end if;
end process;
output2_proc : process(SYSCLK)
begin
if rising_edge(SYSCLK) then
if counter2 >= divider2 - 1 then
output2 <= not output2;
counter2 <= 0;
else
counter2 <= counter2 + 1;
end if;
if RESET_N = '0' then
counter2 <= 0;
output2 <= '1';
end if;
end if;
end process;
OUT1 <= output1;
OUT2 <= output2;
RESET_N_OUT <= '0' when reset else '1';
end Behavioral;
The comments suggest, that the clock-divider is instantiated in a larger design.
If you want to use the generated clock there, you must add a BUFG between signal output2 and the output out2 like this:
out2_bufg : BUFG port map(I => output2, O => out2);
The component BUFG is defined in the library unisim.vcomponents. Same applies to output out1.
The BUFG ensures, that the generated clock is distributed using a clock-tree, so that the clock signal arrives at all destination flip-flops at the same time. This minimizes hold-time violations and gives more room for the setup of data signals.
If you still get the warning/error, then you combined the generated clock signal with another signal elsewhere in the larger design.
The reset_proc process is written with a elsif cycles > 1 then outside the clocked part, and with the condition derived from cycles which is also assigned as part of reset. It is unclear what hardware is actually described here, but it makes the synthesis tool unhappy.
If you want to use RESET_N as asynchronous reset, then just make a simple if RESET_N = '0' then ... end if;, and assign whatever signals or variables required to be reset. Other assignments should be moved to the clocked part.
NOTE: Code was changed after the above update... which may have removed the reason for the question.
Btw. RESET_N is used as asynchronous reset in the reset_proc, but as synchronous reset in the other processes, and this inconsistent use looks like there may be a potential problem with the reset scheme.

How to take samples using fpga?

I want to take samples of digital data coming externaly to FPGA spartan 3.
I want to take 1000 samples/sec initially. How to select a clock frequency in vhdl coding?
Thanks.
Do not use a counter to generate a lower frequency clock signal.
Multiple clock frequencies in an FPGA cause a variety of design problems, some of which come under the heading of "advanced topics" and, while they can (if necessary) all be dealt with and solved, learning how to use a single fast clock is both simpler and generally better practice (synchronous design).
Instead, use whatever fast clock your FPGA board provides, and generate lower frequency timing signals from it, and - crucially - use them as clock enables, not clock signals.
DLLs, DCMs, PLLs and other clock managers do have their uses, but generating 1 kHz clock signals is generally not a good use, even if their limitations permit it. This application is just crying out for a clock enable...
Also, don't mess around with magic numbers, let the VHDL compiler do the work! I have put the timing requirements in a package, so you can share them with the testbench and anything else that needs to use them.
package timing is
-- Change the first two constants to match your system requirements...
constant Clock_Freq : real := 40.0E6;
constant Sample_Rate : real := 1000.0;
-- These are calculated from the above, so stay correct when you make changes
constant Divide : natural := natural(Clock_Freq / Sample_Rate);
-- sometimes you also need a period, e.g. in a testbench.
constant clock_period : time := 1 sec / Clock_Freq;
end package timing;
And we can write the sampler as follows:
(I have split the clock enable out into a separate process to clarify the use of clock enables, but the two processes could be easily rolled into one for some further simplification; the "sample" signal would then be unnecessary)
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;
use work.timing.all;
entity sampler is
Port (
Clock : in std_logic;
Reset : in std_logic;
ADC_In : in signed(7 downto 0);
-- signed for audio, or unsigned, depending on your app
Sampled : out signed(7 downto 0);
);
end sampler;
architecture Behavioral of Sampler is
signal Sample : std_logic;
begin
Gen_Sample : process (Clock,Reset)
variable Count : natural;
begin
if reset = '1' then
Sample <= '0';
Count := 0;
elsif rising_edge(Clock) then
Sample <= '0';
Count := Count + 1;
if Count = Divide then
Sample <= '1';
Count := 0;
end if;
end if;
end process;
Sample_Data : process (Clock)
begin
if rising_edge(Clock) then
if Sample = '1' then
Sampled <= ADC_In;
end if;
end if;
end process;
end Behavioral;
The base clock must be based on an external clock, and can't be generated just through internal resources in a Spartan-3 FPGA. If required, you can use the Spartan-3 FPGA Digital Clock Manager (DCM) resources to scale the external clock. Synthesized VHDL code in itself can't generate a clock.
Once you have some base clock at a higher frequency, for example 100 MHz, you can easily divide this down to generate an indication at 1 kHz for sampling of the external input.
It depends on what clock frequency you have available. If you have a 20MHz clock source, you need to divided it by 20000 in order to get 1KHz, you can do it in VHDL or use a DCM to do this.
This is from an example on how to create a 1kHz clock from a 20MHz input:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity clk20Hz is
Port (
clk_in : in STD_LOGIC;
reset : in STD_LOGIC;
clk_out: out STD_LOGIC
);
end clk200Hz;
architecture Behavioral of clk20Hz is
signal temporal: STD_LOGIC;
signal counter : integer range 0 to 10000 := 0;
begin
frequency_divider: process (reset, clk_in) begin
if (reset = '1') then
temporal <= '0';
counter <= 0;
elsif rising_edge(clk_in) then
if (counter = 10000) then
temporal <= NOT(temporal);
counter <= 0;
else
counter <= counter + 1;
end if;
end if;
end process;
clk_out <= temporal;
end Behavioral;

VHDL code for metal detector

I am working on a metal detector at the moment but can't figure out how to implement it my VHDL code.
ENTITY sensor IS
port ( metaldetector : in std_logic;
metal : out std_logic;
);
END ENTITY sensor;
As long as there isn't any metal close to the sensor 'metaldetector' gets pulses on a 6.1kHz frequency. So as long as the 'metaldetector' keeps getting pulses the out port 'metal' should be '0'.
When there is a pulse missing (or multiple pulses) 'metal' should become '1' until the next pulse.
It shouldn't be that hard to make a code that can do that, but i just can't figure it out. Any help would really be great!
We managed to solve the problem with some help of other students, and a lot of trying.
I'll post our solution down here, hopefully it can be usefull to others. :)
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL;
ENTITY sensor IS
port ( metaldetector : in std_logic;
clk : in std_logic;
metal : out std_logic
);
END ENTITY sensor;
ARCHITECTURE sensorbehav OF sensor IS
signal new_count, count: unsigned(20 downto 0);
begin
process (clk, metaldetector)
begin
if (rising_edge (clk)) then
if (metaldetector = '1') then
count <= (others => '0');
else
count <= new_count;
end if;
end if;
end process;
process (count)
begin
new_count <= count + 1;
end process;
process (count)
begin
if (count > 9000) then
metal <= '1';
else
metal <= '0';
end if;
end process;
END ARCHITECTURE;

Resources