HDLbits 刷题答案 3.2.3 Shift Registers

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'b002'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,21

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,q1q2也置零,否则运行结果不对

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
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值