thermometer_digital/rtl/uart/uart_ctrl_sysreg.v

151 lines
4.6 KiB
Verilog

`timescale 1ns / 1ps
module uart_ctrl_sysreg #(
parameter BAUD = 115200,
parameter CLOCK_FREQ = 50_000_000
)(
input clk
,input rst_n
// UART Interface
,input uart_rx
,output uart_tx
// Register File Interface
,output reg [31:0] o_wrdata //write data to register file
,output reg [24:0] o_addr //register file address
,output reg o_wren //write enable to register file
,output reg o_rden //read enable to register file
,input [31:0] i_rddata //read data from register file
// Auto-Report Mechanism
,input [23:0] i_report_data
,input i_report_vld
);
// --- uart_top ---
wire [31:0] uart_rx_data;
wire uart_rx_done;
reg [31:0] uart_tx_data;
reg uart_tx_go;
wire uart_tx_done;
uart_top_32bit #(
.BAUD(BAUD),
.CLOCK_FREQ(CLOCK_FREQ)
) uart_32bit_inst (
.Clk(clk), .Reset_n(rst_n),
.Send_Go32(uart_tx_go), .Tx_Data32(uart_tx_data), .Tx_Done32(uart_tx_done),
.uart_tx(uart_tx), .uart_rx(uart_rx),
.Rx_Done32(uart_rx_done), .Rx_Data32(uart_rx_data)
);
// Protocol parsing registers
reg [63:0] cmd_reg;
reg [31:0] wr_data_buff;
reg [19:0] data_bytes_len;
// State machine definition
reg [2:0] state;
localparam S_IDLE = 3'd0,
S_RX_CMD_L = 3'd1,
S_PARSE = 3'd2,
S_WAIT_RD = 3'd3,
S_RD_DATA = 3'd4,
S_WR_DATA = 3'd5,
S_REPORT = 3'd6; // Auto-report state
// Latch auto-report data
reg [23:0] report_data_latch;
reg report_pending;
// Capture report pulse: store if busy
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
report_pending <= 1'b0;
report_data_latch <= 24'd0;
end else if(i_report_vld) begin
report_pending <= 1'b1;
report_data_latch <= i_report_data;
end else if(state == S_REPORT) begin
report_pending <= 1'b0; // Clear flag after entering report state
end
end
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
state <= 0;
cmd_reg <= 0;
o_wrdata <= 0;
o_wren <= 0;
o_rden <= 0;
uart_tx_go <= 1'b0;
uart_tx_data <= 1'b0;
end
else begin
case(state)
S_IDLE : begin // IDLE state
uart_tx_go <= 1'b0;
if(uart_rx_done) begin
cmd_reg[63:32] <= uart_rx_data;
state <= S_RX_CMD_L;
end
else if(report_pending) begin
state <= S_REPORT;
end
end
S_RX_CMD_L : begin // Receive lower command word
if(uart_rx_done)begin
cmd_reg[31:0] <= uart_rx_data;
state <= S_PARSE;
end
end
S_PARSE : begin // Parse command
o_addr <= cmd_reg[56:32];
data_bytes_len <= cmd_reg[19:0];
if(cmd_reg[63] == 1'b1) begin // Read command
o_rden <= 1'b1;
state <= S_WAIT_RD;
end
else begin // Write command
state <= S_WR_DATA;
end
end
S_WAIT_RD : begin // Wait for read data ready
o_rden <= 1'b0;
state <= S_RD_DATA;
end
S_RD_DATA :begin // Transmit read data
uart_tx_data <= i_rddata;
uart_tx_go <= 1'b1;
state <= S_IDLE;
end
S_WR_DATA : begin // Receive and write data
o_wren <= 1'b0;
if(data_bytes_len != 0)begin
if(uart_rx_done) begin
o_wrdata <= uart_rx_data;
o_wren <= 1'b1;
data_bytes_len <= data_bytes_len - 20'd4;
end
end
else begin
state <= S_IDLE;
end
end
S_REPORT : begin // Auto-report data
// Construct report packet: [8'hAA (header) + 24bit sensor data]
uart_tx_data <= {8'hAA, report_data_latch};
uart_tx_go <= 1'b1;
state <= S_IDLE;
end
default: state <= S_IDLE;
endcase
end
end
endmodule