Counters
Four-bit binary counter
module top_module (input clk,input reset, // Synchronous active-high resetoutput reg [3:0] q);always @(posedge clk) beginif(reset)q <= 0;elseq <= q + 1;end
endmodule
Decade counter
建立一个计数器,从0计数到9
module top_module (input clk,input reset, // Synchronous active-high resetoutput reg [3:0] q);always @(posedge clk) beginif(reset)q <= 0;else if(q == 9)q <= 0;elseq <= q + 1;end
endmodule
Decade counter again
建立一个计数器,从1计数到10
module top_module (input clk,input reset,output reg [3:0] q);always @(posedge clk) beginif(reset)q <= 1;else if(q == 10)q <= 1;elseq <= 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) beginif(reset)q <= 0;else if(slowena) beginif(q == 9)q <= 0;elseq <= q + 1;endend
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 resetoutput [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]);
endmodulemodule bcd_counter(input clk,input reset,input ena,output reg [3:0] q
);always @(posedge clk) beginif(reset)q <= 0;else if(ena) beginif(q == 9)q <= 0;elseq <= q + 1;endend
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]);// h0always @(posedge clk) beginif(reset)hh[3:0] <= 2;else if(h_ena[0]) beginif(hh == 8'h12)hh[3:0] <= 1;else if(hh == 8'h09)hh[3:0] <= 0;elsehh[3:0] <= hh[3:0] + 1;endend// h1always @(posedge clk) beginif(reset)hh[4] <= 1;else if(h_ena[1])hh[4] <= ~hh[4];end// pmalways @(posedge clk) beginif(reset)pm <= 0;else if(h_ena[0] && hh == 8'h11)pm <= ~pm;end
endmodulemodule bcd_counter(input clk,input reset,input ena,output reg [3:0] q
);always @(posedge clk) beginif(reset)q <= 0;else if(ena) beginif(q == 9)q <= 0;elseq <= q + 1;endend
endmodule
Shift Registers
4-bit shift register
建立一个4bit的移位寄存器,右移,带异步复位、load、ena
module top_module(input clk,input areset, // async active-high reset to zeroinput load,input ena,input [3:0] data,output reg [3:0] q); always @(posedge clk, posedge areset) beginif(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) beginif(load)q <= data;else if(ena == 2'b01) // rightq <= {q[0], q[99:1]};else if(ena == 2'b10) // leftq <= {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) beginif(load)q <= data;else if(ena) begincase(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]};endcaseendend
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'h1output reg [4:0] q
); always @(posedge clk) beginif(reset)q <= 5'h1;elseq <= {q[0], q[4], q[3] ^ q[0], q[2:1]};end
endmodule
3-bit LFSR
实现如下电路:
module top_module (input [2:0] SW, // Rinput [1:0] KEY, // L and clkoutput reg [2:0] LEDR); // Qalways @(posedge KEY[0]) beginLEDR[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'h1output reg [31:0] q
); always @(posedge clk) beginif(reset)q <= 32'h1;elseq <= {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 resetinput in,output out);reg [3:0] taps;always @(posedge clk) beginif(~resetn)taps <= 0;elsetaps <= {in, taps[3:1]};endassign 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]);
endmodulemodule MUXDFF (input clk,input E,input R,input L,input W,output reg Q
);always @(posedge clk) beginQ <= L ? R : (E ? W : Q);end
endmodule