Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Start bit is to short #8

Open
Paebbels opened this issue Apr 15, 2024 · 9 comments
Open

Start bit is to short #8

Paebbels opened this issue Apr 15, 2024 · 9 comments

Comments

@Paebbels
Copy link
Member

When checking the output waveform of OSVVMs UART TX model, it was noticed the Start-bit is to short (half the bit-time).

The transmitted sequence is 0x45 = 0b01000101, so s10100010S (s = start-bit, S = stop-bit), no parity was used, baudrate is 115.200 kBd.

image

@JimLewis
Copy link
Member

Do you have a reproducer? I just reran the test case TbUart_SendGet1.vhd and the start bit looks good.

@Paebbels
Copy link
Member Author

I'll drive home and run the OSVVM regression test can check it there too.

@Paebbels
Copy link
Member Author

I discovered more problems with the UART TX model:

  • the stop bit supports only 1 and 2 bits, but not 1.5 bits. The number of stop bits is transported via IntToModel, thus 1.5 can't be transported from test controller to model.
  • The TX model generates an internal permanently running bit clock. This is not correct, as UART is asynchronous. This has 2 implications:
    1. transactions are synchronized with no reason to the bit clock, but a transaction like send could be started at any time. A start-bit must start immediately after receiving the transaction. Otherwise no arbitrary delays between words can be generated.
    2. a transaction asynchronously send to the bit clock, might wait for a full bit time to copy the transaction data via transmit FIFO into the transmit handler. This causes the serial line to stay almost one full cycle high.

Here is a different example of the TX model not working correctly. A transaction is send at 80 ns. Then the transaction data is forwarded at 4us and generates the start-bit. At 12.680us the start-bit finishes. Thus an artificial delay of ≈4us is introduced.

Similar wrong behavior is expected when executing these commands:

Send(TxUart, x"45");
wait for 1 us;
Send(TxUart, x"9D");

The send operation of 0x45 has already waited the stop-bit time, thus a new start-bit could start immediately. By waiting a short period, the transaction controller is unaligned to the internal TX clock, which will wait for a new rising edge. So an additional full stop-bit is added, instead of 1 us.

image

@Paebbels
Copy link
Member Author

When checking TbUart with test case SendGet1 I found this:

  • A clock is not needed in the test harness, as UART is asynchronous.
  • A reset is not needed as no VC has a reset imput.
  • Signal TestActive is not used.
  • Signal CheckErrors is not used.
  • wait for 4 * UART_BAUD_PERIOD_115200 ;
    • The baudrate doesn't match the VCs baudrate, because the generic uses 125 kBd.
    • There is no need to wait for signal propagation, because the test uses blocking calls and the receiving process has its own timing to reach the barrier.
  • GetAlertLogID(UartTxRec, UartTxID); get artificially delayed due to a wait on a rising edge on the internal TX bit clock.

Further findings in the UART VCs:

  • The default baudrate is set to UART_BAUD_PERIOD_125K, but this is not a well-known baudrate. The closest well-known baudrate is 115.200kBd.
    ⇒ This generic should not be set at all, because a user always needs to provide the correct settings. OSVVMs baud rate guess will be always wrong. Having a default leads to faults in the test harness setup.
    ⇒ A baudrate can be implemented as physical type. See the PoC library's physical package:
    type BAUD is range 0 to integer'high units
      Bd;
      kBd = 1000 Bd;
      MBd = 1000 kBd;
      GBd = 1000 MBd;
    end units;
  • Parity is enabled by default, but actually most interfaces do not use parity at all.
  • Generics like DEFAULT_NUM_DATA_BITS accept any integer value. The generic should be limited to natural range 7 to 9.
  • WaitForTransaction must not synchronize to a clock.

@Paebbels
Copy link
Member Author

This is a reproducer for existing tests in OSVVM. Use TbUart and SendGet1.

Modification to the harness:

  ------------------------------------------------------------
  UartTx_1 : UartTx 
  ------------------------------------------------------------
  generic map (
	DEFAULT_BAUD        => UART_BAUD_PERIOD_115200,
	DEFAULT_PARITY_MODE => UARTTB_PARITY_NONE
	)
	port map (
    TransRec            => UartTxRec,
    SerialDataOut       => SerialData   
  ) ;


  ------------------------------------------------------------
  UartRx_1 : UartRx 
  ------------------------------------------------------------
  generic map (
	DEFAULT_BAUD        => UART_BAUD_PERIOD_115200,
	DEFAULT_PARITY_MODE => UARTTB_PARITY_NONE
	)
  port map (
    TransRec            => UartRxRec,
    SerialDataIn        => SerialData 
  ) ;
  1. configure a well-known baudrate
  2. disable parity

Modifications for the TX process:

  UartTbTxProc : process
    variable UartTxID : AlertLogIDType ; 
    variable TransactionCount, ErrorCount : integer ;
  begin
    
    GetAlertLogID(UartTxRec, UartTxID) ; 
    SetLogEnable(UartTxID, INFO, TRUE) ;
		wait for 10 us;
    -- WaitForClock(UartTxRec, 2) ; 
    
    --  Sequence 1
    Send(UartTxRec, X"55") ;
    Send(UartTxRec, X"51", UARTTB_PARITY_ERROR) ;
  1. disable WaitForClock and add a delay like 10 us to get the transaction asynchronous.
  2. Change first byte to x"55" for a better pattern.
image

For now, this is not producing a short start-bit, I need to get access to the student's PC and check there for modifications.

@JimLewis
Copy link
Member

Internally UART hardware is typically synchronous to a 16x or 32x reference clock. That reference clock is independent from the other UART with which it is communicating. In fact their internal reference clocks can differ by a small percentage and the transfer will be successful.

That said the UARTs use of a 1X clock was just a lazy implementation.

@JimLewis
Copy link
Member

Wrt 1.5 stop bits, my notes show that that was only use with 5 bit transfers and popular uarts 16550 used the same control value to select both 1.5 and 2 stop bits - which one you got was a function of the number of data bits you sent.

Is there something that supports 9 data bits in a uart?

@JimLewis
Copy link
Member

Noted that there are a few extra signals here and there. Open to accepting a pull request to fix these.

@JimLewis
Copy link
Member

JimLewis commented Apr 17, 2024

Once the VC is updated to support a 16x clock, the test case delays you want to use should be expressed as multiples of the 16x clock or at least that is the granularity you should get.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants