|  | // 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 | 
|  | ); | 
|  |  | 
|  | localparam CYCLES_PER_SYMBOL = FREQ/BAUD; | 
|  |  | 
|  | import "DPI-C" function | 
|  | chandle uartdpi_create(input string name); | 
|  |  | 
|  | 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; | 
|  | int file_handle; | 
|  | string file_name; | 
|  |  | 
|  | initial begin | 
|  | ctx = uartdpi_create(NAME); | 
|  | $sformat(file_name, "%s.log", NAME); | 
|  | file_handle = $fopen(file_name, "w"); | 
|  | end | 
|  |  | 
|  | // TX | 
|  | reg txactive; | 
|  | int  txcount; | 
|  | int  txcyccount; | 
|  | reg [9:0] txsymbol; | 
|  |  | 
|  | 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) begin | 
|  | txcyccount <= 0; | 
|  | if (txcount == 9) | 
|  | txactive <= 0; | 
|  | else | 
|  | txcount <= txcount + 1; | 
|  | end | 
|  | end | 
|  | end | 
|  | 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; | 
|  | end else begin | 
|  | if (!rxactive) begin | 
|  | if (!rx_i) begin | 
|  | rxactive <= 1; | 
|  | rxcount <= 0; | 
|  | rxcyccount <= 0; | 
|  | end | 
|  | end else begin | 
|  | if (rxcount == 0) begin | 
|  | if (rxcyccount == CYCLES_PER_SYMBOL/2) 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) begin | 
|  | rxsymbol[rxcount-1] <= rx_i; | 
|  | rxcount <= rxcount + 1; | 
|  | rxcyccount <= 0; | 
|  | end | 
|  | end else begin | 
|  | if (rxcyccount == CYCLES_PER_SYMBOL) begin | 
|  | rxactive <= 0; | 
|  | if (rx_i) begin | 
|  | uartdpi_write(ctx, rxsymbol); | 
|  | $fwrite(file_handle, "%c", rxsymbol); | 
|  | end | 
|  | end | 
|  | end | 
|  | end | 
|  | end // else: !if(rst) | 
|  | end | 
|  |  | 
|  | endmodule |