How to use two switches in vhdl - switch-statement

I want to control the value of a variable using two switches. One for incrementing the value, whereas the other one for decrementing the value. How should i shange this code.
error says that the variable counting is unsynthesisable.
I have tried a lot but could not figure out what exactly the problem is.
ERROR:Xst:827 - line 34: Signal counting0 cannot be synthesized, bad synchronous description. The description style you are using to describe a synchronous element (register, memory, etc.) is not supported in the current software release.
library IEEE;
use IEEE.std_logic_1164.ALL;
use IEEE.numeric_std.ALL;
entity counts is
port(
btn_up : in std_logic;
reset : IN STD_LOGIC;
btn_dn : in std_logic;
counted : out std_logic_vector(8 downto 0)
);
end entity counts;
architecture behaviour of counts is
signal counter : std_logic_vector(8 downto 0);
begin
btupprocess : process(btn_up,reset,counter)
variable counting : unsigned(8 downto 0);
begin
counting := unsigned(counter);
if(reset = '1') then
counting := (others => '0');
elsif (rising_edge(btn_up)) then
if(counting > 399) then
counting := counting - 1;
else
counting := counting + 1;
end if;
end if;
counter <= std_logic_vector(counting);
end process;
btndnprocess : process(btn_dn,counter)
variable counting : unsigned(8 downto 0);
begin
counting := unsigned(counter);
if (falling_edge(btn_dn)) then
if(counting < 200) then
counting := counting + 1;
else
counting := counting - 1;
end if;
end if;
counter <= std_logic_vector(counting);
end process;
counted <= counter;
end behaviour;

Although in some cases it is possible to drive a signal from two different processes, there are better approaches in this case.
A possible solution to your problem is:
add a clock input to your entity; you should probably use a synchronous design
rewrite your architecture to use three processes, with each process driving a single signal:
one process will debounce and detect a rising edge on btn_up; this process will generate the signal btn_up_rising_edge
one process will debounce and detect a rising edge on btn_dn; this process will generate the signal btn_dn_rising_edge
a third process will read btn_up_rising_edge and btn_dn_rising_edge, and increment or decrement the count as appropriate
in all three processes, your sensitiviy list should contain clock and reset only
You can find an example of an edge detector with a debouncer here: https://electronics.stackexchange.com/questions/32260/vhdl-debouncer-circuit

Related

vhdl-fsm with timer- clock cycle delay

i have to write in vhdl an FSM with timer.
I think that,there is no need you to get tired of understanding what my circuit will do.
I just wanted to help me with this:
Every change from a state to another state, there is one (or more) clock cycle delay.
The question is, how can i avoid it?
my vhdl code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_unsigned.ALL;
entity fsm_timers is
port( x: in bit;
clk, rst: in std_logic;
y: out bit);
end fsm_timers;
architecture Behavioral of fsm_timers is
constant T1: std_logic_vector(7 downto 0) :="00000011";
constant T2: std_logic_vector(7 downto 0) :="00000111";
signal t: std_logic_vector(7 downto 0) := (others=>'0');
signal rst_cnt: std_logic :='0';
Type state is (A,B,C);
signal pr_state, nx_state : state := A;
component counter is
port(reset,clock, inner_rst:in std_logic;
cnt:out std_logic_vector(7 downto 0));
end component;
begin
U_sum_counter: counter port map(
reset => rst,
inner_rst => rst_cnt,
clock => clk,
cnt => t);
process(clk,rst)
begin
if (rst='1') then
pr_state<= A;
elsif (rising_edge(clk)) then
pr_state<=nx_state;
end if;
end process;
process(x,t,pr_state)
begin
case pr_state is
when A =>
y<='0';
rst_cnt<='1';
if (x='1') then
nx_state<= B;
else
nx_state<= A;
end if;
when B =>
y<='0';
rst_cnt<='0';
if (x='0' and t=(T1-1)) then
nx_state<= C;
end if;
if ((x='0' and t<(T1-1)) or (x/='0' and t<(T2-1))) then
nx_state<= B;
end if;
if (t=(T2-1)) then
nx_state<= A;
end if;
when C =>
y<='1';
rst_cnt<='0';
if (t=(T2-1)) then
nx_state<= A;
else
nx_state<= C;
end if;
end case;
end process;
end Behavioral;
Thank you in advance
I think you can't avoid at least a single clock delay. The reason is that you have to remember your current state. For saving the state you have to use a register, which will cause the delay. Otherwise you can avoid this by using an asynchronous state machine, but then you will have to be careful about your input.
A usual Moore's state machine has:
\/-------------|
input --> transition logic --> state memory --> output logic --> output
^-clk ^-rst ^-enable
This structure can be nicely expressed by 3 processes. For trying to reduce the latency, you can connect the output logic directly to the transition logic, but you might need a register after that anyway.
For details see this page i googled, it is pretty detailed.

