HDLBITS笔记29:移位寄存器(包括4位移位寄存器,创建100位左/右旋转器,算术偏移,线性反馈移位寄存器等)

题目1:4位移位寄存器(4-bit shift register)

构建一个具有异步复位、同步加载和使能功能的 4 位移位寄存器(右移位)。

reset:将移位寄存器重置为零。
load: 加载数据[3:0]的移位寄存器,而不是移位。
ena:向右移(q[3] 变为零,q[0] 移出并消失)。
q:移位寄存器的内容。
如果同时load和 ena 输入 (1),则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);
**分析:题意要求实现的是右移功能的寄存器,即q[3]传给q[2],q[2]传给q[1],q[1]传给q[0]。

代码实现如下:

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)
                q <= 4'b0;
            else if(load)
                begin
                    q <= data;
                end
             else if(ena)
                 begin
                     q[3] <= 0;
                     q[2:0] <= q[3:1];
                 end
        end
endmodule

仿真结果如下:
在这里插入图片描述
使用quartus ii画出逻辑图如下:
在这里插入图片描述

题目2:构建100位的左/右旋转器(Left/right rotator)

构建一个 100 位左/右旋转器,具有同步负载和左/右使能。旋转器从寄存器的另一端移入移出位,这与丢弃移出位并在零中移位的移位不同。如果启用,旋转器将旋转位,并且不会修改/丢弃它们。

  • load: 加载带有数据[99:0]的移位寄存器,而不是旋转。
  • ena[1:0]:选择是否旋转以及旋转方向。
  • 2’b01 向右旋转一位
    2’b10 向左旋转一位
    2’b00 和 2’b11 不旋转
    q:旋转器的内容

模块声明
module top_module(
input clk,
input load,
input [1:0] ena,
input [99:0] data,
output reg [99:0] q);
分析:这相当于一个100位的环形计数器。其中右移寄存器丢弃的是低位,即q[0];左移寄存器丢弃的是高位,即q[99]。环形计数器通过首尾相连,不会丢弃任何位。

代码实现 :

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)
                q <= data;
            else if(ena == 2'b01)
                q <= {q[0],q[99:1]};//右移
            else if(ena == 2'b10)
                    q <= {q[98:0],q[99]};//左移
           
        end
endmodule

其中: q <= {q[0],q[99:1]};//右移 说明了右移操作,即在时钟上升沿的作用下,将q[0]的数据直接传给q[99],触发器由原来的数据向右移动一位,q[99:1]传给q[98:1],即q[99]传给q[98],q[98]传给q[97],直到q[1]传给q[0]。左移则与上述相反。

题目3:左/右移算术偏移1或8(Left/right arithmetic shift by 1 or 8)

构建一个具有同步负载的64位算术移位寄存器。移位器可以左右移动,也可以移动 1 位或 8 位位置(按量选择)。

算术右移位在移位寄存器(在本例中为q[63])中数字的符号位中移动,而不是像逻辑右移那样为零。另一种思考算术右移位的方法是,它假设被移位的数字是有符号的并保留符号,因此算术右移将有符号数除以2的幂。

逻辑左移和算术左移之间没有区别。

  • load: 加载带有数据[63:0]的移位寄存器,而不是移位。
  • ena:选择是否转移。
  • amount:选择要移位的方向和频次。
    2’b00:向左偏移 1 位。 2’b01:向左偏移 8 位。 2’b10:向右移动 1 位。 2’b11:向右移动 8 位。
    q:移位器的内容。

模块声明
module top_module(
input clk,
input load,
input ena,
input [1:0] amount,
input [63:0] data,
output reg [63:0] q);
**提示:**5 位数字 11000 算术右移 1 是 11100,而逻辑右移将产生 01100。
同样,5 位数字 01000 算术右移 1 是 00100,逻辑右移将产生相同的结果,因为原始数字是非负数。

代码实现如下:

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)
                q <= data;
            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]};
                    endcase        
                end
        end
endmodule

仿真结果如下:
在这里插入图片描述
在这里插入图片描述

题目4:5位LFSR(线性反馈移位寄存器)

线性反馈移位寄存器是一个移位寄存器,通常具有几个XOR门,以产生移位寄存器的下一个状态。 Galois LFSR是一种特殊的排列方式,其中带有“抽头”的位位置与输出位进行XORed以产生其下一个值,而没有抽头的位位置移位。如果仔细选择抽头位置,则可以将LFSR设置为“最大长度”。n 位的最大长度 LFSR 循环通过 2n-1 个状态在重复之前(永远不会达到全零状态)。

