I have stuck on this problem since last week and tried to receive a correct answer from different ways but unfortunately since now it has not worked.
I hae a state machine that receives three patterns and make a matrix for each one of them and then sum all of them together and sends it to output. But the state machine sends the matrix of first pattern to output.
I think the problem is that adder should work with the clock (state one) and state machine goes to the next state with event edge of each clock, therefore it can't synchronize with the adder. But i don't know how i can fix this problem. I would appriciate any help kindly.
P.S The package must be included in the code.
----------------------------------------------------------------------------------
-- Company:
-- Engineer:
--
-- Create Date: 14:11:16 0NUMBITS-1/11/2012
-- Design Name:
-- Module Name: state_machine - Behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_SIGNED.ALL;
use work.my_data_types.all;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity state_machine2 is
port(
pattern : in std_logic_vector(0 to NUMBITS-1); --The incorrect pattern
clk : in std_logic;
result : out matrix2D(0 to NUMBITS-1, 0 to NUMBITS-1)
);
end state_machine2;
architecture Behavioral of state_machine2 is
type state is (zero , one, two);
signal pr_state, nx_state : state ;
signal s_out_matrix : matrix2D(0 to NUMBITS-1, 0 to NUMBITS-1);
signal s_flipflop_adder : matrix2D(0 to NUMBITS-1, 0 to NUMBITS-1):= (others => (others => (others => '0')));
signal q : integer;
begin
process(clk)
begin
if(clk'event and clk = '1')then
pr_state <= nx_state;
end if;
end process;
process(pattern, pr_state)
variable cnt: integer := -1;
begin
case pr_state is
when zero =>
q <= 0; -- state number
if(cnt < NUM_TRAIN_PATTERN)then
cnt := cnt + 1;
nx_state <= one;
else
nx_state <= two;
end if;
when one =>
q <= 1;
For i in 0 to NUMBITS-1 loop --The multiplication in the pattern
For j in 0 to NUMBITS-1 loop
if(i = j) then
s_out_matrix(i,j) <= (others => '0');
elsif(pattern(i) = pattern(j)) then
s_out_matrix(i,j) <= (0 => '1', others => '0');
else
s_out_matrix(i,j) <= (others => '1');
end if;
end loop;
end loop;
if(clk'event and clk = '1')then -- Sum of the matrixes
For i in 0 to NUMBITS-1 loop
For j in 0 to NUMBITS-1 loop
s_flipflop_adder(i,j) <= s_flipflop_adder(i,j) + s_out_matrix(i,j);
end loop;
end loop;
end if;
nx_state <= zero;
when two =>
q <= 2;
result <= s_flipflop_adder;
end case;
test_q <= q;
end process;
end Behavioral;
the package:
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_SIGNED.ALL;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
package my_data_types is
type matrix2D is array (integer range <> , integer range <> ) of signed(2 downto 0); -- Matrix2D
constant NUMBITS : integer := 3;
constant NUM_TRAIN_PATTERN : natural := 3;
end my_data_types;
A few thing stand out...
First of all, whenever you create a state machine, there needs to be a way to reset it, ideally an input signal which forces the sequential elements to a known state. In your case, there is no way to reset pr_state, and thus no way to know from the code what the starting state should be. Also, avoid "resetting" sequential elements by assigning a default value as is done for s_flipflop_adder, because that is likely to lead to a mismatch between simulation and actual implementation.
Second, do not generate sequential and combinatorial signals inside the same process. For each signal, decide if it is sequential (i.e. a flip flop, updated on a clock edge), or combinatorial (i.e. updated almost instantly from the value of other signals, slowed down only by the propagation delays in the logic elements). For sequential signals, create a sequential process in which everything is inside an if rising_edge(clk) or if clk'event and clk = '1' statement (equivalent for most purposes), and with only the clock (and maybe your reset signal, if it is asynchronous) in the sensitivity list. For combinatorial signals, put them in a combinatorial process, which is a process with no clock and a complete sensitivity list.
In your design, the first process is a proper sequential process. The second process, however, starts as a combinatorial process (with an incomplete sensitivity list), but then there is a sequential assignment to s_flipflop_adder nested in a branch of the case statement. The signal s_flipflop_adder is unlikely to ever be assigned because clk is not in the sensitivity list, and even if it was, the synthesis tools will likely not interpret that mix as you intended it.
Finally, do not use a variable to keep state information as you do with the cnt variable, and make sure you update your state only on a clock edge (i.e. sequentially).
With these three points in mind, the state machine will look something more akin to this (I inlined the definitions from the my_data_types package only to make the answer easier to read):
library ieee;
use ieee.std_logic_vector_1164.all;
use ieee.std_logic_arith.all;
entity state_machine2 is
port(
clk : in std_logic;
rst : in std_logic;
pattern : in std_logic_vector(0 to NUMBITS-1);
result : out matrix2D(0 to NUMBITS-1, 0 to NUMBITS-1) );
end state_machine2;
architecture Behavioral of state_machine2 istype state is (zero , one, two);
constant NUMBITS : integer := 3;
constant NUM_TRAIN_PATTERN : natural := 3;
subtype signed3 is signed(NUMBITS-1 downto 0);
type matrix2D is array (integer range <> , integer range <> ) of signed3;
signal pr_state : state;
signal s_flipflop_adder : matrix2D(0 to NUMBITS-1, 0 to NUMBITS-1);
signal cnt : integer;
begin
process(clk) is
variable add_operand : signed3;
begin
if rising_edge(clk) then
if rst = '1' then
pr_state <= zero;
cnt <= -1;
s_flipflop_adder <= (others => (others => (others => '0')));
else
case pr_state is
when zero =>
cnt <= cnt + 1;
if cnt < NUM_TRAIN_PATTERN then
pr_state <= one;
else
pr_state <= two;
end if;
when one =>
for i in 0 to NUMBITS-1 loop
for j in 0 to NUMBITS-1 loop
if i = j then
add_operand := (others => '0');
elsif pattern(i) = pattern(j) then
add_operand := (0 => '1', others => '0');
else
add_operand := (others => '1');
end if;
s_flipflop_adder(i,j) <= s_flipflop_adder(i,j)
+ add_operand;
end loop;
end loop;
when two =>
result <= s_flipflop_adder;
end case;
end if;
end if;
end process;
end Behavioral;
Thank you for posting this question, as these are very common mistakes.
Related
I am a novice coder and don't know if what I did was correct so I would appreciate if someone could double check it for me.
So im trying to make an 8-bit up counter with an active-low count enable control signal. The counter should advance to the next count if cten = 0 and stops at the current count if cten = 1. The counter resets into a state that outputs binary 0 and progresses upward on each clock edge when counting is enabled until it reaches 255. It locks in the state producing output 255. I also tried to change the clock to 1Hz clock from a 50MHz clock the is on a FPGA board that will be used to run some instructions (with there being no more than 255 instructions, hence wanting to lock at that number) based off the count value of int_q.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity counter is
port(
clk, rst, cten: in std_logic;
q: out std_logic_vector(7 downto 0)
);
end entity counter;
architecture moore of counter is
signal d,int_q: std_logic_vector(7 downto 0);
signal cnt: integer range 0 to 25000;
signal clk1Hz: std_logic;
begin
-- drive internal Q signal to output signal
q <= int_q;
-- next-state logic: add 1 unless 255, lock at 255
d <= int_q+1 when int_q < 255;
d <= int_q when int_q = 255;
process(clk)
begin
if rising_edge(clk) then
cnt <= cnt+1;
if cnt = 25000 then
clk1Hz <= not clk1Hz;
cnt <= 0;
end if;
end if;
end process;
-- register process
process(all)
begin
if rising_edge(clk1Hz) then
if rst ='1' then int_q <= "00000000";
elsif cten = '0' then int_q <= int_q+1;
else int_q <= int_q;
end if;
end if;
end process;
end architecture moore;
Several issues:
If rst is unasserted on the rising edge of clk1Hz, then int_q will remain in an unknown state.
clk1Hz is never initialized, so the not operation does nothing.
cnt is never initialized, so incrementing it does nothing.
int_q is being driven in 2 places: both inside and outside a process.
signal d is unused, did you want to connect it to q?
You're only counting to 25_000, but if your source clock is 50 MHz, you need to count to 25_000_000.
If you want a synchronous reset, (which given the name "Moore", I bet this is homework), it's good practice to create a new process specifically to internally synchronize that async reset signal to the system clock, maybe through a 2FF synchronizer for one idea.
If I understood the question correctly, this should get you in the ballpark:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity counter is
port(
clk, rst, cten: in std_logic;
q: out std_logic_vector(7 downto 0)
);
end entity counter;
architecture moore of counter is
signal int_q: std_logic_vector(7 downto 0);
signal cnt: integer range 0 to 25_000_000;
signal clk1Hz: std_logic;
begin
-- indicate when at 255
q <= '1' when int_q = 255 else '0';
process(rst, clk)
begin
if rst = '1' then
-- need to assign initial values
clk1Hz <= '0';
cnt <= 0;
elsif rising_edge(clk) then
if cnt = 25_000_000 then
clk1Hz <= not clk1Hz;
cnt <= 0;
else
cnt <= cnt+1;
end if;
end if;
end process;
-- register process
process(rst, clk1Hz)
begin
if rst = '1' then
int_q <= (others => '0');
elsif rising_edge(clk1Hz) then
if cten = '0' then
int_q <= int_q+1; -- rolls over
end if;
end if;
end process;
end architecture moore;
If you want to map this in an FPGA you cannot generate a clock like you do. Clocks are very special signals with strict electrical requirements. If you need a 1Hz frequency clock and the frequency of your master clock is 50MHz there are basically two options:
Use a clock manager/generator hard macro of your FPGA if it has some, and configure it to generate a 1Hz clock from your master clock. Explicitly pass the output through a clock buffer if your tools don't do it automatically.
Do not generate a 1Hz clock, use an enable signal that you assert high once every 50M clock periods. Or use a rescaler and increment your counter only when the rescaler reaches a predefined value.
As the first option depends on your FPGA, your tools, etc. let's investigate the second:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity counter is
generic(freqHz: positive := 50000000);
port(clk, rst, cten: in std_ulogic;
q: out std_ulogic_vector(7 downto 0));
end entity counter;
architecture moore of counter is
signal rescaler: integer range 0 to freqHz - 1;
signal cnt: integer range 0 to 255;
begin
q <= std_ulogic_vector(to_unsigned(cnt, 8));
process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
rescaler <= freqHz - 1;
cnt <= 0;
elsif cnt /= 255 then
if rescaler /= 0 then
rescaler <= rescaler - 1;
else
rescaler <= freqHz - 1;
cnt <= cnt + 1;
end if;
end if;
end if;
end process;
end architecture moore;
Remarks:
Use ieee.std_logic_unsigned or ieee.numeric_std but not both. And as noted by #JHBonarius, do not use ieee.std_logic_unsigned at all. It is not standard and deprecated. Use ieee.numeric_std_unsigned, instead.
I added a generic parameter (freqHz) with a default value such that you can easily adapt to different clock frequencies.
The 50Mhz to 1Hz rescaler is decremented instead of incremented because a hardware zero detector is frequently slightly smaller and faster than an arbitrary value detector.
If you do not know the difference between std_logic and std_ulogic, always use std_ulogic, never std_logic (and use std_ulogic_vector instead of std_logic_vector, u_unsigned instead of unsigned...) One day or another you will really need std_logic and this day you will understand the difference, and why you should (almost) never use it. And do not listen to people who tell you that std_logic is more standard or better supported by the tools or whatever. They are wrong. The only exception is your teacher or your boss: even if they are wrong, it might be better to obey.
I am unfortunately new to VHDL but not new to software development. What is the equivalency to functions in VHDL? Specifically, in the code below I need to debounce four push buttons instead of one. Obviously repeating my process code four times and suffixing each of my signals with a number to make them unique for the four instances is not the professional nor correct way of doing this. How do I collapse all this down into one process "function" to which I can "pass" the signals so I can excise all this duplicate code?
----------------------------------------------------------------------------------
-- Debounced pushbutton examples
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity pushbutton is
generic(
counter_size : integer := 19 -- counter size (19 bits gives 10.5ms with 50MHz clock)
);
port(
CLK : in std_logic; -- input clock
BTN : in std_logic_vector(0 to 3); -- input buttons
AN : out std_logic_vector(0 to 3); -- 7-segment digit anodes ports
LED : out std_logic_vector(0 to 3) -- LEDs
);
end pushbutton;
architecture pb of pushbutton is
signal flipflops0 : std_logic_vector(1 downto 0); -- input flip flops
signal flipflops1 : std_logic_vector(1 downto 0);
signal flipflops2 : std_logic_vector(1 downto 0);
signal flipflops3 : std_logic_vector(1 downto 0);
signal counter_set0 : std_logic; -- sync reset to zero
signal counter_set1 : std_logic;
signal counter_set2 : std_logic;
signal counter_set3 : std_logic;
signal counter_out0 : std_logic_vector(counter_size downto 0) := (others => '0'); -- counter output
signal counter_out1 : std_logic_vector(counter_size downto 0) := (others => '0');
signal counter_out2 : std_logic_vector(counter_size downto 0) := (others => '0');
signal counter_out3 : std_logic_vector(counter_size downto 0) := (others => '0');
signal button0 : std_logic; -- debounce input
signal button1 : std_logic;
signal button2 : std_logic;
signal button3 : std_logic;
signal result0 : std_logic; -- debounced signal
signal result1 : std_logic;
signal result2 : std_logic;
signal result3 : std_logic;
begin
-- Make sure Mercury BaseBoard 7-Seg Display is disabled (anodes are pulled high)
AN <= (others => '1');
-- Feed buttons into debouncers
button0 <= BTN(0);
button1 <= BTN(1);
button2 <= BTN(2);
button3 <= BTN(3);
-- Start or reset the counter at the right time
counter_set0 <= flipflops0(0) xor flipflops0(1);
counter_set1 <= flipflops1(0) xor flipflops1(1);
counter_set2 <= flipflops2(0) xor flipflops2(1);
counter_set3 <= flipflops3(0) xor flipflops3(1);
-- Feed LEDs from the debounce circuitry
LED(0) <= result0;
LED(1) <= result1;
LED(2) <= result2;
LED(3) <= result3;
-- Debounce circuit 0
process (CLK)
begin
if (CLK'EVENT and CLK = '1') then
flipflops0(0) <= button0;
flipflops0(1) <= flipflops0(0);
if (counter_set0 = '1') then -- reset counter because input is changing
counter_out0 <= (others => '0');
elsif (counter_out0(counter_size) = '0') then -- stable input time is not yet met
counter_out0 <= counter_out0 + 1;
else -- stable input time is met
result0 <= flipflops0(1);
end if;
end if;
end process;
-- Debounce circuit 1
process (CLK)
begin
if (CLK'EVENT and CLK = '1') then
flipflops1(0) <= button1;
flipflops1(1) <= flipflops1(0);
if (counter_set1 = '1') then -- reset counter because input is changing
counter_out1 <= (others => '0');
elsif (counter_out1(counter_size) = '0') then -- stable input time is not yet met
counter_out1 <= counter_out1 + 1;
else -- stable input time is met
result1 <= flipflops1(1);
end if;
end if;
end process;
-- Debounce circuit 2
process (CLK)
begin
if (CLK'EVENT and CLK = '1') then
flipflops2(0) <= button2;
flipflops2(1) <= flipflops2(0);
if (counter_set2 = '1') then -- reset counter because input is changing
counter_out2 <= (others => '0');
elsif (counter_out2(counter_size) = '0') then -- stable input time is not yet met
counter_out2 <= counter_out2 + 1;
else -- stable input time is met
result2 <= flipflops2(1);
end if;
end if;
end process;
-- Debounce circuit 3
process (CLK)
begin
if (CLK'EVENT and CLK = '1') then
flipflops3(0) <= button3;
flipflops3(1) <= flipflops3(0);
if (counter_set3 = '1') then -- reset counter because input is changing
counter_out3 <= (others => '0');
elsif (counter_out3(counter_size) = '0') then -- stable input time is not yet met
counter_out3 <= counter_out3 + 1;
else -- stable input time is met
result3 <= flipflops3(1);
end if;
end if;
end process;
end pb;
VHDL has functions but function calls are expressions and not statements or expression statements as in some programming languages. A function call always returns a value of a type and an expression can't represent a portion of a design hierarchy.
Consider the other subprogram class procedures which are statements instead.
The debouncer processes and associated declarations can also be simplified without using a procedure:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity pushbutton is
generic (
counter_size: integer := 19 -- The left bound of debounce counters
);
port (
clk: in std_logic;
btn: in std_logic_vector(0 to 3);
an: out std_logic_vector(0 to 3);
led: out std_logic_vector(0 to 3)
);
end entity pushbutton;
architecture pb1 of pushbutton is
-- There are two flip flops for each of four buttons:
subtype buttons is std_logic_vector(0 to 3);
type flip_flops is array (0 to 1) of buttons;
signal flipflops: flip_flops;
signal counter_set: std_logic_vector(0 to 3);
use ieee.numeric_std.all;
type counter is array (0 to 3) of
unsigned(counter_size downto 0);
signal counter_out: counter := (others => (others => '0'));
begin
an <= (others => '1');
counter_set <= flipflops(0) xor flipflops(1);
DEBOUNCE:
process (clk)
begin
if rising_edge (clk) then
flipflops(0) <= btn;
flipflops(1) <= flipflops(0);
for i in 0 to 3 loop
if counter_set(i) = '1' then
counter_out(i) <= (others => '0');
elsif counter_out(i)(counter_size) = '0' then
counter_out(i) <= counter_out(i) + 1;
else
led(i) <= flipflops(1)(i);
end if;
end loop;
end if;
end process;
end architecture pb1;
Moving part of the design specification into a procedure:
architecture pb2 of pushbutton is
-- There are two flip flops for each of four buttons:
subtype buttons is std_logic_vector(0 to 3);
type flip_flops is array (0 to 1) of buttons;
signal flipflops: flip_flops;
signal counter_set: std_logic_vector(0 to 3);
use ieee.numeric_std.all;
type counter is array (0 to 3) of
unsigned(counter_size downto 0);
signal counter_out: counter := (others => (others => '0'));
procedure debounce (
-- Can eliminate formals of mode IN within the scope of their declaration:
-- signal counter_set: in std_logic_vector (0 to 3);
-- signal flipflops: in flip_flops;
signal counter_out: inout counter;
signal led: out std_logic_vector(0 to 3)
) is
begin
for i in 0 to 3 loop
if counter_set(i) = '1' then
counter_out(i) <= (others => '0');
elsif counter_out(i)(counter_size) = '0' then
counter_out(i) <= counter_out(i) + 1;
else
led(i) <= flipflops(1)(i);
end if;
end loop;
end procedure;
begin
an <= (others => '1');
counter_set <= flipflops(0) xor flipflops(1);
DEBOUNCER:
process (clk)
begin
if rising_edge (clk) then
flipflops(0) <= btn;
flipflops(1) <= flipflops(0);
-- debounce(counter_set, flipflops, counter_out, led);
debounce (counter_out, led);
end if;
end process;
end architecture pb2;
Here the procedure serves as a collection of sequential statements and doesn't save any lines of code.
Sequential procedure calls can be useful to hide repetitious clutter. The clutter has been removed already by consolidating declarations and using the loop statement. There's a balancing act between the design entry effort, code maintenance effort and user readability, which can also be affected by coding style. Coding style is also affected by RTL constructs implying hardware.
Moving the clock evaluation into a procedure would require the procedure call be be a concurrent statement, similar to an instantiation, which you already have. It doesn't seem worthwhile here should you consolidate signals declared as block declarative items in the architecture body or when using a loop statement.
Note that result and button declarations have been eliminated. Also the use of package numeric_std and type unsigned for the counters prevents inadvertent assignment to other objects with the same subtype. The counter values are treated as unsigned numbers while counter_set for instance is not.
Also there's an independent counter for each input being debounced just as in the original. Without independent counters some events might be lost for independent inputs when a single counter is repetitively cleared.
This code hasn't been validated by simulation, lacking a testbench. With the entity both architectures analyze and elaborate.
There doesn't appear to be anything here other than sequential statements now found in a for loop that would benefit from a function call. Because a function call returns a value the type of that value would either need to be a composite (here a record type) or be split into separate function calls for each assignment target.
There's also the generate statement which can elaborate zero or more copies of declarations and concurrent statements (here a process) as block statements with block declarative items. Any signal used only in an elaborated block can be a block declarative item.
architecture pb3 of pushbutton is
begin
DEBOUNCERS:
for i in btn'range generate
signal flipflops: std_logic_vector (0 to 1);
signal counter_set: std_logic;
signal counter_out: unsigned (counter_size downto 0) :=
(others => '0');
begin
counter_set <= flipflops(0) xor flipflops(1);
DEBOUNCE:
process (clk)
begin
if rising_edge (clk) then
flipflops(0) <= btn(i);
flipflops(1) <= flipflops(0);
if counter_set = '1' then
counter_out <= (others => '0');
elsif counter_out(counter_size) = '0' then
counter_out <= counter_out + 1;
else
led(i) <= flipflops(1);
end if;
end if;
end process;
end generate;
end architecture pb3;
Addendum
The OP pointed out an error made in the above code due to a lack of simulation and complexity hidden by abstraction when synthesizing architecture pb2. While the time for the debounce counter was given at 10.5 ms (50 MHz clock) the name of the generic (counter_size) is also actually the left bound of the counter (given as an unsigned binary counter using type unsigned).
The mistake (two flip flops in the synchronizer for each of four buttons) and simply acceding to the OP's naming convention with respect to the counter has been corrected in the above code.
The OP's synthesis error in the comment relates to the requirement there be a matching element for each element on the left hand or right hand of an aassignment statement.
Without synthesizing the code (which the OP did) the error can't be found without simulation. Because the only thing necessary to find the particular error assigning flipflops(0) is the clock a simple testbench can be written:
use ieee.std_logic_1164.all;
entity pushbutton_tb is
end entity;
architecture fum of pushbutton_tb is
signal clk: std_logic := '0';
signal btn: std_logic_vector (0 to 3);
signal an: std_logic_vector(0 to 3);
signal led: std_logic_vector(0 to 3);
begin
CLOCK:
process
begin
wait for 0.5 ms;
clk <= not clk;
if now > 50 ms then
wait;
end if;
end process;
DUT:
entity work.pushbutton (pb2)
generic map (
counter_size => 4 -- FOR SIMULATION
)
port map (
clk => clk,
btn => btn,
an => an,
led => led
);
STIMULUS:
process
begin
btn <= (others => '0');
wait for 20 ms;
btn(0) <= '1';
wait for 2 ms;
btn(1) <= '1';
wait for 3 ms;
btn(2) <= '1';
wait for 6 ms;
btn(3) <= '1';
wait;
end process;
end architecture;
The corrected code and a testbench to demonstrate there are no matching element errors in assignment during simulation.
Simulation was provided for both architectures with identical results.
The generic was used to reduce the size of the debounce counters using a 1 millisecond clock in the testbench (to avoid simulation time with 50 MHz clock events that don't add to the narrative).
Here's the output of the first architecture's simulation:
The caution here is that designs should be simulated. There's a class of VHDL semantic error conditions that are checked only at runtime (or in synthesis).
Added abstraction for reducing 'uniquified' code otherwise identically performing can introduce such errors.
The generate statement wouldn't have that issue using names in a design hierarchy:
The concurrent statements and declarations found in a generate statement are replicated in any generated block statements implied by the generate statement. Each block statement represents a portion of a design hierarchy.
There's been a trade off between design complexity and waveform display organization for debugging.
A design description depending on hiding repetitious detail should be simulated anyway. Here there are two references to the generate parameter i used in selected names, susceptible to the same errors as ranges should parameter substitution be overlooked.
A multiple bit debouncing circuit might look like this:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.Utilities.all;
entity Debouncer is
generic (
CLOCK_PERIOD_NS : positive := 10;
DEBOUNCE_TIME_MS : positive := 3;
BITS : positive
);
port (
Clock : in std_logic;
Input : in std_logic_vector(BITS - 1 downto 0);
Output : out std_logic_vector(BITS - 1 downto 0) := (others => '0')
);
end entity;
architecture rtl of Debouncer is
begin
genBits: for i in Input'range generate
constant DEBOUNCE_COUNTER_MAX : positive := (DEBOUNCE_TIME_MS * 1000000) / CLOCK_PERIOD_NS;
constant DEBOUNCE_COUNTER_BITS : positive := log2(DEBOUNCE_COUNTER_MAX);
signal DebounceCounter : signed(DEBOUNCE_COUNTER_BITS downto 0) := to_signed(DEBOUNCE_COUNTER_MAX - 3, DEBOUNCE_COUNTER_BITS + 1);
begin
process (Clock)
begin
if rising_edge(Clock) then
-- restart counter, whenever Input(i) was unstable within DEBOUNCE_TIME_MS
if (Input(i) /= Output(i)) then
DebounceCounter <= DebounceCounter - 1;
else
DebounceCounter <= to_signed(DEBOUNCE_COUNTER_MAX - 3, DebounceCounter'length);
end if;
-- latch input bit, if input was stable for DEBOUNCE_TIME_MS
if (DebounceCounter(DebounceCounter'high) = '1') then
Output(i) <= Input(i);
end if;
end if;
end process;
end generate;
end architecture;
In stead of a counter size, it expects the user to provide a frequency (as period in nanoseconds) and a debounce time (in milliseconds).
The referenced package implements a log2 function.
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.
I'm struggling with a VHDL conundrum. Here's some code which should explain what I'm trying to do:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use work.all;
entity forLoopTest is
-- Number of bits known only at compilation
generic(
bits : integer range 1 to 1024; := 256;
);
port(
clk: in std_logic := '0';
-- Single bit inputs from foo
foo: in std_logic_vector(bits-1 downto 0) := (others => '0');
-- Output should be high when all inputs have gone to '1' at some point
bar: out std_logic
);
end forLoopTest;
------------------------------------------------------------------------------------------------------------
architecture implementation of forLoopTest is
-- Create states for finite state machine, where finish implies a '1' has been received
type FSM_states_single is (waitForHigh, finish);
-- Make an array of the states, one for each input bit
type FSM_states_multi is array (bits-1 downto 0) of FSM_states_single;
-- Create signal of states initialised to the waiting condition
signal state : FSM_states_multi := (others => waitForHigh);
begin
process(clk, foo)
-- For each input bit:
for bitNumber in 0 to bits-1 loop
case state(bitNumber) is
-- Whilst waiting, poll the input bit
when waitForHigh =>
-- If it goes high, then switch states
if (foo(bitNumber) = '1') then
state(bitNumber) <= finish;
end if;
-- If input bit has gone high:
when finish =>
-- What is simplest method of setting "bar"?
-- "bar" should be high if and only if all bits have equalled '1' at some point
-- Otherwise it should be '0'
-- Though of dominant setting '0', and submissive setting 'H', but multiple things setting output fails
-- Either explicitly, or only one of them is used, others ignored
end case;
end loop;
end process;
end implementation;
Basically, I am trying to find an optimal method of deducing when all "threads" of the for loop have completed. The above is a hypothetical example to illustrate the point. One method using the above code would be to simply "AND" all of the states. However, I'm not sure how to and an unknown number of variables (pre-compilation). Also I am curious to know what other methods of solving this problem are.
Thanks in advance!
Added the clock and a reset to your process. The reset allows you to clear state.
No bar flip flop, it'd be easy to do, move an if statement.
The case statement was removed because of how bar is derived, evaluating both states isn't necessary:
library ieee;
use ieee.std_logic_1164.all;
-- use ieee.std_logic_arith.all; -- not used
use work.all;
entity forlooptest is
generic (
bits : integer range 1 to 1024 := 256 -- removed ';' 2 places
);
port (
clk: in std_logic;
reset: in std_logic; -- added
foo: in std_logic_vector(bits-1 downto 0) := (others => '0');
bar: out std_logic
);
end entity forlooptest;
architecture foo of forlooptest is
type FSM_states_single is (waitForHigh, finish);
type FSM_states_multi is array (bits-1 downto 0) of FSM_states_single;
signal state : FSM_states_multi := (others => waitForHigh);
begin
FOO_BAR:
process (clk, reset)
variable state_v: FSM_states_multi; -- added
begin -- original missing begin
state_v := state; -- variable can be evaluated after assignment
if reset = '1' then
state_v := (others => WaitForHigh);
elsif rising_edge(clk) then
for bitNumber in 0 to bits-1 loop
if state_v(bitNumber) = waitForHigh and
foo(BitNumber) = '1' then
state_v(bitNumber) := finish;
end if;
end loop;
state <= state_v;
end if;
if state_v = (state_v'range => finish) then
bar <= '1'; -- bar not a FlipFlop move if statement above
else -- preceding end if and add to reset condition for FF
bar <= '0'; -- no latch
end if;
end process;
end architecture;
Making bar a flip flop can be done by moving it's if statement above the preceding end if, removing the else and assignment to '0', and adding bar <= '0' to the reset.
There's also a variable copy of state so any updated bits are available immediately for evaluation. (A signal assignment doesn't take effect immediately while a variable assignment does).
Note the heart of the matter, how to evaluate state (state_v) using an aggregate value with every position set to finish. You can't use an others here. The number of elements and their type has to be discernable from the aggregate expression as an input to the equality operator.
Adding a small testbench with a limited range of bits:
library ieee;
use ieee.std_logic_1164.all;
entity for_loop_test_tb is
end entity;
architecture fum of for_loop_test_tb is
constant bits: integer range 1 to 1024 := 16;
signal clk: std_logic := '0';
signal reset: std_logic; -- added
signal foo: std_logic_vector(bits-1 downto 0) := (others => '0');
signal bar: std_logic;
begin
DUT:
entity work.forlooptest
generic map (bits => bits)
port map (
clk => clk,
reset => reset,
foo => foo,
bar => bar
);
CLOCK:
process
begin
wait for 5 ns;
clk <= not clk;
if now > 150 ns then
wait;
end if;
end process;
STIMULI:
process
begin
wait for 10 ns;
reset <= '1';
wait for 10 ns;
reset <= '0';
wait for 10 ns;
foo <= x"0FF0";
wait for 10 ns;
foo <= x"0001";
wait for 10 ns;
foo <= x"F002";
wait for 10 ns;
foo <= x"0F00";
wait for 10 ns;
foo <= x"FF00";
wait for 10 ns;
foo <= x"0001";
wait for 10 ns;
foo <= x"00F0";
wait for 10 ns;
foo <= x"F0F0";
wait for 10 ns;
foo <= x"0004";
wait for 10 ns;
foo <= x"CCCC";
wait;
end process;
end architecture;
And that gives:
(The value for bits and the number of different input values for foo were restricted to provide a waveform easily interpreted.)
(There are a number of things wrong with the given process : it should probably be clocked, so that it runs on every rising_edge(clk) then there is no need for foo in the sensitivity list. However....)
One approach is a boolean variable, finished which is set to TRUE before entering the for loop.
Any iteration that has not finished (e.g. enters the waitforHigh state or ANY state other than finish) will clear the finished variable ... (optionally, unless it is transitioning to the finish state).
Then, after end loop the next statement if finished then ... will tell you what you want to know.
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;