I am trying to make a basic distance indicating module using ultrasonic sensor. When I dumped the code for the same into my FPGA board(Helium V1.1 developed by IIT-B) all the LEDs in the board started glowing since the clock frequency was too high. So now I am using a frequency divider to reduce my clock speed but I am not getting how to use the output of my frequency divider code as an input to my main code. Can someone help me since this is the first time I am working on FPGA and I dont quite understand VHDL yet?
Code for frequency divider
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
entity Clock_Divider is
port ( clk,reset: in std_logic;
clock_out: out std_logic);
end Clock_Divider;
architecture bhv of Clock_Divider is
signal count: integer:=1;
signal tmp : std_logic := '0';
begin
process(clk,reset)
begin
if(reset='1') then
count<=1;
tmp<='0';
elsif(clk'event and clk='1') then
count <=count+1;
if (count = 25000) then
tmp <= NOT tmp;
count <= 1;
end if;
end if;
clock_out <= tmp;
end process;
end bhv;
Code to measure distance using ultrasonic:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity ultrasonic is
port(
CLOCK: in std_logic;
LED: out std_logic_vector(7 downto 0);
TRIG: out std_logic;
ECHO: in std_logic
);
end ultrasonic;
architecture rtl of ultrasonic is
signal microseconds: std_logic;
signal counter: std_logic_vector(17 downto 0);
signal leds: std_logic_vector(7 downto 0);
signal trigger: std_logic;
begin
process(CLOCK)
variable count0: integer range 0 to 7;
begin
if rising_edge(CLOCK) then
if count0 = 5 then
count0 := 0;
else
count0 := count0 + 1;
end if;
if count0 = 0 then
microseconds <= not microseconds;
end if;
end if;
end process;
process(microseconds)
variable count1: integer range 0 to 262143;
begin
if rising_edge(microseconds) then
if count1 = 0 then
counter <= "000000000000000000";
trigger <= '1';
elsif count1 = 10 then
trigger <= '0';
end if;
if ECHO = '1' then
counter <= counter + 1;
end if;
if count1 = 249999 then
count1 := 0;
else
count1 := count1 + 1;
end if;
end if;
end process;
process(ECHO)
begin
if falling_edge(ECHO) then
if counter < 291 then
leds <= "11111111";
elsif counter < 581 then
leds <= "11111110";
elsif counter < 871 then
leds <= "11111100";
elsif counter < 1161 then
leds <= "11111000";
elsif counter < 1451 then
leds <= "11110000";
elsif counter < 1741 then
leds <= "11100000";
elsif counter < 2031 then
leds <= "11000000";
elsif counter < 2321 then
leds <= "10000000";
else
leds <= "00000000";
end if;
end if;
end process;
LED <= leds;
TRIG <= trigger;
end rtl;
I am using Quartus for simulating these codes.
welcome to the HDL languages :)
For simulation clock_out is missing from the sensitivity list process(...)
For synthesis/implementation you might need to check all processes as they should be dependent on your clock signal. I've learned it's considered bad practice to use rising/falling edge on other signals than clock signals.
You probably want to go for a pattern something like:
...
-- entity declaration
s : in std_logic;
...
-- architecture declaration
signal s_d : std_logic;
begin
...
process(clk)
begin
if rising_edge(clk) then
-- s_d is s one clock cycle delayed
s_d <= s;
-- detect s transition from 0 to 1 == rising edge
if s = '1' and s_d = '0' then
-- Code dependent on rising edge s
end if;
end if;
end process;
NOTE: s may be an internal signal and is not needed to come from entity. If s is a strobe (1 clock cycle long generated with the same clock) s_d is not needed as there is no need to detect the edge, just the signal state.
Related
I'm trying to implement an alarm module for the digital clock in VHDL. I have written architecture for it, but when I run Compilation I get too many Adaptive Logic Modules (around 2000), which I think is too much. I will post my code below.
I think division and modulus operation could be causing it, in this line of code.
alarm_hour1 <= std_logic_vector(to_unsigned(savedHours/10,alarm_hour1'length));
alarm_hour0 <= std_logic_vector(to_unsigned(savedHours mod 10,alarm_hour0'length));
alarm_minute1 <= std_logic_vector(to_unsigned(savedMinutes/10,alarm_minute1'length));
alarm_minute0 <= std_logic_vector(to_unsigned(savedMinutes mod 10,alarm_minute0'length));
Still, I'm not sure how can I work around this.
Also, I would be very grateful if You give more comments on my design, and point out some mistakes, and ways how I can improve my design. I'm fairly new to VHDL so any advice is appreciated.
Thanks a lot.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity alarm is
port(
--INPUTS
reset : in std_logic;
clock : in std_logic;
alarm_enable : in std_logic;
alarm_set : in std_logic;
alarm_increment : in std_logic;
alarm_decrement : in std_logic;
currentTime_hour1 : in std_logic_vector(3 downto 0);
currentTime_hour0 : in std_logic_vector(3 downto 0);
currentTime_minute1 : in std_logic_vector(3 downto 0);
currentTime_minute0 : in std_logic_vector(3 downto 0);
--OUTPUTS
alarm_buzzer : out std_logic;
alarm_hour1 : buffer std_logic_vector(3 downto 0) := "0000";
alarm_hour0 : buffer std_logic_vector(3 downto 0) := "0000";
alarm_minute1 : buffer std_logic_vector(3 downto 0) := "0000";
alarm_minute0 : buffer std_logic_vector(3 downto 0) := "0000"
);
end alarm;
architecture alarmBehaviour of alarm is
--ALARM TIME
signal savedHours : integer := 0;
signal savedMinutes : integer := 0;
signal incrementDecrementbuttonDetect : std_logic;
signal set_lastButtonState : std_logic := '0';
signal setButtonDetect : std_logic := '0';
--STATE MACHINE
type state_type is (idle, setHour, setMinute);
signal state_reg, state_next : state_type;
begin
incrementDecrementbuttonDetect <= alarm_increment or alarm_decrement;
--STATE REGISTER
process(clock, reset)
begin
if (reset = '1') then
state_reg <= idle;
elsif rising_edge(clock) then
state_reg <= state_next;
end if;
end process;
--SET BUTTON PRESSED
process(clock)
begin
if(rising_edge(clock)) then
if(alarm_set = '1' and set_lastButtonState = '0') then
setButtonDetect <= '1';
else
setButtonDetect <= '0';
end if;
set_lastButtonState <= alarm_set;
end if;
end process;
--NEXT STATE
process(state_reg, setButtonDetect)
begin
case state_reg is
when idle =>
if setButtonDetect = '1' then
state_next <= setHour;
else
state_next <= idle;
end if;
when setHour =>
if setButtonDetect = '1' then
state_next <= setMinute;
else
state_next <= setHour;
end if;
when setMinute =>
if setButtonDetect = '1' then
state_next <= idle;
else
state_next <= setMinute;
end if;
end case;
end process;
process (incrementDecrementbuttonDetect, state_reg)
begin
if rising_edge(incrementDecrementbuttonDetect) then
case state_reg is
when idle =>
when setHour =>
if alarm_increment = '1' then
if savedHours = 23 then
savedHours <= 0;
else
savedHours <= savedHours + 1;
end if;
else null;
end if;
if alarm_decrement = '1' then
if savedHours = 0 then
savedHours <= 23;
else
savedHours <= savedHours - 1;
end if;
else null;
end if;
when setMinute =>
if alarm_increment = '1' then
if savedMinutes = 59 then
savedMinutes <= 0;
else
savedMinutes <= savedMinutes + 1;
end if;
else null;
end if;
if alarm_decrement = '1' then
if savedMinutes = 0 then
savedMinutes <= 59;
else
savedMinutes <= savedMinutes - 1;
end if;
else null;
end if;
end case;
end if;
end process;
alarm_hour1 <= std_logic_vector(to_unsigned(savedHours/10,alarm_hour1'length));
alarm_hour0 <= std_logic_vector(to_unsigned(savedHours mod 10,alarm_hour0'length));
alarm_minute1 <= std_logic_vector(to_unsigned(savedMinutes/10,alarm_minute1'length));
alarm_minute0 <= std_logic_vector(to_unsigned(savedMinutes mod 10,alarm_minute0'length));
--ALARM BUZZER CONDITION
process (currentTime_hour1, currentTime_hour0, currentTime_minute1, currentTime_minute0,
alarm_enable, alarm_hour1, alarm_hour0, alarm_minute1, alarm_minute0)
begin
if((alarm_hour1 = currentTime_hour1) and (alarm_hour0 = currentTime_hour0)
and (alarm_minute1 = currentTime_minute1) and (alarm_minute0 = currentTime_minute0) and alarm_enable = '1') then
alarm_buzzer <= '1';
else
alarm_buzzer <= '0';
end if;
end process;
end alarmBehaviour;
Consider keeping the alarm time in Binary-Coded Decimal (BCD) format instead of binary format, whereby you can compare it directly with the current time, that is provided in BCD format.
This is a good example of how using the appropriate internal data format can reduce the computational problem significantly, since you can simply eliminate the costly division and modulo operations by keeping just one data format (BCD) instead of mixing BCD and binary data formats.
The range of signals savedHours and savedMinutes is not specified, so Quartus assumes they are 32 bits wide. Inference of a divider with one 32-bit operand results into a large tree of conditional subtractions.
Updating your code to something like
--ALARM TIME
signal savedHours : natural range 0 to 23 := 0;
signal savedMinutes : natural range 0 to 59 := 0;
will very likely result into less ALM usage.
Also, please note that rising_edge should be used for clock signals only (at VHDL starter level). Instead of connecting logic to the clock input of a register, what you probably want is some button debounce logic.
I'm working on a stopwatch project in VHDL but I don't know how to make the CLK square waveform of the counter? Please help.
Here is my code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_unsigned.ALL;
entity Circuit is
Port ( CLK : in STD_LOGIC := '0';
CLR : in STD_LOGIC;
Q : out STD_LOGIC_VECTOR (5 downto 0));
end Circuit;
architecture Behavioral of Circuit is
signal s: STD_LOGIC_VECTOR := "000000";
begin
process (CLK, CLR)
begin
if rising_edge(CLK) then
if CLR = '1' OR s = "111011" then
s <= "000000";
else
s <= s+1;
end if;
end if;
end process;
Q <= s;
end Behavioral;
Let's say your clock is 1 MHz, but you want the seconds counter process to work at 1 Hz. You would need to divide the incoming clock by 1 million.
constant CLOCK_DIVIDER : integer := 1000000;
signal clock_divide_counter : integer range 0 to CLOCK_DIVIDER-1 := 0;
signal one_hz_pulse : std_logic := '0';
...
process (clk)
begin
if (rising_edge(clk)) then
if (clock_divide_counter = CLOCK_DIVIDER - 1) then
clock_divide_counter <= 0;
one_hz_pulse <= '1';
else
clock_divide_counter <= clock_divide_counter + 1;
one_hz_pulse <= '0';
end if;
end if;
end process;
then modify your existing process to only be enabled when the 1 Hz pulse is high:
process (CLK, CLR)
begin
if rising_edge(CLK) then
if (CLR = '1') then
s <= "000000";
elsif (one_hz_pulse = '1') then
if s = "111011" then
s <= "000000";
else
s <= s+1;
end if;
end if;
end if;
end process;
I haven't run the code, but you should get the idea.
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.
NOTE: D and filtered_right should be connected in the picture.
Hello guys, I am having a difficulty with creating a circuit as one on the picture. The idea is that there is a rotary knot and with every rotation to the right some counter would increment and every rotation to the left it will decrement. When reached some value, I want some LEDs to glow. The principle on which it works is as following: if the left signal activates first, than it is rotation to right, otherwise a rotation to left. But when filtered, the logic is as it is in the code. If there is a rising edge (if the Q and D differ on the D Flip Flop), and the D is a '1', but meanwhile the other signal is '1' then it is a rotation to right, otherwise, a rotaton to left.
I am using a Spartan 3AN-Starter Kit FPGA. I described the filter and DFF in two separate entities and used them as components in my main project, but the warnings continually signal that they remain unconnected no matter what I do, even though it successfully synthesize. I would like to know why is that.
Here is a drawing of the circuit, my VHDL code and the warnings:
This is the main project:
--Main project
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use WORK.all;
entity Demux is
port ( led : OUT std_logic_vector(7 downto 0);
turn_right, turn_left,clk: IN std_logic);
subtype smallint is integer range 0 to 80;
end Demux;
architecture Behavioral of Demux is
component dff
port (set,reset,D,clk: IN std_logic;
Q: OUT std_logic);
end component;
component filter
port (clk,turn_right,turn_left: in std_logic;
filtered_right, filtered_left: out std_logic);
end component;
signal counter: smallint:=0;
signal Q: std_logic;
signal filtered_right: std_logic :='0';
signal filtered_left: std_logic := '0';
signal set: std_logic;
signal reset: std_logic;
begin
set <= '0';
reset <='0';
FF: dff port map (
set=>set,
reset=>reset,
D=>filtered_right,
clk=>clk,
Q=>Q);
filt: filter port map (
turn_right=>turn_right,
turn_left=>turn_left,
filtered_right=>filtered_right,
filtered_left=>filtered_left,
clk=>clk);
compare: process (clk,Q) is
begin
if ((clk'event) and (clk='1')) then
if ((filtered_right /= Q) and (filtered_right='1')) then
if (filtered_left = '1') then
counter <= counter + 1;
elsif (filtered_left = '0') then
counter <= counter - 1;
end if;
end if;
if (counter>80) or (counter<0) then
counter <=0;
end if;
end if;
end process compare;
led(0) <= '1' when counter = 10;
led(1) <= '1' when counter = 20;
led(2) <= '1' when counter = 30;
led(3) <= '1' when counter = 40;
led(4) <= '1' when counter = 50;
led(5) <= '1' when counter = 60;
led(6) <= '1' when counter = 70;
led(7) <= '1' when counter = 80;
end Behavioral;
Here is my realization of the DFF:
Library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
Entity dff is
port (D,set,reset,clk: in std_logic;
Q: out std_logic);
end dff;
Architecture behavioral of dff is
begin
dff: process (clk,set,reset,D) is
begin
if ((clk'event) and (clk='1')) then
if (reset='1') then
Q<='0';
elsif (set='1') then
Q<='1';
else
Q<=D;
end if;
end if;
end process dff;
end behavioral;
Here is my realization of the filter:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity filter is
port (clk,turn_right,turn_left: in std_logic;
filtered_right, filtered_left: out std_logic);
end filter;
architecture Behavioral of filter is
begin
filter: process(clk, turn_right,turn_left) is
variable rotary_conc: std_logic_vector(1 downto 0);
variable filtered_left_temp, filtered_right_temp: std_logic;
begin
if ((clk'event) and (clk='1')) then
rotary_conc:=turn_left & turn_right;
case rotary_conc is
when "00" => filtered_right_temp := '0';
filtered_left_temp := filtered_left_temp;
when "01" => filtered_right_temp := filtered_right_temp;
filtered_left_temp := '0';
when "10" => filtered_right_temp := filtered_right_temp;
filtered_left_temp :='1';
when "11" => filtered_right_temp := '1';
filtered_left_temp := filtered_left_temp;
when OTHERS => filtered_right_temp := filtered_right_temp;
filtered_left_temp := filtered_left_temp;
end case;
filtered_right<=filtered_right_temp;
filtered_left<=filtered_left_temp;
end if;
end process filter;
end Behavioral;
Just so you know, the filter exists because there is a chatter because of the mechanic nature of the rotary knot. That chatter can produce false incrementation/decrementation. To avoid it - I filter it.
Warnings:
WARNING:Xst:1290 - Hierarchical block <FF> is unconnected in block <Demux>.
It will be removed from the design.
WARNING:Xst:1290 - Hierarchical block <filt> is unconnected in block <Demux>.
It will be removed from the design.
WARNING:Xst:2677 - Node <FF/Q> of sequential type is unconnected in block <Demux>.
WARNING:Xst:2677 - Node <filt/filtered_right_temp> of sequential type is unconnected in block <Demux>.
WARNING:Xst:2677 - Node <filt/filtered_left_temp> of sequential type is unconnected in block <Demux>.
Try adding some else clauses to your when clauses in your Demux.vhd.
led(0) <= '1' when counter = 10 else '0';
led(1) <= '1' when counter = 20 else '0';
led(2) <= '1' when counter = 30 else '0';
led(3) <= '1' when counter = 40 else '0';
led(4) <= '1' when counter = 50 else '0';
led(5) <= '1' when counter = 60 else '0';
led(6) <= '1' when counter = 70 else '0';
led(7) <= '1' when counter = 80 else '0';
Without these else clauses, the synthesizer may consider led to always be "11111111" and thus not depending on the inputs.
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;