I have a 3 bit counter that counts upwards from "000". Every time "101" is reached, I want the o_en signal to be HIGH.
I have the following VHDL file.
The behaviour is unfortunately different.
The o_en signal is HIGH, when "110" is reached (delayed by one clock cycle).
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity special_counter is
port(
i_clk : in std_logic;
i_en : in std_logic;
i_rst : in std_logic;
o_data : out std_logic_vector(2 downto 0);
o_en : out std_logic
);
end entity;
architecture behave of special_counter is
signal w_data : std_logic_vector(2 downto 0);
signal w_en : std_logic;
begin
process(i_clk, i_rst) begin
if i_rst = '1' then
w_data <= "000";
elsif rising_edge(i_clk) then
if i_en = '1' then
if w_data = "101" then
w_en <= '1';
w_data <= w_data + 1;
else
w_en <= '0';
w_data <= w_data + 1;
end if;
end if;
end if;
end process;
o_data <= w_data;
o_en <= w_en;
end architecture;
How can I change my program to perform the expected behaviour ?
That is exactly correct and that is what you have coded.
To put it into words:
"At the rising edge of the clock, when the counter has the value 101 then the w_en will be set high."
Thus the w_en signal from which o_en is derived, will be high after the rising edge of the clock.
In the same time as the w_data changes and after the rising clock becomes "110".
There are two solutions:
Test for "100" (so one cycle sooner)
Make w_en (and thus o_en) combinatorial.
For the latter you must move the assignment outside the 'clocked' section
and use e.g.
w_en <= '1' when w_data = "101" else '0';
Related
I am attempting to create a very specific signal in my code. Basically I need a signal to be generated after load_0 ends, in the falling edge, where such signal would be 10 pulses of the 1KHz signal and the rest 0. Which is just preserving 10 pulses that are aligned with the variable Serial_out.
Thus far I have tried an if to attempt this, with a counter to attempt to count to 10 for the 10 pulses i want and discarding the rest. This always ends either not being able to be synthesized due to error or the test bench clk_trig never being initialized.
My coding is quite crude due to the fact that I have not been using xilinx for long.
Main section of the code
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY HAMMING IS
PORT ( CLK_50MHz_M : IN STD_LOGIC;
RST : IN STD_LOGIC;
LOAD_O : IN STD_LOGIC;
input1 : IN STD_LOGIC;
input2 : IN STD_LOGIC;
input3 : IN STD_LOGIC;
input4 : IN STD_LOGIC;
input5 : IN STD_LOGIC;
input6 : IN STD_LOGIC;
CLK_DIV_O : OUT STD_LOGIC;
CLK_TRIG : OUT STD_LOGIC;
Serial_out : OUT STD_LOGIC);
END HAMMING;
ARCHITECTURE ARCH OF HAMMING IS
SIGNAL input_vec : STD_LOGIC_VECTOR(6 DOWNTO 1);
SIGNAL output : STD_LOGIC_VECTOR(9 DOWNTO 0);
SIGNAL CLK_100Hz, CLK_50KHz : STD_LOGIC;
COMPONENT P2S
port(
clk : in STD_LOGIC;
reset : in STD_LOGIC;
load : in STD_LOGIC;
din : in STD_LOGIC_VECTOR(9 downto 0);
dout : out STD_LOGIC);
END COMPONENT;
COMPONENT SCALE_CLOCK
PORT (CLK_50MHz_S : IN STD_LOGIC;
RST : IN STD_LOGIC;
CLK_100Hz : OUT STD_LOGIC);
END COMPONENT;
begin
----------------------------------------------
process (LOAD_O, CLK_100Hz)
begin
if (LOAD_O = '1') then CLK_TRIG <= '0'; -crude attempt at the desired signal
ELSE
CLK_TRIG <= CLK_100Hz;
end if;
end process;
---------------------------------------------
-- BITS DE PALABRA
output(2) <= input_vec(1);
output(4) <= input_vec(2);
output(5) <= input_vec(3);
output(6) <= input_vec(4);
output(8) <= input_vec(5);
output(9) <= input_vec(6);
-- BIT PARIEDAD
output(0) <= input_vec(1) XOR input_vec(2) XOR input_vec(4) XOR input_vec(5);
output(1) <= input_vec(1) XOR input_vec(3) XOR input_vec(4) XOR input_vec(6);
output(3) <= input_vec(2) XOR input_vec(3) XOR input_vec(4);
output(7) <= input_vec(5) XOR input_vec(6);
ClockDiv: SCALE_CLOCK PORT MAP(CLK_50MHz_S => CLK_50MHz_M, RST => RST, CLK_100Hz => CLK_100Hz);
SeriesOut: P2S PORT MAP(clk => CLK_100Hz, din => output, dout => Serial_out, reset => RST, load => LOAD_O);
CLK_DIV_O <= CLK_100Hz;
input_vec <= input1 & input2 & input3 & input4 & input5 & input6;
END ARCH;
FPGA2 code running
You have a 50MHz clock.
from that you probably decided to make a nice 50/50 100Hz clock and then use that.
That is the wrong strategy!
You always want as much as possible a synchronous design.
If you want signals to change at 100Hz the right (synchronous) method is as follows:
Make 100Hz pulses which are high for one 50MHz clock only. (e.g. P100Hz)
Everywhere you use a 100Hz clock go back to using the 50 MHz clock
then in the 50MHz clock section use an additional if P100Hz then
You now have a synchronous design running at effectively 100Hz.
I've written a program in VHDL (for Xilinx Spartan-6) that increments a counter whilst a button is pressed and resets it to zero when another button is pressed.
However, my process throws the error WARNING:Xst:647 - Input is never used. This port will be preserved and left unconnected... for the reset variables - despite the fact that it is used both in the sensitivity of the process and as a condition (just as much as button, yet that doesn't get flagged!).
binary_proc : process(CLK_1Hz, button, reset) --include all inputs on sensitivity list
begin
if rising_edge(CLK_1Hz) and button = '1' then
binary <= binary + 1;
else if reset = '1' then
binary <= (others => '0');
end if;
end if;
end process;
More curiously though, I can fix this by simply using two if statements rather than just an if-else if statement, as shown below;
binary_proc : process(CLK_1Hz, button, reset) --include all inputs on sensitivity list
begin
if rising_edge(CLK_1Hz) and button = '1' then
binary <= binary + 1;
end if;
if reset = '1' then
binary <= (others => '0');
end if;
end process;
My question is: why is the reset variable optimized out of the circuit when an if-else statement is used but not when two if statements are used? What causes this and how can this sort of thing be avoided it?
Thanks very much!
NB: Full code of the program is below in case it helps!
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity button_press is
port(
CLK_200MHz : in std_logic;
button : in std_logic;
reset : in std_logic;
LED : out std_logic_vector(3 downto 0) --array of LED's
);
end button_press;
architecture Behavioral of button_press is
signal CLK_1Hz : std_logic; --input clock (think 200 MHz)
signal counter : std_logic_vector(26 downto 0); --counter to turn 200 MHz clock to 1 Hz
signal binary : std_logic_vector(3 downto 0); --binary vector thats mapped to LED's
begin
-----Create 1 Hz clock signal from 200 MHz system clock-------
prescaler : process(CLK_200MHz)
begin
if rising_edge(CLK_200MHz) then
if (counter < 2500000) then --possibly change to number in binary
counter <= counter + 1;
else
CLK_1Hz <= not CLK_1Hz; --toggle 1 Hz clock
counter <= (others => '0'); --reset counter to 0
end if;
end if;
end process;
------ Increment binary number when on rising clock edge when button pressed -------
binary_proc : process(CLK_1Hz, button, reset) --include all inputs on sensitivity list
begin
if rising_edge(CLK_1Hz) and button = '1' then
binary <= binary + 1;
end if;
if reset = '1' then
binary <= (others => '0');
end if;
end process;
LED <= binary; --map binary number to LED's
end Behavioral;
The problem is, that reset is conditional to not (rising_edge(CLK_1Hz) and button = '1'), and the Xilinx XST tool can't figure out how to map this to FPGA hardware.
VHDL is a Hardware Description Language (HDL part of VHDL), so don't think of it like writing another program (e.g. as in C or Python), but think of it as describing a circuit.
Converting VHDL code to hardware is a complicated task, and Xilinx expects the designer to use some patterns, as described in the "XST Hardware Description Language
(HDL) Coding Techniques" of the Xilinx XST User Guide. The first code part does not follow any of these patterns, and XST fails to convert this to hardware, thus the warning.
As per that coding style, the way to write it would be:
process(CLK_1Hz, reset) is -- Don't include button, since sync. signal
begin
if reset = '1' then
binary <= (others => '0');
elsif rising_edge(CLK_1Hz) then
if button = '1' then
binary <= binary + 1;
end if;
end if;
end process;
Btw. consider not making an extra clock as CLK_1Hz, but make an increment enable signal instead, since every clock requires special handling and resources.
I was stucked in a strange problem with VHDL if statement when I was working on my project. Although I fixed it, I still don't understand why it happened. I stimulated my code using ModelSPIM. Before I changed the code, I expected rd <= inst (20 downto 16); when RegDst = '1', but it gave me rd <= inst (15 downto 11);. I have checked RegDst was really equal to 0, but it gave me the wrong assignment. After I changed the code, everythings became normal. What is the difference between them ?
Before:
fetch: process(inst)
begin
if( inst = x"0000_0000" ) then -- end of program
endRun <= '1';
else
endRun <= '0';
opcode <= inst (31 downto 26);
rs <= inst (25 downto 21);
rt <= inst (20 downto 16);
if( RegDst = '1' ) then
rd <= inst (15 downto 11);
else
rd <= inst (20 downto 16);
end if;
funct <= inst (5 downto 0);
offset <= inst (15 downto 0);
jsec <= inst (25 downto 0);
end if;
end process fetch;
After:
fetch: process(inst)
begin
if( inst = x"0000_0000" ) then -- end of program
endRun <= '1';
else
endRun <= '0';
opcode <= inst (31 downto 26);
rs <= inst (25 downto 21);
rt <= inst (20 downto 16);
funct <= inst (5 downto 0);
offset <= inst (15 downto 0);
jsec <= inst (25 downto 0);
end if;
end process fetch;
rd <= inst (15 downto 11) when (RegDst = '1') else
inst(20 downto 16); -- RegDst mux
It is a problem with your sensitivity list. The sensitivity list is the list of signal in the parentheses after process. A process is executed when an event occurs on any signal in it's sensitivity list.
In your case, only inst was in your sensitivity list. Thus, when regDst would change from '0' to '1', the process would not be executed (if inst didn't change) and rd would not update.
In your second approach, the statement is not in a process, thus is not affected by sensitivity list (to be exact, all signals involved in an out of process statement are considered it it's sensitivity list). Should you add redDst in the sensitivity list, you would have the same results:
process(inst, regDst)
Note that missing signals in sensitivity list is a very common source of mismatch between simulation and implementation since all tools I know ignore them for implementation. If you use VHDL-2008, you can use the keyword all in your sensitivity list, which implies exactly what you think.
I am working on generating a 40 bit length pulse train. I also must be able to adjust the frequency. I tried to make a new low frequency clock and i make a new counter which counts on it's rising edges and give an high output and terminating after 40 bit. It's not working. I tried some other methods. They are not, too.
For example;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.all;
entity con40 is port(clk:in std_ulogic; q:out std_ulogic);
end entity con40;
architecture Behaviour of con40 is
constant s:std_ulogic_vector:="11111111111111111111111111111111";
signal i:unsigned(4 downto 0):="00000";
signal en:std_logic:='1';
signal reset:std_logic:='0';
begin
q<=s(to_integer(i));
process(reset,clk) is begin
if reset='1' then
i<=(others=>'0');
elsif rising_edge(clk) then
if en='1' then
i<=i+1;
end if;
end if;
end process;
end architecture Behaviour;
There is 32-bit length in this code but i wanna make 40 bit but whatever, this is not working too. I think methods for such a pulse train must be common and they are being used widely. But hey! unluckily i can find nothing useful.
I took the liberty of moving en and reset to port signals, also changed your constant to a recognizable 40 bit value, and specified the range to make it a locally static constant.
The issue with your counter is that it isn't big enough to address 40 bits. You have i specified as a 5 bit value while 40 bits requires a 6 bit counter.
I also added a second architecture here with i as an integer type signal. With i as either an unsigned value or an integer type you likely need to roll over the i counter at 39 ("100111") when the first position is 0 ("000000").
library ieee;
use ieee.std_logic_1164.all;
entity con40 is
port(
reset: in std_ulogic;
clk: in std_ulogic;
en: in std_ulogic;
q: out std_ulogic
);
end entity con40;
architecture foo of con40 is
constant s: std_ulogic_vector (0 to 39) := x"feedfacedb";
signal i: natural range 0 to 39;
begin
q <= s(i);
process (reset, clk)
begin
if reset = '1' then
i <= 0;
elsif rising_edge(clk) and en = '1' then
if i = 39 then
i <= 0;
else
i <= i + 1;
end if;
end if;
end process;
end architecture;
library ieee;
use ieee.numeric_std.all;
architecture behave of con40 is
constant s: std_ulogic_vector (0 to 39) := x"feedfacedb";
signal i: unsigned (5 downto 0);
begin
q <= s(to_integer(i));
process (reset, clk)
begin
if reset = '1' then
i <= "000000";
elsif rising_edge(clk) and en = '1' then
if i = "100111" then
i <= "000000";
else
i <= i + 1;
end if;
end if;
end process;
end architecture;
I also did a quick and dirty test bench:
library ieee;
use ieee.std_logic_1164.all;
entity tb_con40 is
end entity;
architecture foo of tb_con40 is
signal clk: std_ulogic := '0';
signal reset: std_ulogic := '1';
signal en: std_ulogic := '0';
signal q: std_ulogic;
begin
DUT:
entity work.con40
port map (
reset => reset,
clk => clk,
en => en,
q => q
);
CLOCK:
process
begin
for i in 0 to 46 loop
wait for 20 ns;
clk <= not clk;
wait for 20 ns;
clk <= not clk;
end loop;
wait;
end process;
STIMULUS1:
reset <= '0' after 40 ns;
STIMULUS2:
en <= '1' after 60 ns;
end architecture;
Which can demonstrate the correct output:
addendum in response to comment question
The pattern X"FEEDFACEDB" is 40 bits long and was substituted for the 32 all '1's value for constant s to demonstrate that you are actually addressing individual elements of the s array value.
To stop the pulse train fro recurring:
For architecture foo (using an integer type for i):
elsif rising_edge(clk) and en = '1' then
-- if i = 39 then
-- i <= 0;
-- else
if i /= 39 then -- added
i <= i + 1;
end if;
This stops the counter from operating when it reaches 39.
For architecture behave (using an unsigned type for i):
elsif rising_edge(clk) and en = '1' then
-- if i = "100111" then
-- i <= "000000";
-- else
if i /= "100111" then -- added
i <= i + 1;
end if;
end if;
Both architectures behave identically stopping the i counter at 39 ("100111").
The counter can be shown to have stopped by simulating:
Without adding an additional control input the only way to get the pulse stream to occur a second time would be by invoking reseet.
The following code could be a simple implementation to generate pulse trains. This module requires a start impulse (StartSequence) and acknowledges the generated sequence with 'SequenceCompleted'.
Instead of an state machine I use a basic RS flip flop with set = StartSequence and rst = SequenceCompleted_i. I also broke up the process into two processes:
state control - this can be extended to a full FSM if needed
used for counter(s)
Initially, the module emits PULSE_TRAIN(0) by default and also after each sequence generation. So if you want to emit 40 ones otherwise zero set PULSE_TRAIN := (0 => '0', 1 to 40 => '1')
This module is variable in the bit count of PULSE_TRAIN, so I needed to include a function called log2ceil, which calculates the 2s logarithm aka needed bits from PULSE_TRAIN's length attribute.
So in case of 'length = 41 bits Counter_us has a range of (5 downto 0).
entity PulseTrain is
generic (
PULSE_TRAIN : STD_LOGIC_VECTOR
);
port (
Clock : in STD_LOGIC;
StartSequence : in STD_LOGIC;
SequenceCompleted : out STD_LOGIC;
Output : out STD_LOGIC
);
end entity;
architecture rtl of PulseTrain is
function log2ceil(arg : POSITIVE) return NATURAL is
variable tmp : POSITIVE := 1;
variable log : NATURAL := 0;
begin
if arg = 1 then return 0; end if;
while arg > tmp loop
tmp := tmp * 2;
log := log + 1;
end loop;
return log;
end function;
signal State : STD_LOGIC := '0';
signal Counter_us : UNSIGNED(log2ceil(PULSE_TRAIN'length) - 1 downto 0) := (others => '0');
signal SequenceCompleted_i : STD_LOGIC;
begin
process(Clock) is
begin
if rising_edge(Clock) then
if (StartSequence = '1') then
State <= '1';
elsif (SequenceCompleted_i = '1') then
State <= '0';
end if;
end if;
end process;
SequenceCompleted_i <= '1' when (Counter_us = (PULSE_TRAIN'length - 1)) else '0';
SequenceCompleted <= SequenceCompleted_i;
process(Clock)
begin
if rising_edge(Clock) then
if (State = '0') then
Counter_us <= (others => '0');
else
Counter_us <= Counter_us + 1;
end if;
end if;
end process;
Output <= PULSE_TRAIN(to_integer(Counter_us));
end;
As what #fru1tbat mentioned, it's not really clear what is "not working" and what you really intend to do. If you would really just want to generate a pulse train, one would think you want to generate a series of alternating '1' and '0', not all '1's like in the code you posted.
Also, the i counter just counts up, and can only be reset to '0' by use of the reset signal, which is fine as long as you intended it that way.
If you'd like to generate a train of '1's and '0's, you'd need something like this (not tested, but should be along these lines):
architecture behaviour of con40 is
constant trainLength:positive:=80;
signal i:unsigned(6 downto 0):=(others=>'0');
...
begin
process(reset,clk) is begin
if reset then
i<=(others=>'0');
q<='0';
elsif rising_edge(clk) then
q<='0'; -- default assignment.
-- Defaults to '0' when if-statement fails.
if i<trainLength then
i<=i+1;
q<=not q;
end if;
end if;
end process;
end architecture behaviour;
This gives you a single-shot pulse train, means there is no way to repeat generation of the pulse train unless you assert the reset signal again. This is fine if it's what you want, otherwise, you'll need more signals to cater for cases where you'd like to re-generate the pulse train without resetting.
Here, I'm assuming you'd like 40 HIGH pulses, which essentially makes the train length 80 clock cycles, not 40. Also, I'm assuming you want a 50% duty cycle, i.e. the HIGH and LOW times are equal. Depending on your requirements, you may need a pulse width that is longer or shorter.
With these assumptions in mind, you'd need at least a 7-bit counter to count 80 clocks. You may think of other better ways to do this as well, but this just comes off the top of my head, and is probably a good place to start.
If your tool doesn't yet support VHDL-2008's enhanced port modes (e.g. ability to read from out-mode ports), then you could declare q as having a buffer mode instead of out. If your tool doesn't support buffer port modes, then you can declare an internal signal and use it for your logic. E.g.:
signal i_q: std_ulogic;
...
i_q<=not i_q; -- use internal signal for logic instead.
q<=i_q; -- drive output from internal signal.
To adjust the frequency, simply supply a higher or lower frequency into your clk input. This can be generated from another PLL, or a frequency divider, or any other oscillating circuitry you have available. Just supply its output into your clk.
Hope this helps.
I want to create a project with Quartus II and its function is to enable three different leds deppending on a code. When you are entering the code, the first led will be ON. Depending on the code entered, the second or the third will be ON. My problem is, when the code is correct I want the second led to be ON 3 seconds, and if it's incorrect, the third led will be ON during 2 seconds. It would be great if you help me.
Thank you!
Notes: leds are declared as a Logic Vector and the numbers of the code are declared as interrup from 0 to 7.
Code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
ENTITY programa IS
PORT
(
interrup : in Std_Logic_Vector (7 downto 0);
clk, rst: in Std_Logic;
led : out Std_Logic_Vector (2 downto 0)
);
END programa;
ARCHITECTURE arch_programa OF programa IS
type state is (zero, one, two, three, four, five, six);
signal pr_state, nx_state : state;
signal A : Std_Logic_Vector (3 downto 0);
BEGIN
process(interrup, pr_state)
begin
case pr_state is
when zero =>
led <= "100";
A(0) <= interrup(7);
nx_state <= one;
when one =>
led <= "100";
A(1) <= interrup(6);
nx_state <= two;
when two =>
led <= "100";
A(2) <= interrup(5);
nx_state <= three;
when three =>
led <= "100";
A(3) <= interrup(3);
nx_state <= four;
when four =>
led <= "100";
if(A = "1111") then nx_state <= five;
else nx_state <= six;
end if;
when five =>
led <= "010";
nx_state <=zero;
when six =>
led <= "001";
nx_state <=zero;
end case;
end process;
process(rst,clk)
begin
if(rst='1') then
pr_state <= zero;
elsif (clk'event and clk = '1') then
pr_state <= nx_state;
end if;
end process;
end arch_programa;
As for the first question, you will need to count either 3 or 2 seconds worth of clock pulses, so you need to know the clock frequency.
For example, start the counter when you turn the LED on, turn the led and counter off when you have counted the correct number of pulses. It is often easier to count down from that value and stop when the counter reaches zero.
As for the second, the button has to be connected via an input port, which you can use as an input to one of your processes.
There is probably a very large number of ways to solve this, but without changing your code, much, here is one (note, not fully tested).
Give each state a count output that depends on the clock rate.
Establish a counter register big enough to hold the largest count.
Decrement the count on each clock, reload it when it's zero.
The reload value comes from the new state.
Switch states on the last count before zero.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
ENTITY programa IS
PORT
(
interrup : in Std_Logic_Vector (7 downto 0);
clk, rst: in Std_Logic;
led : out Std_Logic_Vector (2 downto 0)
);
END programa;
ARCHITECTURE arch_programa OF programa IS
type state is (zero, one, two, three, four, five, six);
signal pr_state, nx_state : state;
signal A : Std_Logic_Vector (3 downto 0);
signal count,pr_count:integer; --NOTE: Synthisizing integers is very unpredictable, should use unsigned
BEGIN
assign_counts:process(pr_state)
begin
--no idea what states need what delay, this is just an example
case pr_state is
when zero | one | two =>
pr_count<=10;
when four =>
pr_count<=20;
when others =>
pr_count<=50;
end case;
end process;
process(interrup, pr_state)
begin
case pr_state is
when zero =>
led <= "100";
A(0) <= interrup(7);
nx_state <= one;
when one =>
led <= "100";
A(1) <= interrup(6);
nx_state <= two;
when two =>
led <= "100";
A(2) <= interrup(5);
nx_state <= three;
when three =>
led <= "100";
A(3) <= interrup(3);
nx_state <= four;
when four =>
led <= "100";
if(A = "1111") then nx_state <= five;
else nx_state <= six;
end if;
when five =>
led <= "010";
nx_state <=zero;
when six =>
led <= "001";
nx_state <=zero;
end case;
end process;
process(rst,clk)
begin
if(rst='1') then
pr_state <= zero;
count<=pr_count;
elsif (clk'event and clk = '1') then
if count=0 then
count<=pr_count;
elsif count=1 then
pr_state <= nx_state;
count<=count-1;
else
count<=count-1;
end if;
end if;
end process;
end architecture;
--Test bench
library IEEE;
use IEEE.STD_LOGIC_1164.all;
entity bench is
end bench;
architecture bench of bench is
component programa IS
PORT (
interrup : in Std_Logic_Vector (7 downto 0);
clk, rst: in Std_Logic;
led : out Std_Logic_Vector (2 downto 0));
END component;
signal clk:std_logic:='1';
signal interrup:std_logic_vector (7 downto 0);
signal rst:std_logic;
constant freq:real:=1.0e6;
begin
do_reset:process
begin
rst<='1';
wait for 10 us;
rst<='0';
wait;
end process;
clk<=not clk after 0.5 sec / freq;
UUT:programa port map (
interrup => interrup,
clk => clk,
rst => rst);
end architecture;