How to correct a phase shift using a clock divider in VHDL? - vhdl

I want to make a UART receiver that reads 8 consecutives bits with a parity bit at the end and with a simple stop bit. My FPGA have a clock of 100Mhz and the data that are transmitted to the uart have a rate of 56700 bauds. The dividing factor is 1736 (56700 * 1736 ≈ 100Mhz). The two outputs are the message of the input decoded by the uart and an error signal that indicates if the uart have correctly read the input. This is what I have :
library ieee;
use ieee.std_logic_1164.ALL;
use ieee.numeric_std.all;
entity uart_receiver is
generic (
clksPerBit : integer := 1736 -- Needs to be set correctly
);
port (
clk : in std_logic;
clk_en_uart : in std_logic ;
reset : in std_logic;
uart_rx : in std_logic;
error : out std_logic;
char : out std_logic_vector(7 downto 0)
);
end uart_receiver;
architecture uart_receiver_arch of uart_receiver is
type etat is (init, start_bit, receiving_bits, parity_bit,
stop_bit );
signal current_state : etat := init ;
signal error_signal : std_logic := '0';
signal clk_count : integer range 0 to clksPerBit-1 := 0;
signal bit_index : integer range 0 to 7 := 0; -- 8 Bits Total
signal data_byte : std_logic_vector(7 downto 0) := (others => '0');
begin
process (clk_en_uart)
begin
if rising_edge(clk_en_uart) then
end if;
end process;
process (clk,reset)
variable check_parity : integer range 0 to 7 := 0;
begin
if (reset = '1') then
current_state <= init;
error_signal <= '0';
clk_count <= 0;
bit_index <= 0;
data_byte <= (others => '0');
elsif rising_edge(clk) then
case current_state is
when init =>
clk_count <= 0;
Bit_Index <= 0;
if uart_rx = '0' then -- Start bit detected
current_state <= start_bit;
else
current_state <= init;
end if;
when start_bit =>
if clk_count = (clksPerBit-1)/2 then
if uart_rx = '0' then
clk_count <= 0; -- reset counter since we found the middle
current_state <= receiving_bits;
else
current_state <= init;
end if;
else
clk_count <= clk_count + 1;
current_state <= start_bit;
end if;
when receiving_bits =>
if clk_count < clksPerBit-1 then
clk_count <= clk_count + 1;
current_state <= receiving_bits;
else
clk_count <= 0;
data_byte(bit_index) <= uart_rx;
if bit_index < 7 then
bit_index <= bit_index + 1;
current_state <= receiving_bits ;
else
bit_index <= 0;
current_state <= parity_bit;
end if;
end if;
when parity_bit =>
if clk_count < clksPerBit-1 then
clk_count <= clk_count + 1;
current_state <= parity_bit;
else
for k in 0 to 7 loop
if ( data_byte(k) = '1' ) then
check_parity := check_parity + 1 ;
end if;
end loop;
if((uart_rx = '1' and check_parity mod 2 = 0) or (uart_rx = '0' and check_parity mod 2 = 1)) then
error_signal <= '1' ;
else
error_signal <= '0';
end if ;
current_state <= stop_bit;
end if;
when stop_bit =>
if clk_count < clksPerBit-1 then
clk_count <= clk_count + 1;
current_state <= stop_bit ;
else
clk_count <= 0;
current_state <= init;
end if;
when others =>
current_state <= init;
end case;
end if;
char <= data_byte ;
error <= error_signal ;
end process;
end uart_receiver_arch;
So there's a phase shift between the data that is transmitted to the uart and his clock. If there's a phase shift, I'm not reading the data at the right time. I think that this code is sufficient to solve this problem. But, I've created a clock_divider and I can't seem to find a way to use it in this code. This is my clock divider :
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity clock_divider is
generic (divfactor : positive := 1736);
Port (clk,clk2, reset : in STD_LOGIC ;
clkdiv, activationsig : out STD_LOGIC );
end clock_divider;
architecture clock_divider_arch of clock_divider is
begin
process(clk,reset)
variable clksigv : std_logic := '0' ;
variable activationsigv : std_logic := '0' ;
variable count : integer := 0 ;
begin
if (reset = '1') then
clksigv := '0' ;
activationsigv := '0' ;
count := 0 ;
elsif ( rising_edge(clk) ) then
count := count + 2 ;
if (activationsigv = '1') then
activationsigv := '0';
end if;
if ( count >= divfactor - 1 ) then
clksigv := not(clksigv) ;
if ( clksigv = '1' ) then
activationsigv := '1' ;
end if;
count := 0 ;
end if ;
end if ;
clkdiv <= clksigv ;
activationsig <= activationsigv;
end process ;
end clock_divider_arch;
The outputs of this clock divider are the clock divided and the activation signal that, when it is at '1', I have to read the data in the uart. So, the two outputs should also be inputs of the uart. In the uart_recevier, clk_en_uart is actually the clock divided, but I'm not using it because I don't know how.
I think that the solution is to 'activate' this divided clock when I enter in the start_bit case so that I have two clocks with the same phase and the same frequency, but I also think that it impossible to set a phase for a clock.
I'm not sure that I've clearly adressed my problem. If there's something that you don't understand in my code or in my explanation, feel free to ask questions.
Thank you for your help, hoping that I find a solution.

Sounds like the suggested solution is complicated for this problem.
A usual approach is that the receiver justs look for the falling edge of the start bit, then count for half a bit time (1736 / 2 cycles in your case), then samples the start bit value there, and subsequently samples the data, parity and stop bit values after each full bit time (1736 cycles in your case). After that start over looking for a new falling edge of the start bit.
The difference between the transmitter and receiver frequencies are then (usually) so small that the sample time will be practically in the middle for messages of only 11 bits at relative low bitrate, and the counter restart at falling edge of start bit ensures that any effect of long time frequency difference is removed.

Related

Different Clock Domain VHDL

