`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 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