User:Operiolloid/sandbox

`include "uvm_macros.svh"

package my_pkg;

import uvm_pkg::*;

///////////////////////////////////////////////////////////////////////////

class uart_tx extends uvm_sequence_item;


   

  bit    i_TX_DV;     

  rand logic [7:0] i_TX_Byte;

  //reg         r_TX_Serial;

  //reg         r_TX_Active;

   

  reg [7:0]   r_RX_Byte;

  reg         r_RX_DV;

  //reg         o_RX_Byte;

 

       //Register with factory for dynamic creation

  `uvm_object_utils(uart_tx)

 

   

  function new (string name = "uart_tx");

      super.new(name);

   endfunction

   function string convert2string();

     return $psprintf("i_TX_DV=%0h  i_TX_Byte=%0h  " ,i_TX_DV,i_TX_Byte);

   endfunction

 

   function string convert3string();

     return $psprintf("i_TX_Byte=%0h  ",i_TX_Byte);

   endfunction

 

   function string convert33string();

     return $psprintf("  r_RX_Byte=%0h ",r_RX_Byte);

   endfunction

 

   function string convert4string();

     return $psprintf("r_RX_Byte=%0h ",r_RX_Byte);

   endfunction

 

  function string convert5string();

    return $psprintf("i_TX_Byte=%0h ",i_TX_Byte);

   endfunction

endclass: uart_tx

//////////////////////////////////////////////////////////////////////

class uart_tx_seq extends uvm_sequence#(uart_tx);

  `uvm_object_utils(uart_tx_seq)

       uart_tx uart_trans;

 

  function new(string name ="");

    super.new(name);

  endfunction

  //Main Body method that gets executed once sequence is started

  task body();

     

     //Create 10 random uart read/write transaction and send to driver

    uart_trans = uart_tx::type_id::create("uart_trans");

      //apb_rw::type_id::create(.name("rw_trans"),.contxt(get_full_name()));

    for(int i=0;i<10;i++) begin

      start_item(uart_trans);

    assert (uart_trans.randomize());

   // assert(uart_trans.randomize() with { i_TX_Byte == 8'h5a;});

     

      finish_item(uart_trans);

     

       

     end

  endtask

 

endclass

/////////////////////////////////////////////////////////////////////////

class uart_tx_sequencer extends uvm_sequencer #(uart_tx);

   `uvm_component_utils(uart_tx_sequencer)


   function new(input string name, uvm_component parent=null);

      super.new(name, parent);

   endfunction : new

endclass : uart_tx_sequencer

/////////////////////////////////////////////////////////////////////////

