根据原理图可知,此处数码管数据时共享的,每个位由片选信号分隔开,考虑人眼的视觉残留,可用扫描的方式更新数据。
这个驱动,有两个比较重要的,就是扫描驱动和二进制转BCD编码了
先说扫描驱动吧,要让第一个位现实,则需要打开SEL0_T并输入段码数据,然后输出第二位,第三位……,这里数据刷新的频率不能太高,一则人眼对100Hz以上的信号已不怎么分辨得出来,二则这里的PNP三极管开关速度也是有限制的
(修改代码中) 原地址:http://blog.sina.com.cn/s/blog_450b0ea901013yps.html
2013/2/28 14:17
扫描模块,这个代码比之前的代码,占用资源更少(少了100个LE的样子,说明以前代码太差了,毕竟那时候初学),
module DIGIT_MODULE
(
input CLK,
input RST,
input [23:0] BCD,
output [7:0] DIG,
output [5:0] SEL
);
assign DIG=rDIG;
assign SEL=rSEL;
//......................................................................................................................
localparam N0 = 8'B11000000, N1 = 8'b11111001, N2 = 8'b10100100, N3 = 8'b10110000, N4 = 8'b10011001,
N5 = 8'B10010010, N6 = 8'b10000010, N7 = 8'b11111000, N8 = 8'b10000000, N9 = 8'b10010000;
reg [3:0] rBCD;
reg [7:0] rDIG;
always @(rBCD or RST)
if(!RST) rDIG<=N0;
else case(rBCD)
4'D0: rDIG<=N0;
4'D1: rDIG<=N1;
4'D2: rDIG<=N2;
4'D3: rDIG<=N3;
4'D4: rDIG<=N4;
4'D5: rDIG<=N5;
4'D6: rDIG<=N6;
4'D7: rDIG<=N7;
4'D8: rDIG<=N8;
4'D9: rDIG<=N9;
default: rDIG<=N0;
endcase
//......................................................................................................................
reg[5:0] rSEL;
reg[2:0] rNumber;
always @ (negedge CLK or negedge RST)
if(!RST) begin
rSEL <=6'B111111;
rBCD <=4'D0;
rNumber <=3'H0;
end
else begin
if(rNumber==3'H5) rNumber<=3'H0;
else rNumber<=rNumber+1'B1;
case(rNumber)
3'H0: begin
rSEL<=6'B111110;
rBCD<=BCD[23:20];
end
3'H1: begin
rSEL<=6'B111101;
rBCD<=BCD[19:16];
end
3'H2: begin
rSEL<=6'B111011;
rBCD<=BCD[15:12];
end
3'H3: begin
rSEL<=6'B110111;
rBCD<=BCD[11:8];
end
3'H4: begin
rSEL<=6'B101111;
rBCD<=BCD[7:4];
end
3'H5: begin
rSEL<=6'B011111;
rBCD<=BCD[3:0];
end
endcase
end
//......................................................................................................................
endmodule
另一个比较重要的就是二进制转BCD(8421)编码,通常使用左移加3的算法,实现方法如图
此处有6位数码管,按最大显示的十进制算,需要23bit的二进制来表示,考虑这里速度要求不高,使用时序逻辑操作(代码编写中,非流水线组合逻辑实现请参考http://blog.sina.com.cn/s/blog_450b0ea901013yps.html)
//======================================================================================================================
module BIN_TO_BCD_MODULE
#(
parameter BIT_WIDTH=20,
parameter BCD_WIDTH=24
)
(
input wClock,
input wReset,
input wEnable,
input wWE,
input [19:0] BIN,
output [23:0] BCD
);
function[3:0] LSA3;
input [3:0] IN;
case (IN)
4'B0000: LSA3 = 4'B0000;
4'B0001: LSA3 = 4'B0001;
4'B0010: LSA3 = 4'B0010;
4'B0011: LSA3 = 4'B0011;
4'B0100: LSA3 = 4'B0100;
4'B0101: LSA3 = 4'B1000;
4'B0110: LSA3 = 4'B1001;
4'B0111: LSA3 = 4'B1010;
4'B1000: LSA3 = 4'B1011;
4'B1001: LSA3 = 4'B1100;
default: LSA3 = 4'B0000;
endcase
endfunction
reg [23:0] rBCD;
reg [23:0] rBCD_OUT;
reg [19:0] rBIN;
reg [4:0] rBitCount;
reg rBusy;
assign BCD=rBCD_OUT;
wire [23:0] wBCD;
assign wBCD={LSA3(rBCD[23:20]),LSA3(rBCD[19:16]),LSA3(rBCD[15:12]),LSA3(rBCD[11:8]),LSA3(rBCD[7:4]),LSA3(rBCD[3:0])};
always @(posedge wClock or negedge wReset)
if(!wReset) begin
rBCD_OUT <=24'H000000;
rBIN <=20'H00000;
rBitCount <=5'D0;
rBusy <=1'B0;
end
else begin
if(!rBusy) begin
if(wWE) begin
rBIN <=BIN;
rBusy <=1'B1;
rBitCount <=5'D0;
rBCD <=24'H000000;
end
end
else begin
if(rBitCount==20) begin
rBCD_OUT<=rBCD;
rBusy<=1'B0;
end
else begin
rBitCount <=rBitCount+1'B1;
{rBCD,rBIN} <={wBCD[22:0],rBIN[19:0],1'B0};
end
end
end
endmodule
该工程 从原来的 472个LE占用,优化大现在190个LE