I am writing a code to generate a PWM wave in VHDL but I am getting a bad synchronous description error for the pwmout node - vhdl

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!

Related

VHDL CLOCK SEQUENCE Q3

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).

VHDL how to assign a input vector value to an integer signal

I'm new to the VHDL, I'm trying to make a counter which receives the value from the input and count to the given value then output a 1;
for example, the input is a 4-bit vector "1011"
I tried to set an integer signal a = input = 1011 = 11 in decimal, then if b = a = 11 output 1, otherwise output 0 and b=b+1
I know that I can do it by a series of if statements, but I'm wondering if there is any better way like assigning the value directly from a input vector to a integer signal? thanks for anyone who can help!
This is untested, but it's the general architecture it sounds like you're after. It's not bad practice to use if statements in VHDL; they're necessary to define sequential (not combinatorial) logic; you just need to be judicious in their use.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity Counter is port (
enable: in std_logic; -- Used to increment the counter. (Active high.)
value: in std_logic_vector(0 to 3);
clk: in std_logic; -- Used to clock the counter.
reset: in std_logic; -- Reset the counter. (Active high.)
output: out std_logic -- Generates a logic high once the count has been reached.
);
end Counter;
architecture Behavioral of Counter is
signal count: unsigned(0 to 3);
begin
process(clk,reset)
begin
-- If reset goes high, reset the count.
if reset='1' then
count <= "0000"; -- Reset the counter.
output <= '0'; -- Set the output low.
elsif(clk'event and clk='1') then -- If not reset, and the rising edge of the input clock...
if enable='1' then -- If the counter is enabled...
if count=unsigned(value) then -- If the count reached the input value...
output <= '1'; -- Set the output high.
else
count <= count + 1; -- Increment the counter.
end if;
end if;
end if;
end process;
end Behavioral;

VHDL signal assignment delay and simulation confusion

New to VHDL and trying to implement a small cache.
Part of my cache.vhd
entity cache is
Port ( clock : in STD_LOGIC;
rw_sel : in STD_LOGIC; --'1' to read from cache ,
--'0' to write to cache
ad_sel: in STD_LOGIC; --'0' to send address, '1' to send data
data_in :in STD_LOGIC_VECTOR (7 downto 0);
--send data or address controled by ad_sel
...
end cache;
architecture Behavioral of cache is
....
signal block_addr_n : integer range 0 to 15;
-- cache block address
signal block_cell_addr_n: integer range 0 to 1;
-- byte-in-cache address
begin
process(clock, init)
begin
case init is
when '0' =>
for i in 0 to 15 loop
cache_memory(i)<="1111111111111111";
tag_memory(i)<="11";
end loop;
when others =>null;
end case;
case ad_sel is
when '0' =>
address<=data_in(6 downto 0);
when '1' => data_cpu_wr<=data_in;
when others =>null;
end case;
block_addr_n <= conv_integer(unsigned(address(4 downto 1)));
block_cell_addr_n<=conv_integer(address(0));
case rw_sel is
....
part of my testbench file :
....
--Inputs
signal clock : std_logic := '0';
signal rw_sel : std_logic := '1';
signal ad_sel : std_logic := '0';
signal init: std_logic:='1';
signal data_in : std_logic_vector(7 downto 0) := (others => '0');
....
stim_proc: process
begin
-- initialize
init<='0';
wait for 100 ns;
-- read address "0101111"(MSB cut), expecting miss
cache_mem_data<="1100110011001100";
ad_sel<='0';
rw_sel<='1';
data_in<="00101111";
clock <= not clock;
wait for 100 ns;
-- write to address "0101111" but written in "0000000" which is default
data_in<="10101010";
ad_sel<='1';
rw_sel<='0';
clock<=not clock;
wait for 100 ns;
data_in<="00101111";
ad_sel<='0';
rw_sel<='1';
clock<=not clock;
wait;
end process;
END;
And what I got in the ISim window is
Why doesn't the block_addr_n and block_cell_addr_n be assigned in the second 100 ns since the signal address be assigned at that time directly? I think this is the reason that causes my program into unexpected results, since the cache block 0 is written while I just set address 0 as default but pass in the address "0101111" after the first 100 ns.
Any ideas?
The sensitivity list does not contain all the signals that are used in the process, since the address is a signal (assigned in the same process, but that does not matter) but the signal is not in the sensitivity list of the process. So the process is not reexecuted by the simulator when the value of address changes. Process parts:
process(clock, init)
begin
...
address<=data_in(6 downto 0);
...
block_addr_n <= conv_integer(unsigned(address(4 downto 1)));
block_cell_addr_n<=conv_integer(address(0));
If you are using VHDL-2008, then you can make the sensitivity list automatically with process (all), but I don't think Xilinx has implemented VHDL-2008 yet, so you must probably make the sensitivity list yourself by manually including all used signals in the sensitivity list.
Btw, consider making the processes either purely combinatorial (gates), or clocked (flip-flops or RAMs), so that combinatorial process should not have for example clock in the sensitivity list.
I think that your actual problem might be a misunderstanding about how to write a clocked process.
The way your process is written now it will generate purely combinational logic and latches.
What you want here is registers, RAM and combinational logic.
A clocked process would be written like this:
process(clock, init) --A clocked process shall have only the clock and reset signal in the sensitivity list. This is correct.
begin
if init = '0' then --"init" is used as a reset signal
for i in 0 to 15 loop
--This will reset the cache memory. It works, but
--doing it this way prevents the synthesis tool from infering a RAM block.
--To allow RAM inference you can write only one memory location per clock cycle.
cache_memory(i)<="1111111111111111";
tag_memory(i)<="11";
end loop;
elsif rising_edge( clock ) then
case ad_sel is
when '0' =>
address<=data_in(6 downto 0);
when '1' => data_cpu_wr<=data_in;
when others =>null;
end case;
block_addr_n <= conv_integer(unsigned(address(4 downto 1)));
block_cell_addr_n<=conv_integer(address(0));
case rw_sel is
...
end if;
Note that this will not work straight away. There are issues in your testbench as well. For example, your init signal is low indefinitely.
You may also want to use "if" statements rather than "case" for simple conditions. Example:
if ad_sel='0' then
address<=data_in(6 downto 0);
else
data_cpu_wr<=data_in;
end if;

VHDL - Comparing present and past inputs

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.

VHDL program to count upto 10 in 4 bit up counter....?

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;

Resources