1
0
mirror of https://github.com/WangXuan95/FpOC.git synced 2025-01-17 23:22:52 +08:00
FpOC/RTL/uart_monitor.v
2023-06-09 20:54:43 +08:00

203 lines
6.0 KiB
Verilog
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//--------------------------------------------------------------------------------------------------------
// 模块uart_monitor
// Type : synthesizable
// Standard: Verilog 2001 (IEEE1364-2001)
// 功能UART发送器格式为115200,8,n,1可以把 i_val0, i_val1, i_val2, i_val3 变成10进制格式放在一行里通过 UART 发送出去
//--------------------------------------------------------------------------------------------------------
module uart_monitor #(
parameter [15:0] CLK_DIV = 217 // UART分频倍率例如若时钟频率为 36.864MHz, CLK_DIV=320则 UART 波特率为 36.864MHz/320=115200
) (
input wire rstn,
input wire clk,
input wire i_en,
input wire signed [15:0] i_val0,
input wire signed [15:0] i_val1,
input wire signed [15:0] i_val2,
input wire signed [15:0] i_val3,
output reg o_uart_tx // UART TX 信号
);
initial o_uart_tx = 1'b1;
localparam [2:0] IDLE = 3'd0,
SELECT = 3'd1,
WAIT = 3'd2,
PARSING = 3'd3,
SENDING = 3'd4;
reg [2:0] stat;
wire tx_rdy;
reg tx_en;
reg [7:0] tx_data;
reg itoa_en;
reg signed [15:0] itoa_val;
reg itoa_oen;
reg [ 7:0] itoa_str [0:5];
reg [ 2:0] vcnt;
reg [ 2:0] cnt;
reg [ 7:0] eov;
wire [ 7:0] s_str[0:7];
assign s_str[0] = itoa_str[0];
assign s_str[1] = itoa_str[1];
assign s_str[2] = itoa_str[2];
assign s_str[3] = itoa_str[3];
assign s_str[4] = itoa_str[4];
assign s_str[5] = itoa_str[5];
assign s_str[6] = 8'h20;
assign s_str[7] = eov;
always @ (*) begin
tx_en = 1'b0;
tx_data = 0;
if(stat==SENDING) begin
tx_en = 1'b1;
tx_data = s_str[cnt];
end
end
always @ (posedge clk or negedge rstn)
if(~rstn) begin
stat <= IDLE;
itoa_en <= 1'b0;
itoa_val <= 0;
vcnt <= 0;
cnt <= 0;
eov <= 8'h20;
end else begin
itoa_en <= 1'b0;
case(stat)
IDLE: if(i_en)
stat <= SELECT;
SELECT: begin
if (vcnt==3'd0) begin
vcnt <= vcnt + 3'd1;
stat <= WAIT;
itoa_en <= 1'b1;
itoa_val <= i_val0;
eov <= 8'h20;
end else if(vcnt==3'd1) begin
vcnt <= vcnt + 3'd1;
stat <= WAIT;
itoa_en <= 1'b1;
itoa_val <= i_val1;
eov <= 8'h20;
end else if(vcnt==3'd2) begin
vcnt <= vcnt + 3'd1;
stat <= WAIT;
itoa_en <= 1'b1;
itoa_val <= i_val2;
eov <= 8'h20;
end else if(vcnt==3'd3) begin
vcnt <= vcnt + 3'd1;
stat <= WAIT;
itoa_en <= 1'b1;
itoa_val <= i_val3;
eov <= 8'h0A;
end else begin
vcnt <= 3'd0;
stat <= IDLE;
eov <= 8'h20;
end
end
WAIT:
stat <= PARSING;
PARSING: if(itoa_oen)
stat <= SENDING;
default: //SENDING:
if(tx_rdy) begin
cnt <= cnt + 3'd1;
if(cnt==3'd7)
stat <= SELECT;
end
endcase
end
reg [ 2:0] itoa_cnt;
reg itoa_sign;
reg itoa_zero;
reg [15:0] itoa_abs;
wire[15:0] itoa_rem_w = (itoa_abs % 16'd10);
reg [ 3:0] itoa_rem;
always @ (posedge clk or negedge rstn)
if(~rstn) begin
itoa_cnt <= 3'd0;
{itoa_sign, itoa_abs, itoa_zero, itoa_rem} <= 0;
itoa_oen <= 1'b0;
itoa_str[0] <= 0;
itoa_str[1] <= 0;
itoa_str[2] <= 0;
itoa_str[3] <= 0;
itoa_str[4] <= 0;
itoa_str[5] <= 0;
end else begin
if(itoa_cnt==3'd0) begin
if(itoa_en)
itoa_cnt <= 3'd1;
itoa_sign <= itoa_val[15];
itoa_abs <= itoa_val[15] ? $unsigned(-itoa_val) : $unsigned(itoa_val);
end else begin
itoa_cnt <= (itoa_cnt + 3'd1);
itoa_abs <= (itoa_abs / 16'd10);
itoa_rem <= itoa_rem_w[3:0];
itoa_zero <= (itoa_abs == 16'd0);
if(itoa_cnt>3'd1) begin
itoa_str[5] <= itoa_str[4];
itoa_str[4] <= itoa_str[3];
itoa_str[3] <= itoa_str[2];
itoa_str[2] <= itoa_str[1];
itoa_str[1] <= itoa_str[0];
if(itoa_cnt>3'd2 && itoa_zero) begin
itoa_str[0] <= itoa_sign ? 8'h2D : 8'h20;
itoa_sign <= 1'b0;
end else begin
itoa_str[0] <= {4'h3, itoa_rem};
end
end
end
itoa_oen <= itoa_cnt == 3'd7;
end
reg [15:0] ccnt;
reg [ 3:0] tx_cnt;
reg [12:1] tx_shift;
assign tx_rdy = (tx_cnt==4'd0);
always @ (posedge clk or negedge rstn)
if(~rstn) begin
o_uart_tx <= 1'b1;
ccnt <= 0;
tx_cnt <= 0;
tx_shift <= 12'hFFF;
end else begin
if(tx_cnt==4'd0) begin
o_uart_tx <= 1'b1;
ccnt <= 0;
if(tx_en) begin
tx_cnt <= 4'd12;
tx_shift <= {2'b10, tx_data[0], tx_data[1], tx_data[2], tx_data[3], tx_data[4], tx_data[5], tx_data[6], tx_data[7], 2'b11};
end
end else begin
o_uart_tx <= tx_shift[tx_cnt];
if( ccnt + 16'd1 < CLK_DIV ) begin
ccnt <= ccnt + 16'd1;
end else begin
ccnt <= 0;
tx_cnt <= tx_cnt - 4'd1;
end
end
end
endmodule