From 89bd71ceb5001c2cce9ee3c76808baeed54957bd Mon Sep 17 00:00:00 2001 From: DevQing66 Date: Fri, 14 Nov 2025 18:41:38 -0500 Subject: [PATCH 1/3] Add UART module with AXI-Lite and FIFO functionality Implement UART module with AXI-Lite interface and FIFO support. --- rtl/io/uart16550.sv | 87 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/rtl/io/uart16550.sv b/rtl/io/uart16550.sv index e69de29..a38ad4e 100644 --- a/rtl/io/uart16550.sv +++ b/rtl/io/uart16550.sv @@ -0,0 +1,87 @@ +`timescale 1ns / 1ps +parameter FIFO_DEPTH = 16; +//UART interface +module UARTmodule( +//clock to generate Baud rate +input wire clk, +//reset signal to initialize/clear registers +input wire rst, +//Axi-lite bus interface +input wire [31:0] CPU_to_UART, +output wire [31:0] UART_to_CPU, +//Recieve/Transmit serial bit +input wire rx_i, +output wire tx_o, +//Interrupt for CPU to read +output wire irq_o + ); +/*******************************BUS BIT FIELDS*****************************/ + //CPU to UART internal signals for write + wire awvalid = CPU_to_UART [0]; + wire wvalid = CPU_to_UART [1]; + wire [2:0] awaddr = CPU_to_UART [4:2]; + wire bready = CPU_to_UART [5]; + wire [7:0] wdata = CPU_to_UART [13:6]; + //UART to CPU internal signals for write + wire awready; + wire wready; + wire bvalid; + wire [1:0] bresp; + //CPU to UART internal signals for read + wire arvalid = CPU_to_UART [15]; + wire [2:0] araddr = CPU_to_UART [18:16]; + wire rready = CPU_to_UART [19]; + //UART to CPU internal signals for read + wire arready; + wire rvalid; + wire [1:0] rresp; + wire [7:0] rdata; + //assign write-related bits + +/**************************REGISTERS & FIFO QUEUE*************************/ + localparam ADDR_WIDTH = $clog2(FIFO_DEPTH); + reg [7:0] THR; + reg [7:0] RBR; + reg [7:0] IER; + reg [7:0] ISR; + reg [7:0] FCR; + reg [7:0] LCR; + reg [7:0] LSR; + reg [7:0] MCR; + reg [7:0] MSR; + reg [7:0] SPR; + reg [7:0] DLL; + reg [7:0] DLM; + reg [7:0] PSD; + //FIFO mem stack, pointers and status + reg [7:0] fifo_mem [0:FIFO_DEPTH-1]; + reg [ADDR_WIDTH-1:0] waddr_ptr; + reg [ADDR_WIDTH-1:0] raddr_ptr; + reg [ADDR_WIDTH:0] count; + wire fifo_full = (count == FIFO_DEPTH); + wire fifo_empty = (count == 0); +/****************************CONFIG REGS*******************************/ +// LCR, IER, FCR, MCR, MSR, LSR, etc. + +/**************************BAUD RATE CALC******************************/ +// Generate baud tick from clk + +/***************************TRANSMIT tx_o******************************/ +// FIFO -> shift register -> serial output + +/***************************RECEIVE rx_i*******************************/ +// Serial input -> shift register -> FIFO + +/***************************UART to CPU********************************/ +// AXI-Lite read/write response +// THR, RBR, FIFO status, line status + +/***************************INTERRUPT irq_o****************************/ +// RX/TX interrupts based on IER and FIFO/line status + +/***************************FIFO MANAGEMENT****************************/ +// Push/pop data, update pointers and count + +/***************************ERROR DETECTION***************************/ +// Parity, framing, overrun errors +endmodule From cdf2171a0cc222e61d451472ac7c5cd0892c8ec2 Mon Sep 17 00:00:00 2001 From: DevQing66 Date: Mon, 17 Nov 2025 22:04:31 -0500 Subject: [PATCH 2/3] UART-Config register the code for config register --- rtl/io/uart16550.sv | 46 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/rtl/io/uart16550.sv b/rtl/io/uart16550.sv index a38ad4e..e74ce08 100644 --- a/rtl/io/uart16550.sv +++ b/rtl/io/uart16550.sv @@ -60,8 +60,51 @@ output wire irq_o reg [ADDR_WIDTH:0] count; wire fifo_full = (count == FIFO_DEPTH); wire fifo_empty = (count == 0); + /****************************CONFIG REGS*******************************/ -// LCR, IER, FCR, MCR, MSR, LSR, etc. + always @(posedge clk or posedge rst) begin + if (rst) begin //reset registers to its reset values + THR <= 8'h00; + RBR <= 8'h00; + IER <= 8'h00; + ISR <= 8'h01; + FCR <= 8'h00; //the datasheet reset value is 0x00? + LCR <= 8'h00; + LSR <= 8'h60; + MCR <= 8'h00; + MSR <= 8'h00; + SPR <= 8'h00; + DLL <= 8'h01; + DLM <= 8'h01; + PSD <= 8'h00; + end + else begin //to handle CPU writes + if (awvalid && wvalid && awready && wready) begin + case (awaddr) //address of the register + 3'b000: begin + if (LCR[7]==1'b0)// check DLAB = 0 -> THR, DLAB = 1 -> DLL + THR <= wdata; // write data to be transmitted + else + DLL <= wdata; // baudrate low byte + end + 3'b001: begin + if (LCR[7]==1'b0) + IER <= wdata; // enable interrupt + else + DLM <= wdata; // baudrate high byte + end + 3'b010: FCR <= wdata; //FIFO control + 3'b011: LCR <= wdata; //Line Control + 3'b100: MCR <= wdata; //Modern control + 3'b101: begin + if (LCR [7] ==1'b1) + PSD <= {4'b0000, wdata[3:0]}; //prescaler division + end + 3'b111: SPR <= wdata; // Scratch Pad + endcase + end + end + end /**************************BAUD RATE CALC******************************/ // Generate baud tick from clk @@ -85,3 +128,4 @@ output wire irq_o /***************************ERROR DETECTION***************************/ // Parity, framing, overrun errors endmodule + From a1cd878496bc362c90e2f52aa4887821ab6e2f89 Mon Sep 17 00:00:00 2001 From: DevQing66 Date: Fri, 6 Feb 2026 19:38:01 -0500 Subject: [PATCH 3/3] UART-Config register/Baud rate --- rtl/io/uart16550.sv | 44 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/rtl/io/uart16550.sv b/rtl/io/uart16550.sv index e74ce08..77bd59c 100644 --- a/rtl/io/uart16550.sv +++ b/rtl/io/uart16550.sv @@ -107,8 +107,47 @@ output wire irq_o end /**************************BAUD RATE CALC******************************/ -// Generate baud tick from clk - +wire [15:0] baud_divisor = {DLM,DLL}; //16-bit divisor from DLM & DLL + wire [3:0] psd_value = PSD [3:0]; // the lower 4-bit are used + + //clk/(16*(PSD+1)*baud_divisor) -- counter holder for the math + reg [3:0] PSD_counter; //for PSD+1 + reg [15:0] divisor_counter; //divides by divisor + reg [3:0] multi_by_16; //divides by 16 + reg baud_tick; //final baud pulse + + always @(posedge clk_i or negedge rst_ni) begin + if (rst_ni) begin //reseting the counter + PSD_counter <= 4'd0; + divisor_counter <= 16'd0; + multi_by_16 <= 4'd0; + baud_tick <= 1'b0; + end + else begin + baud_tick <= 1'b0; //default setting counting clock cycle + + if (PSD_counter == psd_value) begin // divides by PSD + 1 + PSD_counter <= 4'd0; + end + else begin + PSD_counter <= PSD_counter + 1'b1; + end + + if (divisor_counter == baud_divisor - 1) begin //divides by divisor + divisor_counter <= 16'd0; + end + else begin + divisor_counter <= divisor_counter + 1'b1; + end + + if (multi_by_16 == 4'd15) begin // divide by 16 + multi_by_16 <= 16'd0; + baud_tick <= 1'b1; + end else begin + multi_by_16 <= multi_by_16 + 1'b1; + end + end + end /***************************TRANSMIT tx_o******************************/ // FIFO -> shift register -> serial output @@ -129,3 +168,4 @@ output wire irq_o // Parity, framing, overrun errors endmodule +