aboutsummaryrefslogblamecommitdiff
path: root/src/rtl/uart.v
blob: 2a8de7051cfd19aeb48dba24fc140675f1d2814b (plain) (tree)
1
2
3
4
5
6
7
8
9
10






                                                                        


                                                              









                                                                
                            


















                                                                       
                                                                   



                                                                   




















                                                                        
 


                                    
                                         







                                            
 



                                                                    



                                      
 


                                      
 





                                                   
                                                            

                                                      
                            
                                    
                                         
                                     
                                     

 


                                                                    


                            
 






                             

 





                                                                    

                         
 


                              
 


                              
 

                              
 
 








                                                                    
 


                                      
 



                                       
 










                                                                    


                                           
 







                                               
 





                                                
 



                                                                    

                                                   
                                                                    
                                           


                     


                                             


             



                                            
 



                                              
 



                                              



                     
 








                                                                    





                               

                                   
 





                                  
















                                                      
 




























                                                 
 













                                                                 
 







                                       
 




                                                                        
//======================================================================
//
// uart.v
// ------
// Top level wrapper for the uart core.
//
// A simple universal asynchronous receiver/transmitter (UART)
// interface. The interface contains 16 byte wide transmit and
// receivea buffers and can handle start and stop bits. But in
// general is rather simple. The primary purpose is as host
// interface for the coretest design. The core also has a
// loopback mode to allow testing of a serial link.
//
// Note that the UART has a separate API interface to allow
// a control core to change settings such as speed. But the core
// has default values to allow it to start operating directly
// after reset. No config should be needed.
//
//
// Author: Joachim Strombergson
// Copyright (c) 2014, SUNET
//
// Redistribution and use in source and binary forms, with or
// without modification, are permitted provided that the following
// conditions are met:
//
// 1. Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in
//    the documentation and/or other materials provided with the
//    distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//======================================================================

