2010年5月31日 星期一

OPENRISC 4 UART SystemC

Hi all: this is a sample tutorial for "How to write a UART testbench in SystemC". 1.what's "UART" ? You can reference the UART Agenda firstly... or from WiKi Refs: UART Agenda , Serial UART information 2. How and How to work? 2-1. TX/RX (transfer/receiver) this is an asynchronous timing Sequence for UART TX/RX transition. In data (transfer/Receive),we should define our sample and receive rate to catch/push the accurate data. and it depend on our Baud rate and local clk frequency. in this formulation we can calculate out the clock numbers for UART per bit. // Calculate number of clocks per UART bit clocks_per_bit = (int)(clk_freq_hz/uart_baud); Example timing sequence for RX : start_Bit(1) -> star_Bit(0) -> Data_bit(D0) -> Data_bit(D1) ... -> Data_bit(7) -> Stop_Bit(0) -> Stop_Bit(1). 2-2. Baud rate set it define our bit resolution Ex: baud rate for RS232 Display should < %3, if we define our Fclk=12Mhz, smod=1. and we can find a good data resolution rage from XXX to XXX. Black Box Interface *.h (UART_Test_Bench)
class UartSC
  : public sc_core::sc_module
{
public:

  // Constructor
  UartSC (sc_core::sc_module_name  name);

  // The ports
  sc_in < bool >   clk;
  sc_in < bool >   uarttx;
  sc_out < bool >   uartrx;

  // Init function
  void initUart (int clk_freq_hz, int uart_baud) ;
  // Transmit (from ORPSoC) handling function
  void checkTx();

private:
  int clocks_per_bit;
  uint8_t current_char;
  int counter;
  int bits_received;

}; // UartSC ()
define our sensitive type
UartSC::UartSC (sc_core::sc_module_name   name):
  sc_module (name)
{

  SC_METHOD (checkTx);
  dont_initialize();
  sensitive << clk.pos();
  //sensitive << uarttx;
  
}
define our TX method
// Maybe do this with threads instead?!
void 
UartSC::checkTx () {

#ifdef UART_SC_DEBUG
  //printf("Uart TX activity: level is : 0x%x\n", uarttx.read()&1);
#endif
  
  // Check the number of bits received
  if (bits_received==0)
    {
      // Check if tx is low
      if ((uarttx.read()&1) == 0)
 { 
   // Line pulled low, begin receive of new char
   current_char = 0;
   // Start 
   counter = 1;
   bits_received++; // We got the start bit
#ifdef UART_SC_DEBUG
   cout << "UartSC checkTx: got start bit at time " << sc_time_stamp() << endl;
#endif
 }
    }
  else if (bits_received > 0 && bits_received < 9)
    {
      // Check the counter - see if it's time to sample the line
      // We do an extra half-bit delay on first bit read
      if ( ((bits_received==1) && 
     (counter == (clocks_per_bit + (clocks_per_bit/2)))) || 
    ((bits_received > 1) && (counter == clocks_per_bit)) )
 {
   //printf("UartSC checkTx: read bit %d as 0x%x at time", bits_received, uarttx.read()&1);
   //cout << sc_time_stamp() << endl;

   // Shift in the current value of the tx into our char
   current_char |= ((uarttx.read() & 1) << (bits_received-1));
   // Reset the counter
   counter = 1;
   // Increment bit number
   bits_received++;
 }
      else
 counter++;
    }
  else if (bits_received == 9)
    { 
      // Now check for stop bit 1
      if (counter == clocks_per_bit)
 {
   // Check that the value is 1 - this should be the stop bit
   if ((uarttx.read() & 1) != 1)
     {
       printf("UART TX framing error at time\n");
       cout << sc_time_stamp() << endl;

       // Perhaps do something else here to deal with this
       bits_received = 0;
       counter = 0;
     }
   else
     {
       // Print the char
#ifdef UART_SC_DEBUG
       printf("Char received: 0x%2x time: ", current_char);
       cout << sc_time_stamp() << endl;
#endif
       // cout'ing the char didn't work for some systems - jb 090613ol
       //cout << current_char;
       printf("%c",current_char);

       bits_received = 0;
       counter = 0;
     }
 }
      else
 counter++;
    }
}
Ref: http://opencores.org/openrisc,orpsocv21

沒有留言:

張貼留言