Random LED turning on and off in VHDL - random

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.

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!

How to fill a vector bit by bit

I have a 12 bits vector called RDIBits and a in std_logic called InUartToUart. My question is: every time the clock goes to '1', i receive a bit in InUartToUart, and i want to concat all the 12 bits that i will receive in the RDIBits vector. Basically, its a serial communication, thats why i receive 1 bit each time. Is there any simple way to do this? Something similar to RDIBits += InUartToUart in JAVA.
I would code this slightly differently. Maybe consider this.
Sorry about the formatting, Im new to this site. I have also shown how you can initialise the variable.
signal RDIBits : std_logic_vector(11 downto 0) := (Others => '0');
...
process(clk)
begin
if ( rising_edge(clk) ) then
RDIBits(11 downto 1) <= RDIBits(10 downto 0);
RDIBits(0) <= InUartToUart;
end if;
end process;
I added some more things, like the entity, the IOs and a counter for the output register.
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;
ENTITY my_uart IS
PORT(
clk : IN std_logic; -- system clock
rst : IN std_logic; -- reset high active
---------------------------------------------
InUartToUart : IN std_logic;
DataOut : OUT std_logic_vector(11 downto 0)
);
END ENTITY;
ARCHITECTURE struct OF my_uart IS
signal RDIBits : std_logic_vector(11 downto 0);
signal counter : integer range 0 to 12;
begin
calc_proc: process(clk, rst)
begin
if (rst = '1') then
RDIBits <= (others => '0');
counter <= 0;
elsif ( rising_edge(clk) ) then
if (counter < 12) then
RDIBits <= RDIBits(10 downto 0) & InUartToUart;
counter <= counter + 1;
elsif (counter = 12) then
DataOut <= RDIBits;
counter <= 0;
end if;
end if;
end process;
END STRUCT;
This is a typical shift register application. For example:
signal RDIBits : std_logic_vector(11 downto 0);
...
process(clk)
begin
if ( rising_edge(clk) ) then
RDIBits <= RDIBits(10 downto 0) & InUartToUart;
end if;
end process;

vhdl code for producig triangular wave using DAC2904 is not working

