Simulation blinking LED using VHDL with Quartus II and ModelSim - vhdl

I'm new to VHDL, Quartus II and ModelSim. Now I'm doing a lab where we are constructing a blinking LED. How should simulation be handled when the construction deals with relatively long time periods. The frequency of the blinking LED is 1 Hz and the clock on the dev board I'm using (Terasic DE2-115) is 50 MHz. In the code I'm counting the clock pulses and turn on the LED accordingly. However, when I want to verify my code with ModelSim, I get in to troubles dealing with times as long as seconds. So I solved it just by changing the period in the code to a couple of clock cycles to see that the waves behave as expected. For final compilation, I just change the count value that corresponds to 1 second.
But there should be a better way. I don't really want to touch the VHDL code after simulation. Should I use two rtl's, one for synthesis and one for simulation when dealing with time periods approaching 1 ms and higher?
The VHDL code
library ieee;
use ieee.std_logic_1164.all;
entity lab4 is
port( CLOCK_50 : in std_logic; -- DE2-115 internal clock
KEY : in std_logic_vector(0 downto 0); -- Push-buttons, active 0
-- KEY(0) as reset
LEDG : out std_logic_vector(7 downto 0)); -- Green LEDs
end entity lab4;
architecture lab4_rtl of lab4 is
signal RESET_N : std_logic;
begin
-- Parallel VHDL
constant CLK_FRQ : integer := 50000000;
RESET_N <= KEY(0); -- Here we connect reset to a push-button
-- synch process with asynch reset, i.e. reset as soon as reset is active
p1 : process(CLOCK_50, RESET_N)
variable counter : integer := 0;
variable led_num : integer := 0;
begin
-- reset part
if RESET_N = '0' then --KEY is active 0
counter := 0; --reset counter
LEDG(0) <= '0'; --turn OFF leds
-- synch part, updates depending on clock
elsif rising_edge(CLOCK_50) then
counter := counter + 1;
if counter < 50000000 then;
LEDG(0) <= '1';
elsif counter >= 50000000 AND counter < 100000000 then
LEDG(0) <= '0';
else
counter := 0;
end if;
end if;
end process p1;
end architecture lab4_rtl;

You have declared a named constant, then ignored it...
constant CLK_FRQ : integer := 50000000;
First you can rewrite the counter in terms of CLK_FRQ and CLK_FRQ * 2 instead of magic numbers.
Then you can set different values for CLK_FRQ in sim and synth. There are various ways to do it but my preference is for a function.
function Clock_Frequency return natural is
begin
-- synthesis translate_off
return 50;
-- synthesis translate_on
return 50000000;
end Clock_Frequency;
It uses the "magic" pragmas translate_off (and _on) which may vary between synthesis tools but are accepted by most. These direct synthesis to ignore bits of the source : in this case, the first Return which is only seen by the simulator.
Now you can call this function to initialise the constant
constant CLK_FRQ : integer := Clock_Frequency;
Job done.