I'm making a custom hardware ARINC 429 Core.
For now I have described the module in transmission (TX-FSM), according to the ARINC 429 standard and a FIFO in transmission from which it takes the data and sends them to the outside.
The FIFO works at a frequency of 2MHz (clk2M), while TX-FSM can generate a frequency of 100kb / s or 12.5kb / s (clk429) from 2MHz as per standard.
Since the FIFO works at a higher frequency (2 MHz), and the TX-FSM works at a lower frequency (100 kb/s), when the TX-FSM requests a data from the FIFO by raising the "TX_FIFO_rd" signal ("rd_en" on FIFO ), the FIFO supplies all the data contained within it, since in the FIFO clock domain the "rd_en" signal remains high for several cycles.
The FIFO should only provide one data at a time. Once the data has been transmitted, the TX-FSM will request the next data.
How can I make the FIFO and TX-FSM work in sync using a single clock?
FIFO VHDL code:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity FIFO is
generic (
FIFO_WIDTH : natural := 32;
FIFO_DEPTH : integer := 10;
ALMOST_FULL_LEVEL : integer := 8;
ALMOST_EMPTY_LEVEL : integer := 2
);
port (
reset : in std_logic;
clk : in std_logic;
-- FIFO Write Interface
wr_en : in std_logic;
wr_data : in std_logic_vector(FIFO_WIDTH-1 downto 0);
ALMOST_FULL : out std_logic;
FULL : out std_logic;
-- FIFO Read Interface
rd_en : in std_logic;
rd_data : out std_logic_vector(FIFO_WIDTH-1 downto 0);
ALMOST_EMPTY : out std_logic;
EMPTY : out std_logic
);
end FIFO;
architecture rtl of FIFO is
type t_FIFO_DATA is array (0 to FIFO_DEPTH) of std_logic_vector(FIFO_WIDTH-1 downto 0);
signal r_FIFO_DATA : t_FIFO_DATA := (others => (others => '0'));
signal r_WR_INDEX : integer range 0 to FIFO_DEPTH -1 := 0;
signal r_RD_INDEX : integer range 0 to FIFO_DEPTH -1 := 0;
-- # Words in FIFO, has extra range to allow for assert conditions
signal r_FIFO_COUNT : integer range -1 to FIFO_DEPTH+1 := 0;
signal w_FULL : std_logic;
signal w_EMPTY : std_logic;
begin
-- FIFO process
-------------------------------------------------------------------
-------------------------------------------------------------------
WRITE_INDEX : process(clk)
begin
if rising_edge(clk) then
if reset = '1' then
r_WR_INDEX <= 1;
else
if (wr_en = '1' and w_FULL = '0') then
if r_WR_INDEX = FIFO_DEPTH-1 then
r_WR_INDEX <= 1;
else
r_WR_INDEX <= r_WR_INDEX + 1;
end if;
end if;
end if;
end if;
end process;
READ_INDEX : process(clk)
begin
if rising_edge(clk) then
if reset = '1' then
r_RD_INDEX <= 0;
else
if (rd_en = '1' and w_EMPTY = '0') then
if r_RD_INDEX = FIFO_DEPTH-1 then
r_RD_INDEX <= 0;
else
r_RD_INDEX <= r_RD_INDEX + 1;
end if;
end if;
end if;
end if;
end process;
COUNT_INDEX : process(clk)
begin
if rising_edge(clk) then
if reset = '1' then
r_FIFO_COUNT <= 0;
else
if (wr_en = '1' and rd_en = '0') then
r_FIFO_COUNT <= r_FIFO_COUNT + 1;
elsif (wr_en = '0' and rd_en = '1') then
if r_FIFO_COUNT > 0 then
r_FIFO_COUNT <= r_FIFO_COUNT - 1;
end if;
end if;
end if;
end if;
end process;
Write_Data : process (clk) is
begin
if rising_edge(clk) then
if wr_en = '1' then
r_FIFO_DATA(r_WR_INDEX) <= wr_data;
end if;
end if;
end process;
rd_data <= r_FIFO_DATA(r_RD_INDEX);
w_FULL <= '1' when r_FIFO_COUNT = FIFO_DEPTH else '0';
w_EMPTY <= '1' when r_FIFO_COUNT = 0 else '0';
ALMOST_FULL <= '1' when r_FIFO_COUNT > ALMOST_FULL_LEVEL else '0';
ALMOST_EMPTY <= '1' when r_FIFO_COUNT < ALMOST_EMPTY_LEVEL else '0';
FULL <= w_FULL;
EMPTY <= w_EMPTY;
end rtl;
TX-FSM code
-- Arinc 429 trasmitter interface
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity Tx is
port
(
--INPUT
clk2M : in std_logic; -- clock signal
reset : in std_logic; -- reset signal
enable : in std_logic; -- enable signal
en_parity : in std_logic; -- enable parity bit
parity : in std_logic; -- odd/even parity
speed : in std_logic; -- speed 100kbps or 12.5kbps
gap : in std_logic; -- gap between two messages: 4 or 64 bit of gap
TX_FIFO_ep : in std_logic; -- TX FIFO EMPTY
a429TX_in : in std_logic_vector (31 downto 0); -- data in
--OUTPUT
a429TX_outA : out std_logic; -- positive out
a429TX_outB : out std_logic; -- negative out
TX_FIFO_rd : out std_logic -- TX FIFO READ
);
end entity;
architecture RTL_A429TX of Tx is
-- FSM state name
type state_type is (IDLE,START, PAR,TRANSMITTING,WAITING);
signal state : state_type;
-- FSM register
signal shift_reg : std_logic_vector (31 downto 0);
signal shift_counter : std_logic_vector (4 downto 0);
signal gap_counter : std_logic_vector (6 downto 0);
-- speed clock register
signal clk429 : std_logic;
signal clk429_counter : integer;
signal clk429_max_count : integer;
signal clk429_half_count : integer;
begin
-- speed clock process
-------------------------------------------------------------------
-------------------------------------------------------------------
-- select speed process
process (speed)
begin
if (speed = '1') then
clk429_max_count <= 19; -- 100kbs/s
clk429_half_count <= 10;
else
clk429_max_count <= 159; -- 12.5kbs/s
clk429_half_count <= 80;
end if;
end process;
-- clock429 generate speed process
process (clk2M, reset)
begin
if (reset = '1') then
clk429 <= '0';
elsif rising_edge(clk2M) then
if (clk429_counter <= clk429_half_count ) then
clk429 <= '1';
else
clk429 <= '0';
end if;
end if;
end process;
-- counter activity process
process (clk2M, reset)
begin
if (reset = '1') then
clk429_counter <= 0;
elsif rising_edge(clk2M) then
if (clk429_counter >= clk429_max_count) then
clk429_counter <= 0;
else
clk429_counter <= clk429_counter + 1;
end if;
end if;
end process;
-------------------------------------------------------------------
-------------------------------------------------------------------
-- a429TX interface process
process (clk429, reset)
variable p : std_logic;
begin
if reset = '1' then
state <= IDLE;
shift_reg <= (others => '0');
shift_counter <= (others => '0');
gap_counter <= (others => '0');
a429TX_outA <= '0';
a429TX_outB <= '0';
TX_FIFO_rd <= '0';
elsif rising_edge(clk429) then
case state is
when IDLE => -- idle state
if (enable = '1') then
if (gap = '1') then
gap_counter <= "0000100"; -- 4
else
gap_counter <= "1000000"; -- 64
end if;
if TX_FIFO_ep = '0' then
TX_FIFO_rd <= '1';
state <= START;
else
state <= IDLE;
end if;
else
state <= IDLE;
end if;
when START =>
-- data formatting
TX_FIFO_rd <= '0';
shift_reg <= a429TX_in(31 downto 8)& a429TX_in(0) & a429TX_in(1) & a429TX_in(2) & a429TX_in(3) & a429TX_in(4) & a429TX_in(5) & a429TX_in(6) & a429TX_in(7);
shift_counter <= "11111";
if ( en_parity = '1') then
state <= PAR;
else
state <= TRANSMITTING;
end if;
when PAR => -- parity state
--TX_FIFO_rd <= '0';
p := '0';
for I in 31 downto 0 loop
p := p xor shift_reg(I);
end loop;
if (parity = '1') then
shift_reg(31) <= p; -- odd
else
shift_reg(31) <= not p; -- even
end if;
state <= TRANSMITTING;
when TRANSMITTING => -- transmission state
--TX_FIFO_rd <= '0';
a429TX_outA <= shift_reg(0);
a429TX_outB <= not shift_reg(0);
shift_reg <= shift_reg(0) & shift_reg(31 downto 1);
if (shift_counter = "00000") then
state <= WAITING;
else
shift_counter <= shift_counter -1;
state <= TRANSMITTING;
end if;
when WAITING => -- wait state. generate gap
a429TX_outA <= '0';
a429TX_outB <= '0';
if (gap_counter > 0) then
gap_counter <= gap_counter - 1;
state <= WAITING;
else
state <= IDLE;
end if;
when others => -- default
state <= IDLE;
end case;
elsif falling_edge (clk429) then
a429TX_outA <= '0';
a429TX_outB <= '0';
end if;
end process;
clk429 <= clk429;
end architecture;
Thanks for your help.
Run both FIFOs at the 2 MHz clk2M, and then generate a single cycle enable indication on TX_FIFO_rd when FIFO read data transfer is required.
Thereby you can get the benefit from synchronous design, without the hazzle of handling multiple clock domains.
Also, it is not good (but actually very bad :-) synchronous design practice to generate internal clock like the clk429, since it results in error prune design and more complex timing closure with Static Timing Analysis (STA). Instead make an enable signal that is asserted a single cycle, run the design on the clk2M, and the only update the relevant state when the enable signal is high.

