学习了使用FPGA-UART串口发送数据,做个小结
module uart_tx (
input clk,
input rst_n,
input [7:0]data_byte,
input send_en,
input [2:0]baud_set,
output reg RS232_TX,
output reg TX_done,
output reg UART_state
);
reg [15:0]baud_cnt;
reg [15:0]baud_choose;
reg [7:0]r_data_byte;
reg baud_clk;
reg [3:0] baud_count;
localparam START_bit = 1'b0,
STOP_bit = 1'b1;
//波特率 波特率周期 50M时钟计数值
// 9600 104167 5208
// 19200 52083 2604
// 38400 26041 1302
// 57600 17361 868
// 115200 8680 434
//根据波特率选择对应的计数值
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
baud_choose <= 15'd5207;
else
begin
case (baud_set)
0 : baud_choose <= 16'd5207;
1 : baud_choose <= 16'd2603;
2 : baud_choose <= 16'd1301;
3 : baud_choose <= 16'd867;
4 : baud_choose <= 16'd433;
default: baud_choose <= 5207;
endcase
end
end
//波特率计数
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
baud_cnt <= 0;
else if(UART_state)
begin
if(baud_cnt == baud_choose)
baud_cnt <= 0;
else
baud_cnt <= baud_cnt + 1'b1;
end
else
baud_cnt <= 0;
end
//生成波特率时钟
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
baud_clk <= 0;
else if(baud_cnt == 16'd1)
baud_clk <= 1;
else
baud_clk <= 0;
end
//一次传输需要11个波特率脉冲,计数脉冲个数
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
baud_count <= 0;
else if(baud_count == 4'd11)
baud_count <= 0;
else if(baud_clk)
baud_count <= baud_count + 1'b1;
else
baud_count <= baud_count;
end
//数据传输前对data打一拍寄存,保证数据的稳定性
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
r_data_byte <= 0;
else if(send_en)
r_data_byte <= data_byte;
else
r_data_byte <= r_data_byte;
end
//数据传输过程,用线性序列机表示
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
RS232_TX <= 1'b1;
else
begin
case (baud_count)
0: RS232_TX <= 1'b1;
1: RS232_TX <= START_bit;
2: RS232_TX <= r_data_byte[0];
3: RS232_TX <= r_data_byte[1];
4: RS232_TX <= r_data_byte[2];
5: RS232_TX <= r_data_byte[3];
6: RS232_TX <= r_data_byte[4];
7: RS232_TX <= r_data_byte[5];
8: RS232_TX <= r_data_byte[6];
9: RS232_TX <= r_data_byte[7];
10: RS232_TX <= STOP_bit;
default: RS232_TX <= 1'b1;
endcase
end
end
//一次数据传输完成标志位
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
TX_done <= 0;
else if(baud_count == 4'd11)
TX_done <= 1;
else
TX_done <= 0;
end
//串口的状态指示,当其正在传输时为高电平
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
UART_state <= 0;
else if(baud_count == 4'd11)
UART_state <= 0;
else if(send_en)
UART_state <= 1;
else
UART_state <= UART_state;
end
endmodule