VHDL-PWM Weird Behavior and Physical Upper/Lower limitations - vhdl

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.

Related

Assign multiple values to a signal during 1 process

If you assign a value to a signal in a process, does it only become the correct value of the signal at the end of the process?
So there would be no point in assigning a value to a signal more than once per process, because the last assignment would be the only one that would be implemented, correct?
I'm a bit desperate because I'm trying to implement the booth algorithm in VHDL with signals and I can't get it baked. It wasn't a problem with variables, but signals make it all more difficult.
I tried a for loop, but that doesn't work because I have to update the values within the loop.
My next idea is a counter in the testbench.
Would be very thanksful for an idea!
my current Code look like this:
architecture behave of booth is
signal buffer_result1, buffer_result2, buffer_result3: std_logic_vector(7 downto 0) := "0000"&b;
signal s: std_logic:= '0';
signal count1, count2: integer:=0;
begin
assignment: process(counter) is
begin
if counter = "000" then
buffer_result1 <= "0000"&b;
end if;
end process;
add_sub: process(counter) is
begin
if counter <= "011" then
if(buffer_result1(0) = '1' and s = '0') then
buffer_result2 <= buffer_result1(7 downto 4)-a;
else if (buffer_result1(0) = '0' and s = '1') then
buffer_result2 <= buffer_result1(7 downto 4)+a;
end if;
end if;
end process;
shift:process(counter) is
begin
if counter <= "011"
buffer_result3(7) <= buffer_result2(7);
buffer_result3(6 downto 0) <= buffer_result2(7 downto 1);
s<= buffer_result3(0);
else
result<=buffer_result3;
end if;
end behave;
Short answer: that's correct. A signal's value will not update until the end of your process.
Long answer: A signal will only update when its assignment takes effect. Some signal assignments will use after and specify a time, making the transaction time explicit. Without an explicit time given, signals will update after the default "time-delta," an "instant" of simulation time that passes as soon as all concurrently executing statements at the given sim time have completed (e.g. a process). So your signals will hold their initial values until the process completes, at which point sim time moves forward one "delta," and the values update.
That does not mean that multiple signal assignment statements to the same signal don't accomplish anything in a process. VHDL will take note of all assignments, but of a series of assignments given with the same transaction time, only the last assignment will take effect. This can be used for a few tricky things, although I've encountered differences of opinion on how often they should be tried. For instance:
-- Assume I have a 'clk' coming in
signal pulse : std_ulogic;
signal counter : unsigned(2 downto 0);
pulse_on_wrap : process(clk) is
begin
clock : if rising_edge(clk):
pulse <= '0'; -- Default assignment to "pulse" is 0
counter <= counter + 1; -- Counter will increment each clock cycle
if counter = 2**3-1 then
pulse <= '1'; -- Pulse high when the counter drops to 0 (after this cycle)
end if;
end if clock;
end process pulse_on_wrap;
Here, the typical behavior is to assign the value '0' to pulse on each clock cycle. But if counter hits its max value, there will be a following assignment to pulse, which will set it to '1' once simulation time advances. Because it comes after the '0' assignment and also has a "delta" transaction delay, it will override the earlier assignment. So this process will cause the signal pulse, fittingly, to go high for one cycle each time the counter wraps to zero and then drop the next - it's a pulse, after all! :^)
I provide that example only to illustrate the potential benefit of multiple assignments within a process, as you mention that in your question. I do not advise trying anything fancy with assignments until you're clear on the difference between variable assignment and signal assignment - and how that needs to be reflected in your code!
Try to think of things in terms of simulation time and hardware when it comes to signals. Everything is static until time moves forward, then you can handle the new values. It's a learning curve, but it'll happen! ;^)

VHDL finite state machine counter with start

