摸鱼记录 Day_16 (゚O゚)
review
前边已经学习了:
串口接收:Vivado 串口接收优化-CSDN博客
1. 今日摸鱼任务
串口接收数据 并用数码管显示 (゚O゚) 小梅哥视频: 17A 数码管段码显示与动态扫描原理_哔哩哔哩_bilibili 17B 数码管动态扫描显示数字逻辑建模_哔哩哔哩_bilibili 17C 数码管动态扫描显示的Verilog实现_哔哩哔哩_bilibili 17D 使能时钟和门控时钟的原理与差异_哔哩哔哩_bilibili //虽然看起来很多,但是不会很难滴 (゚O゚) |
2. 数码管显示原理
ACZ702 EDA 扩展板上板载的是共阳数码管。同时为了显示数字或字符,必须对数字或字符进行编码译码。
先不考虑小数点也就是简化为 7 段数码管,其编码译码格式如下表所示:
段式数码管工作方式有两种:静态显示方式和动态显示方式。
静态显示:每个数码管的段选必须接一个 8 位数据线来保持显示的字形码。当送入一次字形码后,显示字形可一直保持,直到送入新字形码为止。
这种方法由于每个数码管均需要独立的数据线,硬件电路比较复杂,成本较高,很少使用。
动态显示:将所有位数码管的段选线并联在一起,由位选线控制是哪一位数码管有效。选亮数码管采用动态扫描显示。所谓动态扫描显示即轮流向各位数码管送出字形码和相应的位选,利用发光管的余辉和人眼视觉暂留作用,使人的感觉好像各位数码管同时都在显示。
3. 时钟分频:门控时钟与使能时钟
门控时钟: 使用计数器和逻辑门翻转产生 |
reg [14:0]div_clk; always@(posedge clk or negedge reset_n) if(!reset_n) div_clk <= 1'b0; else if(div_clk == 24999) div_clk <= 1'b0; else div_clk <= div_clk + 1'b1; always@(posedge clk or negedge reset_n) if(!reset_n) clk_1 <= 1'b0; else if(div_clk == 24999) clk_1 <= ~clk_1; |
使能时钟: 用到计数器,但是不会用到反相器,生成的信号也不会直接用于其他电路的触发 |
reg [14:0]div_clk; always@(posedge clk or negedge reset_n) |
对比: 门控时钟的时钟延迟不稳定,且延迟比较大 使得时钟的波形变差 驱动能力差 小结:设计中一般情况下使用使能时钟的时钟分频方式 |
4. hex_8
4.1 design sources
hex_8 |
module hex_8(input clk, //[31:0]disp_data 16hex 4*8 // 1kHz分频时钟 // 位选sel endmodule |
4.2 hex_8_tb
`timescale 1ns / 1ns module hex_8_tb( ); reg clk , reset_n; reg [31:0]disp_data; wire[7:0]sel; wire[7:0]seg; hex_8 hex_8_(. clk(clk), . reset_n(reset_n), . disp_data(disp_data), . sel(sel), . seg(seg) ); initial clk = 1 ; always#10 clk = ~clk; initial begin reset_n = 0 ; #201; reset_n = 1 ; disp_data = 32'h01234567; #10000000; disp_data = 32'h89abcdef; #10000000; $stop; end endmodule |
红色框框内输入数据发生了改变,但是很快就会闪过去 所以没有像串口发送添加一个存储数据让其保持一个运行周期 |
5. 串口接收 + 数码管动态显示
5.1 design sources
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 |
rx_hex8 |
module rx_hex8(input clk, input reset_n, input uart_rx , output [7:0]sel, output [7:0]seg ); reg [1:0] rx_done_flag; reg [31:0]disp_data; wire [7:0] rx_data; wire rx_done; uart_rx uart_rx_(. clk(clk) , . reset_n(reset_n) ,.uart_rx(uart_rx) , . rx_data(rx_data), . rx_done(rx_done) ); always@(posedge clk or negedge reset_n) if(! reset_n) rx_done_flag <= 2'b11 ; else if(rx_done) rx_done_flag <= rx_done_flag + 1'b1 ; always@(posedge clk or negedge reset_n) if(! reset_n) disp_data <= 8'h0000_0000 ; else case(rx_done_flag) 0:begin disp_data <= disp_data; disp_data[7:0] <= rx_data;end 1:begin disp_data <= disp_data; disp_data[15:8] <= rx_data;end 2:begin disp_data <= disp_data; disp_data[23:16] <= rx_data;end 3:begin disp_data <= disp_data; disp_data[31:24] <= rx_data;end endcase hex_8 hex_8_(. clk(clk), . reset_n(reset_n), . disp_data(disp_data), .sel(sel), .seg(seg) ); endmodule |
5.2 rx_hex8_tb
`timescale 1ns / 1ns uart_rx_ = 0 ; #(5208*20);uart_rx_ = 0 ; #(5208*20); uart_rx_ = 1 ; #(5208*20);uart_rx_ = 1 ; #(5208*20); uart_rx_ = 0 ; #(5208*20);uart_rx_ = 1 ; #(5208*20); uart_rx_ = 1 ; #(5208*20);uart_rx_ = 0 ; #(5208*20); uart_rx_ = 1 ; #(5208*20);uart_rx_ = 0 ; #(5208*20); #(5208*20);uart_rx_ = 0 ; #(5208*20); uart_rx_ = 1 ; #(5208*20);uart_rx_ = 1 ; #(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_ = 0 ; #(5208*20);uart_rx_ = 0 ; #(5208*20); uart_rx_ = 1 ; #(5208*20);uart_rx_ = 1 ; #(5208*20); uart_rx_ = 0 ; #(5208*20);uart_rx_ = 0 ; #(5208*20); uart_rx_ = 1 ; #(5208*20);uart_rx_ = 1 ; #(5208*20); uart_rx_ = 0 ; #(5208*20);uart_rx_ = 0 ; #(5208*20); uart_rx_ = 1 ; #(5208*20);uart_rx_ = 1 ; #(5208*20); uart_rx_ = 0 ; #(5208*20);uart_rx_ = 0 ; #(5208*20); uart_rx_ = 1 ; #(5208*20);uart_rx_ = 1 ; #(5208*20); |
//好耶~~~~~
//摸鱼结束哩 (゚O゚)
//顺便挖坑SPI协议