我在上一周做了一个数字钟的实验,当时也用到了数码管,我的开发板上有6个数码管,正好2个给小时,2个给分钟,2个给秒。每一个数码管都有自己的任务,所以就不用考虑消“0”的问题了。但这一次做计算器不一样,比如说:我要输入12,如果显示的是“000012”,那是不合理而且很难看的,所以12前面的4个“0”,我们必须想办法把给干掉。其实很简单,大体模块和之前数字钟的数码管还是一样的数码管,位选加译码,数码管永恒不变的标配,我们只用增加一段代码而已,还是先把代码贴出来。
module sel(
input CLK_1K, //时钟频率1K.
input RSTN,
input [23:0]num_value,
output[3:0] data_num,
output reg[2:0] data_sel
);
reg [2:0]i;
reg [3:0]D1;
//reg [20:0]D2;
parameter bit = 5;
reg [23:0]num_disp;
always@(*)
begin
casex(num_value)
24'h00000x: num_disp = {20'hfffff,num_value[3:0]};
24'h0000xx: num_disp = {16'hffff,num_value[7:0]};
24'h000xxx: num_disp = {12'hfff,num_value[11:0]};
24'h00xxxx: num_disp = {8'hff,num_value[15:0]};
24'h0xxxxx: num_disp = {4'hf,num_value[19:0]};
default: num_disp = num_value;
endcase
end
always@(posedge CLK_1K or negedge RSTN)
begin
if(!RSTN)
begin
i <= 0;
data_sel<= 0;
D1 <= 0;
end
else
case(i)
0: begin D1 <= num_disp[3:0]; data_sel <= bit; i <= i+1;end
1: begin D1 <= num_disp[7:4]; data_sel <=data_sel-1; i <= i+1;end
2: begin D1 <= num_disp[11:8]; data_sel <=data_sel-1; i <= i+1;end
3: begin D1 <= num_disp[15:12];data_sel <=data_sel-1; i <= i+1;end
4: begin D1 <= num_disp[19:16];data_sel <=data_sel-1; i <= i+1;end
5: begin D1 <= num_disp[23:20];data_sel <=data_sel-1; i <= i+1;end
default:i <= 0;
endcase
end
assign data_num = D1;
endmodule
这段代码和普通的数码管数码管扫描几乎别无二致,仅仅多了绿色的那一段而已,没错,为什么我们加这么一段就可以达到消零的目的呢?且听我慢慢道来。
这里用到了一个叫casex的语法,相信大家对case都不陌生,但是大部分初学者估计都没有用过casex,其实不光有casex,他还有个孪生兄弟叫casez,有兴趣的可以去翻一翻夏老师的那本经典教程,其实我写这段代码之前我也不知道有他,多亏高人指点,不然我就傻呵呵的去定义一个变量数输入了多少位数,再去控制位选了。回归正题,casex到底怎么用,其实他和case差不多,只是多了个x,我们都知道,数电里面有高电平1,低电平0,不定态X,高阻态Z。所谓不定态就是不知道它是0还是1。所以放在我们这段代码里意思就是不管x所代表的是0还是1,我都满足casex的条件。如果判断出一个数的前5位都是0,那么我们就给他的前五位赋值成熄灭码,也就是在数码管译码的时候译成全1的值(数码管是共阳)。这里还有一个地方得注意,假如一个数前5位都是0,那是不是以为着,上面5种情况他都满足,那他到底执行哪一种呢?其实case、casex和if else一样是有优先级的,写在最上面的优先级最高。所以判断是否有5个0的,一定要赋予它最高的优先级。
|