VHDL- increment and decrement push button - vhdl

I am trying to increment and decrement with two push-buttons. The algorithm goes well but I have a little issue. Supposedly I am incrementing , when I try to decrement the accumulator it increments once more , and only after that it start
to decrement. Same if I try to decrement first. If it is someone to help me I will be very thankfully.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.std_logic_unsigned.all;
entity my_offset_controller is
port(clk : in std_logic;
input : in std_logic_vector(15 downto 0);
add_button : in std_logic;
sub_button : in std_logic;
output_res : out std_logic_vector(15 downto 0)
);
end my_offset_controller;
architecture Behavioral of my_offset_controller is
signal buttonState_up : std_logic:='0';
signal accumulator : std_logic_vector(15 downto 0);
signal lastButtonState_up : std_logic:='0';
signal buttonState_down : std_logic:='0';
signal lastButtonState_down : std_logic:='0';
signal buttonPushCounter : integer range 0 to 512 :=0;
process(clk)
begin
if rising_edge(clk) then
buttonState_up <= add_button;
buttonState_down <= sub_button;
if (buttonState_up /= lastButtonState_up) then
if (buttonState_up ='1') then
buttonPushCounter <= buttonPushCounter + 1;
accumulator <= std_logic_vector(to_unsigned(buttonPushCounter,accumulator'length));
end if;
lastButtonState_up <= buttonState_up;
elsif (buttonState_down /= lastButtonState_down) then
if (buttonState_down ='1') then
buttonPushCounter <= buttonPushCounter - 1;
accumulator <= std_logic_vector(to_unsigned(buttonPushCounter,accumulator'length));
end if;
lastButtonState_down <= buttonState_down;
end if;
end if;
end process;
output_res<= accumulator + input ;
This particularly module I use to controll the offset of an signal that I plot on an vga screen.

It's hard to help you without more information. You should provide a testbench with a chronogram to make it easier. Yet, by looking at your process I would say that the problem comes from the following lines:
buttonPushCounter <= buttonPushCounter + 1;
accumulator <= std_logic_vector(to_unsigned(buttonPushCounter,accumulator'length));
What you did there is increment buttonPushCounterat the same time that you update accumulator. This way buttonPushCounter will always be shifted by +1 or -1 depending on the last event.
What I can recommend is to update accumulator at every clock cycle instead of every time an event occurs. For example like this:
if rising_edge(clk) then
accumulator <= std_logic_vector(to_unsigned(buttonPushCounter,accumulator'length));
...

Related

Why is my debouncing/counter not working in VHDL?

i am currently trying to display a counter state on a 7-Segment.
If i push a button (physically) it should increase this counter state.
But in my case its displaying a random number, i think its a wrong debouncing/counter method.
I searched the web but i canĀ“t fix this behaviour.
I would be very thankful if someone could help me!
EDIT: The 7-Segment-Display is working well i did a test with all numbers (0-9)
So it is definetly failing in my debounce or counter method.
//debouncer.vhdl
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
entity Debounce is
Port ( CLK100MHZ : in STD_LOGIC;
BTNU : in STD_LOGIC;
BTNU_I : out STD_LOGIC);
end Debounce;
architecture Behavioral of Debounce is
signal keydeb : std_logic := '0';
signal debcnt : integer range 0 to 63 := 0;
begin
process begin
wait until rising_edge(CLK100MHZ);
-- XOR
if (BTNU=keydeb) then debcnt <= 0;
else debcnt <= debcnt+1;
end if;
-- Latch
if (debcnt=63) then keydeb <= BTNU;
end if;
end process;
BTNU_I <= keydeb;
end Behavioral;
//main.vhdl
//declared ports
Port (
BTNU: in std_logic; //button
CPU_RESETN: in std_logic;
CLK100MHZ: in std_logic;
);
//declared signals
signal Qint10m: std_logic_vector(3 downto 0); //number which holds the number to display
signal BTNU_I: std_logic; //button debounced
signal testC: integer range 9 downto 0; //counter
BTNU_debounce: entity Work.Debounce port map(
CLK100MHZ => CLK100MHZ,
BTNU => BTNU,
BTNU_I => BTNU_I);
bcd_counttest: process(CPU_RESETN, CLK100MHZ, BTNU_I)
begin
if(CPU_RESETN='0') then
testC <= 0;
elsif( CLK100MHZ'event and CLK100MHZ = '1') then
if(BTNU_I = '1') then
if(testC = 8) then
testC <= 0;
else
testC <= testC+1 ;
end if;
end if;
end if;
end process bcd_counttest;
Qint10m <= std_logic_vector(to_unsigned(testC, Qint10m'length));
I did not check your code very well, but noticed a de-bounce counter of 63 on a 100MHz clock. That is 630 ns.
A button can easily bounces for several milliseconds (depending on the button type) . So I suggest you start with using a bigger counter.
p.s. I am not very familiar with VHDL but this:
wait until rising_edge(CLK100MHZ);
can not be synthesized in Verilog.
I suggest you have a good look at your whole debounce process as I also see no sensitivity list and a latch!

VHDL Clock problem while creating modulo 16 counter

I've created this simple mod16 counter using basys3 board and something is not right with my clock. The code itself do works, however one count (changing from "1" to "2" etc.) last 40 seconds, instead of 1 second! I've tried to lower the "clk_vector" if condition to 1 but it didn't help either.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity mod_16_k is
Port ( switch : in STD_LOGIC_VECTOR (3 downto 0);
CLK1 : in STD_LOGIC;
reset : in STD_LOGIC;
led : out STD_LOGIC_VECTOR (15 downto 0));
end mod_16_k;
architecture Behavioral of mod_16_k is
signal clk_vector :integer;
signal clk_vec2 :std_logic_vector(15 downto 0);
begin
zegar_wew : process(CLK1)
begin
if(CLK1'event and CLK1 = '1') then
clk_vector <= clk_vector + 1;
if(clk_vector = 100000000) then
clk_vec2 <= std_logic_vector(unsigned(clk_vec2) + 1);
end if;
end if;
end process;
led <= clk_vec2;
end Behavioral;
The .XDC lines for clock are:
If we check the basys3 datasheet, the clock is connected to "W5" port.
Do you have any idea, what might be the problem in here? It might be connected with detecting the rising edge of an clk, however all of the changes (from 1 to 2 etc.) last ~40 seconds.
This is because you forget to reset clk_vector once it reaches 1 second. Because it is an integer, it is 32 bits, thus will count 2^32 instead of 100000000.
This should work:
If(CLK1'event and CLK1 = '1') then
if(clk_vector = 100000000-1) then
clk_vector <= 0;
clk_vec2 <= std_logic_vector(unsigned(clk_vec2) + 1);
else
clk_vector <= clk_vector + 1;
end if;
end if;
Also, notice that to count 1 second, you need to count up to 100000000-1, we start counting from zero!

VHDL:clock divider

i have 27MHz frequency at the input and want to get 400Hz, 100Hz and 1Hz frequencies at the output. but when i simulate it i dont get anything its just undefined, i dont have any idea what's wrong.
code
entity clk_div is
port
(
clk : in std_logic;
clock_set : in std_logic;
clk1_out : out std_logic;
clk100_out : out std_logic;
clk400_out : out std_logic
);
end entity;
architecture rtl of clk_div is
signal q : std_logic_vector(24 downto 0);
begin
process (clk)
begin
if(rising_edge(clk)) then
q <= q+1;
end if;
end process;
clk1_out <= q(24); -- 1Hz freq
clk400_out <= q(15); --400Hz freq
clk100_out <= q(17); --100Hz freq
end rtl;
q is never initalised, so when you add one to it, the result is not defined.
You need something like:
signal q : std_logic_vector(24 downto 0) := (others => '0');
Also, you are performing a mathematical operation on an std_logic_vector. This is not recommended; you should have a look at using the numeric_std package, and make your counter type unsigned.

Random LED turning on and off in VHDL

I want to implement a random-number game on BASYS2. In this game there would be five LEDs chosen out of which one would turn on at random for a second or two (this time can be changed to increase or decrease the difficulty level of the game). Then the user is required to respond to this LED event by pressing the switch button behind it within the time that it is on. If he or she is able to do so successfully a point would be scored and it would be showed on the Seven Segment Display. If he or she fails no point would be scored. There would be 9 such events after which the game can be replayed.
Now following is my code (only for the random LED turning on). However, I am unable to fix it. Please somebody help. The FPGA I am using is BASYS2 SPARTAN 3E-100.
Thanks in advance to everyone.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_unsigned.ALL;
use IEEE.STD_LOGIC_arith.ALL;
entity random_number is
generic ( width : integer := 4 );
port (
clk : in std_logic;
reset : in std_logic;
random_num : out std_logic_vector (width-1 downto 0) --output vector
);
end random_number;
architecture Behavioral of random_number is
signal q: std_logic_vector(23 downto 0);
signal divided_clock: std_logic;
begin
process(clk, reset)
begin
if (reset = '1')then
q <= X"000000";
elsif(rising_edge(clk)) then
q <= q + 1;
end if;
end process;
divided_clock <= q(22);
process (divided_clock)
variable rand_temp : std_logic_vector(width-1 downto 0):=("1000");
variable temp : std_logic := '0';
begin
if(rising_edge(divided_clock)) then
temp := rand_temp(width-1) xor rand_temp(width-2);
rand_temp(width-1 downto 1) := rand_temp(width-2 downto 0);
rand_temp(0) := temp;
end if;
random_num <= rand_temp;
end process;
end Behavioral;
I think the second process should even run with the main clk and the devided clock should be an enable.
signal divided_enable: std_logic;
process(clk, reset)
begin
if (reset = '1')then
q <= X"000000";
elsif(rising_edge(clk)) then
q <= q + 1;
end if;
if (q(22) = '1') then
--short pulse wenn q bit 22 is high
divided_enable <= '1';
q <= (others => '0');
end if;
end process;
process (clk)
variable rand_temp : std_logic_vector(width-1 downto 0):=("1000");
variable temp : std_logic := '0';
begin
if(rising_edge(clk)) then
if(divided_enable = '1') then
temp := rand_temp(width-1) xor rand_temp(width-2);
rand_temp(width-1 downto 1) := rand_temp(width-2 downto 0);
rand_temp(0) := temp;
end if;
end if;
random_num <= rand_temp;
end process;
I don't know if this will fix all your problems. Please discribe compiler errors or errors in the behavior.

Bit shift register vhdl varying size

I'm trying to get two outputs (pulse(0) and pulse(1)) to deliver a short one clock pulse. The latency between these pulses needs to be controlled by some input value. So 0x1 = 1 clock cycle etc.
At the moment, once the trigger switches on, it stays on
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
use work.ipbus.all;
<...snip>
architecture rtl of trig_latency is
signal ack : std_logic;
signal s_level : unsigned(pulse'range);
signal s_level_d1 : std_logic;
signal bit_shift : std_logic_vector(addr_width downto 0);
signal latency: integer:=5;
begin
latency <= to_integer(unsigned(in_data(addr_width -1 downto 0))) when addr_width > 0 else 0;
process(clk)
begin
if rising_edge(clk) then
if ipbus_in.ipb_strobe='1' and ipbus_in.ipb_write = '1' then
s_level <= s_level + 1;
s_level_d1<=s_level(s_level'left);
else
s_level<=(others=>'0);
end if;
bit_shift <= bit_shift(bit_shift'high-1 downto 0) & (s_level(s_level'left) and (not s_level_d1));
ipbus_out.ipb_rdata <= (others => '0');
ack <= ipbus_in.ipb_strobe and not ack;
pulse(0) <= s_level(s_level'left) and (not s_level_d1);
pulse(1)<=bit_shift(latency);
end if;
end process;
ipbus_out.ipb_ack <= ack;
ipbus_out.ipb_err <= '0';
end rtl;
Why can't you just shift your bits the whole way and ignore the fact that they go above N. The usual VHDL shifter uses the & to concatenate the shifted register with the new value:
bit_shift <= bit_shift(bit_shift'high-1 downto 0) & s_level;
That should produce your shift register just fine.
The pulse(1) <= bit_shift(N) ought to work fine.

Resources