VHDL - Debounce Button Press

I have the following button press logic in my code. I have tried debouncing it using a wait delay, but the compiler will not allow this. I have four push buttons on my FPGA, which the "key" array below reflects:
process(clock)
begin
if rising_edge(clock) then
if(key(3)/='1' or key(2)/='1' or key(1)/='1' or key(0)/='1') then --MY ATTEMPT AT DEBOUNCING
wait for 200 ns; ----MY ATTEMPT AT DEBOUNCING
if (key(3)='1' and key(2)='1' and key(1)='0' and last_key_state="1111" and key(0)='1') then
...
elsif (key(3)='1' and key(2)='1' and key(1)='1' and key(0)='0' and last_key_state="1111") then
...
elsif (key(3)='0' and key(2)='1' and key(1)='1' and key(0)='1' and last_key_state="1111") then
...
elsif (key(3)='1' and key(2)='0' and key(1)='1' and key(0)='1' and last_key_state="1111") then
...
end if;
last_key_state<=key;
end if;
end if;
end process;
Can anyone give some really simple example code showing how I could debounce a setup like the one I have above?
Well if you think about how you would do this with real electronics you would probably use a capacitor.. which has a charging time. Same idea applies here, just figure out the time your switch is bouncing (usually a function of clock speed) and then actually set the register.
Simple Example With a 4-Bit Shift Register
So you'd put this between your switch and any other logic blocks
process
begin
if rising_edge(clock) then --You're clock
SHIFT_PB(2 Downto 0) <= SHIFT_PB(3 Downto 1); --Shifting each cycle
SHIFT_PB(3) <= NOT PB; --PB is the pre-bounced signal
If SHIFT_PB(3 Downto 0)="0000" THEN --once the bounce has settled set the debounced value
PB_DEBOUNCED <= '1';
ELSE
PB_DEBOUNCED <= '0';
End if;
end process;
Its basically delaying your signal 4 clock cycles (what you were trying to do with the wait).
Others have shown the way with counters... you also need to synchronise the signal to the clock before feeding it to the counter, otherwise occasionally, the signal will get to different parts of the counter at different times, and the counter will count incorrectly.
Whether this matters depends on the application - if correct operation is important, it is important to synchronise correctly!
You get the error because of wait ... wait is not synthesizeable.
I would do it with a simple counter. So you can use the same code for different clock speeds by adjusting the counter.
-- adjust the counter to you special needs
-- depending on how good your buttons are hardware debounced
-- you can easily think in ms
signal counter : std_logic_vector(7 DOWNTO 0) := "10000000";
process
begin
if rising_edge(clock) then --You're clock
if(key(3) = '0') or (key(2) = '0') or (key(1) = '0') or (key(0) = '0') then
start_debouncing <= '1';
key_vector_out <= key(3) & key(2) & key(1) & key(0);
end if;
if(start_debouncing = '1') then
key_vector_out <= "0000";
counter <= std_logic_vector(unsigned(counter) - 1);
end if;
if(counter = "00000000") then
counter <= "10000000";
start_debouncing <= '0';
end if;
end process;
Your code can produce another problem.
What will happen if you button is released so your input is .. key = "0000" .. right you never get you output. Perhaps it will work 99 out of 100 times but you can get an really hard to find error.

VHDL - Making a clock from another module's output signal

