You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

111 lines
2.9 KiB
Verilog

module uart_tx(
input sys_clk, // U18
input sys_rst, //J15
input start_en,
input [7:0] tx_data, // 需要发送出去的并行数据
output reg txd, // 连接到了外部的 rx, 该信号持续发送串行信号
output reg tx_busy
);
parameter CLK_FREQ = 5000_0000;
parameter BPS = 115200;
localparam B_MAX = CLK_FREQ / BPS;
reg [3:0]tx_d_cnt;
reg [15:0] baud_cnt;
// 当start_en 为高的时候, 临时保存输入的并行数据, 并拉高busy信号
reg [7:0] temp_tx_data; // 临时保存数据的寄存器
always @(posedge sys_clk or negedge sys_rst) begin
if (sys_rst == 1'b0) begin
temp_tx_data <= 'b0;
tx_busy <= 'b0;
end
else if(start_en) begin
temp_tx_data <= tx_data; // 记录外部传过来的并行数据备份
tx_busy <= 'b1; // 拉高 忙信号
end
else if (tx_d_cnt == 'b1001 && baud_cnt == B_MAX-1) begin // 发送一个完整的停止位
temp_tx_data <= 'b0;
tx_busy <= 0;
end
else begin
temp_tx_data <= temp_tx_data;
tx_busy <= tx_busy;
end
end
// 波特率计数器
always @(posedge sys_clk or negedge sys_rst) begin
if (sys_rst == 1'b0) begin
baud_cnt <= 'b0;
end
else if (start_en) begin // 又要发送新数据了, 立刻清零重新计数
baud_cnt <= 'b0;
end
// 必须要开始传输数据
else if (tx_busy) begin
if (baud_cnt == B_MAX-'b1) begin // 从0开始计数的 0~433 一共计数434次
baud_cnt <= 'b0;
end
else begin
baud_cnt <= baud_cnt + 'b1;
end
end
else begin
baud_cnt <= 'b0;
end
end
// 当前发送数据的数据数量
always @(posedge sys_clk or negedge sys_rst) begin
if (sys_rst == 1'b0) begin
tx_d_cnt <= 'b0;
end
else if (start_en) begin // 又要发送新数据了, 立刻清零重新计数
tx_d_cnt <= 'b0;
end
// 必须要开始传输数据
else if (tx_busy) begin
if (baud_cnt == B_MAX-'b1) begin
tx_d_cnt <= tx_d_cnt + 'b1;
end
else begin
tx_d_cnt <= tx_d_cnt;
end
end
else begin
tx_d_cnt <= 'b0;
end
end
always @(posedge sys_clk or negedge sys_rst) begin
if (sys_rst == 1'b0) begin
txd <= 'b1;
end
else if (tx_busy) begin
case (tx_d_cnt)
'b0000: txd <= 'b0;
'b0001: txd <= temp_tx_data[0];
'b0010: txd <= temp_tx_data[1];
'b0011: txd <= temp_tx_data[2];
'b0100: txd <= temp_tx_data[3];
'b0101: txd <= temp_tx_data[4];
'b0110: txd <= temp_tx_data[5];
'b0111: txd <= temp_tx_data[6];
'b1000: txd <= temp_tx_data[7];
'b1001: txd <= 'b1;
default: txd <= 'b1;
endcase
end
else begin
txd <= 'b1;
end
end
endmodule