DE0 Nano LEDs consecutively on and off

Please understand my very low skill-set on the code. I am trying to learn to be better.
Using DE0 Nano board, I am trying to write VHDL to simulate all available LEDs on the board (8 of them)
I labeled them LED0 ~ LED7. Using 50 MHZ and 1/2 s counter, I wanted to operate individual LEDs in order.
For example, if these individual bits represents on and off of the LEDs.
1|0|0|0|0|0|0|0 -> 0|1|0|0|0|0|0|0 -> 0|0|1|0|0|0|0|0 and so on. At the end, counter would reset back to 0 to repeat the sequence again.
Please view my code below with these questions/issues.
1) I get one 1/2 s pause after 8th LED. Why? How do I fix this?
2) Even if i put the variable counter as 8, it repeats as 16 thus I had to implement the reset of the counter to 0. (marked as question 2 in the code)
3) Is there any better way to write these codes? It is completely messy. Could you give tips on any other function or method I can use to shorten this codes?
Please let me know if any questions!
THANKS A LOT FOR THE HELP.
entity ledtest is
port(
clk_50mhz : in std_logic ;
reset_btn : in std_logic;
green_led : out std_logic_vector(7 downto 0)
);
end entity;
architecture behave of ledtest is
signal clk_1hz : std_logic ;
signal scaler : integer range 0 to 25000000 ;
signal counter : integer range 0 to 8;
signal LED : std_logic_vector(7 downto 0);
begin
clk_1hz_process : process( clk_50mhz , reset_btn )
begin
if (reset_btn = '0') then
clk_1hz <= '0';
scaler <= 0;
counter <= 0;
elsif(rising_edge(clk_50mhz)) then
if (scaler < 25000000) then
scaler <= scaler + 1 ;
clk_1hz <= '0';
else
scaler <= 0;
clk_1hz <= '1';
counter <= counter + 1;
if (counter >= 8) then --------question 2
counter <= 0;
end if;
end if;
end if;
end process clk_1hz_process;
blinking_process : process (clk_1hz,reset_btn)
begin
if (reset_btn = '0') then
LED(0) <= '0';
elsif rising_edge(clk_1hz) AND counter = 1 then
LED(0) <= not LED(0) ;
LED(7) <= '0' ;
elsif rising_edge(clk_1hz) AND counter = 2 then
LED(1) <= not LED(1) ;
LED(0) <= not LED(0) ;
elsif rising_edge(clk_1hz) AND counter = 3 then
LED(2) <= not LED(2) ;
LED(1) <= not LED(1) ;
elsif rising_edge(clk_1hz) AND counter = 4 then
LED(3) <= not LED(3) ;
LED(2) <= not LED(2) ;
elsif rising_edge(clk_1hz) AND counter = 5 then
LED(4) <= not LED(4) ;
LED(3) <= not LED(3) ;
elsif rising_edge(clk_1hz) AND counter = 6 then
LED(5) <= not LED(5) ;
LED(4) <= not LED(4) ;
elsif rising_edge(clk_1hz) AND counter = 7 then
LED(6) <= not LED(6) ;
LED(5) <= not LED(5) ;
elsif rising_edge(clk_1hz) AND counter = 8 then
LED(7) <= not LED(7) ;
LED(6) <= not LED(6) ;
end if;
end process blinking_process;
green_led(0) <= LED(0);
green_led(1) <= LED(1);
green_led(2) <= LED(2);
green_led(3) <= LED(3);
green_led(4) <= LED(4);
green_led(5) <= LED(5);
green_led(6) <= LED(6);
green_led(7) <= LED(7);
end behave;
If your readers squint real hard they can treat the original post as one question and two issues. (A questions is singular.)
Please view my code below with these questions/issues.
1) I get one 1/2 s pause after 8th LED. Why? How do I fix this?
There are 9 counter values (0 to 8) and only 8 LEDs (7 downto 0). No assignments occur in the half second between assigning counter to 0 and incrementing by 1 again.
2) Even if i put the variable counter as 8, it repeats as 16 thus I had to implement the reset of the counter to 0. (marked as question 2 in the code)
This issue is tied in with 1). The requirement for evaluating counter greater than or equal to 8 is caused by assigning counter to 8, again there are 9 values and only 8 LEDs. Note that's a synchronous load to 0 and not an asynchronous reset.
3) Is there any better way to write these codes? It is completely messy. Could you give tips on any other function or method I can use to shorten this codes?
Because you're attempting to go directly to FPGA instead of simulating the focus on tips should relate to the question 1) and how to fix it. There are also some synthesis issues, here gating clocks by adding enables to the conditions in if statement elsif alternatives. There's also the issue of design specification complexity and the amount of debugging effort associated with the number of lines of code.
First there are flip flops for all LED elements as well a counter. We can reduce the number of flip flops to one for each LED element by using a ring counter (not to be confused with a Johnson counter).
Assignments to green_led (the std_logic_vector) can be from LED (the std_logic_vector) instead of element by element. There's a one to one correspondence between element indices on both side of the assignment(s).
Also to allow simulation you could virtualize the time interval of a half second loaded into scalar. This has the effect of having fewer clocks represent a half second. The idea is simulation doesn't have to take the 10+ seconds of 100 million clock transitions per second (rising and falling edges).
Throw all these together and the code is changed to look like:
library ieee;
use ieee.std_logic_1164.all;
entity ledtest is
generic (half_second: integer := 24999999); -- zero identity
-- the generic allows fewer clocks per second for simulation
port (
clk_50mhz: in std_logic;
reset_btn: in std_logic;
green_led: out std_logic_vector(7 downto 0)
);
end entity;
architecture behave of ledtest is
signal clk_1hz: std_logic;
signal scaler: integer range 0 to half_second;
-- signal counter: integer range 0 to 8; -- DELETED
signal ring_counter: std_logic_vector (7 downto 0); -- ADDED
signal LED: std_logic_vector (7 downto 0);
signal LED0I: std_logic; -- ADDED
begin
LED0I <= '1' when LED = "00000000" else
'0';
clk_1hz_process:
process (clk_50mhz, reset_btn)
begin
if reset_btn = '0' then
clk_1hz <= '0';
scaler <= 0;
-- counter <= 0;
elsif rising_edge(clk_50mhz) then
if scaler /= half_second then
scaler <= scaler + 1;
clk_1hz <= '0';
else
scaler <= 0;
clk_1hz <= '1';
-- counter <= counter + 1;
-- if counter >= 8 then --------question 2
-- counter <= 0;
-- end if;
end if;
end if;
end process clk_1hz_process;
blinking_process:
process (clk_1hz, reset_btn)
begin
if reset_btn = '0' then
LED <= (others => '0');
-- LED(0) <= '0';
elsif rising_edge(clk_1hz) then
LED <= LED(6 downto 0) & (LED(7) or LED0I);
-- ring counter with a roulette ball lauch after reset
-- elsif rising_edge(clk_1hz) AND counter = 1 then
-- LED(0) <= not LED(0);
-- LED(7) <= '0';
-- elsif rising_edge(clk_1hz) AND counter = 2 then
-- LED(1) <= not LED(1);
-- LED(0) <= not LED(0);
-- elsif rising_edge(clk_1hz) AND counter = 3 then
-- LED(2) <= not LED(2);
-- LED(1) <= not LED(1);
-- elsif rising_edge(clk_1hz) AND counter = 4 then
-- LED(3) <= not LED(3);
-- LED(2) <= not LED(2);
-- elsif rising_edge(clk_1hz) AND counter = 5 then
-- LED(4) <= not LED(4);
-- LED(3) <= not LED(3);
-- elsif rising_edge(clk_1hz) AND counter = 6 then
-- LED(5) <= not LED(5);
-- LED(4) <= not LED(4);
-- elsif rising_edge(clk_1hz) AND counter = 7 then
-- LED(6) <= not LED(6);
-- LED(5) <= not LED(5);
-- elsif rising_edge(clk_1hz) AND counter = 8 then
-- LED(7) <= not LED(7);
-- LED(6) <= not LED(6);
end if;
end process blinking_process;
green_led <= led;
-- green_led(0) <= LED(0);
-- green_led(1) <= LED(1);
-- green_led(2) <= LED(2);
-- green_led(3) <= LED(3);
-- green_led(4) <= LED(4);
-- green_led(5) <= LED(5);
-- green_led(6) <= LED(6);
-- green_led(7) <= LED(7);
end architecture behave;
(Also note the default generic value scalar is reset and loaded to has been decremented to include the unity 0 in the 250,000,000 clocks be half second. The equality test for half_second is simpler than using magnitude comparison.)
Using a ring counter reduces complexity and side steps the issue of a counter range of 9.
The ring counter has a flourish added, the reset value is all '0's which are detected by signal LED0I which is used to start the ring counter after reset. It prevents all the LEDs from being lit during reset.
You can use a testbench with the number of clocks comprising a half second to a much smaller number allowing fast simulation with small waveform dump files:
library ieee;
use ieee.std_logic_1164.all;
entity ledtest_tb is
end entity;
architecture foo of ledtest_tb is
signal clk: std_logic := '0';
signal reset_btn: std_logic := '1';
signal green_led: std_logic_vector (7 downto 0);
begin
DUT:
entity work.ledtest
generic map (half_second => 7)
port map (
clk_50mhz => clk,
reset_btn => reset_btn,
green_led => green_led
);
CLOCK:
process
begin
wait for 0.5 sec / 7;
clk <= not clk;
if now > 19 sec then
wait;
end if;
end process;
STIMULUS:
process
begin
wait for 0.5 sec;
reset_btn <= '0';
wait for 0.5 sec;
reset_btn <= '1';
wait;
end process;
end architecture;
And that gives:
You could eliminate the generic map in the testbench instantiation of ledtest to demonstrate the difference in simulation time and dump file size inherent with simulating every clock transition with a 50 MHz clock. The idea here is it's easier to troubleshoot a simulation than it is to guess from what you can see (here the LEDs). Because the code description was simplified there was debugging required using the original code as a starting point. It did rely on a knowledge of digital electronics and VHDL.
The simulation was done with ghdl and gtkwave.

