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
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 |