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.
- 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:
- 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.
- 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.
- 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.
- Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.