Counters
Four-bit binary counter
module top_module (
input clk,
input reset, // Synchronous active-high reset
output reg [3:0] q);
always @(posedge clk) begin
if(reset)
q <= 0;
else
q <= q + 1;
end
endmodule
Decade counter
建立一个计数器,从0计数到9
module top_module (
input clk,
input reset, // Synchronous active-high reset
output reg [3:0] q);
always @(posedge clk) begin
if(reset)
q <= 0;
else if(q == 9)
q <= 0;
else
q <= q + 1;
end
endmodule
Decade counter again
建立一个计数器,从1计数到10
module top_module (
input clk,
input reset,
output reg [3:0] q);
always @(posedge clk) begin
if(reset)
q <= 1;
else if(q == 10)
q <= 1;
else
q <= q + 1;
end
endmodule
Slow decade counter
建立一个计数器,从0计数到9,带使能
module top_module (
input clk,
input slowena,
input reset,
output reg [3:0] q);
always @(posedge clk) begin
if(reset)
q <= 0;
else if(slowena) begin
if(q == 9)
q <= 0;
else
q <= q + 1;
end
end
endmodule
Counter 1-12
提供一个4bit的计数器,接口如下:
module count4(
input clk,
input enable,
input load,
input [3:0] d,
output reg [3:0] Q
);
用这个模块实现一个计数器,从1计数到12,并输出上面模块的enable、load、d
module top_module (
input clk,
input reset,
input enable,
output [3:0] Q,
output c_enable,
output c_load,
output [3:0] c_d
); //
assign c_enable = enable;
assign c_load = reset | (Q == 12 & enable);
assign c_d = 4'h1;
count4 the_counter (clk, c_enable, c_load, c_d, Q);
endmodule
Counter 1000
提供一个BCD计数器模块,接口如下
module bcdcount (
input clk,
input reset,
input enable,
output reg [3:0] Q
);
输入1000hz的时钟,使用该模块输出1hz信号,保证每秒该信号只有一个时钟周期高电平,并输出每个BCD计数器的使能
module top_module (
input clk,
input reset,
output OneHertz,
output [2:0] c_enable
); //
wire [3:0] bcd0, bcd1, bcd2;
assign c_enable[0] = 1'b1;
assign c_enable[1] = bcd0 == 9;
assign c_enable[2] = c_enable[1] & bcd1 == 9;
bcdcount counter0 (clk, reset, c_enable[0], bcd0);
bcdcount counter1 (clk, reset, c_enable[1], bcd1);
bcdcount counter2 (clk, reset, c_enable[2], bcd2);
assign OneHertz = c_enable[2] & bcd2 == 9;
endmodule
4-digit decimal counter
建立一个四位数的bcd计数器,并输出十位、百位、千位的使能
module top_module (
input clk,
input reset, // Synchronous active-high reset
output [3:1] ena,
output [15:0] q);
assign ena[1] = q[3:0] == 9;
assign ena[2] = ena[1] & q[7:4] == 9;
assign ena[3] = ena[2] & q[11:8] == 9;
bcd_counter u0(clk, reset, 1'b1, q[3:0]);
bcd_counter u1(clk, reset, ena[1], q[7:4]);
bcd_counter u2(clk, reset, ena[2], q[11:8]);
bcd_counter u3(clk, reset, ena[3], q[15:12]);
endmodule
module bcd_counter(
input clk,
input reset,
input ena,
output reg [3:0] q
);
always @(posedge clk) begin
if(reset)
q <= 0;
else if(ena) begin
if(q == 9)
q <= 0;
else
q <= q + 1;
end
end
endmodule
12-hour-clock
建立一个12小时制的时钟,带一个am/pm指示器,复位将时钟设定为12:00AM
,指示器pm为0时,表示AM,为1时,表示PM。
注意:11点过后为12:00,而不是0:00
下面波形展示了从11:59:59AM
翻转到12:00:00PM
和复位的波形。
解题思路:
秒、分的计时范围为00-59,用bcd计数器实现,个位数计数范围为0-9,直接用bcd计数器即可,十位数计数范围0-5,需要在溢出时用reset清零
时钟的计时范围为01-12,不太好用bcd计数器实现,所以单独写always解决
pm只需在11点跳转到12点时翻转即可
module top_module(
input clk,
input reset,
input ena,
output reg pm,
output [7:0] hh,
output [7:0] mm,
output [7:0] ss);
wire [1:0] h_ena, m_ena, s_ena;
assign s_ena[0] = ena;
assign s_ena[1] = s_ena[0] & ss[3:0] == 9;
assign m_ena[0] = s_ena[1] & ss[7:4] == 5;
assign m_ena[1] = m_ena[0] & mm[3:0] == 9;
assign h_ena[0] = m_ena[1] & mm[7:4] == 5;
assign h_ena[1] = h_ena[0] & (hh == 8'h09 || hh == 8'h12);
bcd_counter s0(clk, reset, s_ena[0], ss[3:0]);
bcd_counter s1(clk, reset | m_ena[0], s_ena[1], ss[7:4]);
bcd_counter m0(clk, reset, m_ena[0], mm[3:0]);
bcd_counter m1(clk, reset | h_ena[0], m_ena[1], mm[7:4]);
// h0
always @(posedge clk) begin
if(reset)
hh[3:0] <= 2;
else if(h_ena[0]) begin
if(hh == 8'h12)
hh[3:0] <= 1;
else if(hh == 8'h09)
hh[3:0] <= 0;
else
hh[3:0] <= hh[3:0] + 1;
end
end
// h1
always @(posedge clk) begin
if(reset)
hh[4] <= 1;
else if(h_ena[1])
hh[4] <= ~hh[4];
end
// pm
always @(posedge clk) begin
if(reset)
pm <= 0;
else if(h_ena[0] && hh == 8'h11)
pm <= ~pm;
end
endmodule
module bcd_counter(
input clk,
input reset,
input ena,
output reg [3:0] q
);
always @(posedge clk) begin
if(reset)
q <= 0;
else if(ena) begin
if(q == 9)
q <= 0;
else
q <= q + 1;
end
end
endmodule
Shift Registers
4-bit shift register
建立一个4bit的移位寄存器,右移,带异步复位、load、ena
module top_module(
input clk,
input areset, // async active-high reset to zero
input load,
input ena,
input [3:0] data,
output reg [3:0] q);
always @(posedge clk, posedge areset) begin
if(areset)
q <= 0;
else if(load)
q <= data;
else if(ena)
q <= {1'b0, q[3:1]};
end
endmodule
Left/right rotator
建立一个循环左移/右移寄存器,带load、移位使能,当ena为2'b01
时右移,当ena为2'b10
时左移,其他情况不移位
module top_module(
input clk,
input load,
input [1:0] ena,
input [99:0] data,
output reg [99:0] q);
always @(posedge clk) begin
if(load)
q <= data;
else if(ena == 2'b01) // right
q <= {q[0], q[99:1]};
else if(ena == 2'b10) // left
q <= {q[98:0], q[99]};
end
endmodule
Left/right arithmetic shift by 1 or 8
建立一个64bit的算数移位寄存器,带load,该移位寄存器可以左移、右移1bit或8bit,算数右移时,左侧填充的是符号位,而不是0。左移时和逻辑左移没有区别,移位方向、移位多少是有amount决定的:
- 2’b00: 左移1bit
- 2’b01: 左移8bit
- 2’b10: 右移1bit
- 2’b11: 右移8bit
module top_module(
input clk,
input load,
input ena,
input [1:0] amount,
input [63:0] data,
output reg [63:0] q);
always @(posedge clk) begin
if(load)
q <= data;
else if(ena) begin
case(amount)
2'b00: q <= {q[62:0], 1'b0};
2'b01: q <= {q[55:0], 8'h00};
2'b10: q <= {q[63], q[63:1]};
2'b11: q <= {{8{q[63]}}, q[63:8]};
endcase
end
end
endmodule
5-bit LFSR
LFSR: (linear feedback shift register),线性反馈移位寄存器,通常有几个异或门来产生移位寄存器的下一个状态。实现如下图所示的5bit位宽LFSR,其在5和3位置处添加了taps(tap即表示该寄存器D端和q[0]进行异或,tap位置从1开始):
module top_module(
input clk,
input reset, // Active-high synchronous reset to 5'h1
output reg [4:0] q
);
always @(posedge clk) begin
if(reset)
q <= 5'h1;
else
q <= {q[0], q[4], q[3] ^ q[0], q[2:1]};
end
endmodule
3-bit LFSR
实现如下电路:
module top_module (
input [2:0] SW, // R
input [1:0] KEY, // L and clk
output reg [2:0] LEDR); // Q
always @(posedge KEY[0]) begin
LEDR[0] <= KEY[1] ? SW[0] : LEDR[2];
LEDR[1] <= KEY[1] ? SW[1] : LEDR[0];
LEDR[2] <= KEY[1] ? SW[2] : (LEDR[1] ^ LEDR[2]);
end
endmodule
32-bit LFSR
实现一个32bit的LFSR,在第32、22、2、1位置添加taps,参考5-bit LFSR题目
module top_module(
input clk,
input reset, // Active-high synchronous reset to 32'h1
output reg [31:0] q
);
always @(posedge clk) begin
if(reset)
q <= 32'h1;
else
q <= {q[0], q[31:23], q[0] ^ q[22], q[21:3], q[0] ^ q[2], q[0] ^ q[1]};
end
endmodule
Shift register
实现如下电路:
module top_module (
input clk,
input resetn, // synchronous reset
input in,
output out);
reg [3:0] taps;
always @(posedge clk) begin
if(~resetn)
taps <= 0;
else
taps <= {in, taps[3:1]};
end
assign out = taps[0];
endmodule
Shift register
如下为n-bit的Shift Register:
编写一个模块实现上述电路,假设n=4,编写MUXDFF模块,在顶层实例化4个MUXDFF子模块,假设你要在DE2开发板上实现,端口对应如下:
- R to SW
- clk to KEY[0]
- E to KEY[1]
- L to KEY[2] and
- w to KEY[3]
- Q to LEDR
module top_module (
input [3:0] SW,
input [3:0] KEY,
output [3:0] LEDR
); //
MUXDFF u0(KEY[0], KEY[1], SW[0], KEY[2], LEDR[1], LEDR[0]);
MUXDFF u1(KEY[0], KEY[1], SW[1], KEY[2], LEDR[2], LEDR[1]);
MUXDFF u2(KEY[0], KEY[1], SW[2], KEY[2], LEDR[3], LEDR[2]);
MUXDFF u3(KEY[0], KEY[1], SW[3], KEY[2], KEY[3], LEDR[3]);
endmodule
module MUXDFF (
input clk,
input E,
input R,
input L,
input W,
output reg Q
);
always @(posedge clk) begin
Q <= L ? R : (E ? W : Q);
end
endmodule