i pretty new of vhdl and i'm trying to learn how to do a FSM with vhdl.
At moment i need a code that after a fixed count value, it give me back a pulse, in order to start a second FSM block. (I have a recurring signal every 100 kHz, i need to count it and release this signal after a fixed number of counts).
Actually it work as free run, every time that it see this signal, it start to count, but realy i want to add a "start" signal, so it must start to count this signal after it see this start signal.
at moment my working code is:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
entity counter is
Port (
signal_in : in STD_LOGIC := '0'; --segnale di start
clk : in STD_LOGIC; --clock di ingresso
reset : in STD_LOGIC; --ff reset
signal_out: out STD_LOGIC; --gate in uscita
count_val: in std_logic_vector (7 downto 0);
start : in STD_LOGIC := '0'
);
end counter;
architecture behavioral of counter is
type state_type is (idle, count_up);
signal state : state_type;
begin
process (reset, clk, signal_in, start)
variable index : integer :=0;
variable countlen: integer;
variable count_v: std_logic;
variable countlen2 : std_logic;
begin
countlen := to_integer(unsigned(count_val))-1;
if reset = '1' then
count_v := '0';
index := 0;
state <= idle;
else
--if start = '1' and
--if rising_edge(clk) then
if rising_edge(signal_in) then
case state is
when idle =>
count_v :='0';
index := 0;
if (signal_in = '1') then
state <= count_up;
else
state <= idle;
end if;
when count_up =>
if(index < countlen) then
state <=count_up;
index := index + 1;
elsif
index = countlen then
count_v := '1';
state <=idle;
end if;
when others => null;
end case;
end if;
end if;
signal_out <= count_v;
end process;
end Behavioral;
Any attempt to work with cose with "start = 1" will stop the count.
Please some one have some suggestion?
Kind REgards
Fulvio
Welcome om StackOverflow. Your specification is not 100% clear. What difference do you make between signal_in and start? According to your code and to your explanations, they both seem to act as a starter.
Moreover, there are several strange things with your code:
your process seems to be a synchronous one, with asynchronous reset. Its sensitivity list should contain only the clock and the reset. And its body should be:
process(clk, reset)
<variable declarations>
begin
<NOTHING HERE>
if reset = '1' then
<reset code>
elsif rising_edge(clk) then
<regular code>
end if;
<NOTHING HERE>
end process;
you are using signal_in as a clock and as a logic signal. This is extremely strange. Moreover, your if (signal_in = '1') then is always true (in the synthesis semantics) and thus useless.
You are initializing variables at declaration (index). This is not supported by some synthesizers and hardware targets. Moreover, even when supported, it works only at power up. If:
you intend to synthesize your code,
you want it to be portable across synthesizers and hardware targets,
you want to re-initialize signal and variables not only at power up but also when a reset input is asserted,
prefer a real explicit reset, instead, and guarantee that it is always asserted after power up (or at the beginning of a simulation) for proper first initialization.
you declare variable index with a full integer range, that is, 32 bits minimum, while 8 bits would suffice. This is a potential waste of hardware resources.
It is difficult to propose a solution without a clear and complete specification but assuming you want to count only after start has been asserted and only when signal_in is asserted, the following may be a starting point:
process (clk, reset)
variable index: natural range 0 to 255;
begin
if reset = '1' then
state <= idle;
signal_out <= '0';
index := 0;
elsif rising_edge(clk) then
case state is
when idle =>
signal_out <= '0';
index := 0;
if start = '1' then
state <= count_up;
end if;
when others =>
if signal_in = '1' then
if index = to_integer(unsigned(count_val)) - 1 then
state <= idle;
signal_out <= '1';
else
index := index + 1;
end if;
end if;
end case;
end if;
end process;
Note that this is really synchronous of your clock clk. I suspect that you made a very common mistake: as you wanted to increment your counter when signal_in is asserted you decided more or less to use signal_in as a clock. This is not a real synchronous and safe design. In a real safe synchronous design you do not use logic signals as clocks. You have well identified clocks and you use only these as clocks. In your case there is one single clock: clk. If you want to do something synchronously when a logic signal is asserted, wait for the rising edge of your clock and then test the logic signal and take appropriate actions.
thanks for your support.
Yes the point is that i need to "decimate" (or count) a signal.
This signal had a width of 50-100ns and it repeat itself with a frequency of 100 kHz.
so in my mind, this signal will go in to "signal in". My FPGA is an Actel proasic3 with a clock of 40 MHz.
In my setup this signal will be always on, but i don't want that my FSM will start to count as it see the first "signal in" but only when i send a "start" signal for the number of count that i indicate. (Realy they ask to me the possibility to decimate this signal up to 65000 count, so for sure i need to use a 16bit vector instead of 8bit).
The async reset is here "just in case" i need to reset the whole fsm in the middle of some data record.
Hope to be more clear now what this code should do.
For Old fart, yes indeed all my signal coming outside the fpga will be first synchronized with a simple 2 ff synchronizer with the FPGA clock

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?

Simulation blinking LED using VHDL with Quartus II and ModelSim

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.

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;

Resources