4-bit shift register
- 异步复位的优先级:
areset
为高时,立即复位(不管时钟和其他信号)。 - 加载 vs 移位的优先级:若
load
为 1,无论和ena
为何值,加载优先(先判断load
)。 - 右移操作的行为:右移时,
q[3]
补 0,q[0]
被移出(例如:q=1010
右移后变为0101
)。
Solution
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'b0000;
end else begin
if (load) begin
q <= data;
end else
if(ena) begin
q <= {1'b0,q[3:1]};
end
end
end
endmodule
Left/right rotator
Solution
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) // load
q <= data;
else if (ena) begin
case(ena)
2'b00 : q <= q; // 其实这一行永远不会被执行!所以else分支可以被简化,见下方。
2'b01 : q <= {q[0],q[99:1]}; // 右旋转 (采用分块组合要比使用循环更简便)
2'b10 : q <= {q[98:0],q[99]};// 左旋转
2'b11 : q <= q;
default q <= q;
endcase
end
else begin // 当ena为0时执行 保持不变
q <= q;
end
end
endmodule
简化else之后:
always @(posedge clk) begin
if (load)
q <= data;
else if (ena == 2'b01)
q <= {q[0],q[99:1]}; // 右旋转
else if (ena == 2'b10)
q <= {q[98:0],q[99]}; // 左旋转
// 其他情况(ena=2'b00或2'b11)保持不变
end
Left/right arithmetic shift by 1 or 8
A 5-bit number 11000 arithmetic right-shifted by 1 is 11100, while a logical right shift would produce 01100.
However, there is no difference between logical and arithmetic left shifts.
Solution
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
case (amount)
2'b00: q <= {q[62:0],1'b0};
2'b01: q <= {q[55:0],8'b0};
2'b10: q <= {q[63],q[63:1]};
2'b11: q <= {{8{q[63]}},q[63:8]}; //注意:位拼接语法
default: q <= q;
endcase
end
end
endmodule
5-bit LFSR
线性反馈移位寄存器(LFSR) linear feedback shift register
LFSR 是一种通过移位寄存器和反馈逻辑生成伪随机序列的电路。
Galois 型 LFSR 的特点:
- 反馈逻辑通过 异或(XOR) 连接特定 “抽头”(tap)位,生成下一个状态的最低位(或最高位,依结构而定)。
- 最大长度 LFSR(maximal-length)的抽头位置经过精心选择,可遍历 $2^n-1$ 个状态(
n
为位数,全零状态永远不会出现)。
在本题中:
- 位数:5 位(输出
q[4:0]
,q[4]
是最高位,q[0]
是最低位) - 抽头位置:题目指定抽头在位5和位3(编对应
q[4]
和q[2]
) - 特殊说明:“抽头 5 的异或输入为 0” → 实际反馈逻辑为
q[4] ^ q[2]
(异或 0 不改变值,等价于仅q[2]
参与,但题目明确抽头是 5 和 3,故需保留异或) - 复位:同步高电平复位(
reset
为高时,q
被置为5'h1
,即二进制00001
) - 移位方向:右移。
其实,若只需简单解答此题,并不需要知道什么是tap。图中是一个由D触发器构成的阵列,按照图中连线即可画出。
Solution
module top_module(
input clk,
input reset, // Active-high synchronous reset to 5'h1
output [4:0] q
);
always @(posedge clk) begin
if (reset) // Load
q <= 4'd1;
else begin
q[4] <= 1'b0 ^ q[0];
q[3] <= q[4];
q[2] <= q[3] ^ q[0];
q[1] <= q[2];
q[0] <= q[1];
end
end
endmodule
下面是基于原理的官方Solution:
module top_module(
input clk,
input reset,
output reg [4:0] q);
reg [4:0] q_next; // q_next is not a register
always @(*) begin
q_next = q[4:1];
// Shift all the bits. This is incorrect for q_next[4] and q_next[2]
//q_next = q[4:1] 将当前状态q的高四位(q[4]~q[1])赋值给 q_next 的低四位(q_next[3]~q_next[0]),实现了大部分位的右移。
q_next[4] = q[0];
// Give q_next[4] and q_next[2] their correct assignments
//修正最高位
q_next[2] = q[0] ^ q[3];
//修正抽头位:该操作确保 LFSR 遍历 2^5 - 1=31 个状态(最大长度特性)。
end
always @(posedge clk) begin
if (reset)
q <= 5'h1;
else
q <= q_next;
end
endmodule
3-bit LFSR
二选一选择器:
本题仍是看图连线。
Solution
module top_module (
input [2:0] SW, // R
input [1:0] KEY, // L and clk
output [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[2] ^ LEDR[1]);
end
endmodule
32-bit LFSR
本题是 5-bit LFSR 的扩展,若实例化32个DDF显然不是很方便。
Solution
module top_module(
input clk,
input reset, // Active-high synchronous reset to 32'h1
output [31:0] q
);
reg [31:0] q_next;
always @(*) begin // 组合逻辑块(敏感列表为*)
q_next = q[31:1];
q_next[31] = q[0];
q_next[21] = q[0] ^ q[22];
q_next[1] = q[0] ^ q[2];
q_next[0] = q[0] ^ q[1];
end
always @(posedge clk) begin
if (reset)
q <= 32'h1;
else
q <= q_next;
end
endmodule
Shift register (1)
Solution
module top_module (
input clk,
input resetn, // synchronous reset
input in,
output out);
reg [3:0] Q; //记录每个DDF输出的Q
always @(posedge clk ) begin
if (!resetn) begin
Q <= 0;
end
else begin
Q[0] <= in;
Q[1] <= Q[0];
Q[2] <= Q[1];
Q[3] <= Q[2];
end
end
assign out = Q[3];
endmodule
Official Solution
module top_module (
input clk,
input resetn,
input in,
output out
);
reg [3:0] sr;
// Create a shift register named sr. It shifts in "in".
always @(posedge clk) begin
if (~resetn) // Synchronous active-low reset
sr <= 0;
else
sr <= {sr[2:0], in};
end
assign out = sr[3]; // Output the final bit (sr[3])
endmodule
Shift register (2)
Solution
module top_module (
input [3:0] SW,
input [3:0] KEY,
output [3:0] LEDR
);
MUXDFF u1 (
.clk(KEY[0]),
.w(KEY[3]),
.R(SW[3]),
.E(KEY[1]),
.L(KEY[2]),
.Q(LEDR[3])
);
MUXDFF u2 (
.clk(KEY[0]),
.w(LEDR[3]), //易疏忽:不再是KEY[3]了
.R(SW[2]),
.E(KEY[1]),
.L(KEY[2]),
.Q(LEDR[2])
);
MUXDFF u3 (
.clk(KEY[0]),
.w(LEDR[2]),
.R(SW[1]),
.E(KEY[1]),
.L(KEY[2]),
.Q(LEDR[1])
);
MUXDFF u4 (
.clk(KEY[0]),
.w(LEDR[1]),
.R(SW[0]),
.E(KEY[1]),
.L(KEY[2]),
.Q(LEDR[0])
);
endmodule
//引用自 Latches and Flip-Flops 的 Mux and DFF
module MUXDFF (
input clk,
input w, R, E, L,
output Q
);
wire mid1 = E ? w : Q;
wire mid2 = L ? R : mid1;
always @(posedge clk) begin
Q <= mid2;
end
endmodule
3-input LUT
“移位寄存器设计” + “3 输入查找表(LUT)实现”
8 位移位寄存器:
- 输入
S
逐位移入,MSB( Most Significant Bit) 先移入,enable
控制是否移位。 - 8 个 D 触发器的输出标记为
Q[0]
到Q[7]
(移位顺序决定了Q[0]
是最新移入的位,Q[7]
是最早移入的位)。 S
连接到第一个触发器(Q[0]
)的输入,每个触发器的输出连接到下一个触发器的输入。当
enable=1
时,每个时钟沿clk
到来时:Q[0]
接收新输入S
;Q[1]
接收原来的Q[0]
;Q[2]
接收原来的Q[1]
;- ……
Q[7]
接收原来的Q[6]
。
(效果:数据右移,Q[0]
是最新位,Q[7]
是最旧位,MSB 先存入Q[7]
。)
- 输入
3 输入查找表(LUT):
- 输入
A、B、C
作为地址(3 位,共 8 种组合:000
~111
)。 - 输出
Z
根据地址选择移位寄存器的对应位:ABC=000
选Q[0]
,ABC=001
选Q[1]
,…,ABC=111
选Q[7]
。
- 输入
Solution
module top_module (
input clk,
input enable, // 移位使能(高有效)
input S, // 移位输入(MSB先移入)
input A, B, C, // 3位地址输入
output Z
);
reg [7:0] q;
// 移位寄存器逻辑:
always @(posedge clk) begin
if (enable) begin
q <= {q[6:0], S};
// 右移操作(左低位右高位,低位变到高位。但是目前索引中这样写是左高右低):S→q[0],q[0]→q[1],…,q[6]→q[7]
end
end
// 用A、B、C作为地址,直接用{A,B,C}制作索引
assign Z = q[{A, B, C}];
endmodule