設計思路
需要一個模3計數器和模10計數器,這裏需要設計一個可變模數的計數器,並對兩個計數器進行級聯。顯示模塊則採用最常用的七段顯示器,這裏需要注意的是,當十位數爲0時,應該令顯示器熄滅,合理控制計數器控制端即可。
變模計數器
思路
採用行爲級建模。
代碼實現
設計模塊
//filename:_24count.v
module varmodcnt(CP,CLR,EN,Q,carry_out);
parameter n=4,MOD=10;
input CP,CLR,EN;
output reg[n-1:0] Q;
output carry_out;
/*參數說明:
輸入:CP爲時鐘信號,CLR爲清零信號,EN爲使能信號
輸出:Q爲輸出,carry_out爲進位信號
*/
//敏感信號:CP上升沿,CLR下降沿
always@(posedge CP,negedge CLR)
begin
if(!CLR) Q<='d0;//置零
else if(!EN) Q<=Q; //保持
else begin
if(Q==MOD-1) Q<='d0; //達到MOD-1,歸零
else Q<=Q+1;//未達到MOD-1時,加一
end
end
assign carry_out=(Q==MOD-1); //Q=MOD-1時,進位信號有效
endmodule
module _24count(
input CP,
input CR,
output [3:0]Q0,Q1);
/*端口說明:
輸入:
CP爲時鐘信號,CR爲輸入清零信號
輸出:
Q1爲十位上數字對應的四位二進制,Q0爲十位上數字對應的四位二進制數
*/
//中間變量:TC進位信號,CLR爲爲24模的清零信號
wire TC0,TC1;
wire CLR;
varmodcnt #(4,10) U0(CP,CLR,EN,Q0,TC0); //個位信號
varmodcnt #(4,3) U1(CP,CLR,TC0,Q1,TC1); //十位信號
assign CLR=CR&(~({Q1,Q0}==8'b0010_0101)); //當外部清零信號有效或者輸出爲24時,進行清零
endmodule
測試模塊
//filename:tb_24count
`timescale 100ms/10ms
module tb_24count();
reg CP;
reg CR;
wire [3:0] Q0,Q1;
/*端口說明:
輸入:
CP爲時鐘信號,CR爲輸入清零信號
輸出:
Q1爲十位上數字對應的四位二進制,Q0爲十位上數字對應的四位二進制數
*/
//中間
_24count U(CP,CR,Q0,Q1);
initial
$monitor($time,"\tQ0=%b,Q1=%b\n",Q0,Q1);
//時鐘信號
initial
CP=0;
always
#5 CP=~CP;
//元件例化
initial
begin
//清零
CR=0;
#5;
//計數25s
CR=1;
#300;
$stop;
end
endmodule
仿真結果
顯示
思路
七段顯示器74HC4511之前已經進行了仿真,這裏只需注意十位顯示器的控制輸入應該在十位爲0的時候無效。注意這一點即可。
代碼顯示
設計模塊
//filename:_24show.v
module _24show(
input CP,CR,BL,LT,
output [6:0] L1,L0);
/*端口描述:
CP爲時鐘信號,CR爲清零信號,BL,LT實現滅燈和燈測試
*/
wire [3:0]Q0,Q1;
wire BL1;
_24count U(CP,CR,Q0,Q1);
assign BL1=BL&(Q1!=4'b0000);//十位顯示器的控制輸入應該在十位爲0的時候無效
_74HC4511 U1(1'b0,BL,LT,Q1,L1);
_74HC4511 U0(1'b0,BL,LT,Q0,L0);
endmodule
module _74HC4511(
input LE,BL,LT,
input [3:0] D,
output reg [6:0] L); //輸入輸出
wire [2:0] E;
assign E={LE,BL,LT}; //中間變量用於後續的控制端優先級判斷
always@(*)
begin
if(LE==0&&BL==1&<==1)
begin
case(D)
4'b0000:L=7'b111_1110;
4'b0001:L=7'b011_0000;
4'b0010:L=7'b110_1101;
4'b0011:L=7'b111_1001;
4'b0100:L=7'b011_0011;
4'b0101:L=7'b101_1011;
4'b0110:L=7'b001_1111;
4'b0111:L=7'b111_0000;
4'b1000:L=7'b111_1111;
4'b1001:L=7'b111_1011;
4'b1010:L=7'b000_0000;//以下爲無效狀態
4'b1011:L=7'b000_0000;
4'b1100:L=7'b000_0000;
4'b1101:L=7'b000_0000;
4'b1110:L=7'b000_0000;
4'b1111:L=7'b000_0000;
endcase
end
else
begin
casex(E)
3'bxx0:L=7'b111_1111; //燈測試
3'bx01:L=7'b000_0000; //滅燈
3'b111:L<=L; //鎖存
endcase
end
end
endmodule
//filename:_24count.v
module _24count(
input CP,
input CR,
output [3:0]Q0,Q1);
/*端口說明:
輸入:
CP爲時鐘信號,CR爲輸入清零信號
輸出:
Q1爲十位上數字對應的四位二進制,Q0爲十位上數字對應的四位二進制數
*/
//中間變量:TC進位信號,CLR爲爲24模的清零信號
wire TC0,TC1;
wire CLR;
varmodcnt #(4,10) U0(CP,CLR,EN,Q0,TC0); //個位信號
varmodcnt #(4,3) U1(CP,CLR,TC0,Q1,TC1); //十位信號
assign CLR=CR&(~({Q1,Q0}==8'b0010_0101)); //當外部清零信號有效或者輸出爲24時,進行清零
endmodule
測試模塊
//filename:tb_show.v
`timescale 100ms/10ms
module tb_show();
reg CP,CR;
reg BL,LT;
wire [6:0] L1,L0;
_24show U3(CP,CR,BL,LT,L1,L0); //實例化元器件
initial
$monitor($time,"\tL1=%b,L0=%b\n,",L1,L0);
//時鐘信號
initial
CP=0;
always
#5 CP=~CP;
initial
begin
//清零
CR=0;BL=1'b1;LT=1'b1;
#5;
//24s計時器開始計數
CR=1;BL=1'b1;LT=1'b1;
#300;
$stop;
end
endmodule
仿真