blob: 97fae47674df4b64622b932c6532d32995b2785e [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
module uartdpi #(
parameter BAUD = 'x,
parameter FREQ = 'x,
parameter string NAME = "uart0"
)(
input logic clk_i,
input logic rst_ni,
output logic tx_o,
input logic rx_i
);
// Path to a log file. Used if none is specified through the `UARTDPI_LOG_<name>` plusarg.
localparam string DEFAULT_LOG_FILE = {NAME, ".log"};
// Min cycles is 2 for fast test mode
localparam int CYCLES_PER_SYMBOL = FREQ / BAUD;
import "DPI-C" function
chandle uartdpi_create(input string name, input string log_file_path);
import "DPI-C" function
void uartdpi_close(input chandle ctx);
import "DPI-C" function
byte uartdpi_read(input chandle ctx);
import "DPI-C" function
int uartdpi_can_read(input chandle ctx);
import "DPI-C" function
void uartdpi_write(input chandle ctx, int data);
chandle ctx;
string log_file_path = DEFAULT_LOG_FILE;
initial begin
$value$plusargs({"UARTDPI_LOG_", NAME, "=%s"}, log_file_path);
ctx = uartdpi_create(NAME, log_file_path);
end
final begin
uartdpi_close(ctx);
ctx = null;
end
// TX
reg txactive;
int txcount;
int txcyccount;
reg [9:0] txsymbol;
reg seen_reset;
always_ff @(negedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
tx_o <= 1;
txactive <= 0;
end else begin
if (!txactive) begin
tx_o <= 1;
if (uartdpi_can_read(ctx)) begin
automatic int c = uartdpi_read(ctx);
txsymbol <= {1'b1, c[7:0], 1'b0};
txactive <= 1;
txcount <= 0;
txcyccount <= 0;
end
end else begin
txcyccount <= txcyccount + 1;
tx_o <= txsymbol[txcount];
if (txcyccount == CYCLES_PER_SYMBOL - 1) begin
txcyccount <= 0;
if (txcount == 9)
txactive <= 0;
else
txcount <= txcount + 1;
end
end
end
end
initial begin
// Prevent falling edges of rx_i before reset causing spurious characters
seen_reset = 0;
end
// RX
reg rxactive;
int rxcount;
int rxcyccount;
reg [7:0] rxsymbol;
always_ff @(negedge clk_i or negedge rst_ni) begin
rxcyccount <= rxcyccount + 1;
if (!rst_ni) begin
rxactive <= 0;
seen_reset <= 1;
end else begin
if (!rxactive) begin
if (!rx_i && seen_reset) begin
rxactive <= 1;
rxcount <= 0;
rxcyccount <= 0;
end
end else begin
if (rxcount == 0) begin
if (rxcyccount == CYCLES_PER_SYMBOL/2 - 1) begin
if (rx_i) begin
rxactive <= 0;
end else begin
rxcount <= rxcount + 1;
rxcyccount <= 0;
end
end
end else if (rxcount <= 8) begin
if (rxcyccount == CYCLES_PER_SYMBOL - 1) begin
rxsymbol[rxcount-1] <= rx_i;
rxcount <= rxcount + 1;
rxcyccount <= 0;
end
end else begin
if (rxcyccount == CYCLES_PER_SYMBOL - 1) begin
rxactive <= 0;
if (rx_i) begin
uartdpi_write(ctx, rxsymbol);
end
end
end
end
end
end
endmodule