目录
工程的基本原理:
1.动态显示
8位数码管在每(20/8)ms左右的间隔情况之下循环亮灭,同时在每个数码管单独显示每一位相对应的数字或者字母,因为循环亮灭的时间很短,这里利用人的视觉暂留效应,使得有8位数码管同时显示的错觉。更加通俗的说,类似于我们平时用的灯管,灯管两端接上50HZ交流电后,灯管以(1/50)s的周期循环亮灭,但实际上人眼所观察到的确是灯管一直在亮。
2.数码管结构
如上图15.18所示,左边图(a)为单个数码管,其中共分为(a-h)8端,其中h段也就是图中的dp段,代表小数点。
右图(b)则分别显示共阴极(低电平有效)和共阳极的两类数码管。
以一位数码管显示数字‘1’为例,如果为共阳极数码管那么hgfedcba对应11111001,
若为共阴极数码管那么hgfedcba对应00000110.
3.译码表
如下图15.1,为8段的数码管显示所对应的16进制译码表
4.结构图:
首先,利用分频器得到频率为50MHZ的方波,通过得到的方波信号来控制3位的计数器。得到的3位输出num作为三八译码器的输入从而来控制输出sel端,即代表哪一个数码管来亮。同时,输入了32位的数据disp_data,再通过上述的三位计数器控制,借助多路数据选择器来输出disp_tmp,从而选择所要显示的内容,以seg为输出。
代码实现:
源代码:
module dongtaishumaguan( input clk, input rst_n, input [31:0] data, output reg [7:0] sel,//位选 output reg [7:0] seg//段选 ); reg [14:0] div_cnt; always@(posedge clk or negedge rst_n)begin if(!rst_n) div_cnt<= 0; else if(div_cnt>=24999) div_cnt<= 0; else div_cnt<= div_cnt+1'b1; end reg clk_1; always@(posedge clk or negedge rst_n)begin if(!rst_n) clk_1<= 0; else if(div_cnt==24999) clk_1<= ~clk_1; end reg [2:0] cnt; always@(posedge clk_1 or negedge rst_n)begin if(!rst_n) cnt<= 0; else cnt<= cnt+1'b1; end always@(*)begin case(cnt) 0:sel = 8'b0000_0001; 1:sel = 8'b0000_0010; 2:sel = 8'b0000_0100; 3:sel = 8'b0000_1000; 4:sel = 8'b0001_0000; 5:sel = 8'b0010_0000; 6:sel = 8'b0100_0000; 7:sel = 8'b1000_0000; endcase end reg [3:0] data_1; always@(*)begin case(cnt) 0:data_1 = data[31:28]; 1:data_1 = data[27:24]; 2:data_1 = data[23:20]; 3:data_1 = data[19:16]; 4:data_1 = data[15:12]; 5:data_1 = data[11:8]; 6:data_1 = data[7:4]; 7:data_1 = data[3:0]; endcase end always@(*)begin case(data_1) 0:seg = 8'hc0; 1:seg = 8'hf9; 2:seg = 8'ha4; 3:seg = 8'hb0; 4:seg = 8'h99; 5:seg = 8'h92; 6:seg = 8'h82; 7:seg = 8'hf8; 8:seg = 8'h80; 9:seg = 8'h90; 4'ha:seg = 8'h88; 4'hb:seg = 8'h83; 4'hc:seg = 8'hc6; 4'hd:seg = 8'ha1; 4'he:seg = 8'h86; 4'hf:seg = 8'h8e; endcase end endmodule
tb文件 :
module tb_dongtaishumaguan; // Inputs reg clk; reg rst_n; reg [31:0] data; // Outputs wire [7:0] sel; wire [7:0] seg; // Instantiate the Unit Under Test (UUT) dongtaishumaguan uut ( .clk(clk), .rst_n(rst_n), .data(data), .sel(sel), .seg(seg) ); always #10 clk=~clk; initial begin // Initialize Inputs clk = 1; rst_n = 0; data = 0;//32'h0000_0000; // Wait 100 ns for global reset to finish #201; rst_n = 1; #2000; data = 32'h87654321; #20000000; data = 32'habcdef12; // Add stimulus here end endmodule
仿真波形图:
这里我们可以右键输出或者输入信号,点击Radix可以去选择各种进制的显示,为了方便查错,这里对seg信号我们选择16进制显示 ,发现恰好与上面的译码表一一对应。