Skip to content

Commit

Permalink
rtl: Add FIFO in uart
Browse files Browse the repository at this point in the history
  • Loading branch information
saursin committed Dec 30, 2023
1 parent 53296bf commit da85ef0
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 19 deletions.
3 changes: 2 additions & 1 deletion rtl/config/uart.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"vdefines": [],
"vsrcs": [
"${RVATOM}/rtl/uncore/uart/UART.v",
"${RVATOM}/rtl/uncore/uart/UART_core.v"
"${RVATOM}/rtl/uncore/uart/UART_core.v",
"${RVATOM}/rtl/uncore/uart/FIFO_sync.v"
],
"incdirs": [
"${RVATOM}/rtl/common"
Expand Down
6 changes: 5 additions & 1 deletion rtl/soc/hydrogensoc/HydrogenSoC.v
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,11 @@ module HydrogenSoC(
wire uart_wb_ack_o;
wire uart_wb_err_o = 0;

UART uart (
UART #(
.DEFAULT_DIV(1),
.FIFO_EN (`SOC_UART_FIFO_EN),
.FIFO_DEPTH (`SOC_UART_FIFO_DEPTH)
) uart (
.wb_clk_i (wb_clk_i),
.wb_rst_i (wb_rst_i),

Expand Down
2 changes: 2 additions & 0 deletions rtl/soc/hydrogensoc/HydrogenSoC_Config.vh
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@
// `define SOC_EN_UART
`define SOC_UART_ADDR 32'h4000_0000
`define SOC_UART_SIZE 16 // 4 words
`define SOC_UART_FIFO_EN 1
`define SOC_UART_FIFO_DEPTH 4


/*
Expand Down
50 changes: 50 additions & 0 deletions rtl/uncore/uart/FIFO_sync.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
module FIFO_sync #(
parameter DEPTH = 32,
parameter DATAW = 8
)(
input wire clk_i,
input wire rst_i,
input wire we_i,
input wire re_i,
input wire [DATAW-1:0] dat_i,
output wire [DATAW-1:0] dat_o,
output wire full_o,
output wire empty_o
);
parameter ADDRW = $clog2(DEPTH);

reg [DATAW-1:0] mem [0: DEPTH-1];
reg [ADDRW:0] count;
reg [ADDRW-1:0] w_ptr;
reg [ADDRW-1:0] r_ptr;

wire enq_cond = we_i & !full_o;
wire deq_cond = re_i & !empty_o;

always@(posedge clk_i) begin
if(rst_i) begin
w_ptr <= 0;
r_ptr <= 0;
count <= 0;
end else begin
if(enq_cond)begin
mem[w_ptr] <= dat_i;
w_ptr <= w_ptr + 1;
count <= count +1;
end

if(deq_cond) begin
r_ptr <= r_ptr + 1;
count <= count - 1;
end

if(enq_cond && deq_cond) begin
count <= count;
end
end
end
assign dat_o = mem[r_ptr];

assign empty_o = (count == 0);
assign full_o = (count == DEPTH);
endmodule
75 changes: 58 additions & 17 deletions rtl/uncore/uart/UART.v
Original file line number Diff line number Diff line change
Expand Up @@ -7,36 +7,28 @@
`default_nettype none

module UART#(
parameter DEFAULT_DIV = 1
parameter DEFAULT_DIV = 1,
parameter FIFO_EN = 1,
parameter FIFO_DEPTH = 4
)(
// Wishbone Interface
input wire wb_clk_i,
input wire wb_rst_i,

input wire [3:2] wb_adr_i,
output reg [31:0] wb_dat_o,
input wire [31:0] wb_dat_i /* verilator public */,
input wire [31:0] wb_dat_i,
input wire wb_we_i,
input wire [3:0] wb_sel_i,

input wire wb_stb_i,
output reg wb_ack_o,

// Serial Interface
/* verilator lint_off UNUSED */
input wire rx_i,
/* verilator lint_on UNUSED */

/* verilator lint_off UNDRIVEN */
output wire tx_o
/* verilator lint_on UNDRIVEN */
);
////////////////////////////////////////////////////////////////////////////////////////////////////
/*
if __ATOMSIM_SIMULATION__ is defined, this module behaves as a stub. simpleuart is not
instantiated, instead reg_status, reg_data, and reg_div are converted to actual registers
which are written externally by atomsim for the purpose of the simulation of uart communication.
*/

// Set Ack_o
always @(posedge wb_clk_i) begin
Expand All @@ -55,6 +47,52 @@ reg [31:0] reg_div = 0;
wire reg_data_we = (wb_adr_i == 2'b00) && wb_we_i && wb_stb_i && wb_sel_i[0];
wire reg_data_re = (wb_adr_i == 2'b00) && !wb_we_i && wb_stb_i;

wire rxfifo_empty_o;
wire rxfifo_full_o;
wire [7:0] rxfifo_data_o;

wire txfifo_full_o;
wire txfifo_empty_o;
wire [7:0] txfifo_data_o;
generate
if (FIFO_EN) begin
FIFO_sync #(
.DEPTH(FIFO_DEPTH),
.DATAW(8)
) rxfifo (
.clk_i (wb_clk_i),
.rst_i (wb_rst_i),
.we_i (core_recv_buf_valid & reg_lcr[0]),
.re_i (reg_data_re & wb_ack_o),
.dat_i (core_reg_data),
.dat_o (rxfifo_data_o),
.full_o (rxfifo_full_o),
.empty_o (rxfifo_empty_o)
);

FIFO_sync #(
.DEPTH(FIFO_DEPTH),
.DATAW(8)
) txfifo (
.clk_i (wb_clk_i),
.rst_i (wb_rst_i),
.we_i (reg_data_we & wb_ack_o),
.re_i (core_send_buf_empty & reg_lcr[1]),
.dat_i (wb_dat_i[7:0]),
.dat_o (txfifo_data_o),
.full_o (txfifo_full_o),
.empty_o (txfifo_empty_o)
);
end else begin
assign rxfifo_empty_o = 1'dx;
assign rxfifo_full_o = 1'dx;
assign rxfifo_data_o = 8'dx;
assign txfifo_full_o = 1'dx;
assign txfifo_empty_o = 1'dx;
assign txfifo_data_o = 8'dx;
end
endgenerate

// Handle Writes
always @(posedge wb_clk_i) begin
if(wb_rst_i) begin
Expand All @@ -79,9 +117,12 @@ end
// Handle Reads
always @(*) /* COMBINATORIAL */ begin
case(wb_adr_i)
2'b00: /* THR-RBR */ wb_dat_o = {24'd0, core_reg_data};
2'b00: /* THR-RBR */ wb_dat_o = {24'd0, FIFO_EN ? rxfifo_data_o: core_reg_data};
2'b01: /* LCR */ wb_dat_o = {24'd0, reg_lcr};
2'b10: /* LSR */ wb_dat_o = {27'd0, core_rx_parity_bit, core_err_parity, core_err_framing, core_send_buf_empty, core_recv_buf_valid};
2'b10: /* LSR */ wb_dat_o = {27'd0, core_rx_parity_bit, core_err_parity, core_err_framing,
(FIFO_EN ? ~txfifo_full_o : core_send_buf_empty),
(FIFO_EN ? ~rxfifo_empty_o: core_recv_buf_valid)
};
2'b11: /* DIV */ wb_dat_o = reg_div;
endcase
end
Expand All @@ -101,9 +142,9 @@ UART_core uart_core_i
.ser_tx (tx_o),
.ser_rx (reg_lcr[7] ? tx_o : rx_i), // loopback
.divisor (reg_div),
.reg_dat_we (reg_data_we),
.reg_dat_re (reg_data_re),
.reg_dat_di (wb_dat_i[7:0]),
.reg_dat_we (FIFO_EN ? ~txfifo_empty_o : reg_data_we),
.reg_dat_re (FIFO_EN ? ~rxfifo_full_o : reg_data_re),
.reg_dat_di (FIFO_EN ? txfifo_data_o : wb_dat_i[7:0]),
.reg_dat_do (core_reg_data),

.rx_en (reg_lcr[0]),
Expand Down

0 comments on commit da85ef0

Please sign in to comment.