class uart_tx_config extends uvm_object;

   `uvm_object_utils(uart_tx_config)

   virtual UART_IF vif;

  function new(string name="uart_tx_config");

     super.new(name);

  endfunction

endclass

typedef uart_tx_config;

typedef uart_tx_agent;

typedef uart_rx_agent;

///////////////////////////////////////////////////////////////////////

class uart_tx_driver extends uvm_driver #(uart_tx);

 

  `uvm_component_utils(uart_tx_driver)

 

  virtual UART_IF vif ;

          //uart_tx_config cfg_tx;

  function new(input string name, uvm_component parent=null);

      super.new(name, parent);

   endfunction : new

 

   function void build_phase(uvm_phase phase);

    /* uart_tx_agent agent;

     //super.build_phase(phase);

     if ($cast(agent, get_parent()) && agent != null) begin

         vif = agent.vif;

     end

     else begin*/

       if (!uvm_config_db#(virtual UART_IF)::get(this, "", "vif", vif)) begin

         `uvm_fatal("UART/DRV/NOVIF", "No virtual interface specified for this driver instance")

         end

    // end

   endfunction

 

  virtual task run_phase(uvm_phase phase);

    super.run_phase(phase);

   

     vif.i_TX_Byte=0;

       vif.i_TX_DV=0;

       vif.o_TX_Serial=0;

     forever begin

       uart_tx tr;

        //@ (posedge vif.i_Clock);

     

       

       @ (posedge vif.i_Clock);

       //First get an item from sequencer

       seq_item_port.get_next_item(tr);

      // @ (this.vif.i_Clock);

       uvm_report_info("UART_DRIVER ", $psprintf("Got Transaction %s",tr.convert2string()));

   

   

    @ (this.vif.o_Bit_Clk);

       

       vif.i_TX_DV<=1;   

       vif.i_TX_Byte<=tr.i_TX_Byte;

           

       

       @ (posedge vif.i_Clock);

          vif.i_TX_DV<=0;

       

       

       

       seq_item_port.item_done();

       

     end

  endtask

endclass:uart_tx_driver

/////////////////////////////////////////////////

 

  class uart_tx_monitor extends uvm_monitor;

     virtual UART_IF vif;

  //Analysis port -parameterized to apb_rw transaction

  ///Monitor writes transaction objects to this port once detected on interface

    uvm_analysis_port#(uart_tx) item_collected_port_tx;

  //config class handle

  uart_tx_config cfg;

  `uvm_component_utils(uart_tx_monitor)

   function new(string name, uvm_component parent = null);

     super.new(name, parent);

     item_collected_port_tx = new("item_collected_port_tx", this);

   endfunction: new

   //Build Phase - Get handle to virtual if from agent/config_db

   virtual function void build_phase(uvm_phase phase);

     uart_tx_agent agent;

     if ($cast(agent, get_parent()) && agent != null) begin

       vif = agent.vif;

     end

     else begin

       virtual UART_IF tmp;

       if (!uvm_config_db#(virtual UART_IF)::get(this, "", "UART_IF", tmp)) begin

         `uvm_fatal("APB/MON/NOVIF", "No virtual interface specified for this monitor instance")

       end

       vif = tmp;

     end

   endfunction

   

virtual task run_phase(uvm_phase phase);

    // super.run_phase(phase);

     //  super.run_phase(phase);

     uart_tx tr;

     tr =uart_tx::type_id::create("tr");

   //tr.o_TX_Serial=0;

    forever begin

    //  uart_tx tr;

      @(posedge vif.i_Clock);

      if(vif.i_TX_DV==1)begin  

        $display("i_TX_DV is high");

        // tr.r_TX_Serial = vif.o_TX_Serial;

        // tr.r_TX_Active = vif.o_TX_Active;

           tr.i_TX_Byte = vif.i_TX_Byte;

          item_collected_port_tx.write(tr);

        uvm_report_info("UART_TX_MONITER ", $psprintf("Got Transaction %s",tr.convert5string()));

     

         

     // @ (this.vif.i_Clock);

      // item_collected_port_tx.write(tr);

      end

      end

   

endtask

     

      endclass: uart_tx_monitor

///////////////////////////////////////////////////////     

     

      class uart_tx_agent extends uvm_agent;

   //Agent will have the sequencer, driver and monitor components for the APB interface

   uart_tx_sequencer sqr;

   uart_tx_driver drv;

   uart_tx_monitor mon;

   virtual UART_IF  vif;

   `uvm_component_utils_begin(uart_tx_agent)

      `uvm_field_object(sqr, UVM_ALL_ON)

      `uvm_field_object(drv, UVM_ALL_ON)

      `uvm_field_object(mon, UVM_ALL_ON)

   `uvm_component_utils_end

   

   function new(string name, uvm_component parent = null);

      super.new(name, parent);

   endfunction

   //Build phase of agent - construct sequencer, driver and monitor

   //get handle to virtual interface from env (parent) config_db

   //and pass handle down to srq/driver/monitor

   virtual function void build_phase(uvm_phase phase);

      sqr = uart_tx_sequencer::type_id::create("sqr", this);

      drv = uart_tx_driver::type_id::create("drv", this);

      mon = uart_tx_monitor::type_id::create("mon", this);

     

     if (!uvm_config_db#(virtual UART_IF)::get(this, "", "vif", vif)) begin

         `uvm_fatal("APB/AGT/NOVIF", "No virtual interface specified for this agent instance")

      end

     uvm_config_db#(virtual UART_IF)::set( this, "sqr", "vif", vif);

     uvm_config_db#(virtual UART_IF)::set( this, "drv", "vif", vif);

     uvm_config_db#(virtual UART_IF)::set( this, "mon", "vif", vif);

   endfunction: build_phase

   //Connect - driver and sequencer port to export

   virtual function void connect_phase(uvm_phase phase);

      drv.seq_item_port.connect(sqr.seq_item_export);

     uvm_report_info("uart_tx_agent::", "connect_phase, Connected driver to sequencer");

     endfunction

       

      endclass

/////////////////////////////////////////////////////////

     

      class uart_rx_monitor extends uvm_monitor;

     virtual UART_IF vif;

         uart_tx tr;

  //Analysis port -parameterized to apb_rw transaction

  ///Monitor writes transaction objects to this port once detected on interface

        uvm_analysis_port#(uart_tx) item_collected_port_rx;

  //config class handle

// uart_tx_config cfg;

        `uvm_component_utils(uart_rx_monitor)

   function new(string name, uvm_component parent = null);

     super.new(name, parent);

     item_collected_port_rx = new("item_collected_port_rx", this);

   endfunction: new

   //Build Phase - Get handle to virtual if from agent/config_db

   virtual function void build_phase(uvm_phase phase);

     uart_rx_agent agent;

     if ($cast(agent, get_parent()) && agent != null) begin

       vif = agent.vif;

     end

     else begin

       virtual UART_IF tmp;

     if (!uvm_config_db#(virtual UART_IF)::get(this, "", "UART_IF", vif)) begin

       `uvm_fatal("UART/MON/NOVIF", "No virtual interface specified for this monitor instance")

       end

       vif = tmp;

     end

   endfunction

       

       

       

   

virtual task run_phase(uvm_phase phase);

  //   super.run_phase(phase);

     uart_tx tr;

     tr =uart_tx::type_id::create("tr");

    forever begin

      @(posedge vif.i_Clock)

      if(vif.o_RX_DV==1) begin

         tr.r_RX_Byte = vif.o_RX_Byte;

         //vif.o_RX_DV = 1'b1;

         //tr.r_RX_DV = vif.o_RX_DV;

     

      uvm_report_info("UART_RX_MONITER ", $psprintf("Got Transaction %s",tr.convert4string()));

     

        @(posedge vif.i_Clock)

      item_collected_port_rx.write(tr);

         //vif.o_RX_DV = 1'b0;

      end

    end

     

      endtask

     

      endclass: uart_rx_monitor

////////////////////////////////////////////////////////

     

        class uart_rx_agent extends uvm_agent;

   //Agent will have the sequencer, driver and monitor components for the APB interface

   

   uart_rx_monitor mon;

   uart_tx_sequencer  sqr;

   uart_tx_driver drv;

   virtual UART_IF  vif;

         

    uvm_active_passive_enum is_active = UVM_PASSIVE;

    `uvm_component_utils_begin (uart_rx_agent)   

          `uvm_field_object(mon, UVM_ALL_ON)

          `uvm_field_object(sqr, UVM_ALL_ON)

          `uvm_field_object(drv, UVM_ALL_ON)

   `uvm_component_utils_end

   

   function new(string name, uvm_component parent = null);

      super.new(name, parent);

   endfunction

   //Build phase of agent - construct sequencer, driver and monitor

   //get handle to virtual interface from env (parent) config_db

   //and pass handle down to srq/driver/monitor

   virtual function void build_phase(uvm_phase phase);

     

     if(is_active==UVM_ACTIVE) begin

      sqr = uart_tx_sequencer::type_id::create("sqr", this);

      drv = uart_tx_driver::type_id::create("drv", this);

     end

      mon = uart_rx_monitor::type_id::create("mon", this);

             

     if (!uvm_config_db#(virtual UART_IF)::get(this, "", "vif", vif)) begin

         `uvm_fatal("APB/AGT/NOVIF", "No virtual interface specified for this agent instance")

      end

     if (is_active==UVM_ACTIVE) begin

     uvm_config_db#(virtual UART_IF)::set( this, "sqr", "vif", vif);

     uvm_config_db#(virtual UART_IF)::set( this, "drv", "vif", vif);

       

     end

         

     uvm_config_db#(virtual UART_IF)::set( this, "mon", "vif", vif);

   

     

   endfunction: build_phase

         

   //Connect - driver and sequencer port to export

   virtual function void connect_phase(uvm_phase phase);

     if (is_active==UVM_ACTIVE) begin

      drv.seq_item_port.connect(sqr.seq_item_export);

      end

   

     endfunction

     

      endclass : uart_rx_agent

///////////////////////////////////////////////////////////////

     

   class uart_scoreboard extends uvm_scoreboard;

  `uvm_component_utils(uart_scoreboard);

                       

     uvm_tlm_analysis_fifo #(uart_tx) tx_fifo;

     uvm_tlm_analysis_fifo #(uart_tx) rx_fifo;

 

  uart_tx  input_sequence_item;

  uart_tx output_sequence_item;

                 

  function new(string name,uvm_component parent);

    super.new(name,parent);

  endfunction  

               

  function void build_phase(uvm_phase phase);

    super.build_phase(phase);

    tx_fifo = new("tx_fifo",this);

    rx_fifo = new("rx_fifo",this);

  endfunction

 

   task run_phase(uvm_phase phase);

   uart_tx input_sequence_item, output_sequence_item;

  forever begin

    `uvm_info("scoreboard run task", "Waiting for EXPECTED values",UVM_MEDIUM)

    tx_fifo.get(input_sequence_item);

    `uvm_info("scoreboard run task", "Waiting for ACTUAL values",UVM_MEDIUM)

    rx_fifo.get(output_sequence_item);

   

    //`uvm_info("scoreboard ",$sformatf( "input_sequence_item=%h output_sequence_item=%h",input_sequence_item.convert3string(), output_sequence_item.convert33string()),UVM_MEDIUM)

   

    `uvm_info("scoreboard ",$sformatf( "input_sequence_item=%h output_sequence_item=%h",input_sequence_item.i_TX_Byte, output_sequence_item.r_RX_Byte),UVM_MEDIUM)

    ///////////////////////////////////////////////////////////////////

 

    if (output_sequence_item.r_RX_Byte == input_sequence_item.i_TX_Byte) begin

   

      //////////////////////////////////////////////////////////////////  

      `uvm_info ("ACTUAL = EXPECTED ", $sformatf("ACTUAL=%s EXPECTED=%s \n",output_sequence_item.convert33string(),input_sequence_item.convert3string()), UVM_NONE);

      $display("PPPPPPP    AA     SSSSSSS   SSSSSSS\nPP   PP  AA  AA   SS        SS\nPPPPPP  AAAAAAAA  SSSSSSS   SSSSSSS\nPP      AA    AA       SS        SS\nPP      AA    AA  SSSSSSS   SSSSSSS");

    end  

else begin

  `uvm_error("ACTUAL != EXPECTED", $sformatf("ACTUAL=%s EXPECTED=%s \n",output_sequence_item.convert33string(), input_sequence_item.convert3string()));

 

$display("FFFFFFF    AA     IIIIIIII   LL\nFF       AA  AA      II      LL\nFFFFF   AAAAAAAA     II      LL\nFF      AA    AA     II      LL\nFF      AA    AA  IIIIIIII   LLLLLLL");

end

end

endtask

endclass:uart_scoreboard

 

//endclass:fifo_scoreboard

/////////////////////////////////////////////////////////////////////////////

     

/////////////////////////////////////////////////////////////////////////////

class uart_env  extends uvm_env;

  virtual UART_IF  vif;

   `uvm_component_utils(uart_env);

     uart_tx_agent agent_tx;

     uart_rx_agent agent_rx;

  uart_scoreboard scoreboard;

   //ENV class will have agent as its sub component

  // apb_agent  agt;

   //virtual interface for APB interface

 

   function new(string name, uvm_component parent = null);

      super.new(name, parent);

   endfunction

   //Build phase - Construct agent and get virtual interface handle from test  and pass it down to agent

   function void build_phase(uvm_phase phase);

     agent_tx = uart_tx_agent::type_id::create("agent_tx", this);

     agent_rx = uart_rx_agent::type_id::create("agent_rx", this);

    scoreboard =uart_scoreboard::type_id::create("scoreboard",this);   

     if (!uvm_config_db#(virtual UART_IF)::get(this, "", "vif", vif)) begin

         `uvm_fatal("APB/AGT/NOVIF", "No virtual interface specified for this env instance")

     end

     uvm_config_db#(virtual UART_IF)::set( this, "agent_tx", "vif", vif);

     uvm_config_db#(virtual UART_IF)::set( this, "agent_rx", "vif", vif);

   endfunction: build_phase

   

  function void connect_phase(uvm_phase phase);

    agent_tx.mon.item_collected_port_tx.connect(scoreboard.tx_fifo.analysis_export);

    `uvm_info("environment","TX monitor  connected scoreboard",UVM_LOW);   

    agent_rx.mon.item_collected_port_rx.connect(scoreboard.rx_fifo.analysis_export);

    `uvm_info("environment","RX monitor connected to scoreboard",UVM_LOW);

  endfunction  

             

              endclass:uart_env

       

//////////////////////////////////////////////////////////////////////////

        class uart_base_test extends uvm_test;

  //Register with factory

          `uvm_component_utils(uart_base_test);

uart_env  env;

  uart_tx_config cfg;

           uart_tx_seq uart_seq;

  virtual UART_IF vif;

 

          function new(string name = "uart_base_test", uvm_component parent = null);

    super.new(name, parent);

  endfunction

  //Build phase - Construct the cfg and env class using factory

  //Get the virtual interface handle from Test and then set it config db for the env component

  function void build_phase(uvm_phase phase);

    cfg = uart_tx_config::type_id::create("cfg", this);

    env = uart_env::type_id::create("env", this);

    //

    if (!uvm_config_db#(virtual UART_IF)::get(this, "", "vif", vif)) begin

      `uvm_fatal("UART/DRV/NOVIF", "No virtual interface specified for this test instance")

    end

    uvm_config_db#(virtual UART_IF)::set( this, "env", "vif", vif);

  endfunction

  //Run phase - Create an abp_sequence and start it on the apb_sequencer

  task run_phase( uvm_phase phase );

    uart_tx_seq uart_seq;

    uart_seq = uart_tx_seq::type_id::create("uart_seq");

    phase.raise_objection( this, "Starting uart_tx_seqin main phase" );

    `uvm_info ("UART/TEST","Phase raise Objection",UVM_LOW)

    $display("%t Starting sequence uart_seq run_phase",$time);

    uart_seq.start(env.agent_tx.sqr);

    #100000ns;

    phase.drop_objection( this , "Finished uart_seq in main phase" );

    `uvm_info ("UART/TEST","Phase drop Objection",UVM_LOW)

    $display("%t ending sequence uart_seq run_phase",$time);

  endtask: run_phase

 

 

endclass  

              endpackage

////////////////////////////////////////////////////////

             

//`timescale 1ns/10ps

`include "UART_TX.v"

module UART_TB ();

 

   import uvm_pkg::*;

   import my_pkg::*;


  UART_IF vif();

  // Testbench uses a 25 MHz clock

  // Want to interface to 115200 baud UART

  // 25000000 / 115200 = 217 Clocks Per Bit.

  parameter c_CLOCK_PERIOD_NS = 40;

  parameter c_CLKS_PER_BIT    = 217;

  parameter c_BIT_PERIOD      = 8600;

 

  bit i_Clock;

  wire y;

  wire x;

  UART_RX #(c_CLKS_PER_BIT) UART_RX_Inst

  (.i_Clock(vif.i_Clock),

   .i_RX_Serial(x),

     .o_RX_DV(vif.o_RX_DV),

   .o_RX_Byte(vif.o_RX_Byte)

     );

 

  UART_TX #(c_CLKS_PER_BIT) UART_TX_Inst

     (.i_Clock(vif.i_Clock),

     .i_TX_DV(vif.i_TX_DV),

    .i_TX_Byte(vif.i_TX_Byte),

     .o_TX_Active(vif.o_TX_Active),

      .o_TX_Serial(y),

      .i_Rst_L(vif.i_Rst_L),

      .o_Bit_Clk(vif.o_Bit_Clk),

     .o_TX_Done()

     );

 

 

   always begin

     #(c_CLOCK_PERIOD_NS/2) i_Clock = !i_Clock;

   

 

//     $display("top_i_Clock=%d ",i_Clock);

     

   end

  initial begin

     

    //Pass this physical interface to test top (which will further pass it down to env->agent->drv/sqr/mon

    uvm_config_db#(virtual UART_IF)::set(null,"*", "vif", vif);

   

    `uvm_info("top","uvm_config_db set for uvm_test_top",UVM_LOW);

    //Call the test - but passing run_test argument as test class name

    //Another option is to not pass any test argument and use +UVM_TEST on command line to sepecify which test to run

    run_test("uart_base_test");

  end

 

   

// initial $dumpvars(0, UART_TB);

   assign vif.i_Clock=i_Clock;

   assign x = y;

 

 

  initial  begin

    $dumpfile("dump.vcd");

    $dumpvars(0,UART_TB);

  #2000ns;

  end

 

endmodule



interface UART_IF;

 

  //rx

  parameter c_CLOCK_PERIOD_NS = 40;

   logic        i_Clock;

   logic        i_Rst_L;

   logic        i_RX_Serial;

   logic        o_RX_DV ;

   logic    [7:0] o_RX_Byte;

 

  //tx

 

   logic        i_TX_DV;

   logic    [7:0] i_TX_Byte;

   logic      o_TX_Active;

   logic      o_TX_Serial;

   logic      o_TX_Done ;

   logic      o_Bit_Clk;

 

   

 


/* clocking UART_TX @(posedge i_Clock);

   

    output i_Clock,i_TX_DV ,i_TX_Byte;

   

    input o_TX_Active,o_TX_Serial,o_TX_Done;

   

  endclocking : UART_TX

 

  clocking UART_RX @(posedge i_Clock);

   

    output i_Clock,i_RX_Serial;

   

    input o_RX_DV,o_RX_Byte;

   

  endclocking : UART_RX

  clocking MONITER @(posedge i_Clock);

    input i_Clock,i_TX_DV ,i_TX_Byte,o_TX_Active,o_TX_Serial,o_TX_Done  , i_RX_Serial, o_RX_DV,o_RX_Byte;

   

  endclocking: MONITER

 

  modport uart_tx(clocking UART_TX);

  modport uart_rx(clocking UART_RX);

  modport moniter(clocking MONITER);*/

   

 

    endinterface : UART_IF

   

 

 

 


//////////////////////////////////////////////////////////////////////

// File Downloaded from http://www.nandland.com

//////////////////////////////////////////////////////////////////////

// This file contains the UART Receiver.  This receiver is able to

// receive 8 bits of serial data, one start bit, one stop bit,

// and no parity bit.  When receive is complete o_rx_dv will be

// driven high for one clock cycle.

//

// Set Parameter CLKS_PER_BIT as follows:

// CLKS_PER_BIT = (Frequency of i_Clock)/(Frequency of UART)

// Example: 25 MHz Clock, 115200 baud UART

// (25000000)/(115200) = 217


module UART_RX

  #(parameter CLKS_PER_BIT = 217)

  (

   input        i_Clock,

   input        i_RX_Serial,

   output       o_RX_DV,

   output [7:0] o_RX_Byte

   );

   

  parameter IDLE         = 3'b000;

  parameter RX_START_BIT = 3'b001;

  parameter RX_DATA_BITS = 3'b010;

  parameter RX_STOP_BIT  = 3'b011;

  parameter CLEANUP      = 3'b100;

 

  reg [7:0] r_Clock_Count = 0;

  reg [2:0] r_Bit_Index   = 0; //8 bits total

  reg [7:0] r_RX_Byte     = 0;

  reg       r_RX_DV       = 0;

  reg [2:0] r_SM_Main     = 0;

 

 

  // Purpose: Control RX state machine

  always @(posedge i_Clock)

  begin

     

    case (r_SM_Main)

      IDLE :

        begin

          r_RX_DV       <= 1'b0;

          r_Clock_Count <= 0;

          r_Bit_Index   <= 0;

         

          if (i_RX_Serial == 1'b0)          // Start bit detected

            r_SM_Main <= RX_START_BIT;

          else

            r_SM_Main <= IDLE;

        end

     

      // Check middle of start bit to make sure it's still low

      RX_START_BIT :

        begin

          if (r_Clock_Count == (CLKS_PER_BIT-1)/2)

          begin

            if (i_RX_Serial == 1'b0)

            begin

              r_Clock_Count <= 0;  // reset counter, found the middle

              r_SM_Main     <= RX_DATA_BITS;

            end

            else

              r_SM_Main <= IDLE;

          end

          else

          begin

            r_Clock_Count <= r_Clock_Count + 1;

            r_SM_Main     <= RX_START_BIT;

          end

        end // case: RX_START_BIT

     

     

      // Wait CLKS_PER_BIT-1 clock cycles to sample serial data

      RX_DATA_BITS :

        begin

          if (r_Clock_Count < CLKS_PER_BIT-1)

          begin

            r_Clock_Count <= r_Clock_Count + 1;

            r_SM_Main     <= RX_DATA_BITS;

          end

          else

          begin

            r_Clock_Count          <= 0;

            r_RX_Byte[r_Bit_Index] <= i_RX_Serial;

           

            // Check if we have received all bits

            if (r_Bit_Index < 7)

            begin

              r_Bit_Index <= r_Bit_Index + 1;

              r_SM_Main   <= RX_DATA_BITS;

            end

            else

            begin

              r_Bit_Index <= 0;

              r_SM_Main   <= RX_STOP_BIT;

            end

          end

        end // case: RX_DATA_BITS

     

     

      // Receive Stop bit.  Stop bit = 1

      RX_STOP_BIT :

        begin

          // Wait CLKS_PER_BIT-1 clock cycles for Stop bit to finish

          if (r_Clock_Count < CLKS_PER_BIT-1)

          begin

            r_Clock_Count <= r_Clock_Count + 1;

          r_SM_Main     <= RX_STOP_BIT;

          end

          else

          begin

            r_RX_DV       <= 1'b1;

            r_Clock_Count <= 0;

            r_SM_Main     <= CLEANUP;

          end

        end // case: RX_STOP_BIT

     

     

      // Stay here 1 clock

      CLEANUP :

        begin

          r_SM_Main <= IDLE;

          r_RX_DV   <= 1'b0;

        end

     

     

      default :

        r_SM_Main <= IDLE;

     

    endcase

  end   

 

  assign o_RX_DV   = r_RX_DV;

  assign o_RX_Byte = r_RX_Byte ^ 1;

 

endmodule // UART_RX



//////////////////////////////////////////////////////////////////////

// Author: Russell Merrick

//////////////////////////////////////////////////////////////////////

// This file contains the UART Transmitter.  This transmitter is able

// to transmit 8 bits of serial data, one start bit, one stop bit,

// and no parity bit.  When transmit is complete o_Tx_done will be

// driven high for one clock cycle.

//

// Set Parameter CLKS_PER_BIT as follows:

// CLKS_PER_BIT = (Frequency of i_Clock)/(Frequency of UART)

// Example: 25 MHz Clock, 115200 baud UART

// (25000000)/(115200) = 217


module UART_TX

  #(parameter CLKS_PER_BIT = 217)

  (

   output reg  i_Rst_L = 1,

   input       i_Clock,

   input       i_TX_DV,

   input [7:0] i_TX_Byte,

   output reg  o_TX_Active = 1,

   output reg  o_TX_Serial,

   output reg  o_Bit_Clk = 0,

   output reg  o_TX_Done = 0

   );


  localparam IDLE         = 2'b00;

  localparam TX_START_BIT = 2'b01;

  localparam TX_DATA_BITS = 2'b10;

  localparam TX_STOP_BIT  = 2'b11;

 

  reg [2:0] r_SM_Main;

  reg [$clog2(CLKS_PER_BIT):0] r_Clock_Count;

  reg [2:0] r_Bit_Index;

  reg [7:0] r_TX_Data = 0;

  reg  r_TX_Bit = 0;

  reg  [3:0] r_Bit_Count = -1;

  reg [7:0] r_Clock_Countr = 0;

 

  always @(posedge i_Clock or negedge i_Rst_L)

    if(r_Clock_Countr == 217)

      r_Clock_Countr <= 0;

    else

      r_Clock_Countr <= r_Clock_Countr + 1;

  always @(posedge i_Clock or negedge i_Rst_L)

    if(r_Clock_Countr == 8'h01)

      r_TX_Bit =~ r_TX_Bit;

    else

      r_TX_Bit <= r_TX_Bit;

 

  always @(negedge r_TX_Bit)

    if(r_Bit_Count == 11)

      r_Bit_Count <= 0;

    else

        r_Bit_Count <= r_Bit_Count + 1;

 

  always @(r_TX_Bit)

    if(r_Bit_Count < 5)

      o_Bit_Clk =1;

    else if(r_Bit_Count > 5)

      o_Bit_Clk =0;

    else

      o_Bit_Clk <= o_Bit_Clk;

   

  // Purpose: Control TX state machine

  always @(posedge i_Clock or negedge i_Rst_L)

  begin

    if (~i_Rst_L)

    begin

      r_SM_Main <= 3'b000;

    end

    else

    begin

     

      o_TX_Done <= 1'b0;

      case (r_SM_Main)

      IDLE :

        begin

          o_TX_Serial   <= 1'b1;         // Drive Line High for Idle

          r_Clock_Count <= 0;

          r_Bit_Index   <= 0;

         

          if (i_TX_DV == 1'b1)

          begin

            o_TX_Active <= 1'b1;

            r_TX_Data   <= i_TX_Byte;

            r_SM_Main   <= TX_START_BIT;

          end

          else

            r_SM_Main <= IDLE;

        end // case: IDLE

     

     

      // Send out Start Bit. Start bit = 0

      TX_START_BIT :

        begin

          o_TX_Serial <= 1'b0;

         

          // Wait CLKS_PER_BIT-1 clock cycles for start bit to finish

          if (r_Clock_Count < CLKS_PER_BIT-1)

          begin

            r_Clock_Count <= r_Clock_Count + 1;

            r_SM_Main     <= TX_START_BIT;

          end

          else

          begin

            r_Clock_Count <= 0;

            r_SM_Main     <= TX_DATA_BITS;

          end

        end // case: TX_START_BIT

     

     

      // Wait CLKS_PER_BIT-1 clock cycles for data bits to finish         

      TX_DATA_BITS :

        begin

          o_TX_Serial <= r_TX_Data[r_Bit_Index];

         

          if (r_Clock_Count < CLKS_PER_BIT-1)

          begin

            r_Clock_Count <= r_Clock_Count + 1;

            r_SM_Main     <= TX_DATA_BITS;

          end

          else

          begin

            r_Clock_Count <= 0;

           

            // Check if we have sent out all bits

            if (r_Bit_Index < 7)

            begin

              r_Bit_Index <= r_Bit_Index + 1;

              r_SM_Main   <= TX_DATA_BITS;

            end

            else

            begin

              r_Bit_Index <= 0;

              r_SM_Main   <= TX_STOP_BIT;

            end

          end

        end // case: TX_DATA_BITS

     

     

      // Send out Stop bit.  Stop bit = 1

      TX_STOP_BIT :

        begin

          o_TX_Serial <= 1'b1;

         

          // Wait CLKS_PER_BIT-1 clock cycles for Stop bit to finish

          if (r_Clock_Count < CLKS_PER_BIT-1)

          begin

            r_Clock_Count <= r_Clock_Count + 1;

            r_SM_Main     <= TX_STOP_BIT;

          end

          else

          begin

            o_TX_Done     <= 1'b1;

            r_Clock_Count <= 0;

            r_SM_Main     <= IDLE;

            o_TX_Active   <= 1'b0;

          end

        end // case: TX_STOP_BIT     

     

      default :

        r_SM_Main <= IDLE;

     

    endcase

    end // else: !if(~i_Rst_L)

  end // always @ (posedge i_Clock or negedge i_Rst_L)

 

endmodule

Content Disclaimer

Informasi ini disarikan dari Wikipedia dan disajikan kembali untuk tujuan edukasi. Konten tersedia di bawah lisensi CC BY-SA 3.0. Kami tidak bertanggung jawab atas ketidakakuratan data yang bersumber dari kontribusi publik tersebut.

  1. The information displayed on this website is sourced in part or in whole from Wikipedia and has been adapted for the purpose of restating it. We strive to provide accurate and relevant information, however:
  2. There is no guarantee of absolute accuracy. Wikipedia is an open, collaborative project that can be edited by anyone, so information is subject to change.
  3. It is not intended to constitute professional advice. The content displayed is for informational and educational purposes only. For important decisions (e.g., medical, legal, or financial), please consult a professional.
  4. Content copyright. Wikipedia is licensed under the Creative Commons Attribution-ShareAlike License (CC BY-SA). This means that content may be reused with appropriate attribution and shared under a similar license.
  5. Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.