0

Hello everyone I wrote some VHDL code that implement a UART-TX from my FPGA to my desktop. To trigger data sending I use the signal(debounced ofc) coming from the on-board switch.

As long as the button is pressed data is being sent. Inevitably, for as quick as I can be pushing and releasing this switch, the FPGA sends many UART packet duplicates to the laptop. This is because i directly connected the button signal to the start bit of the UART-TX entity. Therefore, I removed this direct connection and instead use the button to actually generate a short bit pulse to trigger the UART-TX entity just once.

So I did this:

--start_deb is the start bit (debounced? coming from the switch

i_TX_DV_gen: process(start_deb, clk) is
variable counter: natural := 0;
begin
if rising_edge(start_deb) then
    i_TX_DV <= '1';
end if;
if i_TX_DV = '1' and rising_edge(clk) then
    counter := counter + 1;
    if counter > 10_000 then
        i_TX_DV <= '0';
        counter := 0;
    end if;
end if;
end process;

So the trigger bit to the UART entity is set to '1' when I press the button and then after a number of clock cycles (which I unsured smaller than the ones necessary to send one packet) it goes to '0' again avoiding the send any duplicates.

This works in simulation, I attached the waveform:

Top Level Testbench

These are the signals description

clk:system clock
start_n: button signal (pressed when low)
start: not(start_n)
shift_input_n: button signal to select the next byte code. 
o_TX_serial: serial output of the TX entity
packet: byte to be sent
i_TX_DV: trigger bit to start UART-TX trasmission
start_deb: start signal but debounced

The problem is that when I download it to my FPGA, the i_TX_DV is set to '1' only the first time.

[ To visualize this I used a FPGA-built-in LED, which produces a light burst every time the i_TX_DV is set to '1'( for its very short amount of time). ]

Therefore, the UART-TX entity is triggered only the first time I pressed the button. Apparently when on FPGA for some reason, i_TX_DV is not set to '1' anymore, or is set to '0' just right after.

I am using the fpga Crosslink-NX Family 8MG289C from Lattice Semiconductor.

acefrrag
  • 41
  • 6
  • 1
    Provide a [mcve]. It'd go a long way toward understanding the handshaking. Note you have i_TX_DV set to '1' on the rising edge of and conditionally when it's '1' and counter greater than 10000 set to'0' on the rising edge of clk. Historically that's not a synthesis eligible construct, a register with two different clocks and it doesn't appear to work. Use one clock domain. – user16145658 Oct 06 '22 at 12:39

1 Answers1

0

Thank you guys, I thought of others ways to include it in a FSM and I ended up modifying the FSM of the UART-TX entity. Basically I don't go back to the idle state as long as the input start button is still pressed. This is a section of the FSM which contains the part I modified

        when s_Cleanup =>
            o_TX_Active <= '0';
            r_TX_Done   <= '1';
            ***if i_TX_DV = '1' then
                r_SM_Main <= s_Cleanup;
            else
                r_SM_Main <= s_Idle;
            end if;***

Anyway back at my original implementation, this was the netlist analyzer output for the pulse trigger generator:

enter image description here

It uses a register and a full adder to implement the counter. A register stores the value of i_TX_DV. The two multiplexer at the left are apparently used to either hold the value of the counter, updating it with the next value or "reset" it. The reset apparently is carried in this way: it comes from the d1 constant input data of bottom-left multiplexer wihch is tied to a 0. Therefore at the next clock cycle, when it holds the value it should be resetting itself. For some reason this still didn't work.

I apologize for my careless when writing the VHDL code, but when wiriting the code I just assumed that as long the simulation went well, the synthesis tool would have done the rest. Also I decided to not include too much code in order to be more coincise, because I had done several testing and made sure that all the other entities and modules were working correctly.

acefrrag
  • 41
  • 6
  • You cannot assume that your design is correct and synthesizible, if simulation goes well. There are many things that cannot be synthesized. Your best bet is to first simulate to approach a solution, then synthesize, and **then simulate the synthesized logic**. Only if the last step works with different conditions (variation in propagation delays, and so on) as required, you can gain confidence in your design. – the busybee Oct 06 '22 at 13:48
  • OK, your synthesizer separated the counter and the flip-flop for `i_TX_DV`, and tries to reset the flip-flop asynchronously. You could check how long the output of the comparator is active, and if it meets timing requirements. – the busybee Oct 06 '22 at 13:53