Interface DHT22 to FPGA - elbert v2

Now i make a circuit to measure temperature and humidity, then display on LCD. This is my code for DHT22, i use Elbert V2.
After genarating my project, it did not go right.
I tested and my program did not to come to "end_sl"( last state). And i dont know why?. Any suggestions for me? thank you.
my code
----------------------------------------------------------------------------------------------------------------------------------------------------------------
entity DHT11 is
generic (
CLK_PERIOD_NS : positive := 83; -- 12MHz
N: positive:= 40);
port(
clk,rst : in std_logic ;
singer_bus: inout std_logic;
dataout: out std_logic_vector (N-1 downto 0);
tick_done: out std_logic
);
end DHT11;
architecture Behavioral of DHT11 is
constant DELAY_1_MS: positive := 1*10**6/CLK_PERIOD_NS+1;
constant DELAY_40_US: positive := 40*10**3/CLK_PERIOD_NS+1;
constant DELAY_80_US: positive := 80*10**3/CLK_PERIOD_NS+1;
constant DELAY_50_US: positive := 50*10**3/CLK_PERIOD_NS+1; --
constant TIME_70_US: positive := 80*10**3/CLK_PERIOD_NS+1; --bit > 70 us
constant TIME_28_uS: positive := 30*10**3/CLK_PERIOD_NS+1; -- bit 0 > 28 us
constant MAX_DELAY : positive := 5*10**6/CLK_PERIOD_NS+1; -- 5 ms
type state_type is (reset,start_m,wait_res_sl,response_sl,delay_sl,start_sl,consider_logic,end_sl);
signal index, next_index : natural range 0 to MAX_DELAY;
signal state, next_state : state_type;
signal data_out,next_data_out: std_logic_vector (N-1 downto 0);
signal bit_in, next_bit_in: std_logic;
signal number_bit,next_number_bit: natural range 0 to 40;
signal oe: std_logic; -- help to set input and output port.
begin
--register
regis_state:process (clk,rst) begin
if rst = '1' then
state <= reset;
index <= MAX_DELAY;
number_bit <= 0;
bit_in <= '1';
data_out <= (others => '0');
elsif rising_edge(clk) then
state <= next_state;
index <= next_index;
number_bit <= next_number_bit;
bit_in <= next_bit_in;
data_out <= next_data_out;
end if;
end process regis_state;
proces_state: process (singer_bus,index,state,bit_in,number_bit,data_out) begin
tick_done <= '0';
next_data_out <= data_out;
next_number_bit <= number_bit;
next_state <= state;
next_data_out <= data_out;
next_index <= index;
dataout <= (others => '0');
oe <= '0';
next_bit_in <= bit_in;
case(state) is
when reset => -- initial
if index = 0 then
next_state <= start_m;
next_index <= DELAY_1_MS;
next_number_bit <= N-1;
else
next_state <= reset;
next_index <= index - 1;
end if;
when start_m => -- master send '1' in 1ms
if index = 0 then
next_state <= wait_res_sl;
next_index <= DELAY_40_US;
else
oe <= '1';
next_state <= start_m;
next_index <= index -1;
end if ;
when wait_res_sl => -- wait for slave response in 40us --
next_bit_in <= singer_bus;
if bit_in ='1' and next_bit_in = '0' then --
next_state <= response_sl;
else
next_state <= wait_res_sl;
end if;
when response_sl => -- slave response in 80us
next_bit_in <= singer_bus;
if bit_in ='0' and next_bit_in = '1' then
next_state <= delay_sl;
else
next_state <= response_sl;
end if;
when delay_sl => -- wait for slave delay in 80us
if bit_in = '1' and next_bit_in ='0' then
next_state <= start_sl;
else
next_state <= delay_sl;
end if;
when start_sl => -- start to prepare in 50us
if (bit_in = '0') and (next_bit_in = '1') then
next_state <= consider_logic;
next_index <= 0;
elsif number_bit = 0 then
next_state <= end_sl;
next_index <= DELAY_50_US;
else
next_state <= start_sl;
end if;
when consider_logic => -- determine 1 bit-data of slave
next_index <= index + 1;
next_bit_in <= singer_bus;
if bit_in = '1' and next_bit_in = '0' then -- the end of logic state
next_number_bit <= number_bit -1;
if (index < TIME_28_uS) then -- time ~ 28 us - logic = '0'
next_data_out <= data_out(N-2 downto 0) & '0';
elsif (index < TIME_70_US) then -- time ~70 us - logic ='1'
next_data_out <= data_out(N-2 downto 0) & '1';
end if;
next_state <= start_sl;
next_index <= DELAY_50_US;
elsif bit_in ='1' and next_bit_in ='1' then
next_state <= consider_logic;
end if;
when end_sl => -- tick_done = '1' then dataout has full 40 bit.
if index = 0 then
next_index <= MAX_DELAY;
next_state <= reset;
else
tick_done <= '1';
dataout <= data_out;
next_index <= index -1;
next_state <= end_sl;
end if;
end case;
end process proces_state;
--tristate IOBUFFER
singer_bus <= '0' when oe ='1' else 'Z';
end Behavioral;
There are many errors in your code. How did you debug exactly? Because it seems like you did not.
Why wait for 60 ms after the reset? you waste (valuable) simulation time. 6 ms is more then enough.
Looking at the simulation output, you can see the state does not advance at all: it's stuck ini wait_res_sl. The problem is that you have not added all the signals read in the process to the sensitivity list. I.e.
bit_in ='1' and next_bit_in = '0'
Will not detect a change if next_bit_in is not in the sensitivity list.
A problem -a common mistake made- is that your 'test bench' only provides input stimuli.... But it does not actually test anything.
And then the counters. Why is the delay counter called index? It doesn't index anything.
Why do your time delays not match their label? 70us -> 80 us. 28us -> 30 us.
Small thing don't call a RTL architecture behavioral
I tried to clean your code, seems to work now.
library ieee;
use ieee.std_logic_1164.all;
entity dht2 is
generic (
clk_period_ns : positive := 83; -- 12mhz
data_width: positive:= 40);
port(
clk,rst : in std_logic ;
singer_bus: inout std_logic;
dataout: out std_logic_vector(data_width-1 downto 0);
tick_done: out std_logic
);
end entity;
architecture rtl of dht2 is
constant delay_1_ms: positive := 1*10**6/clk_period_ns+1;
constant delay_40_us: positive := 40*10**3/clk_period_ns+1;
constant delay_80_us: positive := 80*10**3/clk_period_ns+1;
constant delay_50_us: positive := 50*10**3/clk_period_ns+1; --
constant time_70_us: positive := 70*10**3/clk_period_ns+1; --bit > 70 us
constant time_28_us: positive := 28*10**3/clk_period_ns+1; -- bit 0 > 28 us
constant max_delay : positive := 5*10**6/clk_period_ns+1; -- 5 ms
signal input_sync : std_logic_vector(0 to 2);
type state_type is (reset,start_m,wait_res_sl,response_sl,delay_sl,start_sl,consider_logic,end_sl);
signal state : state_type;
signal delay_counter : natural range 0 to max_delay;
signal data_out : std_logic_vector (data_width-1 downto 0);
signal bus_rising_edge, bus_falling_edge : boolean;
signal number_bit : natural range 0 to data_width;
signal oe: std_logic; -- help to set input and output port.
begin
input_syncronizer : process(clk) begin
if rising_edge(clk) then
input_sync <= to_x01(singer_bus)&input_sync(0 to 1);
end if;
end process;
bus_rising_edge <= input_sync(1 to 2) = "10";
bus_falling_edge <= input_sync(1 to 2) = "01";
--register
regis_state:process (clk) begin
if rising_edge(clk) then
case(state) is
when reset => -- initial
if delay_counter = 0 then
number_bit <= data_width;
oe <= '1';
delay_counter <= delay_1_ms;
state <= start_m;
else
delay_counter <= delay_counter - 1;
end if;
when start_m => -- master send '1' in 1ms
if delay_counter = 0 then
oe <= '0';
delay_counter <= delay_40_us;
state <= wait_res_sl;
else
delay_counter <= delay_counter -1;
end if ;
when wait_res_sl => -- wait for slave response in 40us --
if bus_falling_edge then --
state <= response_sl;
end if;
when response_sl => -- slave response in 80us
if bus_rising_edge then
state <= delay_sl;
end if;
when delay_sl => -- wait for slave delay in 80us
if bus_falling_edge then
state <= start_sl;
end if;
when start_sl => -- start to prepare in 50us
if bus_rising_edge then
delay_counter <= 0;
state <= consider_logic;
elsif number_bit = 0 then
delay_counter <= delay_50_us;
state <= end_sl;
end if;
when consider_logic => -- determine 1 bit-data of slave
if bus_falling_edge then -- the end of logic state
number_bit <= number_bit - 1;
if (delay_counter < time_28_us) then -- time ~ 28 us - logic = '0'
data_out <= data_out(data_width-2 downto 0) & '0';
elsif (delay_counter < time_70_us) then -- time ~70 us - logic ='1'
data_out <= data_out(data_width-2 downto 0) & '1';
end if;
delay_counter <= delay_50_us;
state <= start_sl;
end if;
delay_counter <= delay_counter + 1;
when end_sl => -- tick_done = '1' then dataout has full 40 bit.
if delay_counter = 0 then
delay_counter <= max_delay;
state <= reset;
else
tick_done <= '1';
dataout <= data_out;
delay_counter <= delay_counter - 1;
end if;
end case;
if rst = '1' then
number_bit <= 0;
data_out <= (others => '0');
delay_counter <= max_delay;
state <= reset;
end if;
end if;
end process regis_state;
--tristate iobuffer
singer_bus <= '0' when oe ='1' else 'Z';
end architecture;
And test bench: I added one check, but you should make more checks: every time you do something, it should have an effect. You should test if that effect actually happens.
entity dht2_tb is end dht2_tb;
library ieee;
architecture behavior of dht2_tb is
use ieee.std_logic_1164.all;
--inputs
signal clk : std_logic := '0';
signal rst : std_logic := '0';
--bidirs
signal singer_bus : std_logic := 'H';
--outputs
signal tick_done : std_logic;
-- clock period definitions
constant clk_period : time := 83.33 ns; -- 12mhz
use ieee.math_real.all;
-- This function generates a 'slv_length'-bit std_logic_vector with
-- random values.
function random_slv(slv_length : positive) return std_logic_vector is
variable output : std_logic_vector(slv_length-1 downto 0);
variable seed1, seed2 : positive := 65; -- required for the uniform function
variable rand : real;
-- Assume mantissa of 23, according to IEEE-754:
-- as UNIFORM returns a 32-bit floating point value between 0 and 1
-- only 23 bits will be random: the rest has no value to us.
constant rand_bits : positive := 23;
-- for simplicity, calculate remaining number of bits here
constant end_bits : natural := slv_length rem rand_bits;
use ieee.numeric_std.all;
begin
-- fill sets of 23-bit of the output with the random values.
for i in 0 to slv_length/rand_bits-1 loop
uniform(seed1, seed2, rand); -- create random float
-- convert float to int and fill output
output((i+1)*rand_bits-1 downto i*rand_bits) :=
std_logic_vector(to_unsigned(integer(rand*(2.0**rand_bits)), rand_bits));
end loop;
-- fill final bits (< 23, so above loop will not work.
uniform(seed1, seed2, rand);
if end_bits /= 0 then
output(slv_length-1 downto slv_length-end_bits) :=
std_logic_vector(to_unsigned(integer(rand*(2.0**end_bits)), end_bits));
end if;
return output;
end function;
-- input + output definitions
constant test_data_length : positive := 32;
constant test_data : std_logic_vector(test_data_length-1 downto 0) := random_slv(test_data_length);
signal data_out : std_logic_vector(test_data_length-1 downto 0);
begin
-- instantiate the unit under test (uut)
uut: entity work.dht2 -- use entity instantiation: no component declaration needed
generic map (
clk_period_ns => clk_period / 1 ns,
data_width => test_data_length)
port map (
clk => clk,
rst => rst,
singer_bus => singer_bus,
dataout => data_out,
tick_done => tick_done
);
-- clock stimuli
clk_process: process begin
clk <= '0', '1' after clk_period/2;
wait for clk_period;
end process;
-- reset stimuli
rst_proc : process begin
rst <= '1', '0' after 100 us;
wait;
end process;
-- bidir bus pull-up
-- as you drive the bus from the uut and this test bench, it is a bidir
-- you need to simulate a pull-up ('H' = weak '1'). slv will resolve this.
singer_bus <= 'H';
-- stimulus process
bus_proc: process
-- we use procedures for stimuli. Increases maintainability of test bench
-- procedure bus_init initializes the slave device. (copied this from your code)
procedure bus_init is begin
-- singer_bus <= 'Z'; -- initial
wait for 6 ms;
-- singer_bus <= '0'; -- master send
-- wait for 1 ms;
singer_bus <= 'Z'; -- wait response for slave
wait for 40 us;
singer_bus <= '0'; -- slave pull low
wait for 80 us;
singer_bus <= 'Z'; -- slave pull up
wait for 80 us;
end procedure;
function to_string(input : std_logic_vector) return string is
variable output : string(1 to input'length);
variable j : positive := 1;
begin
for i in input'range loop
output(j) := std_logic'image(input(i))(2);
j := j + 1;
end loop;
return output;
end function;
-- procedure send_data
procedure send_data(data : std_logic_vector) is begin
-- we can now send a vector of data,length detected automatically
for i in data'range loop
singer_bus <= '0'; -- slave start data transmission
wait for 50 us;
singer_bus <= 'Z'; -- slave send bit;
-- I found the only difference between sending bit '0'
-- and '1' is the length of the delay after a '0' was send.
case data(i) is
when '0' => wait for 24 us;
when '1' => wait for 68 us;
when others =>
report "metavalues not supported for bus_proc send_data"
severity failure;
end case;
singer_bus <= '0';
end loop;
-- next is VHDL-2008 (else use ieee.std_logic_textio.all;)
report "transmitted: "&to_string(data);
end procedure;
begin
wait until rst = '0';
bus_init; -- call procedure
send_data(test_data); -- call procedure
wait for 100 us; -- final delay
singer_bus <= 'Z'; -- release bus
report "received: "&to_string(data_out);
-- test correctness of output
assert data_out = test_data
report "data output does not match send data"
severity error;
report "end of simulation" severity failure;
end process;
end architecture;

VHDL : Signal s Cannot be Synthesised

line 62: Signal s cannot be synthesized, bad synchronous description.
The description style you are using to describe a synchronous element
(register, memory, etc.) is not supported in the current software
release.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity clock is
Port ( start : in STD_LOGIC;
reset : in STD_LOGIC;
CLOCK : in STD_LOGIC;
setH, setM, setS : in STD_LOGIC;
alarmH, alarmM, alarmS : in STD_LOGIC;
Alarm_On : in STD_LOGIC;
Buzzer_Stop : in STD_LOGIC;
BUZZER : out STD_LOGIC;
hh, mm, ss : out INTEGER);
end clock;
architecture Behavioral of clock is
signal h, m, s : INTEGER range 0 to 60 := 0;
signal hA, mA, sA : INTEGER range 0 to 60 := 0;
signal clk : std_logic :='0';
signal count : integer :=1;
begin
Frequency_Reducer : process(CLOCK) --Reducing Frequency From 40MHz to 1Hz
begin
if rising_edge(CLOCK) then
count <= count + 1;
if(count = 20000000) then
clk <= not clk;
count <=1;
end if;
end if;
end process;
Clock_Logic : process(start, reset, clk)
begin
if reset = '1' then
h <= 00;
m <= 00;
s <= 0;
end if;
if start = '1' then
if rising_edge(clk) then --Clock Logic Start
s <= s + 1;
end if;
end if;
if s = 60 then
s <= 0;
m <= m + 1;
end if;
if m = 60 then
m <= 0;
h <= h + 1;
end if;
if h = 24 then
h <= 0;
end if; --Clock Logic End
if setH = '1' then --Set Time Logic Start
h <= h + 1;
end if;
if setM = '1' then
m <= m + 1;
end if;
if setS = '1' then
s <= s + 1;
end if; -- Set Time Logic End
end process;
hh <= h;
mm <= m;
ss <= s;
end Behavioral;
Let's take a look at the assignments of signal s only:
Clock_Logic : process(start, reset, clk)
begin
if reset = '1' then
s <= 0;
end if;
if start = '1' then
if rising_edge(clk) then --Clock Logic Start
s <= s + 1;
end if;
end if;
if s = 60 then
s <= 0;
end if;
if setS = '1' then
s <= s + 1;
end if; -- Set Time Logic End
end process;
In the last assignment, you are requesting that s is incremented when setS is high and the process is executed (resumed). The process is executed initially after system startup and every time when one of the signals in the sensitivity list changes. Thus, you are requesting flipf-flops clocked on both edges of three signals start, reset and clock. I suspect, that this increment should be done only on the rising edge of the clock:
if rising_edge(clk) then --Clock Logic Start
if setS = '1' then
s <= s + 1;
end if; -- Set Time Logic End
end if;
The asynchronous reset of s when s reaches 60 is possible, but error prone due to glitches. s is is multi-bit signal in hardware. Thus, when it is incremented it could be equal to 60 for short moments in time even when the final value is below 60! You should reset it synchronously to 0, when current value is 59.
The increment of s when start is high and a rising-edge on the clock occur is ok, but synthesis tool often request to re-arrange this so that the outer if block checks for the rising edge:
if rising_edge(clk) then --Clock Logic Start
if start = '1' then
s <= s + 1;
end if;
end if;
Finally, the asynchronous reset (or set) inputs on flip-flops have always a higher priority then the synchronous data inputs. Thus, you must arrange it either this way:
Clock_Logic : process(reset, clk)
begin
if reset = '1' then
-- asynchronous part
s <= 0;
elsif rising_edge(clk) then
-- synchronous part (add more conditions if required)
s <= s + 1;
end if;
end process;
or this way:
Clock_Logic : process(reset, clk)
begin
if rising_edge(clk) then
-- synchronous part (add more conditions if required)
s <= s + 1;
end if;
if reset = '1' then
-- asynchronous part
s <= 0;
end if;
end process;
The synchronous assignments can be more complex. For example, if you want to synchronously reset a counter when it reaches 59 and to increment it otherwise when the signal setS is high:
Clock_Logic : process(reset, clk)
begin
if reset = '1' then
-- asynchronous part
s <= 0;
elsif rising_edge(clk) then
-- synchronous part
if s = 59 then
s <= 0;
elsif setS = '1' then
s <= s + 1;
end if;
end if;
end process;

reset statement is not synthesizable since it does not hold its value under NOT(clock-edge) condition

I have searched about this problem but it all seemed Greek to me so I came here as last effort.I have the following VHDL code that I want to be implemented on an fpga.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.std_logic_arith.all;
use work.conversions.all;
entity counter is
port ( clk_in: in std_logic; --new clock
target : in std_logic_vector(7 downto 1); --Set the target with the switches (SW7-SW1)
start : in std_logic; --Start/pause (SW0)
rst : in std_logic; --Reset (BT0)
LD : out std_logic_vector(7 downto 1); --Leds show the target at binary (LD7-LD1)
LD0 : out std_logic; --LD0 indicates thw the limit has been reached
seg : out std_logic_vector(7 downto 0); --7 segment display
digit : out std_logic_vector(3 downto 0)
);
end counter;
architecture Behavioral of counter is
begin
process(clk_in,target,rst)
variable timer : natural := 0;
variable counter : natural := 0;
variable display_counter : natural range 0 to 4 := 0;
begin
LD0 <= '0';
LD <= target; --Show the target at the leds
digit <= "1110"; --Last digit active
seg <= "00000011"; --Show zero
<--->if(rst='1') then --Reset counter
counter := 0;
timer := 0;
digit <= "1110"; --Last digit active
seg <= "00000011"; --Show zero
LD0 <= '0';
elsif rising_edge(clk_in) then
if(start = '0') then --Pause
--counter := counter;
elsif(counter = conv_integer(unsigned(target))) then --timer limit has been reached
LD0 <= '1';
else
counter := counter + 1;
display_counter := display_counter + 1;
if(counter rem 10 = 0) then --one second has elapsed (10Hz cycle)
timer := timer + 1; --increase timer
end if;
case display_counter is --Select which digits are gonna be activated and with what
when 1 =>
seg <= int2led(timer/1000);
if(int2led(timer/1000) = "00000000") then
digit(3) <= '1';
else
digit(3) <= '0';
end if;
when 2 =>
seg <= int2led((timer/100) mod 10);
if(int2led((timer/100) mod 10) = "00000000") then
digit(2) <= '1';
else
digit(2) <= '0';
end if;
when 3 =>
seg <= int2led((timer/10) mod 10);
if(int2led((timer/10) mod 10) = "00000000") then
digit(1) <= '1';
else
digit(1) <= '0';
end if;
when others =>
seg <= int2led(timer/10);
if(int2led(timer/10) = "00000000") then
digit(1) <= '1';
else
digit(1) <= '0';
end if;
end case;
if (display_counter = 4) then --reset the display counter from time to time
display_counter := 0;
else
display_counter := display_counter;
end if;
end if;
end if;
end process;
end Behavioral;
The problem is at if(rst='1') then. Can anyone explain to me in plain English why is this happening and a solution to it so I won't have the same kind problems again? Thanks in advance
You have default signal assignments before the if rst='1' then clause.
That means, when rst returns to 0 (in simulation) these default assignments will execute, and delete the reset values of those signals.
XST is telling you that the hardware can't actually do that.
The solution is to delete those default assignments, which will restore this process to a standard form. Then think carefully about what they were for and how to keep their functionality if you need to.
The traditional place for such assignments is immediately after the elsif rising_edge(clk) then clause, where they will be executed on every clock edge (provided Rst is low) then overridden by any other assignments that are executed yb the process.

Resources