3.2.3 Shift Registers
3.2.3.1 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: The contents of the shift register
如果load 和 ena都有效,load 的优先级更高
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 or posedge areset) begin
if(areset) begin
q <= 4'd0;
end
else if(load) begin
q <= data;
end
else if(ena) begin
q <= {1'b0, q[3:1]};
end
end
endmodule
3.2.3.2 Left/right ratator
设计一个100-bit的左/右移的移位寄存器,有同步置位信号load
和同步左/右移使能信号ena
循环移位形式,不会舍弃某1bit
也不会补0
- load:将
data[9:0]
输入至寄存器内 - ena[1:0]:选择是否移位或移位的方向
-
2'b01
:右移一位 -
2'b10
:左移一位 -
2'b00
和2'b11
不移动 - 移位寄存器内的数据
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) begin
q <= data;
end
else if(ena == 2'b01) begin
q <= {q[0],q[99:1]};
end
else if(ena == 2'b10) begin
q <= {q[98:0],q[99]};
end
end
endmodule
3.2.3.3 Left/right arithmetic shift by 1 or 8
设计一个64-bit
带同步置位的算法移位寄存器,该寄存器可以通过amount
控制移动方向和每次移动的位数。
算术右移移位寄存器中的符号位q[63]
移位,不像是逻辑右移中进行补零的操作,而是保留符号位后再进行移位
左移移位寄存器和算法移位寄存器没有区别
- load:将·data[63:0`赋值为移位寄存器
- ena:选择是否移位
- amount:选择移动方向和移位次数
- 2’b00 : 左移
1bit
- 2’b01 : 左移
8bits
- 2’b10 : 右移
1bit
- 2’b11 : 右移
8bits
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) begin
q <= data;
end
else if(ena)begin
if(amount == 2'b00) begin
q <= {q[62:0],1'b0};
end
else if(amount == 2'b01) begin
q <= {q[55:0],8'b0};
end
else if(amount == 2'b10) begin
q <= {q[63],q[63:1]};
end
else if(amount == 2'b11) begin
q <= {{8{q[63]}},q[63:8]};
end
end
end
endmodule
3.2.3.4 5-bit LFSR
线性反馈移位寄存器(LFSR)通常带有一个异或门来产生下一个状态的移位寄存器。Galois LFSR是一个特殊的移位寄存器,其中带有"tap"位的位置与输出位XOR产生下一个值没有"tap"位标志的正常移位。如果"tap"位置经过仔细选择后,LFSR将设置为最大长度。再重复之前LFSR的最大长度为2^n-1。
下图所示LFSR为在位置5和位置3包含"tap"位的5-bit最大长度LFSR。开始为位置1,输入为0。
设计如上图所示LFSR,复位信号使LFSR复位为1.
module top_module(
input clk,
input reset, // Active-high synchronous reset to 5'h1
output [4:0] q
);
always @ (posedge clk) begin
if(reset) begin
q <= 4'd1;
end
else begin
q[4] <= 0 ^ q[0];
q[3] <= q[4];
q[2] <= q[3] ^ q[0];
q[1] <= q[2];
q[0] <= q[1];
end
end
endmodule
3.2.3.5 3-bit LFSR
使用Verilog实现上述功能,允许建立子模块,但顶层模块要命名为top_module
将输入端口R
连接到板子上的拨动开关,clock
端口接到按键 KEY[0]
,端口 L
接到按键 KEY[1]
。输出端口 Q
连接到板子上的红色 LED。
module top_module (
input [2:0] SW, // R
input [1:0] KEY, // L and clk
output [2:0] LEDR); // Q
wire clk = KEY[0];
wire sel = KEY[1];
/*if (sel == 1)
q0 = r0;
q1 = r1;
q2 = r2;
if(sel == 0)
q0 = q2;
q1 = q0;
q2 = q2 ^ q1;
*/
wire [2:0] d = sel ? SW : {LEDR[2] ^ LEDR[1], LEDR[0], LEDR[2]};
always @ (posedge clk) begin
LEDR <= d;
end
endmodule
3.2.3.6 32-bit LFSR
建立一个32-bit
的Galois LFSR,tap
位于32
,22
,2
和1
module top_module(
input clk,
input reset, // Active-high synchronous reset to 32'h1
output [31:0] q
);
always @ (posedge clk) begin
if(reset) begin
q <= 32'b1;
end
else begin
q <= {q[0] ^ 0, q[31:23], q[22] ^ q[0], q[21:3], q[2] ^ q[0], q[1] ^ q[0]};
end
end
endmodule
3.2.3.7 Shift register
实现该电路
module top_module (
input clk,
input resetn, // synchronous reset
input in,
output out);
reg q0;
reg q1;
reg q2;
always @ (posedge clk) begin
if(!resetn) begin
q0 <= 0;
q1 <= 0;
q2 <= 0;
out <= 0;
end
else begin
q0 <= in;
q1 <= q0;
q2 <= q1;
out <= q2;
end
end
endmodule
复位的时候,需要把q0
,q1
和q2
也置零,否则运行结果不对
3.2.3.8 Shift register
写一个顶层的Verilog (命名top_module),假设n=4
写一个子模块,命名MUXDFF,通过例化的形式实现上述电路
其中:
R
连接SW
clk
连接KEY[0]
E
-->KEY[1]
L
-->KEY[2]
W
-->KEY[3]
- 输出连接到
LEDR[3:0]
module top_module (
input [3:0] SW,
input [3:0] KEY,
output [3:0] LEDR
); //
MUXDFF u3 (.clk(KEY[0]), .e(KEY[1]), .l(KEY[2]), .w(KEY[3]), .r(SW[3]),.dout(LEDR[3]));
MUXDFF u2 (.clk(KEY[0]), .e(KEY[1]), .l(KEY[2]), .w(LEDR[3]), .r(SW[2]),.dout(LEDR[2]));
MUXDFF u1 (.clk(KEY[0]), .e(KEY[1]), .l(KEY[2]), .w(LEDR[2]), .r(SW[1]),.dout(LEDR[1]));
MUXDFF u0 (.clk(KEY[0]), .e(KEY[1]), .l(KEY[2]), .w(LEDR[1]), .r(SW[0]),.dout(LEDR[0]));
endmodule
module MUXDFF (clk,e,l,w,r,dout);
input clk;
input e;
input l;
input w;
input r;
output dout;
reg dout;
always @ (posedge clk) begin
if(l) begin
dout <= r;
end
else begin
if(e) begin
dout <= w;
end
else begin
dout <= dout;
end
end
end
endmodule
3.2.3.9 3-input LUT
在这个中,将设计一个8x1存储器的电路,其中写入存储器是通过移位完成的,读取是“随机访问”,就像在一个典型的 RAM 中一样。然后,将使用电路实现一个3输入逻辑功能。
首先用8个D触发器创建一个8-bit
移位寄存器,寄存器的输出记作q[7]......q[0]
,移位寄存器的输入记作S
,并连接到q[0]
,enable
控制是否进行移位
扩展电路中,有三个额外输入端A,B,C
和一个输出端Z
,当ABC=0
时,Z=q[0]
,当ABC=001
时,Z=q[1]
…
module top_module (
input clk,
input enable,
input S,
input A, B, C,
output Z );
reg [7:0] q;
always @ (posedge clk) begin
if(enable) begin
/*q[0] <= S;
q[7:1] <= q[6:0];*/
q <= {q[6:0],S};
end
end
always @ (A or B or C) begin
case ({A,B,C})
3'b000 : Z = q[0];
3'b001 : Z = q[1];
3'b010 : Z = q[2];
3'b011 : Z = q[3];
3'b100 : Z = q[4];
3'b101 : Z = q[5];
3'b110 : Z = q[6];
3'b111 : Z = q[7];
endcase
end
endmodule