How to resolve "Register/latch pins with no clock driven by root clock pin" error in Vivado? - vhdl

As a learning exercise I am doing some HDMI experiments on an FPGA using VHDL. When coming to implement it in Vivado (2017.1) I am encountering the following warning in the timing report:
There are 11 register/latch pins with no clock driven by root clock pin: Hsync_i_reg/Q (HIGH)
I have opened the implemented schematic and looked for the pin in question. It seems to be connected to the same clock that everything else is connected to (and those are not flagged in the timing report), so I am confused as to what the errors above are referring to. Here are some shots from the schematics:
Here is the VHDL code of the offending design:
library ieee;
use ieee.std_logic_1164.all;
entity ctrl_gen is
generic (
ha: integer := 96; --hpulse
hb: integer := 144; --hpulse+hbp
hc: integer := 784; --hpulse+hbp+hactive
hd: integer := 800; --hpulse+hbp+hactive+hfp
va: integer := 2; --vpulse
vb: integer := 35; --vpulse+vbp
vc: integer := 515; --vpulse+vbp+vactive
vd: integer := 525 --vpulse+vbp+vactive+vfp
);
port (
clk25: in std_logic; --tmds clock (25mhz)
hsync: out std_logic; --horizontal sync
vsync: out std_logic; --vertical sync
hactive: out std_logic; --active portion of hsync
vactive: out std_logic; --active portion of vsync
dena: out std_logic --display enable
);
end entity;
architecture behavioral of ctrl_gen is
signal hsync_i, hactive_i, vactive_i, vsync_i : std_logic;
begin
-- horizontal signals generation
hproc : process (clk25)
variable hcount: integer range 0 to hd := 0;
begin
if rising_edge(clk25) then
hcount := hcount + 1;
if (hcount=ha) then
hsync_i <= '1';
elsif (hcount=hb) then
hactive_i <= '1';
elsif (hcount=hc) then
hactive_i <= '0';
elsif (hcount=hd) then
hsync_i <= '0';
hcount := 0;
end if;
end if;
end process;
-- vertical signals generation
vproc : process (hsync_i)
variable vcount: integer range 0 to vd := 0;
begin
if falling_edge(hsync_i) then
vcount := vcount + 1;
if (vcount=va) then
vsync_i <= '1';
elsif (vcount=vb) then
vactive_i <= '1';
elsif (vcount=vc) then
vactive_i <= '0';
elsif (vcount=vd) then
vsync_i <= '0';
vcount := 0;
end if;
end if;
end process;
dena <= hactive_i and vactive_i;
hsync <= hsync_i;
vactive <= vactive_i;
hactive <= hactive_i;
end behavioral;
On reflection, I think that the warning is telling me that Hsync_i_reg/Q is the clock used for the Vcount registers, not that Hsync_i_reg itself if not connected to the root clock pin?
Is the method I have used bad practice and unlikely to work? The overall design is not working and I'm trying to understand whether this is the cause.
Thanks.

I see potential design issues. First being the use of variable for objects that are actually clocked signals. Secondly, you're using a generated signal as a clock input. That's also not nice.
I would modify your code to the following (not tested if it completely does what your code did before)
library ieee;
use ieee.std_logic_1164.all;
entity ctrl_gen is
generic (
ha: integer := 96; --hpulse
hb: integer := 144; --hpulse+hbp
hc: integer := 784; --hpulse+hbp+hactive
hd: integer := 800; --hpulse+hbp+hactive+hfp
va: integer := 2; --vpulse
vb: integer := 35; --vpulse+vbp
vc: integer := 515; --vpulse+vbp+vactive
vd: integer := 525 --vpulse+vbp+vactive+vfp
);
port (
clk25: in std_logic; --tmds clock (25mhz)
hsync: out std_logic; --horizontal sync
vsync: out std_logic; --vertical sync
hactive: out std_logic; --active portion of hsync
vactive: out std_logic; --active portion of vsync
dena: out std_logic --display enable
);
end entity;
architecture behavioral of ctrl_gen is
signal hsync_i, hactive_i, vactive_i, vsync_i : std_logic;
signal hcount: integer range 0 to hd-1 := 0;
signal vcount: integer range 0 to vd-1 := 0;
begin
-- horizontal signals generation
hproc : process (clk25)
begin
if rising_edge(clk25) then
if hcount < hd-1 then
hcount <= hcount + 1;
else
hcount <= 0;
end if;
if (hcount=ha-1) then
hsync <= '1';
end if;
if (hcount=hb-1) then
hactive_i <= '1';
end if;
if (hcount=hc-1) then
hactive_i <= '0';
end if;
if (hcount=hd-1) then
hsync <= '0';
end if;
end if;
end process;
-- vertical signals generation
vproc : process (clk25)
begin
if rising_edge(clk25) then
if hcount = hd-1 then -- moment of falling_edge hsync.
if vcount < vd-1 then
vcount <= vcount + 1;
else
vcount <= 0;
end if;
if (vcount=va-1) then
vsync <= '1';
end if;
if (vcount=vb-1) then
vactive_i <= '1';
end if;
if (vcount=vc-1) then
vactive_i <= '0';
end if;
if (vcount=vd-1) then
vsync <= '0';
end if;
end if;
end if;
end process;
dena <= hactive_i and vactive_i;
vactive <= vactive_i;
hactive <= hactive_i;
end behavioral;

