Vivado 摸鱼记录 Day_11 |•'-'•)و✧
review
day_10串口接收原理与实验 Vivado 串口通信(UART)原理B ------串口接收仿真-CSDN博客
day_9 实现了串口发送模块与使用 Vivado 串口通信(UART)------串口发送-CSDN博客
day_8 Vivado 串口通信(UART)原理A ------串口发送实验_vivadouart1-CSDN博客
串口发送:并 ---> 串
串口接收:串 ---> 并
1. 摸鱼任务
day_10 实现了简单的串口接收,今天搞一下串口接收优化|•'-'•)و✧
B站大学指路: 13C_UART串口接收设计优化_哔哩哔哩_bilibili
2. 串口接收存在的小问题 |•'-'•)و✧
正常传输: |
波特率115200 位时间 1s/115200 = 8680.5ns 传输10位 8680.5ns*10 = 86805ns |
误差传输:eg位时间少10ns |
波特率115200 位时间少10ns 1s/115200 -10ns = 8670.5ns 传输10位 8670.5ns*10 = 86705ns |
![]() |
解决方法:
原: |
现: |
STOP位在位时间中点,即可停止数据接收,节省0.5位的时间,避免下一个信号到来时,错过起始位。 |
(rx_flag==9)&&(counter_bps == bps_c - 1) -----------------------------》 (rx_flag==9)&&(counter_bps == bps_c / 2) |
3. design sources
原: |
module uart_rx_1(input clk , input reset_n , input uart_rx , output reg [7:0]rx_data, output reg rx_done ); //默认使用波特率BAUD 9600 时钟频率 CLK_FREQ 50MHz // parameter start_bit = 0 ; // parameter stop_bit = 1 ; parameter BAUD = 9600; parameter CLK_FREQ = 50_000_000; parameter bps_c = CLK_FREQ / BAUD ; reg rx_en ; reg[3:0] rx_flag; // bps reg [30:0] counter_bps ; always@(posedge clk or negedge reset_n) if(! reset_n) counter_bps <= 0 ; else if (rx_en) if(counter_bps == bps_c - 1) counter_bps <= 0 ; else counter_bps <= counter_bps + 1'b1 ; else counter_bps <= 0 ; reg dff_rx_0 , dff_rx_1 ; reg r_uart_rx; wire neg_rx_go ; always@(posedge clk ) dff_rx_0 <= uart_rx ; always@(posedge clk ) dff_rx_1 <= dff_rx_0 ; always@(posedge clk ) r_uart_rx <= dff_rx_1 ; assign neg_rx_go = (dff_rx_1 == 0)&&(r_uart_rx == 1); // rx_en always@(posedge clk or negedge reset_n) if(! reset_n) rx_en <= 0 ; else if(neg_rx_go) rx_en <= 1 ; else if((rx_flag==9)&&(counter_bps == bps_c - 1)) rx_en <= 0 ; else if((rx_flag==0)&&(counter_bps == bps_c/2 )&&(dff_rx_1==1)) rx_en <= 0 ; // rx_flag always@(posedge clk or negedge reset_n) if(!reset_n) rx_flag <= 4'b0000 ; else if(counter_bps == bps_c - 1) begin if(rx_flag == 9) rx_flag <= 0 ; else rx_flag <= rx_flag + 1'b1 ; end // [7:0]r_rx_data reg [7:0] r_rx_data; always@(posedge clk ) if(!rx_en) r_rx_data <= r_rx_data; else if(counter_bps == bps_c / 2) begin case(rx_flag) 1 : r_rx_data[0] <= dff_rx_1; 2 : r_rx_data[1] <= dff_rx_1; 3 : r_rx_data[2] <= dff_rx_1; 4 : r_rx_data[3] <= dff_rx_1; 5 : r_rx_data[4] <= dff_rx_1; 6 : r_rx_data[5] <= dff_rx_1; 7 : r_rx_data[6] <= dff_rx_1; 8 : r_rx_data[7] <= dff_rx_1; default : r_rx_data <= r_rx_data; endcase end // rx_done always@(posedge clk) rx_done <= (rx_flag==9)&&(counter_bps == bps_c - 1); // rx_data ; always@(posedge clk) if(rx_done) rx_data <= r_rx_data; endmodule |
现: |
module uart_rx(input clk , input reset_n , input uart_rx , output reg [7:0]rx_data, output reg rx_done ); //默认使用波特率BAUD 9600 时钟频率 CLK_FREQ 50MHz // parameter start_bit = 0 ; // parameter stop_bit = 1 ; parameter BAUD = 9600; parameter CLK_FREQ = 50_000_000; parameter bps_c = CLK_FREQ / BAUD ; reg rx_en ; reg[3:0] rx_flag; // bps reg [30:0] counter_bps ; always@(posedge clk or negedge reset_n) if(! reset_n) counter_bps <= 0 ; else if (rx_en) if(counter_bps == bps_c - 1) counter_bps <= 0 ; else counter_bps <= counter_bps + 1'b1 ; else counter_bps <= 0 ; reg dff_rx_0 , dff_rx_1 ; reg r_uart_rx; wire neg_rx_go ; always@(posedge clk ) dff_rx_0 <= uart_rx ; always@(posedge clk ) dff_rx_1 <= dff_rx_0 ; always@(posedge clk ) r_uart_rx <= dff_rx_1 ; assign neg_rx_go = (dff_rx_1 == 0)&&(r_uart_rx == 1); // rx_en always@(posedge clk or negedge reset_n) if(! reset_n) rx_en <= 0 ; else if(neg_rx_go) rx_en <= 1 ; else if((rx_flag==9)&&(counter_bps == bps_c / 2)) rx_en <= 0 ; else if((rx_flag==0)&&(counter_bps == bps_c/2 )&&(dff_rx_1==1)) rx_en <= 0 ; // rx_flag always@(posedge clk or negedge reset_n) if(!reset_n) rx_flag <= 4'b0000 ; else if((rx_flag == 9)&&(counter_bps == bps_c /2)) rx_flag <= 4'b0000 ; else if(counter_bps == bps_c - 1) rx_flag <= rx_flag + 1'b1 ; // [7:0]r_rx_data reg [7:0] r_rx_data; always@(posedge clk ) if(!rx_en) r_rx_data <= r_rx_data; else if(counter_bps == bps_c / 2) begin case(rx_flag) 1 : r_rx_data[0] <= dff_rx_1; 2 : r_rx_data[1] <= dff_rx_1; 3 : r_rx_data[2] <= dff_rx_1; 4 : r_rx_data[3] <= dff_rx_1; 5 : r_rx_data[4] <= dff_rx_1; 6 : r_rx_data[5] <= dff_rx_1; 7 : r_rx_data[6] <= dff_rx_1; 8 : r_rx_data[7] <= dff_rx_1; default : r_rx_data <= r_rx_data; endcase end // rx_done always@(posedge clk) rx_done <= (rx_flag==9)&&(counter_bps == bps_c /2); // rx_data ; always@(posedge clk) if(rx_done) rx_data <= r_rx_data; endmodule |
else if (rx_en) 为啥不用改呢? 因为rx_en决定了此处 ,只要控制rx_en即可 |
// rx_flag 这里调试了好几次hhhh 别粗心哈 else if(counter_bps == bps_c - 1) rx_flag <= rx_flag + 1'b1 ; |
4. uart_rx_tb
橙色框为原代码 蓝色框为修改后 |
|
|
小框框可以看出,已经成功把停止位的接收时间变为一半啦~ (不过本tb没有按照设定的发送时间每个少10ns写,溜溜~~~) |
5. 小结
![]() |
![]() |
先保存一下,说不定会用得到|•'-'•)و✧ |
//好耶~~~~~
//摸鱼结束哩 |•'-'•)و✧