I am doing a project in college and want to produce a triangular wave using a DAC2904 and a Spartan 3 xc3s5000 board.
I have written code for it but is not working.
I don't know may be it is the problem in code or in my ucf file:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity traingular is
Port (
clk : in std_logic; -- on board clock
reset : in std_logic;
dac_clk : out std_logic; -- clk for dac module
output : out std_logic_vector(13 downto 0); -- output to dac
wr_dac : out std_logic -- pulse given to write pin of dac ic.
);
end traingular;
architecture Behavioral of traingular is
signal counter : unsigned(3 downto 0);
signal divide : std_logic_vector(15 downto 0);
signal sampling_clk , clk_s : std_logic;
signal decade : std_logic_vector(3 downto 0);
-- decade counter used because on board clk freq is 40 hz
-- so the code written below reduce the freq which is applied to dac module very much
begin
process(clk, reset)
begin
if (reset = '1' ) then
decade <= (others => '0');
elsif (clk' event and clk = '1') then
if (decade = "1010") then
decade <= (others => '0');
else
decade <= std_logic_vector(unsigned(decade) + 1);
end if;
end if;
end process;
clk_s <= '1' when decade = "1010" else
'0';
process(clk_s , reset)
begin
if (reset='1') then
divide <= (others => '0');
elsif (clk_s'event and clk_s = '1') then
divide <= std_logic_vector(unsigned(divide) + 1);
end if;
end process;
sampling_clk <= divide(2);
-- input click is still fast so clock is divided further
dac_clk <= sampling_clk;
wr_dac <= sampling_clk;
process(clk , reset)
begin
-- code below is for counter which will further feed to dac to produce traingular wave.
if (reset = '1' ) then
counter <= (others => '0');
elsif (clk' event and clk = '1') then
if (counter = "1010") then
counter <= (others => '0');
else
counter <= counter + 1;
end if;
end if;
end process;
output <= "0000000000" & std_logic_vector(counter); -- output to dac.
end Behavioral;
So, can you guys tell me what is the problem in my code.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_signed.all;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity tri_wave is
Port ( clk : in STD_LOGIC;
rst :in STD_LOGIC;
up_step_size,down_step_size:in std_logic_vector(2 downto 0);
dac_out : out STD_LOGIC_VECTOR (7 downto 0));
end tri_wave;
architecture Behavioral of tri_wave is
signal dac_wav:std_logic_vector(7 downto 0);
signal count:std_logic_vector(7 downto 0);
signal dir:std_logic:='0';
begin
process(clk,rst,dir)
begin
if rst='1' then
count<=(others=>'0');
elsif dir='0' then
if clk'event and clk='1' then
if count="01111111" then
dir<='1' ;
else
count<= count + up_step_size;
end if;
end if;
elsif dir='1' then
if clk'event and clk='1' then
if count="10000000" then
dir<='0' ;
else
count<= count - down_step_size;
end if;
end if;
end if;
end process;
--dac_out<=count;
dac_out<=count(count'high) & count(6 downto 0);
end Behavioral;
i think this code gives u better idea just creaet tb and simulae i odelsim u will get it.

Trying to show one cycle of 8 bit LFSR with VHDL

I'm trying to do a VHDL code with the objective to make a 8 bit LFSR and show all the random states, and after one cycle (when the last state be the same seed value) it stop. But I'm have a problems, keep saying: "loop must terminate within 10,000 iterations". I'm using Quartus II-Altera.
Code:
entity lfsr_8bit is
--generic ( n : integer := 2**8 );
port (
clk : in bit;
rst : in bit;
lfsr : out bit_vector(7 downto 0)
);
end lfsr_8bit;
architecture behaviour of lfsr_8bit is
--signal i : integer := 0;
--signal seed : bit_vector(7 downto 0) := "10000000";
signal rand : bit_vector(7 downto 0);
begin
ciclo : process (clk,rst)
begin
loop
if (rst='0') then
rand <= "10000000";
elsif (clk'event and clk='1') then
rand(0) <= rand(6) xor rand(7);
rand(7 downto 1) <= rand(6 downto 0);
end if;
-- wait until rand = "10000000" for 100 ns;
exit when rand = "10000000";
-- case rand is
-- when "10000000" => EXIT;
-- when others => NULL;
-- end case;
-- i <= i +1;
end loop;
lfsr <= rand(7 downto 0);
end process ciclo;
end behaviour;
Thank you for all help.
Get rid of that loop, that loop does not work the way you think it does! Stop thinking like a software designer and think like a hardware designer. Loops in hardware are used to replicate logic. So that loop of yours is literally trying to generate 10,000 LFSRs!
I don't believe that you need to be using that loop there at all. If you remove it your LFSR should work as intended. You may need to add a control signal to enable/disable the LFSR, but definitely do not use a loop.
Here's some example code demonstrating this. Change the default value of rand to something else or the LFSR will never run! It will immediately set the lfsr_done signal.
ciclo : process (clk,rst)
begin
if (rst='0') then
rand <= "10000000"; -- SET THIS TO SOMETHING DIFFERENT
lfsr_done <= '0';
elsif (clk'event and clk='1') then
if rand = "10000000" then
lfsr_done <= '1';
end if;
if lfsr_done = '0' then
rand(0) <= rand(6) xor rand(7);
rand(7 downto 1) <= rand(6 downto 0);
end if;
end if;

VHDL shift register with enable

I am newbie to VHDL. I am implementing serial in serial out 72 bit shift register using VHDL. When the enable signal is high, I want the shift register to shift 72 times, irrespective of whether enable continues to be high or low. I have written the following code which is working only when the enable is high. Can anyone please help me to shift data once enable is high and then does not depend on enable to shift the data?
library ieee;
use ieee.std_logic_1164.all;
entity SR is
port(clk, din, rst, enable : in std_logic;
sr_out : inout std_logic_vector(71 downto 0));
end SR;
architecture behavioral of SR is
signal shift_reg: std_logic_vector(71 downto 0);
begin
process (clk, rst)
begin
if (rst = '0') then
shift_reg <= (others => '0');
elsif (clk'event and clk = '1') then
if enable= '1' then
shift_reg(70 downto 0) <= shift_reg(71 downto 1);
shift_reg(71) <= din;
end if;
end if;
end process;
sr_out <= shift_reg;
end behavioral;
Thanks a lot!
I think you need an RS-FlipFlop which is set by a start signal. Its output is your enable signal. The start signal also starts a 72 clock cycle counter. When the counter rolls over (or reaches zero, depending on its direction) you reset the FlipFlop which results in a disabled shift register.
edit: In addition you can add a gate to the start signal which blocks new start impulses while the counter is active. So you can be sure your data is only shifted with a multiple of 72 bits.
You need a two states machine to do so. Here's a very good idea of how to do it. I'm pretty sure it does what you need or is very close to.
library ieee;
use ieee.std_logic_1164.all;
entity SR is
port(
clk : in std_logic;
din : in std_logic;
rst : in std_logic;
enable : in std_logic;
sr_out : inout std_logic_vector(71 downto 0)
);
end SR;
architecture behavioral of SR is
signal shift_reg : std_logic_vector(71 downto 0);
signal shift_cnt : integer range 0 to 72 := 0;
type T_STATE_TYPE is (IDLE, COUNTING);
signal current_state : T_STATE_TYPE;
begin
p_shift_counter : process(clk,rst)
begin
if rst = '1' then
current_state <= IDLE;
shift_cnt <= 0;
elsif rising_edge(clk) then
if (current_state = IDLE) then --no enable detected yet
shift_cnt <= 0;
if enable = '1' then
current_state <= COUNTING;
end if;
elsif (current_state = COUNTING) then --will stay in that state until it finishes counting
if (shift_cnt < 72) then
shift_reg(0) <= din;
for i in 0 to 71 loop shift_reg(i+1) <= shift_reg(i); end loop; --shifting register
shift_cnt <= shift_cnt + 1;
else
current_state <= IDLE; --finished counting
end if;
end if;
end if;
end process;
sr_out <= shift_reg;
end behavioral;

Resources