Vivado 摸鱼记录 Day_10 ๑乛v乛๑
review
day_9 实现了串口发送模块与使用 Vivado 串口通信(UART)------串口发送-CSDN博客
day_8 串口发送原理 Vivado 串口通信(UART)原理A ------串口发送实验-CSDN博客
串口发送:并 ---> 串
串口接收:串 ---> 并
1. 串口接收原理
小梅哥视频链接 13A_UART串口接收逻辑设计要点分析_哔哩哔哩_bilibili
Q1: 如何从串行数据准确的接收每一位数据? 取计数中点 |
|
Q2: 如何检测起始位的下降沿 ? 下降沿检测电路 |
|
Q3: 波特率分频计数器使能逻辑 对于毛刺信号的处理 |
|
Q4: 判断当前信号是第几位? 使用位计数器 |
|
2. 今日摸鱼任务 ๑乛v乛๑ 完成串口接收仿真
3. uart_rx
3.1 design sources
module uart_rx_1(input clk , input reset_n , input uart_rx , output reg [7:0]rx_data, output reg rx_done );
// bps // neg_rx_go 避免亚稳态的影响,采用如下电路 关于亚稳态亚稳态浅浅学习 ( ੭ ˙ᗜ˙ )੭-CSDN博客 // rx_en // rx_flag // [7:0]rx_data // rx_done endmodule |
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 ; //调试发现rx_flag一直为0,结果问题出在没写! 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]rx_data always@(posedge clk ) if(!rx_en) rx_data <= rx_data; else if(counter_bps == bps_c / 2) //取计数中点 begin case(rx_flag) 1 : rx_data[0] <= dff_rx_1; 2 : rx_data[1] <= dff_rx_1; 3 : rx_data[2] <= dff_rx_1; 4 : rx_data[3] <= dff_rx_1; 5 : rx_data[4] <= dff_rx_1; 6 : rx_data[5] <= dff_rx_1; 7 : rx_data[6] <= dff_rx_1; 8 : rx_data[7] <= dff_rx_1; default : rx_data <= rx_data; endcase end // rx_done always@(posedge clk) rx_done <= (rx_flag==9)&&(counter_bps == bps_c - 1); endmodule |
3.2 uart_rx_text_tb
`timescale 1ns / 1ns module uart_rx_tb(); reg clk , reset_n ; reg uart_rx; wire [7:0]rx_data; wire rx_done; uart_rx_1 uart_rx_tb_( .clk(clk) , .reset_n(reset_n) , .uart_rx(uart_rx) , .rx_data(rx_data), .rx_done(rx_done) ); initial clk = 1 ; always #10 clk = ~clk ; initial begin reset_n = 0 ; uart_rx = 1 ; #201; reset_n = 1 ; #2000; // 0F 0000_1111 uart_rx = 0 ; #(5208*20); uart_rx = 0 ; #(5208*20); uart_rx = 0 ; #(5208*20); uart_rx = 0 ; #(5208*20); uart_rx = 0 ; #(5208*20); uart_rx = 1 ; #(5208*20); uart_rx = 1 ; #(5208*20); uart_rx = 1 ; #(5208*20); uart_rx = 1 ; #(5208*20); uart_rx = 1 ; #(5208*20); #200000; // 55 0101_0101 uart_rx = 0 ; #(5208*20); uart_rx = 1 ; #(5208*20); uart_rx = 0 ; #(5208*20); uart_rx = 1 ; #(5208*20); uart_rx = 0 ; #(5208*20); uart_rx = 1 ; #(5208*20); uart_rx = 0 ; #(5208*20); uart_rx = 1 ; #(5208*20); uart_rx = 0 ; #(5208*20); uart_rx = 1 ; #(5208*20); #200000; $stop; end endmodule |
|
红框部分表示输出rx_data会在传送过程中有变化,同串口发送,设置锁存data
3.3 设置 r_rx_data 后 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 |
//嘎嘎嘎~~~~~
//好啦,摸鱼结束哩 ๑乛v乛๑
//下一次完成摸鱼任务白白~