1. Count15(Four-bit binary counter)
由于输出q为4-bit,当执行到15+1时,会自动回到0,故不需要设计清零步骤。
module top_module (
input clk, reset,
output [3:0] q
);
always @(posedge clk) begin
if (reset) begin
q <= 0;
end
else begin
q <= q + 1'b1;
end
end
endmodule
2. Count10(Decade counter)
由于我们要用十六进制计数器设计十进制计数器,故要设计清零步骤。这里采用清零法,当技术到9时,在下一个时钟信号上升沿对q进行清零。
module top_module (
input clk, reset,
output [3:0] q
);
always @(posedge clk) begin
if (reset || q==4'h9) begin
q <= 0;
end
else begin
q <= q + 1'b1;
end
end
endmodule
3. Count1to10(Decade counter again)
虽同为十进制计数器,但与上一个不同,前者为0-9计数,后者为1-10计数。故这里使用置数法设计清零步骤,当计数到10时,在下一个时钟信号上升沿将q置数为1。
module top_module (
input clk, reset,
output [3:0] q
);
always @(posedge clk) begin
if (reset || q==4'ha) begin
q <= 4'h1;
end
else begin
q <= q + 1'b1;
end
end
endmodule
4. Countslow(Slow decade counter)
该题的清零步骤(不考虑reset清零)又与第二题的设计有所不同,此题的清零需要在slowena处于高电平时才能执行,否则q的值保持不变。
module top_module (
input clk, slowena, reset,
output [3:0] q
);
always @(posedge clk) begin
if (reset) begin
q <= 0;
end
else if (slowena && q<4'h9) begin
q <= q + 1'b1;
end
else if (slowena && q==4'h9) begin
q <= 0;
end
end
endmodule
5. Exams/ece241 2014 q7a(Counter 1-12)
module top_module (
input clk,
input reset,
input enable,
output [3:0] Q,
output c_enable,
output c_load,
output [3:0] c_d
);
count4 the_counter ( clk, c_enable, c_load, c_d, Q );
assign c_enable = enable;
assign c_load = reset || ((Q==4'd12) && (enable==1'b1));
assign c_d = c_load ? 4'd1 : 4'd0;
endmodule
6. Exams/ece241 2014 q7b(Counter 1000)
方法1:
module top_module (
input clk,
input reset,
output OneHertz,
output [2:0] c_enable
);
wire [3:0] a, b, c;
assign c_enable = { (a==4'd9)&&(b==4'd9), (a==4'd9), 1'b1 };
assign OneHertz = (a[0]&&b[0]&&c[0]) && (a[3]&&b[3]&&c[3]);
bcdcount counter0 ( clk, reset, c_enable[0], a );
bcdcount counter1 ( clk, reset, c_enable[1], b );
bcdcount counter2 ( clk, reset, c_enable[2], c );
endmodule
方法2:
module top_module (
input clk,
input reset,
output OneHertz,
output [2:0] c_enable
);
wire [3:0] a, b, c;
assign c_enable = { (a==4'd9)&&(b==4'd9), (a==4'd9), 1'b1 };
assign OneHertz = (a==4'd9) && (b==4'd9) && (c==4'd9);
bcdcount counter0 ( clk, reset, c_enable[0], a );
bcdcount counter1 ( clk, reset, c_enable[1], b );
bcdcount counter2 ( clk, reset, c_enable[2], c );
endmodule
7. Countbcd(4-digit decimal counter)
module top_module (
input clk,
input reset,
output [3:1] ena,
output [15:0] q
);
countbcd M1 ( .q(q[3:0]), .clk(clk), .reset(reset), .enable(1'b1) );
countbcd M2 ( .q(q[7:4]), .clk(clk), .reset(reset), .enable(ena[1]) );
countbcd M3 ( .q(q[11:8]), .clk(clk), .reset(reset), .enable(ena[2]) );
countbcd M4 ( .q(q[15:12]), .clk(clk), .reset(reset), .enable(ena[3]) );
assign ena = { ((q[3:0]==4'd9) && (q[7:4]==4'd9) && (q[11:8]==4'd9)),
((q[3:0]==4'd9) && (q[7:4]==4'd9)),
(q[3:0]==4'd9)};
endmodule
module countbcd (
output reg [3:0] q,
input clk,
input reset,
input enable
);
always @(posedge clk) begin
if (reset) begin
q <= 0;
end
else if (enable && q==4'd9) begin
q <= 0;
end
else if (enable && q<4'd9) begin
q <= q + 1'b1;
end
end
endmodule
8. Count clock(12-hour clock)
这里有个比较迷惑的点就是PM位的循环,它与时钟的循环是错开了一个周期的。
时钟的循环范围是(1-12),而PM的循环范围是(0-11),相当于
1 AM ➡️ 11 AM ➡️ 12 PM ➡️ 1PM ➡️ 11PM ➡️ 12AM ➡️ 1AM ➡️ ...
所以实际上PM的循环范围是(0(12)-11)【钟表上0与12是重合的】。
方法1:
module top_module(
output pm,
output [7:0] hh,
output [7:0] mm,
output [7:0] ss,
input clk,
input reset,
input ena
);
wire sso_ena, sst_ena; // sso使能信号,sst使能信号
wire mmo_ena, mmt_ena; // mmo使能信号,mmt使能信号
wire hho_ena; // hho使能信号
wire hht_ena; // hht使能信号
wire h_cycle; // hht、hho置数信号
wire pm_ena; // pm翻转信号
wire [3:0] sso, sst; // 秒钟个位、秒钟十位
wire [3:0] mmo, mmt; // 分钟个位、分钟十位
wire [7:0] hto; // 时钟
assign hh = hto; // 时钟输出赋值
assign mm = {mmt, mmo}; // 分钟输出赋值
assign ss = {sst, sso}; // 秒钟输出赋值
PM M1 ( .P(pm), .CLK(clk), .RST(reset), .ENP(pm_ena) );
Count_h M2 ( .Q(hto), .CLK(clk), .RST(reset), .ENT(hht_ena), .ENO(hho_ena), .ENC(h_cycle) );
Count_ten M3 ( .Q(mmt), .CLK(clk), .RST(reset), .EN(mmt_ena) );
Count_one M4 ( .Q(mmo), .CLK(clk), .RST(reset), .EN(mmo_ena) );
Count_ten M5 ( .Q(sst), .CLK(clk), .RST(reset), .EN(sst_ena) );
Count_one M6 ( .Q(sso), .CLK(clk), .RST(reset), .EN(sso_ena) );
// 各例化模块的使能信号
assign pm_ena = hho_ena && (hto[7:4]==4'd1) && (hto[3:0]==4'd1);
assign h_cycle = hho_ena && (hto[7:4]==4'd1) && (hto[3:0]==4'd2);
assign hht_ena = hho_ena && (hto[3:0]==4'd9);
assign hho_ena = mmt_ena && (mmt==4'd5);
assign mmt_ena = mmo_ena && (mmo==4'd9);
assign mmo_ena = sst_ena && (sst==4'd5);
assign sst_ena = sso_ena && (sso==4'd9);
assign sso_ena = ena;
endmodule
// PM位模块
module PM (
output P,
inout CLK, RST,
input ENP
);
always @(posedge CLK) begin
if (RST) begin
P <= 1'b0;
end
else if (ENP) begin
P <= ~P;
end
end
endmodule
// 时钟模块
module Count_h (
output reg [7:0] Q,
input CLK, RST,
input ENT, ENO, ENC
);
always @(posedge CLK) begin
if (RST) begin
Q[7:4] <= 4'd1;
end
else if (ENC) begin
Q[7:4] <= 4'd0;
end
else if (ENT) begin
Q[7:4] <= Q[7:4] + 1'b1;
end
end
always @(posedge CLK) begin
if (RST) begin
Q[3:0] <= 4'd2;
end
else if (ENC) begin
Q[3:0] <= 4'd1;
end
else if (ENO && Q==4'd9) begin
Q[3:0] <= 4'd0;
end
else if (ENO) begin
Q[3:0] <= Q[3:0] + 1'b1;
end
end
endmodule
// 十位片模块
module Count_ten (
output reg [3:0] Q,
input CLK, RST,
input EN
);
always @(posedge CLK) begin
if (RST) begin
Q <= 4'd0;
end
else if (EN) begin
if (Q==4'd5) begin
Q <= 4'd0;
end
else begin
Q <= Q + 1'b1;
end
end
end
endmodule
// 个位片模块
module Count_one (
output reg [3:0] Q,
input CLK, RST,
input EN
);
always @(posedge CLK) begin
if (RST) begin
Q <= 4'd0;
end
else if (EN) begin
if (Q==4'd9) begin
Q <= 4'd0;
end
else begin
Q <= Q + 1'b1;
end
end
end
endmodule
方法2:
module top_module (
output reg pm,
output reg [7:0] hh,
output reg [7:0] mm,
output reg [7:0] ss,
input clk,
input reset,
input ena
);
wire sso_sta, sso_end; // sso使能信号、sso清零信号
wire sst_sta, sst_end; // sst使能信号、sst清零信号
wire mmo_sta, mmo_end; // mmo使能信号、mmo清零信号
wire mmt_sta, mmt_end; // mmt使能信号、mmt清零信号
wire hho_sta, hho_end_0, hho_end_1; // hho使能信号、hho清零信号、hho置1信号
wire hht_sta, hht_end; // hht使能信号、hht清零信号
wire pm_ena; // pm翻转信号
// PM位 start
always @(posedge clk) begin
if (reset) begin
pm <= 0;
end
else if (pm_ena) begin
pm <= ~pm; // pm信号翻转
end
end
// 当hh[7:4]==8'd11, mm[7:4]==8'd59, ss[7:4]==8'd59(即11:59:59)时,pm翻转信号为1。
assign pm_ena = hho_sta && (hh[7:4]==4'd1) && (hh[3:0]==4'd1);
// end
// 时钟十位hht start
always @(posedge clk) begin
if (reset) begin
hh[7:4] <= 1;
end
else if (hht_end) begin
hh[7:4] <= 0;
end
else if (hht_sta) begin
hh[7:4] <= hh[7:4] + 1;
end
end
assign hht_sta = hho_end_0;
assign hht_end = hho_end_1;
// end
// 时钟个位hho start
always @(posedge clk) begin
if (reset) begin
hh[3:0] <= 2;
end
else if (hho_end_0) begin
hh[3:0] <= 0;
end
else if (hho_end_1) begin
hh[3:0] <= 1;
end
else if (hho_sta) begin
hh[3:0] <= hh[3:0] + 1;
end
end
assign hho_sta = mmt_end;
assign hho_end_0 = hho_sta && (hh[3:0]==4'd9);
assign hho_end_1 = hho_sta && (hh[7:4]==4'd1) && (hh[3:0]==4'd2);
// end
// 分钟十位mmt start
always @(posedge clk) begin
if (reset) begin
mm[7:4] <= 0;
end
else if (mmt_end) begin
mm[7:4] <= 0;
end
else if (mmt_sta) begin
mm[7:4] <= mm[7:4] + 1;
end
end
assign mmt_sta = mmo_end;
assign mmt_end = mmt_sta && mm[7:4]==4'd5;
// end
// 分钟个位mmo start
always @(posedge clk) begin
if (reset) begin
mm[3:0] <= 0;
end
else if (mmo_end) begin
mm[3:0] <= 0;
end
else if (mmo_sta) begin
mm[3:0] <= mm[3:0] + 1;
end
end
assign mmo_sta = sst_end;
assign mmo_end = mmo_sta && mm[3:0]==4'd9;
// end
// 秒钟十位sst start
always @(posedge clk) begin
if (reset) begin
ss[7:4] <= 0;
end
else if (sst_end) begin
ss[7:4] <= 0;
end
else if (sst_sta) begin
ss[7:4] <= ss[7:4] + 1;
end
end
assign sst_sta = sso_end;
assign sst_end = sst_sta && ss[7:4]==4'd5;
// end
// 秒钟个位sso start
always @(posedge clk) begin
if (reset) begin
ss[3:0] <= 0;
end
else if (sso_end) begin
ss[3:0] <= 0;
end
else if (sso_sta) begin
ss[3:0] <= ss[3:0] + 1;
end
end
assign sso_sta = ena;
assign sso_end = sso_sta && (ss[3:0]==4'd9);
// end
endmodule