I would not change the clock frequency, because this doesn't change the count of events which have to be simulated by the simulator (this is also the time consuming factor). I think it's better to change the number of cycles which must pass until you change the LED output.
You can define a VHDL function which returns TRUE if you are in a simulation environment:
function SIMULATION return boolean is
variable ret : boolean;
begin
ret := false;
--synthesis translate_off
if Is_X('X') then ret := true; end if;
--synthesis translate_on
return ret;
end function;
In addition to this, you can define a if-then-else function to simplify your code:
function ite(cond : BOOLEAN; value1 : INTEGER; value2 : INTEGER) return INTEGER is
begin
if cond then
return value1;
else
return value2;
end if;
end function;
And now it's possible to select the counter's max value in one line like this:
constant COUNTER_MAX : INTEGER := ite(SIMULATION, 500, 50000);
Reviewing your code from above, there are some errors:
the LED is blinking at 0.5 Hz not 1 Hz (regarding your if
the duty-cycle is not 50.00000 %, because your counter is set to zero one cycle to late.
I think it's not intended that LED is synthesized as an addition Flip-Flop.

Related

Generic clock divider in VHDL

I want to write in VHDL a general clock divider like this:
entity Generic_Clk_Divider is
Generic(
INPUT_FREQ: integer := 100;
OUTPUT_FREQ: integer := 25;
);
Port (
Clk: in std_logic;
Rst: in std_logic;
Generated_Clk: out std_logic
);
end entity;
architecture Behavioral of Generic_Clk_Divider is
signal Cnt: integer := 0;
signal Gen_Clk : std_logic := '0';
constant MaxCnt: integer := (integer (INPUT_FREQ/OUTPUT_FREQ)) - 1;
begin
process(clk, Rst)
begin
if (Rst = '1') then
Cnt <= 0;
elsif rising_edge(Clk) then
Cnt <= Cnt + 1 ;
if (Cnt = MaxCnt) then
Gen_Clk <= not Gen_Clk;
Cnt <= 0;
end if;
end if;
Generated_Clk <= Gen_Clk;
end process;
end architecture;
It works if I test it with a test bench but it is not working if I use the generated Clk singal with another component (VGA controller in this case) if I but it on a board. My question is about that division between 2 integers, th board seems not to recognize it.
Integer/ Integer, returns an integer, with the remainder discarded. So for situations where INPUT/OUTPUT are integer multiples of each other, this is fine. But otherwise, it won't work.
eg.
200/75 = 2
150/40 = 3
etc.
The only way this is really going to work is with real types so you can find the fractional relationships, and then use a much larger counter value to get exact relationships.
But, this isnt really going to help at all, as clock dividers like this are highly discouraged. Logic generated clocks make timing analysis difficult and cause timing problems. It is much safer to use a real clock and generate clock enables instead.

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.

Count Edges over specific Period of Time in VHDL

For speed measurement of an electric motor I would like to count the amount of rising and falling edges of an encoder-input in a time-interval of 10ms.
To do this I have implementet a clock divider for my 40 MHz Clock as follows:
entity SpeedCLK is
Port ( CLK : in STD_LOGIC;
CLKspeed : out STD_LOGIC);
end SpeedCLK;
architecture Behavioral of SpeedCLK is
signal CounterCLK : NATURAL range 0 to 400001;
begin
SpeedCounter : process
begin
wait until rising_edge(CLK);
CounterCLK <= CounterCLK + 1;
if CounterCLK < 400000 then
CLKspeed <= '0';
else
CLKspeed <= '1';
CounterCLK <= 0;
end if;
end process SpeedCounter;
end Behavioral;
This should make CLKSpeed '1' every 10 ms. I use this block as a component in my Toplevel VHDL-Module. In the next Block I count the Edges from my encoderinput(QEPA) with a shift register to debounce the Input Signal.
entity SpeedMeasure is
Port (
QEPA : in STD_LOGIC;
CLK : in STD_LOGIC;
CLKSpeed : in STD_LOGIC;
Speed : OUT INTEGER -- in rpm
);
end SpeedMeasure;
architecture Behavioral of SpeedMeasure is
begin
Edges : process(CLKSpeed, CLK)
variable detect : STD_LOGIC_VECTOR(5 downto 0) := "000000";
variable EdgesPerTime : INTEGER := 0;
variable CountQEPA : INTEGER := 0;
begin
if CLKSpeed = '1' then
EdgesPerTime := countQEPA;
countQEPA := 0;
ELSIF (CLK'EVENT AND CLK = '1') THEN
detect(5 downto 1) := detect(4 downto 0);
detect(0) := QEPA;
if (detect = "011111") OR (detect = "100000") then
countQEPA := countQEPA + 1;
else
countQEPA := countQEPA;
end if;
end if;
Speed <= EdgesPerTime;
end process Edges;
end Behavioral;
This should write the current value of CountQEPA in my variable edgesPerTime every 10 ms and reset the Counter afterwards.
The signal Speed gets transmitted via uart. Unfortunatly with the reset of CountQEPA every 10ms I receive a constant value of 0 for EdgesPerTime. If I remove the reset line in the code, I can receive an increasing value for EdgesPerTime until the largest number for Integer (2^16) is reached, at which Point the Counter resets to 0.
What is the correct implementation in VHDL to count rising and falling edges in a set period of time?
Any help is greatly apreciated as I am still very new to vhdl.
You're building a latch using a variable. Your synthesis tool inferred an asynchronous reset CLKSpeed for countQEPA and since your latch EdgesPerTime latches countQEPA when its write enable CLKSpeed is asserted, you only see the reset countQEPA value of 0.
You should build proper synchronous logic:
signal CountQEPA : integer := 0;
signal detect : std_logic_vector(5 downto 0) := (others => '0');
begin
edge_cnt_p : process (
CLK
)
begin
if (rising_edge(CLK)) then
-- synchronous reset
if (CLKSpeed = '1') then
countQEPA <= 0;
elsif ((detect = "011111") or (detect = "100000")) then
countQEPA <= countQEPA + 1;
end if;
end if;
end process edge_cnt_p;
edge_debounce_p : process (
CLK
)
begin
if (rising_edge(CLK)) then
detect <= detect(detect'left downto 1) & QEPA;
end if;
end process edge_debounce_p;
count_register_p : process (
CLK
)
begin
if (rising_edge(CLK)) then
-- synchronous write enable
if (CLKSpeed = '1') then
Speed <= countQEPA;
end if;
end if;
end process count_register_p;
I'm not a big fan of variables, but it seems synthesis tools got a lot smarter these days. As you can see, I made three separate processes to show what we actually want going on. CountQEPA and debounce are signals now, because they need to be readable from other processes.
I assume CLKSpeed is synchronous to CLK (40 MHz). If it isn't, then you should think about handshaking between the clock domains.
You can of course make a single process out of these individual processes. In general, I try to avoid variables, because they can easily be used to describe behavior that is not synthesizable, like you found out the hard way.
I'm not sure how long your encoder bounces, but if you do sample at 40 MHz, a 6 bit shift register will likely not work as that's only a 125 ns debounce (you use the lower 5 bits only for debouncing, the top bit for noticing state changes).
Speaking of your debouncer. Consider the following case:
debounce QEPA
111111 1
111111 0 <-- glitch/bounce on encoder line; 25 ns wide
111110 1
111101 1
111011 1
110111 1
101111 1
011111 1 <-- fake edge detected
That's probably not what you want. You should compare your debounced signal to the last stable state instead of assuming state'delayed(5 * clk_period) being a stable state.
As I said above, I'm assuming CLK is your 40 MHz clock. You needn't sample your encoder signal that fast, because a proper debouncer would take a large number of shift register bits at no added value to you, because you have to divide that clock down to 1 kHz anyway for your time-slot counting.
Instead, take into account the maximum frequency of your encoder signal. You would want to oversample that at least by double that frequency, quadruple that frequency to be safe. So you have four samples per "bit time".
Since you're expecting many edges at 1 kHz, I assume your encoder is at least two orders of magnitude fast, i.e. 100 kHz. So scale 40 Mhz down to 400 kHz and shift in QEPA for debouncing. Sample these 400 kHz down to 1 kHz for your time slot measurements.
On a side note: What kind of motor encoding only uses a single bit? Are you sure you're not dealing with a quadrature encoder?

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-PWM Weird Behavior and Physical Upper/Lower limitations

I am trying to generate picosecond PWM signal using the Spartan 3e board in VHDL (Xilinx ISE+ISim).
library ieee;
use ieee.std_logic_1164.all;
entity pwm is
port(clk : in std_logic;
pwm_out : buffer std_logic);
end entity;
architecture rtl of pwm is
begin
process (clk)
variable count : integer range 0 to 50000;
variable duty_cycle : integer range 0 to 50000;
variable flag : integer range 0 to 1;
begin
if (rising_edge(clk)) then
count := count+1;
if (count = duty_cycle) then
pwm_out <= '1';
end if;
if (count = 50000) then
pwm_out <= '0';
count := 0;
if(flag = 0) then
duty_cycle := duty_cycle+50;
else
duty_cycle := duty_cycle-50;
end if;
if(duty_cycle = 50000) then
flag := 1;
elsif(duty_cycle = 0) then
flag := 0;
end if;
end if;
end if;
end process;
end rtl;
I am using the embedded 50Mhz for the global clock (C9) but the simulation showed a weird behavior; from 0ps to 1000000ps clk (clock) and pwm_out (output) seems to be HIGH always and there is nothing after 1000000ps both for clk and pwm_out in time domain under ISim.
I am trying to do is to investigate and solve this behavior and then increase the frequency of output (pwm_out). Also I would like to learn about how fast (rise/fall times and in the frequency) can I generate the pulse (physical limitations).
I would appreciate some guidance from experienced users.
The pwm_out output has not initial value, so it has to be assigned in the process before it gets a well defined value. But the process variables (holding process state) all have an initial value of zero, and since count is incremented first thing in the process loop, count will not equal duty_cycle (being 0) at the beginning. So pwm_out is not assigned until it equals 50000, which (with a 50 MHz clock) happens at 50000 / 50 MHz = 1 ms.
However, if you synthesize this and run it in the FPGA, you may experience some unexpected behavior, depending on your clock source and control. For example, if the pwm module is running from a clock that is not stable right when the FPGA is loaded, for example an internal PLL clock, then the initial clock behavior may not adhere to the timing constraints applied to the design, and any value may end up in for example the duty_cycle variable (register). But, the design is based on the assumption that the duty_cycle register has a value of (50 * n), and otherwise it won't increment and decrement as anticipated due to the equal compare (=) with 0 and 50000. So if the duty_cycle get the value 1, due to initial timing violations as a result of an initial "invalid" clock, the flag variable (state) won't operate as expected, and so on. One way to amend this is to add a reset input and apply this to the variable state until the clock is stable, or use inequality operators for comparison.

Resources