i have to create a VHDL sequence thats takes only a clock input and out puts a 5 led sequence see picture
am i correct in thinking that using the std_logic_vector i can then connect each vector output to a single LED in order to create this sequence or am i miss interpreting the use of the std_logic_vector?
the code i have used is
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all; -- i have used this package as my CLK-CNT signal counts in integer format rather than binary and i am performing an ADD sum of the CLK_CNT
entity REG_LED is
PORT(CLK: IN std_logic; -- CLK input
LEDS: Out std_logic_vector (4 downto 0) ); -- initialise output
End REG_LED;
ARCHITECTURE behavioral OF REG_LED IS
SIGNAL CLK_CNT: integer range 0 to 9:= 0; -- initailise comparison signal used for counting clock pulses.
-- This signal will be used by the program to recognise where in the sequnce the program is and thus determine the next state required for the sequence.
BEGIN
CLK_Process: PROCESS (CLK) -- begin the CLK_CNT Process
BEGIN
if rising_edge(CLK) Then
if CLK_CNT = 8 then
CLK_CNT <= 0; -- this resets the clock pulse count to 0
else
CLK_CNT <= CLK_CNT + 1 ; -- used to count each clock pulse upto the reset
End if;
-- this process has been kept seperate to the LED output process in order to isolate the event from the output process and limit the possiblities of errors
END IF;
END PROCESS ;
LED_PROCESS: Process (CLK_CNT) -- LED Outputs based on Temp count
BEGIN -- begin the output sequence
Case CLK_CNT is
-- i use a case statement to compare the value of the CLK_CNT signal and produce the required LEDS output
-- this ensures the
When 0 =>
LEDS <= "11111"; -- S0 when clock count is 0
When 1 =>
LEDS <= "00001"; -- S1 when clock count is 1
When 2 =>
LEDS <= "00001"; -- S2 when clock count is 2
When 3 =>
LEDS <= "11111"; -- S3 when clock count is 3
When 4 =>
LEDS <= "00000"; -- S4 when clock count is 4
When 5 =>
LEDS <= "11111"; -- S5 when clock count is 5
When 6 =>
LEDS <= "00100"; -- S6 when clock count is 6
When 7 =>
LEDS <= "01010"; -- S7 when clock count is 7
When 8 =>
LEDS <= "10001"; -- S8 when clock count is 8 this is the final clock count state
When others =>
LEDS <= "11111"; -- Restart Sequence
End Case;
End Process;
END behavioral;
i have simulated the waveform and it produces the 5 outputs as required by the sequence but can this output beused to drive 5 different leds or will it just be a 5 bit word that is output of one port? im new to VHDL so any help would be appreciated
Your code looks fine, and if your simulation indicates it is functioning according to what you need then you are almost good to go.
A std_logic_vector is really a number of wires (bus). You have to think about what it physically means, because that's what really happens when you program an FPGA. So yes, you can split up (or breakout) the bus into individual lines. This can be done as such:
signal LED_LINE_0 : std_logic;
signal LED_LINE_1 : std_logic;
LED_LINE_0 <= LEDS(0);
LED_LINE_1 <= LEDS(1);
...and so on. This rips out one wire at a time. You can also split a bus into smaller buses by ripping out multiple wires at a time. e.g.
signal small_bus_1 : std_logic_vector(1 downto 0);
signal small_bus_2 : std_logic_vector(1 downto 0);
signal big_bus : std_logic_vector(3 downto 0);
small_bus_1 <= big_bus(3 downto 2);
small_bus_2 <= big_bus(1 downto 0);
You can then write in your constraints file (or use the GUI in the IDE of your FPGA brand) to specify which pin on the FPGA you'd like each of these std_logic to be assigned to (that drives the LED you need).
Related
I have to write program in VHDL which calculate sqrt using Newton method. I wrote the code which seems to me to be ok but it does not work.
Behavioral simulation gives proper output value but post synthesis (and launched on hardware) not.
Program was implemented as state machine. Input value is an integer (used format is std_logic_vector), and output is fixed point (for calculation
purposes input value was multiplied by 64^2 so output value has 6 LSB bits are fractional part).
I used function to divide in vhdl from vhdlguru blogspot.
In behavioral simulation calculating sqrt takes about 350 ns (Tclk=10 ns) but in post synthesis only 50 ns.
Used code:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity moore_sqrt is
port (clk : in std_logic;
enable : in std_logic;
input : in std_logic_vector (15 downto 0);
data_ready : out std_logic;
output : out std_logic_vector (31 downto 0)
);
end moore_sqrt;
architecture behavioral of moore_sqrt is
------------------------------------------------------------
function division (x : std_logic_vector; y : std_logic_vector) return std_logic_vector is
variable a1 : std_logic_vector(x'length-1 downto 0):=x;
variable b1 : std_logic_vector(y'length-1 downto 0):=y;
variable p1 : std_logic_vector(y'length downto 0):= (others => '0');
variable i : integer:=0;
begin
for i in 0 to y'length-1 loop
p1(y'length-1 downto 1) := p1(y'length-2 downto 0);
p1(0) := a1(x'length-1);
a1(x'length-1 downto 1) := a1(x'length-2 downto 0);
p1 := p1-b1;
if(p1(y'length-1) ='1') then
a1(0) :='0';
p1 := p1+b1;
else
a1(0) :='1';
end if;
end loop;
return a1;
end division;
--------------------------------------------------------------
type state_type is (s0, s1, s2, s3, s4, s5, s6); --type of state machine
signal current_state,next_state: state_type; --current and next state declaration
signal xk : std_logic_vector (31 downto 0);
signal temp : std_logic_vector (31 downto 0);
signal latched_input : std_logic_vector (15 downto 0);
signal iterations : integer := 0;
signal max_iterations : integer := 10; --corresponds with accuracy
begin
process (clk,enable)
begin
if enable = '0' then
current_state <= s0;
elsif clk'event and clk = '1' then
current_state <= next_state; --state change
end if;
end process;
--state machine
process (current_state)
begin
case current_state is
when s0 => -- reset
output <= "00000000000000000000000000000000";
data_ready <= '0';
next_state <= s1;
when s1 => -- latching input data
latched_input <= input;
next_state <= s2;
when s2 => -- start calculating
-- initial value is set as a half of input data
output <= "00000000000000000000000000000000";
data_ready <= '0';
xk <= "0000000000000000" & division(latched_input, "0000000000000010");
next_state <= s3;
iterations <= 0;
when s3 => -- division
temp <= division ("0000" & latched_input & "000000000000", xk);
next_state <= s4;
when s4 => -- calculating
if(iterations < max_iterations) then
xk <= xk + temp;
next_state <= s5;
iterations <= iterations + 1;
else
next_state <= s6;
end if;
when s5 => -- shift logic right by 1
xk <= division(xk, "00000000000000000000000000000010");
next_state <= s3;
when s6 => -- stop - proper data
-- output <= division(xk, "00000000000000000000000001000000"); --the nearest integer value
output <= xk; -- fixed point 24.6, sqrt = output/64;
data_ready <= '1';
end case;
end process;
end behavioral;
Below screenshoots of behavioral and post-sythesis simulation results:
Behavioral simulation
Post-synthesis simulation
I have only little experience with VHDL and I have no idea what can I do to fix problem. I tried to exclude other process which was for calculation but it also did not work.
I hope you can help me.
Platform: Zynq ZedBoard
IDE: Vivado 2014.4
Regards,
Michal
A lot of the problems can be eliminated if you rewrite the state machine in single process form, in a pattern similar to this. That will eliminate both the unwanted latches, and the simulation /synthesis mismatches arising from sensitivity list errors.
I believe you are also going to have to rewrite the division function with its loop in the form of a state machine - either a separate state machine, handshaking with the main one to start a divide and signal its completion, or as part of a single hierarchical state machine as described in this Q&A.
This code is neither correct for simulation nor for synthesis.
Simulation issues:
Your sensitivity list is not complete, so the simulation does not show the correct behavior of the synthesized hardware. All right-hand-side signals should be include if the process is not clocked.
Synthesis issues:
Your code produces masses of latches. There is only one register called current_state. Latches should be avoided unless you know exactly what you are doing.
You can't divide numbers in the way you are using the function, if you want to keep a proper frequency of your circuit.
=> So check your Fmax report and
=> the RTL schematic or synthesis report for resource utilization.
Don't use the devision to shift bits. Neither in software the compiler implements a division if a value is shifted by a power of two. Us a shift operation to shift a value.
Other things to rethink:
enable is a low active asynchronous reset. Synchronous resets are better for FPGA implementations.
VHDL code may by synthesizable or not, and the synthesis result may behave as the simulation, or not. This depends on the code, the synthesizer, and the target platform, and is very normal.
Behavioral code is good for test-benches, but - in general - cannot be synthesized.
Here I see the most obvious issue with your code:
process (current_state)
begin
[...]
iterations <= iterations + 1;
[...]
end process;
You are iterating over a signal which does not appear in the sensitivity list of the process. This might be ok for the simulator which executes the process blocks just like software. On the other hand side, the synthesis result is totally unpredictable. But adding iterations to the sensitivity list is not enough. You would just end up with an asynchronous design. Your target platform is a clocked device. State changes may only occur at the trigger edge of the clock.
You need to tell the synthesizer how to map the iterations required to perform this calculation over the clock cycles. The safest way to do that is to break down the behavioural code into RTL code (https://en.wikipedia.org/wiki/Register-transfer_level#RTL_in_the_circuit_design_cycle).
I have a system that has a 3 input D_in which is read at every positive clk edge.
If say I want to see if the current input, D_in is greater then the previous D_in by at least 2, then a count will increment. How do I write this in VHDL?
if clk'event and clk = '1' then --read at positive edge
if D_in > (D_in + 010) then <---I am sure this is wrong. How to write the proper code?
Entity ABC is
Port(D_in: in std_logic_vector(2 downto 0);
Count: out std_logic_vector(2 downto 0));
Architecture ABC_1 of ABC is
signal D_last: std_logic_vector(2 downto 0);
Begin
Process(D_in)
D_last <= D_in;
if clk'event and clk = '1' then
if D_last > (D_in + 2) then
count <= count + 1;
end if;
end process;
end ABC_1;
The "good" way to write this process is as follow :
process (clk)
begin
if (rising_edge(clk)) then
-- store the value for the next time the process will be activated
-- Note that D_last value will be changed after the whole process is completed
D_last <= D_in;
-- compare the actual D_in value with the previous one stored in D_last.
-- D_last value is its value at the very beginning of the process activation
if (D_in > D_last + 2) then
-- increment the counter
count <= count + 1;
end if;
end if;
end process;
Note that D_in, D_last and count has to be declared as unsigned and not as std_logic_vector.
I suggest you to read this post which explains how a process actually works : when are signals updated and which signal value is used into the process.
Cheers
[edit] This answer should be fine for your question. But the code you show has other errors :
The signal clk has to be an input for your entity.
The signal count can't be read in your architecture because it's defined as output in the entity. Then the line "count <= count + 1" can't be resolved. You have to use an internal signal and then assign its value to "count" outside of a process :
count <= count_in;
There are several other errors in your design specification as well. This answer attempts to answer all concerns in one place.
VHDL is simulated by executing processes in simulation cycles. Every
concurrent statement can be expresses as either an equivalent process
statement or combination of process statements and block statements.
Signal assignment is to a projected output waveform queue for a specified
time. When no time is specified it's the current time, and the value will be updated
prior to executing processes in the next simulation cycle, a delta cycle, simulation
time is advanced when there are no remaining events scheduled for the
current simulation time.
To avoid confusion over when signal assignments occur, view them as
separate processes (whether you express them that way or not).
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity abc is
port (
clk: in std_logic; -- Note 1
d_in: in std_logic_vector(2 downto 0);
count: out std_logic_vector(2 downto 0)
);
end entity; -- Note 2
architecture foo of abc is
signal d_last: std_logic_vector(2 downto 0);
begin
DLAST: -- Note 3
process (clk)
begin
if rising_edge(clk) then -- Note 4
d_last <= d_in;
end if;
end process;
INC_COUNT:
process (clk)
variable cnt: unsigned(2 downto 0) := "000"; -- Note 5
begin
if rising_edge(clk) and
unsigned(d_last) > unsigned(d_in) + 2 then -- Mote 6,7
cnt := cnt + 1;
end if;
count <= std_logic_vector(cnt);
end process;
end architecture;
Notes
Missing clk from port interface
Missing end statement for entity ABC.
Conceptually view D_last
register separately from Count counter sensitive to clk. (Can be
merged as one process)
rising_edge function expresses clk'event and clk = '1' ('event
and "=" are both functions)
The counter must represent a binary value for "+" to produce a
binary result
"+" is higher priority than ">", which is higher priority than "and"
(you don't need parentheses)
Package numeric_std provide relational and adding operators for
type sign and type unsigned, requiring type conversion for D_last
and D_in.
Alternatively use Synopsys package std_logic_unsigned which
depends on Synopsys package std_logic_arith and treats
std_logic_vector as unsigned. This avoids type conversion, and
allows array types to be declared as type std_logic_vector.
The variable cnt can be done away with if port count were to be declared mode buffer and provided a default value:
count: buffer std_logic_vector(2 downto 0) :="000" -- Note 5
and
INC_COUNT:
process (clk)
begin
if rising_edge(clk) and
unsigned(d_last) > unsigned(d_in) + 2 then -- Note 6,7
count <= std_logic_vector(unsigned(count) + 1);
end if;
end process;
You can't use Count as mode out to algorithmically modify it's own value. The ability to access the value of a mode out port is intended for verification and is a IEEE Std 1076-2008 feature.
And about now you can see the value of Synopsys's std_logic_unsigned package, at least as far avoiding type conversions.
Also, i got another question. If d_in is 0 for 3 consecutive clk cycles, i want to reset count to 0. How do i write the code to represent for 3 clk cycles?
Add another pipeline signal for D_in:
signal d_last: std_logic_vector(2 downto 0) := "000";
signal d_last1: std_logic_vector(2 downto 0) := "000";
Note these also have default values, which FPGA synthesis will generally honor, it's represented by the state of the flip flop in the bistream image used for programming the FPGA.
And modify how the counter is operated:
INC_COUNT:
process (clk)
begin
if rising_edge(clk) then
if d_in = "000" and d_last = "000" and d_last1 = "000" then
count <= "000";
elsif unsigned(d_last) > unsigned(d_in) + 2 then -- Note 6,7
count <= std_logic_vector(unsigned(count) + 1);
end if;
end if;
end process;
The three incarnations of the example all analyze, they haven't been simulation and should be synthesis eligible.
I have written a LFSR in VHDL. I have tested it in simulation and it works as expected (generates random integers between 1 and 512). However when I put it onto hardware it always generates "000000000"
The code is as follows:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity LFSR is
port(clk, reset : in bit;
random : out std_logic_vector (8 downto 0));
end entity LFSR;
architecture behaviour of LFSR is
signal temp : std_logic_vector (8 downto 0) := (8 => '1', others => '0');
begin
process(clk)
begin
if(clk'event and clk='1') then
if(reset='0') then --reset on signal high, carry out normal function
temp(0) <= temp(8);
temp(1) <= temp(0);
temp(2) <= temp(1) XOR temp(8);
temp(3) <= temp(2) XOR temp(8);
temp(4) <= temp(3) XOR temp(8);
temp(8 downto 5) <= temp(7 downto 4);
else
--RESET
temp <= "100000000";
end if;
end if;
random <= temp;
end process;
end architecture behaviour;
It was tested in Modelsim and compiled in Quartus II for a Cyclone III DE0 board.
Can anyone see why it is not working (in practice, the simulation is fine) and explain what I need to change to get it to work?
If reset is directly from a FPGA pin, then it is probably not synchronized
with clk, so proper synchronous reset operation is not ensured.
Add two flip-flops for synchronization of reset to clk before it is used in
the process. This can be done with:
...
signal reset_meta : bit; -- Meta-stable flip-flop
signal reset_sync : bit; -- Synchronized reset
begin
process(clk)
begin
if(clk'event and clk='1') then
reset_meta <= reset;
reset_sync <= reset_meta;
if (reset_sync = '0') then -- Normal operation
...
Altera have some comment about this in External Reset Should be Correctly
Synchronized.
The description covers flip-flops with asynchronous reset, but the use of two
flip-flops for synchronisation of external reset applies equally in your case.
Still remember to move the random <= temp inside the if as David pointed
out.
If you haven't any luck you might take a look at the synthesized schematic or perform post-synthesis simulation. I occasionally swap RTL models out for post - synth models for verification if there's something that isn't obvious in behavioral simulation.
-Jerry
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_signed.all;
entity counter is
port(CLK, CLR : in std_logic;
output : inout std_logic_vector(3 downto 0));
end counter;
architecture archi of counter is
signal tmp: std_logic_vector(3 downto 0);
begin
process (CLK, CLR)
variable i: integer:=0;
begin
if (CLR='1') then
tmp <= "0000";
elsif (clk = '1') then
for i in 0 to 6 loop
tmp <= tmp + 1;
end loop;
end if;
to count upto 7 i have done for i in 0 to 10. it is not showing any error but it counts from 0000 to 1111
end process;
output <= tmp;
end architecture;
could you please suggest how to do it....sorry for wrong grammar in english
Needs to operate off one clock edge
Because your counter port has clk in it, we can assume you want the counter to count synchronous to the clock.
You're operating off of both clock edges
elsif (clk = '1') then
should be something like
elsif clk'event and clk = '1' then
or
elsif rising_edge(clk) then
These examples use the rising edge of clk. You can't synthesize something that uses both clock edges under the IEEE-1076.6 IEEE Standard for VHDL Register
Transfer Level (RTL) Synthesis. It's not a recognized clocking method.
Making a modulo 10 counter
Under the assumption you want the counter to go from 0 to 9 and rollover this
for i in 0 to 6 loop
tmp <= tmp + 1;
end loop;
Should be something like
if tmp = "1001" then # binary 9
tmp <= (others => '0'); # equivalent to "0000"
else
tmp <= tmp + 1;
end if;
And this emulates a synchronous load that takes priority over increment driven by an external 'state' recognizer. With an asynchronous clear it would emulate an 74163 4 bit counter with an external 4 input gate recognizing "1001" and producing a synchronous parallel load signal loading "0000".
What's wrong with the loop statement
The loop process as shown would result in a single increment and resulting counter rollover at "1111" like you describe. You could remove the for ... loop and end loop; statements and it would behave identically. There's only one schedule future update for a signal for each driver, and a process only has one driver for each signal it assigns. All the loop iterations occur at the same clk event. tmp won't get updated until the next simulation cycle (after the loop is completed) and it's assignment is identical in all loop iterations, the expression tmp + 1. The last loop iterated assignment would be the one that actually occurs and the value it assigns would be identical.
Using a loop statement isn't necessary when counter is state driven (state ≃ tmp). The additional state represented by i isn't needed.
entity mod10 is
Port ( d : out std_logic_vector(3 downto 0);
clr: in std_logic;
clk : in std_logic);
end mod10;
architecture Behavioral of mod10 is
begin
process(clk)
variable temp:std_logic_vector(3 downto 0);
begin
if(clr='1') then temp:="0000";
elsif(rising_edge(clk)) then
temp:=temp+1;
if(temp="1010") then temp:="0000";
end if;
end if;
d<=temp;
end process;
end Behavioral;
assuming a full 0 to 15 count of the gclk to be one period of the output pwm wave,
the pwmin reflects the duty cycle. as the count decreases from 15+1 to 0 first the
bufferreg value gets the pwmin value at the rising edge of the gclk and on each consecutive clock edge checks the countreg value and gives pwmout based on that
entity pwm is
port(gclk: in std_logic;
reset: in std_logic;
pwmin: in std_logic_vector(3 downto 0); --input reg to reflect the duty cycle
pwmout: out std_logic );
end pwm;
architecture Behavioral of pwm is
signal bufferreg,countreg: unsigned(3 downto 0);
signal count: integer:=16; -- count value for the one full cycle of PWM
begin
process(gclk, reset, pwmin)
begin
case reset is --asynchronous reset
when '0' =>
loop1: for count in 16 downto 0 loop --count is 15+1
if (rising_edge(gclk)) then --the buffer reg is loaded athe first clock edge
if (count=16) then
bufferreg<=unsigned(pwmin);
countreg<="0000";
else
if (countreg<=bufferreg) then
pwmout<='1'; --output high for on period
elsif (countreg>bufferreg) then
pwmout<='0'; --output low for off period
end if;
countreg<=countreg+1 --updating of countreg
end if;
end if;
--next;
end loop loop1;
when others =>
end case;
end process;
end Behavioral;
you should write your code somewhat like the following:
process(gclk, reset)
begin
if reset='1' then -- asynchronous reset, high active
...
elsif rising_edge(gclk) then -- synchronous stuff on rising edge
loop1: for count...
...
be aware that your "for count in 16 downto 0 loop" leads to 17 steps!