I think:
signal hcount: integer range 0 to hd-1 := 0;
signal vcount: integer range 0 to vd-1 := 0;
Is not a valid synthesis type for hcount, vcount: it should be std_logic_vector

Related

VHDL - Using output of one entitiy as input of another

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.

How can i reduce number of ALMs in my VHDL design?

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.

VHDL delayed monostable initialisation

Idea is to generate a delayed pulse when Trig input is activated, both delay and pulse width are adjustable respectively with 'delay' and 'ton'. I use an integer counter to compare delay then delay+ton to toggle the Pulse output.
The issue is that timing sequence starts just after board programming: sigPulseCounter is incremented ... even if signals are initialized. Any tips ?
Reset works well and Trig also but there is an unwanted pulse on startup.
Thanks for your feedback.
library ieee;
use ieee.std_logic_1164.all;
entity DelayedMonostable is
generic(
delay :integer:= 2*40000000;
ton :integer:= 2*40000000);
port (
Clk: in std_logic;
Reset: in std_logic;
Trig: in std_logic;
Pulse: out std_logic;
Debug: out std_logic);
end DelayedMonostable;
architecture Behavioral of DelayedMonostable is
-- Signal declaration
signal sigPulseCounterEnable: std_logic := '0';
signal sigPulseCounter : integer := 0;
signal sigPulse : std_logic :='0';
signal sigDebug: std_logic := '0';
begin
Debug <= not sigPulseCounterEnable;
Pulse <= not sigPulse;
Counter : process(Clk, Reset)
begin
if Reset='0' then
sigPulseCounter <= 0;
sigPulseCounterEnable <= '0';
sigPulse <= '0';
elsif Trig='0' then
sigPulseCounter <= 0;
sigPulseCounterEnable <= '1';
sigPulse <= '0';
elsif rising_edge(Clk) then
if(sigPulseCounterEnable='1') then
if(sigPulseCounter = delay) then
sigPulse <= '1';
end if;
if(sigPulseCounter = delay+ton) then
sigPulse <= '0';
sigPulseCounterEnable <= '0';
sigPulseCounter <= 0;
end if;
sigPulseCounter <= sigPulseCounter + 1;
end if;
end if;
end process Counter;
end Behavioral;
I have tried to invert the Trig logic in the process without success:
elsif Trig='0'
with
elsif Trig='1'
EDIT:
I have split in 3 parts the architecture, each assign value to a signal or port - Works good now.
library ieee;
use ieee.std_logic_1164.all;
entity DelayedMonostable is
generic(
delay : integer := 40000000/2;
ton : integer := 2*40000000);
port(
Clk: in std_logic;
Reset: in std_logic;
Trig: in std_logic;
Pulse: out std_logic;
Debug: out std_logic);
end DelayedMonostable;
---------------------------------------
architecture Behavioral of DelayedMonostable is
-- Signal declaration
signal PWMCounter : integer;
signal sigTrig: std_logic;
begin
Debug <= not sigTrig;
Counter : process(Clk, Reset)
begin
if (Reset='0') then
PWMCounter <= 0;
elsif(rising_edge(Clk) and sigTrig='1') then
if(PWMCounter = ton+delay) then
PWMCounter <= 0;
else
PWMCounter <= PWMCounter + 1;
end if;
end if;
end process Counter;
Trigger: process(Reset, Trig)
begin
if (Reset='0') then
sigTrig <= '0';
elsif (Trig='0') then
sigTrig <= '1';
elsif (PwmCounter = ton+delay) then
sigTrig <= '0';
end if;
end process Trigger;
Generator : process(Clk, Reset)
begin
if (Reset='0') then
Pulse <= not '0';
elsif(rising_edge(Clk)) then
if(PwmCounter=delay) then
Pulse <= not '1';
end if;
if(PwmCounter=delay+ton) then
Pulse <= not '0';
end if;
end if;
end process Generator;
end Behavioral;