下图显示了一个 5 位最大长度 Galois LFSR,在位位置 5 和 3 处有抽头。(抽头位置通常从 1 开始编号)。请注意,为了保持一致性,我在位置 5 处绘制了异或门,但其中一个异或门输入为 0。
在这里插入图片描述
构建此 LFSR。重置应将 LFSR 重置为 1。

模块声明
module top_module(
input clk,
input reset, // Active-high synchronous reset to 5’h1
output [4:0] q
);

分析:按照所给的图写代码出来就好。

module top_module(
    input clk,
    input reset,    // Active-high synchronous reset to 5'h1
    output [4:0] q
); 
    always @(posedge clk)
        begin
            if(reset)
                q <= 5'b1;
            else
                begin
                    q[4] <= q[0]^1'b0;
                    q[3] <= q[4];
                    q[2] <= q[3]^q[0];
                    q[1] <= q[2];
                    q[0] <= q[1];
                end
        end
endmodule

仿真结果如下:
在这里插入图片描述

题目5:3位LSFR

摘自2015年中期问题5。另请参阅此问题的第一部分:mt2015_muxdff

在这里插入图片描述
为此顺序电路编写Verilog代码(子模块是可以的,但顶层必须命名为top_module)。假设您将在 DE1-SoC 板上实现该电路。将R输入连接到SW 开关,将Clock 连接到KEY[0],L连接到KEY[1]。将 Q 输出连接到红灯 LEDR。

模块声明
module top_module (
input [2:0] SW, // R
input [1:0] KEY, // L and clk
output [2:0] LEDR); // Q
提示:
该电路是线性反馈移位寄存器(LFSR)的一个例子。最大周期 LFSR 可用于生成伪随机数,因为它循环通过 2n重复前-1个组合。全零组合不在此序列中出现。
分析:通过编写子模块、并在顶层模块中调用的方式来实现。
代码编写如下:

module top_module (
	 	input [2:0] SW,      // R
	input [1:0] KEY,     // L and clk
	output [2:0] LEDR);  // Q
         lsfr u1(.clk(KEY[0]),.r(SW),.L(KEY[1]),.q(LEDR));   

endmodule
module lsfr(L,clk,r,q);
    input L,clk;
	 input [2:0] r;
    output q;
	 reg [2:0] q;
    always @(posedge clk)
        begin
            if(L)
				q <=r;

            else
                begin
					 q[0] <= q[2];
					 q[1] <= q[0];
					 q[2] <= q[1]^q[2];
					 end
        end
endmodule

使用quartus ii画出逻辑图:
顶层模块:
在这里插入图片描述
子模块:
在这里插入图片描述

题目6:32位LFSR

有关说明,请参阅 Lfsr5。

构建一个 32 位 Galois LFSR,在位位置 32、22、2 和 1 处使用抽头。
模块声明
module top_module(
input clk,
input reset, // Active-high synchronous reset to 32’h1
output [31:0] q
);

**参考题目4。**使用抽头即增加了异或门。

module top_module(
    input clk,
    input reset,    // Active-high synchronous reset to 32'h1
    output [31:0] q
); 
    always @(posedge clk)
        begin
            if(reset)
                q <= 32'h1;
            else
                begin
                    q[31] <= q[0]^32'h0;
                    q[30:22] <= q[31:23];
                    q[21] <= q[22]^q[0];
                    q[20:2] <= q[21:3];
                    q[1] <= q[2]^q[0];
                    q[0] <= q[1]^q[0];
                end
        end
endmodule

题目7:移位寄存器(Exams/m2014 q4k)

实现以下电路:
在这里插入图片描述
模块声明
module top_module (
input clk,
input resetn, // synchronous reset
input in,
output out);
代码实现如下:

module top_module (
    input clk,
    input resetn,   // synchronous reset
    input in,
    output out);
    reg [3:0] q;
    always @(posedge clk)
        begin
            if(~resetn)
                q <= 4'b0;
            else
                begin
                 q <= {q[2:0], in};
                end
                           
        end
 assign       out = q[3];  
endmodule

题目8:移位寄存器(Exams/2014 q4b)