module uart(
            input wire           clk,
            input wire           reset_n,

            // External interface.
            input wire           rxd,
            output wire          txd,

            // Internal receive interface.
            output wire          rxd_syn,
            output [7 : 0]       rxd_data,
            input wire           rxd_ack,

            // Internal transmit interface.
            input wire           txd_syn,
            input wire [7 : 0]   txd_data,
            output wire          txd_ack,

            // API interface.
            input wire           cs,
            input wire           we,
            input wire [7 : 0]   address,
            input wire [31 : 0]  write_data,
            output wire [31 : 0] read_data,
            output wire          error,

            // Debug output.
            output wire [7 : 0]  debug
           );


  //----------------------------------------------------------------
  // Internal constant and parameter definitions.
  //----------------------------------------------------------------
  // API addresses.
  parameter ADDR_CORE_NAME0   = 8'h00;
  parameter ADDR_CORE_NAME1   = 8'h01;
  parameter ADDR_CORE_TYPE    = 8'h02;
  parameter ADDR_CORE_VERSION = 8'h03;

  parameter ADDR_BIT_RATE     = 8'h10;
  parameter ADDR_DATA_BITS    = 8'h11;
  parameter ADDR_STOP_BITS    = 8'h12;

  // Core ID constants.
  parameter CORE_NAME0   = 32'h75617274;  // "uart"
  parameter CORE_NAME1   = 32'h20202020;  // "    "
  parameter CORE_TYPE    = 32'h20202031;  // "   1"
  parameter CORE_VERSION = 32'h302e3031;  // "0.01"

  // The default bit rate is based on target clock frequency
  // divided by the bit rate times in order to hit the
  // center of the bits. I.e.
  // Clock: 50 MHz, 9600 bps
  // Divisor = 50*10E6 / 9600 = 5208
  parameter DEFAULT_BIT_RATE  = 16'd5208;
  parameter DEFAULT_DATA_BITS = 4'h8;
  parameter DEFAULT_STOP_BITS = 2'h1;


  //----------------------------------------------------------------
  // Registers including update variables and write enable.
  //----------------------------------------------------------------
  reg [15 : 0] bit_rate_reg;
  reg [15 : 0] bit_rate_new;
  reg          bit_rate_we;

  reg [3 : 0]  data_bits_reg;
  reg [3 : 0]  data_bits_new;
  reg          data_bits_we;

  reg [1 : 0]  stop_bits_reg;
  reg [1 : 0]  stop_bits_new;
  reg          stop_bits_we;


  //----------------------------------------------------------------
  // Wires.
  //----------------------------------------------------------------
  wire [15 : 0] bit_rate;
  wire [1 : 0]  stop_bits;

  wire          core_rxd;
  wire          core_txd;

  wire          core_rxd_syn;
  wire [7 : 0]  core_rxd_data;
  wire          core_rxd_ack;

  wire          core_txd_syn;
  wire [7 : 0]  core_txd_data;
  wire          core_txd_ack;

  reg [31 : 0]  tmp_read_data;
  reg           tmp_error;


  //----------------------------------------------------------------
  // Concurrent connectivity for ports etc.
  //----------------------------------------------------------------
  assign txd           = core_txd;
  assign core_rxd      = rxd;

  assign rxd_syn       = core_rxd_syn;
  assign rxd_data      = core_rxd_data;
  assign core_rxd_ack  = rxd_ack;

  assign core_txd_syn  = txd_syn;
  assign core_txd_data = txd_data;
  assign txd_ack       = core_txd_ack;

  assign read_data     = tmp_read_data;
  assign error         = tmp_error;

  assign debug         = core_rxd_data;


  //----------------------------------------------------------------
  // core
  //
  // Instantiation of the uart core.
  //----------------------------------------------------------------
  uart_core core(
                 .clk(clk),
                 .reset_n(reset_n),

                 // Configuration parameters
                 .bit_rate(bit_rate_reg),
                 .data_bits(data_bits_reg),
                 .stop_bits(stop_bits_reg),

                 // External data interface
                 .rxd(core_rxd),
                 .txd(core_txd),

                 // Internal receive interface.
                 .rxd_syn(core_rxd_syn),
                 .rxd_data(core_rxd_data),
                 .rxd_ack(core_rxd_ack),

                 // Internal transmit interface.
                 .txd_syn(core_txd_syn),
                 .txd_data(core_txd_data),
                 .txd_ack(core_txd_ack)
                );


  //----------------------------------------------------------------
  // reg_update
  //
  // Update functionality for all registers in the core.
  // All registers are positive edge triggered with
  // asynchronous active low reset.
  //----------------------------------------------------------------
  always @ (posedge clk or negedge reset_n)
    begin: reg_update
      if (!reset_n)
        begin
          bit_rate_reg  <= DEFAULT_BIT_RATE;
          data_bits_reg <= DEFAULT_DATA_BITS;
          stop_bits_reg <= DEFAULT_STOP_BITS;
        end
      else
        begin
          if (bit_rate_we)
            begin
              bit_rate_reg  <= bit_rate_new;
            end

          if (data_bits_we)
            begin
              data_bits_reg  <= data_bits_new;
            end

          if (stop_bits_we)
            begin
              stop_bits_reg  <= stop_bits_new;
            end

        end
    end // reg_update


  //----------------------------------------------------------------
  // api
  //
  // The core API that allows an internal host to control the
  // core functionality.
  //----------------------------------------------------------------
  always @*
    begin: api
      // Default assignments.
      bit_rate_new  = 16'h0000;
      bit_rate_we   = 0;
      data_bits_new = 4'h0;
      data_bits_we  = 0;
      stop_bits_new = 2'b00;
      stop_bits_we  = 0;
      tmp_read_data = 32'h00000000;
      tmp_error     = 0;

      if (cs)
        begin
          if (we)
            begin
              // Write operations.
              case (address)
                ADDR_BIT_RATE:
                  begin
                    bit_rate_new = write_data[15 : 0];
                    bit_rate_we  = 1;
                  end

                ADDR_DATA_BITS:
                  begin
                    data_bits_new = write_data[3 : 0];
                    data_bits_we  = 1;
                  end

                ADDR_STOP_BITS:
                  begin
                    stop_bits_new = write_data[1 : 0];
                    stop_bits_we  = 1;
                  end

                default:
                  begin
                    tmp_error = 1;
                  end
              endcase // case (address)
            end
          else
            begin
              // Read operations.
              case (address)
                ADDR_CORE_NAME0:
                  begin
                    tmp_read_data = CORE_NAME0;
                  end

                ADDR_CORE_NAME1:
                  begin
                    tmp_read_data = CORE_NAME1;
                  end

                ADDR_CORE_TYPE:
                  begin
                    tmp_read_data = CORE_TYPE;
                  end

                ADDR_CORE_VERSION:
                  begin
                    tmp_read_data = CORE_VERSION;
                  end

                ADDR_BIT_RATE:
                  begin
                    tmp_read_data = {16'h0000, bit_rate_reg};
                  end

                ADDR_DATA_BITS:
                  begin
                    tmp_read_data = {28'h0000000, data_bits_reg};
                  end

                ADDR_STOP_BITS:
                  begin
                    tmp_read_data = {30'h0000000, stop_bits_reg};
                  end

                default:
                  begin
                    tmp_error = 1;
                  end
              endcase // case (address)
            end
        end
    end

endmodule // uart

//======================================================================
// EOF uart.v
//======================================================================