I am modifying a simple keyboard interface I found on the net to my use. The idea is whenever there is a new scancode, it will make the output named "Scan_Dav" go high, and then go low. So when I direct Scan_Dav to another module as a clock, that module's clock will have a rising edge whenever a new ScanCode is pressed. Is there any error in my way of thinking? Because I tried it and directed the scancode and scan_dav to the rest of my project -which writes letters side by side with the given scancodes and shows them on seven segment display- the displayed text had 2 of each character ( i.e. when I write FLY the text was like FFLLYY). If there is no errors, I will share my code and ask you why it is not working. Thanks :)
EDIT: This is where the shifting is done according to values of Scan_Dav
signal bytes : std_logic_vector(63 downto 0);
signal Scan_Dav_Sync: std_logic_vector(1 downto 0):="00";
signal Previous_Scan_Dav: std_logic:='0';
begin
process (clk) begin --, Scan_Dav) begin
if rising_edge(clk) then
Scan_Dav_Sync(0) <= Scan_Dav;
Scan_Dav_Sync(1) <= Scan_Dav_Sync(0);
Previous_Scan_Dav <= Scan_Dav_Sync(1);
if (Previous_Scan_Dav = '0') and (Scan_Dav_Sync(1) = '1') then
bytes <= bytes (bytes'high-8 downto 0) & Data_in;
end if;
end if;
end process;
This is where Scan_Dav comes from, the code is taken from here:
(You may ignore the filtering part)
Architecture Behavioral of KeyboardController is
signal PS2_Datr : std_logic;
subtype Filter_t is std_logic_vector(7 downto 0);
signal Filter : Filter_t;
signal Fall_Clk : std_logic;
signal Bit_Cnt : unsigned (3 downto 0);
signal Scan_DAVi : std_logic;
signal S_Reg : std_logic_vector(8 downto 0);
signal PS2_Clk_f : std_logic;
Type State_t is (Idle, Shifting);
signal State : State_t;
signal Scan_Code : std_logic_vector(7 downto 0);
signal Flag : std_logic:='0';
begin
process (Clk,Reset)
begin
if Reset='1' then
PS2_Datr <= '0';
PS2_Clk_f <= '0';
Filter <= (others=>'0');
Fall_Clk <= '0';
elsif rising_edge (Clk) then
PS2_Datr <= PS2_Data and PS2_Data; -- also turns 'H' into '1'
Fall_Clk <= '0';
Filter <= (PS2_Clk and PS2_CLK) & Filter(Filter'high downto 1);
if Filter = Filter_t'(others=>'1') then
PS2_Clk_f <= '1';
elsif Filter = Filter_t'(others=>'0') then
PS2_Clk_f <= '0';
if PS2_Clk_f = '1' then
Fall_Clk <= '1';
end if;
end if;
end if;
end process;
-- This simple State Machine reads in the Serial Data
-- coming from the PS/2 peripheral.
process(Clk,Reset)
begin
if Reset='1' then
State <= Idle;
Bit_Cnt <= (others => '0');
S_Reg <= (others => '0');
Scan_Code <= (others => '0');
Scan_Out <= (others => '0');
Scan_Davi <= '0';
elsif rising_edge (Clk) then
-- if Scan_Davi = '1' then
-- Scan_Davi <= '0';
-- end if;
case State is
when Idle =>
Bit_Cnt <= (others => '0');
-- note that we dont need to clear the Shift Register
if Fall_Clk='1' and PS2_Datr='0' then -- Start bit
State <= Shifting;
end if;
when Shifting =>
if Bit_Cnt >= 9 then
if Fall_Clk='1' then -- Stop Bit
Scan_Code <= S_Reg(7 downto 0);
if (Flag = '1' and Scan_Code /= "11110000") then
--to ignore makecode
Scan_Out <= Scan_Code;
Flag <= '0';
Scan_Davi <= '1';
end if;
if (Flag = '0' and Scan_Code = "11110000") then
--to ignore F0
Flag <= '1';
Scan_Davi <= '0';
end if;
State <= Idle;
end if;
elsif Fall_Clk='1' then
Bit_Cnt <= Bit_Cnt + 1;
S_Reg <= PS2_Datr & S_Reg (S_Reg'high downto 1); -- Shift right
end if;
when others => -- never reached
State <= Idle;
end case;
end if;
end process;
Scan_DAV <= Scan_DAVi;
end Behavioral;
UPDATE: The only problem that remains is the delayed display and shifting of the letter and the text. While writing VHDL, I get nothing after pressing V, then I get V when I press H and it goes like that. The last letter does not appear until another key is pressed.It seems to be an issue about Scan_Dav, yet I can not resolve what it is. Any help will be appreciated.
Driving a clock input from logic output is generally bad practice (and some FPGA fabrics will not allow it at all). Clocks run best when sourced from dedicated clock logic inside the part, and good designs should minimize the number of clocks. Ideally you'd have only one, but that's not always possible.
Instead of running a clock input from logic, consider running everything off of one clock and use "enables" to activate the logic only when needed. In this case, you would detect the rising-edge transition of scan_dav inside of the downstream module and only react when that transition occurs. The detection logic would run off of the same clock as the scan_dav module.
I don't think this explains why you're seeing double characters, you would need to post some code to analyze. However, I would recommend that you re-tool to not drive clocks from logic.
If I see it right you avoid the F0 when you release the Key but you do not filter the second scancode.
It's always like this
Scancode --- press Key
F0 --- relesase Key
Scancode
on some Keys (e.g ALT GR) you can get an E0 too.
It not complete description but the most importand thinks are shown.
http://en.wikipedia.org/wiki/Scancode
This would lead to the descripted problem. FLY -> FFLLYY.

Delay a signal in vhdl

I would like to delay a signal several cycles in vhdl, but I have problems using how to delay a signal for several cycles in vhdl
Wouldn't I need a registered signal? I mean, something like:
a_store and a_store_registered would be std_logic_vector(cycles_delayed-1 downto 0)
process(clk)
begin
if rising_edge(clk) then
a_store_registered <= a_store;
end if;
end process;
a_out <= a_store_registered(cycles_delayed-1);
process(a_store_registered, a)
begin
a_store <= a_store_registered(size-2 downto 0) & a;
end process;
The solution you link to is a registered signal - the very act of writing to a signal inside a process with a rising_edge(clk) qualifier creates registers.
An even simpler implementation of a delay-line can be had in one line of code (+ another one if you want to copy the high bit to an output)
a_store <= (a_store(a_store'high-1 downto 0) & a) when rising_edge(clk);
a_out <= a_store(a_store'high);
Not sure why I didn't mention this in my answer to the linked question!
I am not sure why you are approaching the problem as you are; there is no need for a second process here. What is wrong with the method suggested in the linked question?
if rising_edge(clk) then
a_store <= a_store(store'high-1 downto 0) & a;
a_out <= a_store(a_store'high);
end if;
In this case your input is a and your output is a_out. If you want to make the delay longer, increase the size of a_store by resizing the signal declaration.
If you want to access the intermediate signal for other reasons, you could do this:
a_store <= a_store_registered(cycles_delayed-2 downto 0) & a;
process(clk)
begin
if rising_edge(clk) then
a_store_registered <= a_store;
end if;
end process;
a_out <= a_store_registered(cycles_delayed-1);
Remember that you can use the foo'delayed(N ns) attribute or foo <= sig after N ns in simulations.

how to delay a signal for several cycles in vhdl

How to delay signal for a given number of cycles in VHDL?
Number of cycles is given as a generic.
Any other options instead of
process(CLK) is
begin
if rising_edge(CLK) then
a_q <= a;
a_q_q <= a_q;
a_q_q_q <= a_q_q;
-- etc
end if;
end process;
?
Create an 1-d array (let's call it a_store) of the appropriate type of signal with the length of the array related to the number of cycles. This may mean you have to create a new type for the array unless there's already a vector type you can use: eg. std_logic_vector or integer_vector (the latter is standard only in VHDL-2008).
Then shuffle the array along each tick:
if rising_edge(clk) then
a_store <= a_store(store'high-1 downto 0) & a;
a_out <= a_store(a_store'high);
end if;

Resources