考虑下面所示的n位移位寄存器电路:
在这里插入图片描述
为移位寄存器编写一个顶级 Verilog 模块(名为 top_module),假设 n = 4。在顶级模块中实例化 MUXDFF 子循环的四个副本。假设您将在 DE2 板上实现该电路。

  • 将 R 输入连接到SW ,
  • clk to KEY[0],
  • E 到 KEY[1],
  • L 到 KEY[2],以及w 到 KEY[3]。
  • 将输出连接到红灯 LEDR[3:0]。
    从考试/2014_q4a中重复使用您的 MUXDFF。链接:题目6:n位移位寄存器:Exams/2014 q4a

**法一,采用题目6:n位移位寄存器:Exams/2014 q4a的编写方法:

module top_module (
    input [3:0] SW,
    input [3:0] KEY,
    output [3:0] LEDR
); //
    MUXDFF u1(.clk(KEY[0]),.e(KEY[1]),.r(SW[0]),.l(KEY[2]),.w(LEDR[1]),.q(LEDR[0]));
    MUXDFF u2(.clk(KEY[0]),.e(KEY[1]),.r(SW[1]),.l(KEY[2]),.w(LEDR[2]),.q(LEDR[1]));
    MUXDFF u3(.clk(KEY[0]),.e(KEY[1]),.r(SW[2]),.l(KEY[2]),.w(LEDR[3]),.q(LEDR[2]));
    MUXDFF u4(.clk(KEY[0]),.e(KEY[1]),.r(SW[3]),.l(KEY[2]),.w(KEY[3]),.q(LEDR[3]));
endmodule

module MUXDFF (clk,w,e,l,r,q);
    input clk,w,e,l,r;
    output [3:0] q;
    always @(posedge clk)
        begin
            if(l==1)
                q <= r;
             else
                 begin
                     if(e == 1)
                         q <= w;
                     else
                         q <= q;
                 end
        end
endmodule

**法2:另一种子模块的编写方法:

module top_module (
    input [3:0] SW,
    input [3:0] KEY,
    output [3:0] LEDR
); //
    MUXDFF u1(.clk(KEY[0]),.e(KEY[1]),.r(SW[0]),.l(KEY[2]),.w(LEDR[1]),.q(LEDR[0]));
    MUXDFF u2(.clk(KEY[0]),.e(KEY[1]),.r(SW[1]),.l(KEY[2]),.w(LEDR[2]),.q(LEDR[1]));
    MUXDFF u3(.clk(KEY[0]),.e(KEY[1]),.r(SW[2]),.l(KEY[2]),.w(LEDR[3]),.q(LEDR[2]));
    MUXDFF u4(.clk(KEY[0]),.e(KEY[1]),.r(SW[3]),.l(KEY[2]),.w(KEY[3]),.q(LEDR[3]));
endmodule

module MUXDFF (clk,w,e,l,r,q);
    input clk,w,e,l,r;
    output [3:0] q;
    always @(posedge clk)
        begin
            if(~l)
                begin
                    if(~e)
                q <= q;
                    else
                q <= w; 
                end
            else
                q <= r;

        end
endmodule

题目8:为8x1存储器设计一个电路(Exams/ece241 2013 q12)-3-input LUT

在本课程中,您将为8x1存储器设计一个电路,其中写入存储器是通过移入位完成的,读取是“随机访问”,就像在典型的RAM中一样。然后,您将使用电路实现3输入逻辑功能。

首先,创建一个具有8个D型触发器的8位移位寄存器。标记的触发器输出 Q[0]…Q[7].。移位寄存器输入应称为S,它为Q[0]的输入供电(MSB首先移位)。enable输入控制是否移位。然后,扩展电路以具有3个额外的输入A,B,C和一个输出Z。电路的行为应如下所示:当 ABC 为 000 时,Z=Q[0],当 ABC 为 001 时,Z=Q[1],依此类推。您的电路应仅包含8位移位寄存器和多路复用器。(题外话:该电路称为3输入查找表(LUT)

模块声明
module top_module (
input clk,
input enable,
input S,
input A, B, C,
output Z );

分析:多读几次 题目要求即可。代码实现如下:

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)
                q <= {q[6:0],S};
               // q <= {q[7:0],S};//左移操作
        end
    assign Z = q[{A,B,C}];
        
endmodule

使用q <= {q[7:0],S};或者q <= {q[6:0],S};均可实现,q[6:0]默认丢弃q[7],q[7:0]则保留,因此使用q <= {q[7:0],S};会出现警告。

仿真结果:
在这里插入图片描述

  • 3
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值