3
\$\begingroup\$

I was studying the VHDL uart core given here. At the bottom of the page is shown the transmitter code. Notice the line

 tx_data <= "1"&data_i&"01";

This line adds the start and the stop bit to the data string. But why is there an additional '1' bit at the rightmost of the string? Wouldn't the code below suffice?

 tx_data <= "1"&data_i&"0";

There is no parity implemented in the core, and only 1 bit stop. Thus, that additional bit really confuses me. Why is it there?

\$\endgroup\$
1
\$\begingroup\$

The design is hard-coded to send 11 bits per byte. tx_ctr_bit runs from "0000" through "1010", inclusive. So it's obvious that the designer wanted two stop bits per byte.

It is, however, a bizarre choice to send the extra stop bit at the beginning of the byte rather that at the end (i.e., tx_data <= "11"&data_i&"0";). All that does is to increase the latency of the transmitter — when the system wants to send a byte, the start bit comes out one bit time later than it otherwise could.


Another odd thing is the initialization value for tx_data:

  if reset='1' then
    tx_data <= "10111111111";

Why is the 0 bit in there? It doesn't really matter, because this data is never used anyway (except for the LSB, which sets the idle state of the output), but why not just set it to all ones?

\$\endgroup\$
  • 1
    \$\begingroup\$ So you reply my question with more questions :) \$\endgroup\$ – zeke Aug 18 '19 at 13:22
  • \$\begingroup\$ Well, the hidden answer is that there's no good reason for what you found :-) In fact, if you end up using this core, it would be worth your while to submit patches back to the owner to clean up issues like these. \$\endgroup\$ – Dave Tweed Aug 18 '19 at 13:23
-1
\$\begingroup\$

Without seeing the rest of the VHDL design, it's impossible to say definitively. If you post that, I could comment further.

But it may may be to ensure that the idle state of the transmitter output is a '1', if this isn't being done elsewhere, by bad design. It could also be to ensure that the same designer's receiver gets a second bit of idle time, if that's what they found it needed. But there's no obvious good reason. It effectively produces two transmitted stop bits.


REVISED ANSWER:

Seeing the link to the source design*, I've examined the transmitter.

This is not a good UART design and is quite over-complicated from those I've designed myself. Nonetheless...

The transmitter does not align itself to a free-running baud-rate prescaler. Instead, it times bit periods when running using the awfully (i.e. ambiguously) named 'tx_counter'.

It will accept the write of a new byte immediately after shifting out the STOP bit. This would cut short the STOP bit so the transmitter is inserting another STOP bit to ensure there's at least one full bit period of STOP level transmitted.

main_tx_process:
process(clk)
begin
if clk'event and clk='1' then

  if reset='1' then
    tx_data <= "10111111111";
    tx_busy <= '0';
    tx_irq <= '0';
    tx_ctr_bit <= "0000";
    tx_counter <= (others => '0');
  elsif load_tx_reg='1' and tx_busy='0' then
    tx_data <= "1"&data_i&"01";
    tx_busy <= '1';
  else
    if tx_busy='1' then
      if tx_counter = bit_period_reg then
        tx_counter <= (others => '0');
        tx_data(9 downto 0) <= tx_data(10 downto 1);
        tx_data(10) <= '1';
        if tx_ctr_bit = "1010" then
           tx_busy <= '0';
           tx_irq <= '1';
           tx_ctr_bit <= "0000";
        else
           tx_ctr_bit <= tx_ctr_bit + 1;
        end if;
      else
        tx_counter <= tx_counter + 1;
      end if;
    else
      tx_irq <= '0';
    end if;
  end if;
end if;
end process main_tx_process;

txd_o <= tx_data(0);

This could have been resolved by shifting the transmitter when a free-running baud-rate generator signals a bit period start then counting bit periods to include a STOP bit. I do that and it produces a shorter, simpler circuit and a simpler-to-follow design, from what others have said.

  • Design, not 'code'. VHDL does not produce op-codes for a CPU.
\$\endgroup\$
  • \$\begingroup\$ Click the word "here" on the original post. I shared the link there. \$\endgroup\$ – zeke Aug 18 '19 at 12:30
  • \$\begingroup\$ Seems to hit the nail on the head. The output signal is wired as txd_o <= tx_data(0), so the extra 1 is needed to keep the line high when data is being loaded. \$\endgroup\$ – Tom Carpenter Aug 18 '19 at 12:55
  • \$\begingroup\$ I still don't get this. The stop bit is already a '1'. No matter what, the last bit of a transmission is a '1'. So why send it again? \$\endgroup\$ – zeke Aug 18 '19 at 13:00
  • 1
    \$\begingroup\$ Your analysis is flawed. The logic won't load the next byte until all 11 bits of the previous byte have been transmitted and tx_busy is set to 0 again. The asynchronous startup merely extends the time between the two stop bits by an arbitrary amount -- and in general, there's no requirement for the idle time be an integer number of bit periods anyway. \$\endgroup\$ – Dave Tweed Aug 18 '19 at 14:12
  • 2
    \$\begingroup\$ P.S. The input to a compiler, regardless of whether it's a programming language or a hardware description language, is called "source code". \$\endgroup\$ – Dave Tweed Aug 18 '19 at 14:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.