Vivado 摸鱼记录 Day_9 (∪。∪)。。。zzz
review
day_8 串口发送原理 Vivado 串口通信(UART)原理A ------串口发送实验-CSDN博客
day_8 实现了一个简单的串口程序
1. 今日摸鱼任务 (∪。∪)。。。zzz
1. 实现 uart_tx(input clk , input reset_n , input [7:0]data , input Send_Go ,
output reg uart_tx , output reg Tx_Done )
2. 使用uart_tx 实现day_8任务
2. uart_tx
分析:Send_Go为一个短暂时间信号,如按键按下、人路过等
对比day_8:
显然需要在接收到Send_Go 后设置使能信号Send_en控制信号发送
2.1 design sources
module UART_tx(input clk , input reset_n , input [7:0]data , input Send_Go , output reg uart_tx , output reg Tx_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 Send_en; always@(posedge clk or negedge reset_n ) if(! reset_n) Send_en <= 0 ; else if(Send_Go ) Send_en <= 1 ; else if((tx_flag==9)&&(counter_bps == bps_c - 1)) //else if (Tx_Done) tx_flag <= 0 ; Send_en <= 0 ; // bps reg [30:0] counter_bps ; always@(posedge clk or negedge reset_n) if(! reset_n) counter_bps <= 0 ; else if (Send_en) if(counter_bps == bps_c - 1) counter_bps <= 0 ; else counter_bps <= counter_bps + 1'b1 ; else counter_bps <= 0 ; // 发送状态 reg [3:0] tx_flag; always@(posedge clk or negedge reset_n) if(! reset_n) tx_flag <= 0 ; else if (!Send_en) tx_flag <= 0 ; else if ((tx_flag==9)&&(counter_bps == bps_c - 1)) //else if (Tx_Done) tx_flag <= 0 ; tx_flag <= 0 ; else if(counter_bps == bps_c - 1) tx_flag <= tx_flag + 1'b1 ; // Send_Go改变发送信号 reg [7:0]r_data; always@(posedge clk) if(Send_Go ) r_data <= data; else r_data <= r_data; // tx_flag always@(*) if(!Send_en) uart_tx <= 1'b1; else begin case(tx_flag) 4'b0000 : uart_tx <= start_bit; 4'b0001 : uart_tx <= r_data[0]; 4'b0010 : uart_tx <= r_data[1]; 4'b0011 : uart_tx <= r_data[2]; 4'b0100 : uart_tx <= r_data[3]; 4'b0101 : uart_tx <= r_data[4]; 4'b0110 : uart_tx <= r_data[5]; 4'b0111 : uart_tx <= r_data[6]; 4'b1000 : uart_tx <= r_data[7]; 4'b1001 : uart_tx <= stop_bit; default : uart_tx <= uart_tx; endcase end always@(posedge clk or negedge reset_n) Tx_Done <= (tx_flag==9)&&(counter_bps == bps_c - 1); endmodule |
2.2 uart_tx_tb
`timescale 1ns / 1ns module UART_tx_tb(); reg clk ,reset_n , Send_Go ; reg [7:0]data; wire uart_tx , Tx_Done; UART_tx uart_t_1(.clk(clk) , .reset_n(reset_n) , .data(data) ,.Send_Go(Send_Go), .uart_tx(uart_tx) , .Tx_Done(Tx_Done) ); initial clk = 1 ; always #10 clk = ~clk ; initial begin Send_Go = 0; data = 8'b0110_0000; reset_n = 0 ; #20001; reset_n = 1 ; Send_Go = 1 ; #40; Send_Go = 0 ; #400000; data = 8'b0101_1111; Send_Go = 0 ; #500000; data = 8'b1101_0101;#500000; Send_Go = 1 ;#40; Send_Go = 0 ;#1200000 ; $stop; end endmodule |
2.2.1 Tx_Done 与 (tx_flag==9)&&(counter_bps == bps_c - 1)
else if (Tx_Done) |
|
由上面两个图可以看出,tx_flag出现了一个时钟周期的状态a 虽然对uart_tx无影响 default : uart_tx <= uart_tx; 但还是修改一下: |
else if (tx_flag==9)&&(counter_bps == bps_c - 1)) |
|
2.2.2 data 与 r_data
无r_data uart_tx <= data[*]; |
|
由上图可以看出:直接输出data,在data变化且正在输出时,会使输出数据错误 |
// Send_Go改变发送信号 reg [7:0]r_data; always@(posedge clk) if(Send_Go) r_data <= data; else r_data <= r_data; |
|
由上面两图可以看出,使用r_data 在Send_Go 信号后对data锁存,可以保证每次发送的是当时时刻的数据。 |
3. uart_tx_test 实现今日摸鱼任务(∪。∪)。。。zzz
3.1 design sources
module uart_tx_test(input clk , input reset_n , input [7:0]data , output uart_tx , output reg LED); reg Send_Go ; wire Tx_Done; UART_tx #(.BAUD(115200)) uart_tx_test_(.clk(clk) , .reset_n(reset_n) , .data(data) ,.Send_Go(Send_Go), .uart_tx(uart_tx) , .Tx_Done(Tx_Done) ); // 1s parameter counter_second = 50000000; reg [30:0] counter ; always@(posedge clk or negedge reset_n) if(! reset_n) counter <= 0 ; else if(counter == counter_second - 1) counter <= 0 ; else counter <= counter + 1'b1 ; // tx Send_Go always@(posedge clk or negedge reset_n) if(! reset_n) Send_Go <= 1 ; else if(counter == counter_second - 1) Send_Go <= 1 ; else Send_Go <= 0 ; // led always@(posedge clk or negedge reset_n) if(! reset_n) LED <= 0 ; else if(Tx_Done) LED <= 1 ; else LED <= 0 ; endmodule |
wire Tx_Done; Tx_Done 是 UART_tx 的输出 |
UART_tx #(.BAUD(115200)) 本次实验要求波特率为115200 |
3.2 uart_tx_text_tb
`timescale 1ns / 1ns module uart_tx_text_tb(); reg clk ,reset_n ; reg [7:0]data; wire uart_tx , LED ; uart_tx_test#(.counter_second(8000)) text_tb(.clk(clk) , .reset_n(reset_n) , .data(data) , .uart_tx(uart_tx) , .LED(LED)); initial clk = 1 ; always #10 clk = ~clk ; initial begin data = 8'b0101_1111; reset_n = 0 ; #20001; reset_n = 1 ; #80000 ; data = 8'b1101_0111;#60; #200000 ; data = 8'b1101_0000;#60; #200000 ; $stop; end endmodule |
uart_tx_test#(.counter_second(8000)) 本次波特率115200 , 为测试方便,减少周期时间 |
看着貌似没有问题,不过上板测试发现LED闪时间太短啦!
// led always@(posedge clk or negedge reset_n) if(! reset_n) LED <= 0 ; else if(Tx_Done) LED <= 1 ; else if(Send_Go) LED <= 0 ; //不过感觉变成了一直亮 |
(主要原因是波特率115200 )86.8us观察也太难为人了有点(∪。∪)。。。zzz
//好啦,摸鱼结束哩(∪。∪)。。。zzz