Altera FPGA hardware (has an issue) vs ModelSim simulation (ok) - self implemented UART

I have an issue with self implemented UART in VHDL.
I wrote VHDL code which generates proper waveform when running on Altera ModelSim:
UART.vhd:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
use ieee.numeric_std.ALL;
entity UART is
port (
clk_10mhz: in STD_LOGIC;
uart_clk: out STD_LOGIC;
txPin: out STD_LOGIC
);
end entity;
architecture Test of UART is
signal txStart: STD_LOGIC := '0';
signal txIdle: STD_LOGIC;
signal txData: STD_LOGIC_VECTOR(7 downto 0);
component TX is
port (
clk_in: in STD_LOGIC;
start: in STD_LOGIC;
data: in STD_LOGIC_VECTOR(7 downto 0);
tx: out STD_LOGIC;
txIdle: out STD_LOGIC;
debug_clk: out STD_LOGIC
);
end component TX;
begin
process (clk_10mhz)
variable clkDividerCounter : integer range 0 to 10000000;
variable textToSend : string(1 to 31) := "Hello darkness my old friend!" & LF & CR;
variable currentCharacterIndex : integer range 1 to 31 := 1;
variable startSending : std_logic := '0';
variable characterReceivedByTX : std_logic := '1';
begin
if (rising_edge(clk_10mhz)) then
if (startSending = '1') then
if (txIdle = '0') then
characterReceivedByTX := '1';
end if;
if (txIdle = '1' and characterReceivedByTX = '1') then
txData <= std_logic_vector(to_unsigned(character'pos(textToSend(currentCharacterIndex)), 8));
txStart <= '1';
if (currentCharacterIndex < 31) then
currentCharacterIndex := currentCharacterIndex + 1;
characterReceivedByTX := '0';
else
txStart <= '0';
currentCharacterIndex := 1;
startSending := '0';
end if;
end if;
else
if (clkDividerCounter < 10000000) then
clkDividerCounter := clkDividerCounter + 1;
startSending := '0';
else
clkDividerCounter := 0;
startSending := '1';
end if;
end if;
end if;
end process;
u1: TX port map (clk_10mhz, txStart, txData, txPin, txIdle, uart_clk);
end Test;
TX.vhd:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
use ieee.numeric_std.ALL;
entity TX is
port (
clk_in: in STD_LOGIC;
start: in STD_LOGIC;
data: in STD_LOGIC_VECTOR(7 downto 0);
tx: out STD_LOGIC := '1';
txIdle: out STD_LOGIC := '1';
debug_clk: out STD_LOGIC := '0'
);
end entity;
architecture Test of TX is
signal idle: STD_LOGIC := '1';
begin
process (clk_in)
variable bitIndex : integer range 0 to 9;
variable clkDividerCounter : integer range 0 to 1042;
variable dataFrame : STD_LOGIC_VECTOR(9 downto 0);
variable dataFrameCurrentIndex : integer range 0 to 9;
begin
if (rising_edge(clk_in)) then
if (start = '1' and idle = '1') then
dataFrame(0) := '0';
dataFrame(8 downto 1) := data;
dataFrame(9) := '1';
dataFrameCurrentIndex := 0;
idle <= '0';
end if;
if (idle = '0') then
if (clkDividerCounter < 521) then
debug_clk <= '0';
else
debug_clk <= '1';
end if;
if (clkDividerCounter < 1041) then
clkDividerCounter := clkDividerCounter + 1;
else
if (dataFrameCurrentIndex < 9) then
tx <= dataFrame(dataFrameCurrentIndex);
dataFrameCurrentIndex := dataFrameCurrentIndex + 1;
else
tx <= dataFrame(dataFrameCurrentIndex);
idle <= '1';
end if;
clkDividerCounter := 0;
end if;
else
debug_clk <= '0';
end if;
end if;
end process;
txIdle <= idle;
end Test;
Unfortunately, on hardware, instead of "Hello darkness my old friend!" sent, it sends "HHello darkness my old friend!" with double H at the beginning.
I checked it on SignalTap II and waveform confirms the problem:
What can cause this problem? How may I debug such an issue?

Square Waveform Generation in VHDL

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.

Resources