ADC to RAM signal reconstruction (after send it to VGA) - vhdl

I should reconstruct a wave from the ADC into the RAM and later send it to the VGA.
I wrote this module, but when I synthesize, vivado produces an error:[Synth 8-3380] loop condition does not converge after 2000 iterations.
The error refers to the while loop, but i don't understand the reason. Unfortunately, if I can't synthezise the module i don't understand if it works well.
This is the module:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
--use ieee.std_logic_arith.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 leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity Data_Elab is
Generic (
C: integer := 640; -- Colonne 640
R: integer := 480 -- Righe 480
);
Port (
--clk: in std_logic;
DRP_Data: in std_logic_vector(15 downto 0);
DRP_Ready: in std_logic;
RAM_addr: out std_logic_vector(17 downto 0);
RAM_Data: out std_logic;
RAM_en: out std_logic
);
end Data_Elab;
architecture Behavioral of Data_Elab is
signal data_reg: integer range 0 to 2**16;
--signal flag: std_logic;
begin
process(DRP_Ready, DRP_Data)
begin
if(DRP_Ready'event and DRP_Ready = '1') then
data_reg <= to_integer(unsigned(DRP_Data));
end if;
end process;
process(data_reg)
variable Cont_W: integer range 0 to C-1 := 0; -- contatore per spostamento tra colonne
variable Cont_i: integer range 0 to C := 1; -- contatore colonne
variable Cont_x: integer range 0 to R := 1; -- contaore per spostamento tra righe
variable Cont_R: integer range 0 to R := 0; -- contatore righe
begin
if(Cont_i <= C) then
if( data_reg <= (2**16/R)*Cont_x ) then
RAM_addr <= std_logic_vector(to_unsigned( (C*(R-Cont_x))+Cont_W, RAM_addr'length));
RAM_en<= '1';
RAM_Data <= '1'; -- pixel corrispondente alla forma d'onda (bianchi)
Cont_W := Cont_W+1;
Cont_i := Cont_i+1;
--Cont_R := Cont_R+1;
--Cont_x := 1;
while Cont_R < R loop
RAM_addr <= std_logic_vector(to_unsigned( (C*(R-Cont_x))+Cont_W, RAM_addr'length));
RAM_en<= '1';
RAM_Data <= '0'; -- pixel neri
Cont_R := Cont_R+1;
Cont_x:= Cont_x+1;
end loop;
Cont_R := 0;
else
RAM_addr <= std_logic_vector(to_unsigned( (C*(R-Cont_x))+Cont_W, RAM_addr'length));
RAM_en<= '1';
RAM_Data <= '0'; -- pixel neri
Cont_R := Cont_R+1;
Cont_x:= Cont_x+1;
end if;
else
RAM_en<= '0';
Cont_W := 0;
Cont_i := 1;
Cont_x := 1;
Cont_R := 0;
end if;
end process;
end Behavioral;
The module tries to write the full image from 640*480 pixel in the RAM block, in this way i can read later the values stored in the RAM and send them tothe VGA module.
Thank you.

I guess the synthesizer is not smart enough to know how many times the while loop would run, because it changes in every loop. I would recommend using a for loop instead.
for Cont_R in 0 to R-1 loop
RAM_addr <= std_logic_vector(to_unsigned( (C*(R-Cont_x))+Cont_W, RAM_addr'length));
RAM_en<= '1';
RAM_Data <= '0'; -- pixel neri
Cont_x:= Cont_x+1;
end loop;

Related

PWM controlled LED using VHDL

I've written the following VHDL code and test-bench to control the brightness of LEDs. Then tried with Altera ModelSim to simulate the code. However, I'm facing some technical difficulties. It would be really nice if someone will compile the code and share me the simulated result with me. Thanks in advance.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.all;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity main_testbench is
end main_testbench;
architecture behavior of main_testbench is
component led_controller is
Port ( clk, reset: in std_logic; -- system clock is assumed 10KHz
in_word: in std_logic_vector(7 downto 0); -- LS 4 bits - frequency & MS 4 bits - duty-cycle
LEDs: out std_logic_vector(3 downto 0));
end component;
signal clk, reset: std_logic := '0';
signal in_word: std_logic_vector(7 downto 0) := "00010001"; -- 0.2 Hz, 10% duty cycle
signal LEDs: std_logic_vector(3 downto 0) := "0000";
type in_word_commands is array (0 to 15) of std_logic_vector(7 downto 0);
signal in_words: in_word_commands := ("00010001", "00010010", "00010100", "00011000", -- 10% duty cycle with 0.2Hz, 0.5Hz, 1Hz, 2Hz
"00100001", "00100010", "00100100", "00101000", -- 30% duty cycle with 0.2Hz, 0.5Hz, 1Hz, 2Hz
"01000001", "01000010", "01000100", "01001000", -- 60% duty cycle with 0.2Hz, 0.5Hz, 1Hz, 2Hz
"10000001", "10000010", "10000100", "10001000"); -- 85% duty cycle with 0.2Hz, 0.5Hz, 1Hz, 2Hz
signal command_num : integer := 0;
begin
dut: led_controller port map (clk, reset, in_word, LEDs);
clk <= not clk after 50 us; -- 0.1ms/2 = 50us
command_num <= command_num + 1 after 5000 ms; -- 5000ms = 5s
in_word <= in_words(command_num);
end behavior;
controller:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.all;
entity led_controller is
Port ( clk, reset: in std_logic;
in_word: in std_logic_vector(7 downto 0);
LEDs: out std_logic_vector(3 downto 0));
end led_controller;
architecture behavior of led_controller is
--------------------- signals ---------------------
type freq is array (0 to 3) of integer range 0 to 50000;
signal frq: freq := (25000, 10000, 5000, 2500);
signal led_freq_count: integer range 0 to 50000 := frq(0);
type d is array (0 to 3) of integer range 0 to 100;
signal duty: d := (10, 30, 60, 85);
signal duty_cycle: integer range 0 to 100 := duty(0);
signal LED_switch, new_command: std_logic := '0';
begin
--------- clock process / sync reset configuration ---------------
process (clk)
variable duty_counter: integer range 0 to 100 := 100;
variable freq_counter: integer range 0 to 50000 := led_freq_count;
begin
if rising_edge(clk) then
------- if reset was high or new in_word were arrived --------
if reset = '1' or new_command = '1' then
LEDs <= "0000";
duty_counter := 100;
freq_counter := led_freq_count;
new_command <= '0';
else
------- blinking process --------
if freq_counter = 0 then
freq_counter := led_freq_count;
LED_switch <= not LED_switch;
end if;
freq_counter := freq_counter - 1;
if duty_counter = 0 then
duty_counter := 100;
end if;
duty_counter := duty_counter - 1;
------ output assignment -------
if LED_switch = '1' and duty_counter < duty_cycle then
LEDs <= "1111";
else
LEDs <= "0000";
end if;
end if;
end if;
end process;
--------- input process---------------
process (in_word)
begin
case in_word(3 downto 0) is
when "0001" => led_freq_count <= frq(0);
when "0010" => led_freq_count <= frq(1);
when "0100" => led_freq_count <= frq(2);
when "1000" => led_freq_count <= frq(3);
when others => led_freq_count <= frq(0);
end case;
case in_word(7 downto 4) is
when "0001" => duty_cycle <= duty(0);
when "0010" => duty_cycle <= duty(1);
when "0100" => duty_cycle <= duty(2);
when "1000" => duty_cycle <= duty(3);
when others => duty_cycle <= duty(0);
end case;
new_command <= '1';
end process;
end behavior;
if freq_counter = 0 then
freq_counter := led_freq_count;
LED_switch <= not LED_switch;
else
freq_counter := freq_counter - 1;
end if;
if duty_counter = 0 then
duty_counter := 100;
else
duty_counter := duty_counter - 1;
end if;

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

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

Implementing a VHDL binary search on a std_logic_vector [vhdl]

I'm attempting to create synthesizable VHDL (function or procedure) for an ASIC (it must be part of the ASIC) that will look for the first '1' in a standard_logic_vector and output which vector position that '1' was in. For example, I have an 8-bit slv of "10001000" (a '1' in position 3 and 7). If I use this slv, the output should be 4 (the output is 1 based).
The actual VHDL will be searching a large slv, up to 512 bits in length. I tried implementing a binary search function but I get synthesis errors that states "Could not synthesize non-constant range values. [CDFG-231] [elaborate]
The non-constant range values are in file '...' on line 61" I indicated in the code below where it complains. I'm not sure how to implement a binary search algorithm without having non-constant range values. How would I modify this code so it's synthesizable?
I have attempted to search for binary search algorithms for HDL for potential code to look at and for my error, but I didn't find anything.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_misc.all;
entity bin_search is
generic (
constant NREGS : positive := 16 -- number of registers
);
port (
clk_i : in std_logic; -- clock
bin_i : in unsigned( NREGS-1 downto 0 ); -- input
en_i : in std_logic; -- input enable
addr_o : out natural range 0 to NREGS -- first binary location
);
end bin_search;
architecture rtl of bin_search is
function f_bin_search( input: unsigned; nob: positive ) return natural is
constant nbits : positive := 2**nob;
variable lower : natural range 0 to 1 := 0;
variable upper : natural range 0 to 1 := 0;
variable idx : natural range 0 to nob := 4;
variable cnt : natural range 0 to nbits := 0;
variable mid : positive range 1 to nbits := nbits/2; --
variable ll : natural range 0 to nbits := 0;
variable ul : positive range 1 to nbits := nbits; --
begin
if input = 0 then
cnt := 0;
return cnt;
else
loop1: while ( idx > 0 ) loop
if ( input( mid-1 downto ll ) > 0 ) then -- <===WHERE SYNTH COMPLAINS
lower := 1;
else
lower := 0;
end if;
if ( input( ul-1 downto mid ) > 0 ) then
upper := 1;
else
upper := 0;
end if;
if ( idx = 1 ) then
if ( lower = 1 ) then
cnt := mid;
else
cnt := ul;
end if;
elsif ( lower = 1 ) then
ul := mid;
mid := ( ( ll+ul )/2 );
elsif ( upper = 1 ) then
ll := mid;
mid := ( ll+ul )/2;
else
cnt := 0;
exit loop1;
end if;
idx := idx-1;
end loop loop1;
return cnt;
end if;
end f_bin_search;
begin
test_proc: process ( clk_i )
begin
if rising_edge( clk_i ) then
if en_i = '1' then
addr_o <= f_bin_search( bin_i, 4 );
end if;
end if;
end process test_proc;
end rtl;
Here's a simple test bench where the input is inc'd by '1'. The addr_o should be the location (1 based) of the input lsb with a '1'.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_misc.all;
use ieee.numeric_std.all;
entity bin_search_tb is
end bin_search_tb;
architecture behavior of bin_search_tb is
constant NREGS : positive := 16;
signal clk : std_logic;
signal input : unsigned( NREGS-1 downto 0 );
signal start : std_logic;
signal addr : natural range 0 to NREGS;
constant clk_per : time := 1 ns;
signal row : natural range 0 to 2**NREGS-1;
begin
bin_search_inst: entity work.bin_search( rtl )
generic map (
NREGS => NREGS
)
port map (
clk_i => clk, -- master clock
bin_i => input, -- captured events
en_i => start, -- start binary search
addr_o => addr -- addr where the first '1' appears
);
-- master clock process
clk_proc: process
begin
clk <= '0';
wait for clk_per / 2;
clk <= '1';
wait for clk_per / 2;
end process clk_proc;
--
stim1_proc: process
begin
input <= ( others => '0' );
start <= '0';
row <= 1;
wait until clk'event and clk = '1';
loop
wait until clk'event and clk = '1';
input <= to_unsigned( row, input'length );
start <= '1';
wait until clk'event and clk = '1';
start <= '0';
wait for 4*clk_per;
row <= row+1;
end loop;
end process stim1_proc;
end architecture behavior;
Thanks for your assistance!
-Jason
Edited code and added a testbench
Your design will most certainly depend on latency and other performance requirements, but, you could use some combination of or-reduction, sequencers (for mux selection of sliced vectors), shift register, and counters. I drew up a simple circuit that should find your lsb instance of "1" in ~30 clock cycles
The RTL translation that implements this design should be straight forward.
You say that you are thinking in hardware, but in fact you're not. Or you are misleading yourself.
input( mid-1 downto ll ) > 0
is not an OR-reduction, but a comparison operation. You must know > is the larger than comparison operator. The synthesis will therefor infer a comparator. But how many inputs must that comparator have, I ask? Well, there's your problem: it depends on the value of mid, which:
initially depends on the value of nbits, which depends on the value of nob which is a variable input for the function.
is changed within the loop. Thus it's value is not constant.
A hardware component cannot have a variable amount of wires.
But why do you want binary search? Why not keep-it-simple?
library ieee;
use ieee.std_logic_1164.all;
entity detect_one is
generic(
input_size : positive := 512);
port(
input : in std_logic_vector (input_size-1 downto 0);
output : out natural range 0 to input_size);
end entity;
architecture rtl of detect_one is
begin
main: process(input)
begin
output <= 0;
for i in input_size-1 downto 0 loop
if input(i)='1' then
output <= i+1;
end if;
end loop;
end process;
end architecture;
entity detect_one_tb is end entity;
library ieee;
architecture behavior of detect_one_tb is
constant input_size : positive := 512;
use ieee.std_logic_1164.all;
signal input : std_logic_vector (input_size-1 downto 0) := (others => '0');
signal output : integer;
begin
DUT : entity work.detect_one
generic map ( input_size => input_size )
port map(
input => input,
output => output);
test: process begin
wait for 1 ns;
assert (output = 0) report "initial test failure" severity warning;
for i in 0 to input_size-1 loop
input <= (others => '0');
input(i) <= '1';
wait for 1 ns;
assert (output = i+1) report "single ones test failure" severity warning;
end loop;
input <= (others => '1');
wait for 1 ns;
assert (output = 1) report "initial multiple ones test failure" severity warning;
for i in 0 to input_size-2 loop
input(i) <= '0';
wait for 1 ns;
assert (output = i+2) report "multiple ones test failure" severity warning;
end loop;
wait;
end process;
end architecture;

Self implemented UART in VHDL always skips second character

I am learning VHDL right now and I tried to implement UART (1 start bit, 8 data bits, 1 stop bit) to periodically send a hardcoded string.
Everything works as expected - I receive string every 1 second. However, there is no second character.
No matter how long the string is, which character it is. I checked this fact on a oscilloscope and there is no waveform for this particular character. 1 start bit, 8 bits for first character, stop bit, start bit and 8 bits for third character, not the second one.
Following code is for 10 MHz clock divided to send with ~38 400 bits per second, I also tried with 9600 bits per second, both the same problem.
I'm using Altera MAX10 dev board: http://maximator-fpga.org/
Short video how it works:
https://gfycat.com/JoyousIlliterateGuillemot
UART.vhd:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
use ieee.numeric_std.ALL;
use ieee.std_logic_arith.all;
entity UART is
port (
clk_10mhz: in STD_LOGIC;
txPin: out STD_LOGIC
);
end entity;
architecture Test of UART is
signal txStart: STD_LOGIC;
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
);
end component TX;
begin
process (clk_10mhz, txIdle)
variable clkDividerCounter : integer range 0 to 10000000;
variable textToSend : string(1 to 31) := "Hello darkness my old friend!" & CR & LF;
variable currentCharacterIndex : integer range 0 to 31;
begin
if (rising_edge(clk_10mhz)) then
if (clkDividerCounter < 10000000) then
clkDividerCounter := clkDividerCounter + 1;
else
clkDividerCounter := 0;
currentCharacterIndex := 1;
end if;
if (txIdle = '1' and currentCharacterIndex > 0) then
txData <= CONV_STD_LOGIC_VECTOR(character'pos(textToSend(currentCharacterIndex)),8);
txStart <= '1';
if (currentCharacterIndex < 31) then
currentCharacterIndex := currentCharacterIndex + 1;
else
currentCharacterIndex := 0;
txStart <= '0';
end if;
end if;
end if;
end process;
u1: TX port map (clk_10mhz, txStart, txData, txPin, txIdle);
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;
txIdle: out STD_LOGIC
);
end entity;
architecture Test of TX is
signal idle: STD_LOGIC;
begin
process (clk_in)
variable bitIndex : integer range 0 to 9;
variable clkDividerCounter : integer range 0 to 260;
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 < 260) then
clkDividerCounter := clkDividerCounter + 1;
else
if (dataFrameCurrentIndex <= 9) then
tx <= dataFrame(dataFrameCurrentIndex);
dataFrameCurrentIndex := dataFrameCurrentIndex + 1;
else
idle <= '1';
end if;
clkDividerCounter := 0;
end if;
end if;
txIdle <= idle;
end if;
end process;
end Test;
Move the line
txIdle <= idle;
from TX.vhd outside the process. Signals take their new value after the process ends.
For example:
idle <= '0';
txIdle <= idle;
Will set txIdle to '1' if idle was '1' when the two statements were executed inside a process. You should notice that this means that txIdle will be '1' for two consecutive cycles and causes currentCharacterIndex to increment twice at the start.
Note that contrary to signals, variable take their new value when the assigning statement is encountered, and not at the end of the process as signals do.
While your code is not that terrible for a beginner, I recommend to use only signal when you start learning VHDL. It is much easier to make mistake with variables, or describe sub-optimal or broken implementation.
Also, as Brian mentioned, don't use std_logic_arith, especially when using numeric_std. They are conflicting with each other (some tools deal with it though) and std_logic_arith is not a IEEE standard, while numeric_std is.
Finally, simulation is a crucial part of hardware design. To avoid uninitialized pin, add a reset to your circuit, which is generally a good idea.

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?

Resources