首次提交
This commit is contained in:
215
stream_rx_buffer/sim/func001/vip_uart.sv
Normal file
215
stream_rx_buffer/sim/func001/vip_uart.sv
Normal file
@@ -0,0 +1,215 @@
|
||||
`ifndef _VIP_UART_SV_
|
||||
`define _VIP_UART_SV_
|
||||
|
||||
module vip_uart
|
||||
(
|
||||
input logic rx,
|
||||
output logic tx
|
||||
);
|
||||
|
||||
parameter CAPTURE = "none"; // "none": no capture, "hex": hex capture, "raw": raw capture(ascii)
|
||||
parameter DW = 8;
|
||||
parameter BAUD_RATE = 115200;
|
||||
parameter CHK_MODE = "none";
|
||||
parameter STOP_BITS = 1.0;
|
||||
parameter BAUD_ERROR = 0.0;
|
||||
parameter SAMPLES = 32;
|
||||
parameter SAMPLE_TH = $floor(SAMPLES*0.9);
|
||||
parameter IDLE_BYTES_MS = 0;
|
||||
|
||||
parameter RX_BIT_WIDTH_NS = 1.0/(BAUD_RATE) * 1e9;//receiption do not take baud rate skew into account
|
||||
parameter TX_BIT_WIDTH_NS = 1.0/(BAUD_RATE * (1 - BAUD_ERROR)) * 1e9;//transmit takes baud rate skew into account
|
||||
|
||||
parameter TX_STOP_WIDTH_NS = STOP_BITS * TX_BIT_WIDTH_NS;
|
||||
parameter RX_SAMPLE_WIDTH_NS = RX_BIT_WIDTH_NS/SAMPLES;
|
||||
|
||||
parameter integer STOP_BIT_SAMPLES = $ceil(STOP_BITS*SAMPLES);
|
||||
|
||||
logic rx_clk;
|
||||
logic [SAMPLES-1:0] rx_sample_bits;
|
||||
logic [STOP_BIT_SAMPLES-1:0] rx_sample_stop_bits;
|
||||
logic [DW-1:0]rx_data;//valid while rx_valid =1
|
||||
logic rx_valid;//asserted when a new word receiption has just completed,deasserted when new receiption starts,
|
||||
logic parity_error;//asserted when a parity error has been detected,deasserted when new receiption starts
|
||||
logic stop_error;//asserted when a stop error has been detected,deasserted when new receiption starts
|
||||
|
||||
initial begin
|
||||
tx = 1;
|
||||
rx_valid = 0;
|
||||
parity_error = 0;
|
||||
stop_error = 0;
|
||||
end
|
||||
|
||||
initial begin
|
||||
integer log_file;
|
||||
string full_path;
|
||||
string instance_name;
|
||||
int last_dot_pos;
|
||||
|
||||
// Get the full hierarchical path into a string
|
||||
full_path = $sformatf("%m");
|
||||
|
||||
instance_name = full_path;
|
||||
|
||||
if (CAPTURE != "none") begin
|
||||
log_file = $fopen({instance_name,"_capture.log"},"w");
|
||||
if(log_file == 0) begin
|
||||
$error("Failed to open log file for writing.");
|
||||
end
|
||||
end
|
||||
|
||||
if (CAPTURE == "hex") begin
|
||||
$fwrite(log_file,"# %s hex capture log:\n",instance_name);
|
||||
forever begin
|
||||
repeat(16) begin
|
||||
@(posedge rx_valid);
|
||||
$fwrite(log_file,"%02x ",rx_data);
|
||||
$fwrite(log_file,"\n");
|
||||
end
|
||||
end
|
||||
end else if (CAPTURE == "raw") begin
|
||||
$fwrite(log_file,"// %s raw capture log:\n",instance_name);
|
||||
forever @(posedge rx_valid) begin
|
||||
$fwrite(log_file,"%c",rx_data);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
task automatic send(logic [DW-1:0] data);
|
||||
tx = 0;
|
||||
#(TX_BIT_WIDTH_NS*1ns);
|
||||
for(int i = 0;i < DW;i++) begin
|
||||
tx = data[i];
|
||||
#(TX_BIT_WIDTH_NS*1ns);
|
||||
end
|
||||
|
||||
case (CHK_MODE)
|
||||
"odd":begin
|
||||
tx = (^data) ^ 1;
|
||||
#(TX_BIT_WIDTH_NS*1ns);
|
||||
end
|
||||
"even":begin
|
||||
tx = (^data) ^ 0;
|
||||
#(TX_BIT_WIDTH_NS*1ns);
|
||||
end
|
||||
endcase
|
||||
|
||||
tx = 1;
|
||||
#(TX_STOP_WIDTH_NS*1ns);
|
||||
#(IDLE_BYTES_MS*1ms);
|
||||
endtask
|
||||
|
||||
initial begin
|
||||
rx_clk = 0;
|
||||
forever begin
|
||||
rx_clk =#(RX_BIT_WIDTH_NS/SAMPLES/2*1ns) ~rx_clk;//generate 32x clk for receive
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function automatic logic vote(logic [SAMPLES-1:0] data,int th);
|
||||
int count_ones = 0;
|
||||
logic [SAMPLES-1:0] mask;
|
||||
|
||||
int i = 0;
|
||||
do begin
|
||||
i++;
|
||||
end while(data[i] == 0 && i < SAMPLES);//jump over contineous zeros
|
||||
|
||||
do begin
|
||||
i++;
|
||||
end while(data[i] == 1 && i < SAMPLES);//jump over contineous ones
|
||||
|
||||
mask = ~(2**i-1);
|
||||
if(i < SAMPLES && (data & mask != 0)) begin//the remaining should be all zeros
|
||||
$warning("samples=%b,glitch occured",data);
|
||||
end
|
||||
|
||||
foreach(data[i]) begin
|
||||
count_ones = data[i] ? (count_ones + 1) : count_ones;//only logic high is weighted
|
||||
end
|
||||
|
||||
if(count_ones >= th) begin//find the majority by threshold
|
||||
return 1;
|
||||
end else begin
|
||||
return 0;
|
||||
end;
|
||||
endfunction
|
||||
|
||||
initial begin
|
||||
forever begin
|
||||
receive();
|
||||
end
|
||||
end
|
||||
|
||||
task automatic receive();
|
||||
logic stop_bit;
|
||||
logic calc_parity;
|
||||
logic parity_bit;
|
||||
logic rx_bit;
|
||||
@(negedge rx);
|
||||
rx_valid = 0;
|
||||
parity_error = 0;
|
||||
stop_error = 0;
|
||||
|
||||
sample_one_bit(rx_bit);
|
||||
if(rx_bit == 0) begin
|
||||
for(int i = 0;i<DW;i++)begin
|
||||
sample_one_bit(rx_data[i]);
|
||||
end
|
||||
|
||||
case (CHK_MODE)
|
||||
"odd","even":begin
|
||||
sample_one_bit(parity_bit);
|
||||
end
|
||||
endcase
|
||||
|
||||
do_sample(STOP_BIT_SAMPLES, rx_sample_stop_bits);
|
||||
stop_bit = vote(rx_sample_stop_bits,STOP_BIT_SAMPLES*0.9);
|
||||
|
||||
calc_parity = (^rx_data) ^ parity_bit;
|
||||
case (CHK_MODE)
|
||||
"odd":begin
|
||||
if(calc_parity != 1) begin
|
||||
$warning("%s parity error,data=%08b,parity=%01b",CHK_MODE,rx_data,parity_bit);
|
||||
parity_error = 1;
|
||||
end
|
||||
end
|
||||
"even":begin
|
||||
if(calc_parity != 0) begin
|
||||
$warning("%s parity error,data=%08b,parity=%01b",CHK_MODE,rx_data,parity_bit);
|
||||
parity_error = 1;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
|
||||
if(stop_bit != 1) begin
|
||||
$warning("stop error,stop=%f,samples = %b",STOP_BITS,rx_sample_bits);
|
||||
stop_error = 1;
|
||||
end
|
||||
|
||||
rx_valid = 1;
|
||||
end else begin
|
||||
$display("searching start bit...,samples = %b",rx_sample_bits);
|
||||
end
|
||||
|
||||
endtask
|
||||
|
||||
task automatic sample_one_bit(output logic rx_bit);
|
||||
do_sample(SAMPLES, rx_sample_bits);
|
||||
rx_bit = vote(rx_sample_bits, SAMPLE_TH);
|
||||
endtask
|
||||
|
||||
task automatic do_sample(input int xpoints, output logic [(STOP_BIT_SAMPLES > SAMPLES ? STOP_BIT_SAMPLES : SAMPLES)-1:0] rx_vec);
|
||||
rx_vec = 0;
|
||||
#((RX_SAMPLE_WIDTH_NS/2.0)*1ns);
|
||||
rx_vec[0] = rx;
|
||||
for(int i = 1;i<xpoints;i++) begin
|
||||
#(RX_SAMPLE_WIDTH_NS*1ns);
|
||||
rx_vec[i] = rx;
|
||||
end
|
||||
#((RX_SAMPLE_WIDTH_NS/2.0)*1ns);
|
||||
endtask
|
||||
endmodule
|
||||
|
||||
`endif
|
||||
Reference in New Issue
Block a user