HDLBits(16)4.19
3 电路
3.2 时序逻辑
3.2.2 计数器
- Count1to10(Decade counter again)
与上题一样,区别是复位为1
module top_module(
input clk,
input reset,
output [3:0] q);
always @(posedge clk)
begin
if(reset)
q <= 4'b0001; //复位为1
else if(q <= 4'b1001)
q <= q + 1'b1;
else
q <= 4'b0001;
end
endmodule
- Coutslow(Slow decade couter)
一个0-9,同步复位且复位为0的计数器,但计数器不随clk变化而递增,而是由slowena使能信号控制
module top_module (
input clk,
input slowena,
input reset,
output [3:0] q);
always @ (posedge clk)
begin
if(reset)
q <= 4'b0;
else if(slowena == 1'b1)
begin
if(q == 4'd9)
q <= 4'b0;
else
q <= q + 4'd1;
end
end
endmodule
- Counter 1-12
根据以下输入输出信号设计一个计算1~12的计数器
Reset:同步复位信号,高复位,将计数器复位为1.
Enable:使能信号高有效
Clk:时钟上升沿触发计数器工作
Q[3:0]:计数器输出
c_enable, c_load, c_d[3:0]:题目中给我们提供了一个4-bit的计数器,这三个信号是用于该4-bit计数器的控制信号。
题目提供给我们4-bit计数器
- 有enable信号,带复位和置位的计数器,将该计数器例化至我们的代码中。
- 再用一些其他的逻辑门来完成本题
module top_module (
input clk,
input reset,
input enable,
output [3:0]Q,
output c_enable,
output c_load,
output [3:0]c_d
);
reg [3:0] temp; //4-bit 计数器的控制信号
assign c_enable = enable;
assign c_load = reset | (Q == 4'd12 & enable == 1'b1);
assign c_d = 4'b1;
count4 the_counter (clk,c_enable,c_load,c_d,Q);
endmodule
- Counter1000
OneHertz: 从1000Hz中分离出1Hz的信号;这个信号主要用作于数字时钟中。
利用一个模10的BCD计数器和尽量少的逻辑门建立一个时钟分频器。同时输出每个BCD计算器的使能信号(c_enable[0]为高位,c_enable[2]为低位)
module bcdcount (
input clk,
input reset,
output OneHertz,
output [2:0] c_enable
);
wire [3:0] q0,q1,q2; //1000 -> 100(q2) -> 10(q1) -> 1(q0)
assign c_enable = {q1==4'd9 && q0==4'd9,q0==4'd9,1'b1};
assign OneHertz = {q2==4'd9 && q1==4'd9 && q0==4'd9};
bcdcount counter0 (clk, reset, c_enable[0], q0);
bcdcount counter1 (clk, reset, c_enable[1], q1);
bcdcount counter2 (clk, reset, c_enable[2], q2);
endmodule
- Countbcd(4-digit decimal counter)
设计一个4位BCD计数器。每个十进制数字使用4-bit来表示:q[3:0]是个位,q[4:7]是十位等,ena[3:1]表示个位、十位、百位的进位
module top_module (
input clk,
input reset,
output [3:1] ena,
outout [15:0] q
);
//分别实例化个十百千四个计数器子模块
//one
count Inst1_count
(
.clk(clk),
.reset(reset),
.ena(1'b1),
.q(q[3:0])
);
//ten
count Inst2_count
(
.clk(clk),
.reset(reset),
.ena(q[3:0] == 4'd9),
.q(q[7:4])
);
//hundred
count Inst3_count
(
.clk(clk),
.reset(reset),
.ena(q[7:4] == 4'd9 && q[3:0] == 4'd9),
.q(q[11:8])
);
//thousand
count Inst4_count
(
.clk(clk),
.reset(reset),
.ena(q[11:8] == 4'd9 && q[7:4] == 4'd9 && q[3:0] == 4'd9),
.q(q[15:12])
);
assign ena = {q[11:8] == 4'd9 && q[7:4] == 4'd9 && q[3:0] == 4'd9 , q[7:4] == 4'd9 && q[3:0] == 4'd9 , q[3:0] == 4'd9}
endmodule
module count
(
input clk,
input reset,
input ena,
output reg[3:0] q
);
always @ (posedge clk)
begin
if(reset)
q <= 4'b0;
else if (ena)
begin
if(q == 4'd9)
q <= 4'd0;
else
q <= q+1'b1;
end
end
endmodule
//不用子模块的方法,但此方法用到求余(%),实际FPGA中应避免使用除法和求余,因为需要使用很多资源
module top_module (
input clk,
input reset, // Synchronous active-high reset
output [3:1] ena,
output [15:0] q
);
assign ena = {
q[11:8]==4'd9 && q[7:4]==4'd9 && q[3:0]==4'd9,
q[7:4]==4'd9 && q[3:0]==4'd9,
q[3:0]==4'd9
};
always @(posedge clk)
if(reset)
q <= 16'b0;
else
begin
q[3:0] <= (q[3:0] + 1) % 10;
if(ena[1])
q[7:4] <= (q[7:4] + 1) % 10;
if(ena[2])
q[11:8] <= (q[11:8] + 1) % 10;
if(ena[3])
q[15:12] <= (q[15:12] + 1) % 10;
end
endmodule
- Count clock
用计数器设计一个带AM/PM的12小时时钟。该计数器通过一个CLK进行计时,用ena使能信号来驱动时钟的递增。
reset信号将时钟复位为12:00 AM。 信号pm为0代表AM,为1代表PM。hh、mm和ss由数两个BCD计器构成hours(01~12), minutes(00~59) , second(00~59)。Reset信号比enable信号有更高的优先级,即使没有enable信号也可以进行复位操作。
Hint:需要注意的是从11:59:59 PM 到12:00:00 AM和从12:59:59 PM到01:00:00 PM的变化。
module top_module
(
input clk,
input reset,
input ena,
output pm,
output [7:0] hh,
output [7:0] mm,
output [7:0] ss
);
reg p; //0 is am, 1 is pm
reg [7:0] h;
reg [7:0] m;
reg [7:0] s;
always @ (posedge clk)
begin
if(reset) //reset to 12:00:00 AM
begin
p <= 0;
h <= 8'h12; //为什么采用16进制?
m <= 8'h00;
s <= 8'h00;
end
else
begin
if(ena)
begin
if(s < 8'h59)
begin
if(s[3:0] < 4'h9) //s[3:0] is ones digit
begin
s[3:0] <= s[3:0] + 1'h1;
end
else
begin
s[3:0] <= 0; //59->00
s[7:4] <= s[7:4] + 1'h1; //tens digit
end
end
else
begin
s <= 0; //s清零
if(m < 8'h59) //m同理s
begin
if(m[3:0] < 4'h9)
begin
m[3:0] <= m[3:0] + 1'h1;
end
else
begin
m[3:0] <= 0;
m[7:4] <= m[7:4] + 1'h1;
end
end
else
begin
m <= 1'h0;
if(h == 8'h11) //AM / PM 转换
p = !p;
if(h < 8'h12)
begin
if(h[3:0] < 4'h9)
h[3:0] <= h[3:0] + 1'h1;
else
begin
h[3:0] <= 4'h0;
h[7:4] <= h[7:4] + 1'h1;
end
end
else
begin //hour 12 -> 1
h <= 1'h1;
end
end
end
end
end
end
assign pm = p;
assign hh = h;
assign mm = m;
assign ss = s;
endmodule
3.2.3 移位寄存器
- Shift4(4-bit shift register)
设计一个4bit异步复位,拥有同步置位和使能的右移移位寄存器
areset : 寄存器复位为0
load : 将data[3:0]输入至移位寄存器中
ena : 使能信号控制向右移动(q[3]q[2]q[1]q[0] ---> 0q[3]q[2]q[1],q[0]在移动后消失了,原先q[3]的位置变为0)
q : 移位寄存器中的数据
如果ena和load同时为高,load有更高的优先级。
module top_module(
input clk,
input areset,
input load,
input ena,
input [3:0] data,
output reg [3:0] q
);
always @ (posedge clk or posedge areset)
begin
if(areset)
q <= 4'b0;
else if (load)
q <= data;
else if (ena)
begin
q[3:0] <= {1'b0,q[3:1]};
end
end
endmodule