thermometer_digital/rtl/uart/uart_top_32bit.v

163 lines
5.0 KiB
Verilog

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer: yangshenbo
//
// Create Date: 2026/03/31 10:53:24
// Design Name:
// Module Name: uart_top_32bit
//
//////////////////////////////////////////////////////////////////////////////////
module uart_top_32bit #(
parameter BAUD = 9600,
parameter CLOCK_FREQ = 50_000_000
)
(
input Clk,
input Reset_n,
// 32-bit Transmit Interface
input Send_Go32, // 32-bit transmit start pulse
input [31:0] Tx_Data32, // 32-bit data to transmit
output Tx_Done32, // 32-bit transmit done flag
output uart_tx, // Physical TX pin
// 32-bit Receive Interface
input uart_rx, // Physical RX pin
output reg Rx_Done32, // 32-bit receive done flag
output reg [31:0] Rx_Data32 // 32-bit received data
);
// --- Internal Wires ---
wire byte_tx_go;
wire [7:0] byte_tx_data;
wire byte_tx_done;
wire byte_rx_done;
wire [7:0] byte_rx_data;
// ============================================================
// 1. Transmit Control Logic (32-bit to 4x8-bit)
// ============================================================
reg [3:0] tx_state;
reg [31:0] tx_data_buffer;
reg byte_tx_go_reg;
reg [7:0] byte_tx_data_reg;
assign byte_tx_go = byte_tx_go_reg;
assign byte_tx_data = byte_tx_data_reg;
always @(posedge Clk or negedge Reset_n) begin
if (!Reset_n) begin
tx_state <= 0;
byte_tx_go_reg <= 0;
tx_data_buffer <= 0;
end else begin
case (tx_state)
0: begin // Wait for transmit trigger
if (Send_Go32) begin
tx_data_buffer <= Tx_Data32;
tx_state <= 1;
end
end
1, 2, 3, 4: begin // Send byte 0, 1, 2, 3 sequentially
byte_tx_data_reg <= tx_data_buffer[31:24]; // Send high byte first (Big-endian)
byte_tx_go_reg <= 1;
tx_state <= tx_state + 4; // Jump to wait state
end
// States 5, 6, 7, 8: Wait for byte_tx_done
5, 6, 7, 8: begin
byte_tx_go_reg <= 0;
if (byte_tx_done) begin
tx_data_buffer <= tx_data_buffer << 8; // Shift for next byte
if (tx_state == 8) tx_state <= 0; // 4 bytes sent
else tx_state <= tx_state - 3; // Return to next send state
end
end
endcase
end
end
assign Tx_Done32 = (tx_state == 8 && byte_tx_done);
// ============================================================
// 2. Receive Control Logic (4x8-bit to 32-bit)
// ============================================================
reg [1:0] rx_cnt;
reg [31:0] rx_data_buffer;
reg rx_done32_reg;
always @(posedge Clk or negedge Reset_n) begin
if (!Reset_n) begin
rx_cnt <= 0;
rx_data_buffer <= 0;
rx_done32_reg <= 0;
end else begin
rx_done32_reg <= 0;
if (byte_rx_done) begin
// Concatenate data (Big-endian mode)
case(rx_cnt)
0: rx_data_buffer[31:24] <= byte_rx_data;
1: rx_data_buffer[23:16] <= byte_rx_data;
2: rx_data_buffer[15:8] <= byte_rx_data;
3: rx_data_buffer[7:0] <= byte_rx_data;
endcase
if (rx_cnt == 3) begin
rx_cnt <= 0;
rx_done32_reg <= 1;
end else begin
rx_cnt <= rx_cnt + 1;
end
end
end
end
always @(posedge Clk or negedge Reset_n) begin
if(!Reset_n) begin
Rx_Data32 <= 1'b0;
Rx_Done32 <= 1'b0;
end
else if(rx_done32_reg)begin
Rx_Data32 <= rx_data_buffer;
Rx_Done32 <= rx_done32_reg;
end
else begin
Rx_Data32 <= Rx_Data32;
Rx_Done32 <= 0;
end
end
// ============================================================
// 3. Module Instantiation
// ============================================================
// Instantiate byte transmit module
uart_byte_tx #(
.BAUD(BAUD),
.CLOCK_FREQ(CLOCK_FREQ)
) u_uart_byte_tx (
.Clk(Clk),
.Reset_n(Reset_n),
.Send_Go(byte_tx_go),
.Data(byte_tx_data),
.uart_tx(uart_tx),
.Tx_Done(byte_tx_done)
);
// Instantiate byte receive module
uart_byte_rx #(
.BAUD(BAUD),
.CLOCK_FREQ(CLOCK_FREQ)
) u_uart_byte_rx (
.Clk(Clk),
.Reset_n(Reset_n),
.uart_rx(uart_rx),
.Rx_Done(byte_rx_done),
.Rx_Data(byte_rx_data)
);
endmodule