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

二选一选择器:

二选一选择器.png

本题仍是看图连线。

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)实现”

  1. 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]。)
  2. 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