HDLBits(九)学习笔记——verilog实现移位寄存器、More Circuits(三输入查找表)

本文介绍了移位寄存器的各种类型和实现,包括左移、右移、算术移位以及线性反馈移位寄存器(LFSR)的Verilog代码实现。详细展示了不同操作,如同步加载、异步复位、旋转以及不同位数的移位,并提供了多个实例,如4位、100位、32位LFSR等。
摘要由CSDN通过智能技术生成

一、知识储备

1、 采用位拼接技术实现移位寄存器

1.1 左移

舍去高位,让输入补低位。(波形中out是16位表示的)

module invert(input  in,input clk,input rst_n,output reg [7:0] out);      
    
	always@(posedge clk)  
        if(!rst_n)
            out <= 8'd0;
        else
            out <= {out[6:0],in}; 

在这里插入图片描述

1.2右移

舍去低位,让输入补高位。(波形中out是16位表示的)

module invert(input  in,input clk,input rst_n,output reg [7:0] out);      
    
	always@(posedge clk)  
        if(!rst_n)
            out <= 8'd0;
        else
            out <= {in,out[7:1]}; //右移

在这里插入图片描述

二、HDLBits题目练习

Shift4四位移位寄存器

构建一个4bit的移位寄存器(右移),含异步复位、同步加载和使能信号

  • areset:让寄存器复位为0
  • load:加载4bit数据到移位寄存器中,不移位
  • ena:使能右移
  • 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
); 
    always @ (posedge clk or posedge areset)begin
        if(areset)begin
            q <= 4'b0;
        end
        else if(load)begin
            q <= data;
        end
        else if(ena)begin
            q <= {1'b0,q[3:1]};
        end
        else
            q <= q;
    end

endmodule

Rotate100

构建一个100位的左右旋转器,有同步负载load信号,左右旋转的使能信号。旋转器是从另一端输入移出的位,不像移位器那样丢弃移出位而以零位移位。如果使能信号有效,旋转器就会旋转这些位,而不会修改或丢弃它们。

  • load:加载100位的移位寄存器数据
  • ena[1:0]:2’b01 右转1bit; 2’b10 左转1bit;
  • 其他情况不转(q保持不变)
    q:旋转输出内容
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 begin
            case(ena)
                2'b01 : q <= {q[0],q[99:1]};
                2'b10 : q <= {q[98:0],q[99]};
                default : q <= q;
            endcase
        end
    end

endmodule

Shift18

构建一个具有同步负载的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
); 
    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]};
            endcase         
        end
        else
            q <= q;
    end
endmodule

Lfsr5

线性反馈移位寄存器是一个移位寄存器,通常具有几个异或栅极,以产生移位寄存器的下一个状态。其中带有“抽头”的位位置与输出位进行XOR,以产生其下一个值,而没有抽头的位位置移位.
下图显示了一个 5 位最大长度 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
); 

    always @ (posedge clk )begin
        if(reset)begin
            q <= 5'b1;
        end
        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

3位LSFR

为如下序列电路编写Verilog代码。假设你要在DE1-SoC板上实现这个电路。将R输入连接到SW开关,将时钟连接到密钥[0],将L连接到密钥[1],将Q输出连接到红灯LEDR上。

在这里插入图片描述

module top_module (
	input [2:0] SW,      // R
	input [1:0] KEY,     // L and clk
	output [2:0] LEDR
);  // Q
    
    wire clk;
    assign clk = KEY[0];
    always @ (posedge clk) begin
        if(KEY[1])begin
            LEDR[0] <= SW[0];
            LEDR[1] <= SW[1];
            LEDR[2] <= SW[2];
        end
        else begin
            LEDR[0] <= LEDR[2];
            LEDR[1] <= LEDR[0];
            LEDR[2] <= LEDR[1]^LEDR[2];
            
        end
    end

endmodule

Lfsr32

构建一个 32 位 Galois LFSR,在位位置 32、22、2 和 1 处使用抽头。(抽头如题目Lfsr5中一样,进行异或计算,另外重置的时候置为1,抽头是从1开始的)

module top_module(
    input clk,
    input reset,    // Active-high synchronous reset to 32'h1
    output [31:0] q
); 
    integer i;
    always @ (posedge clk)begin
        if(reset)begin
            q <= 32'b1;  //
        end
        else begin
            for(i=0;i<32;i++)begin
                if((i==21)||(i==1)||(i==0))begin
                    q[i] <= q[i+1]^q[0];            
                end
                else if(i==31)begin
                    q[i] <= 1'b0^q[0]; 
                end
                else begin
                    q[i] <= q[i+1];   
                end
            end
        end
    end

endmodule

shift register

在这里插入图片描述

module top_module (
    input clk,
    input resetn,   // synchronous reset
    input in,
    output out);

    reg [3:0] tmp;
    assign out = tmp[0];
    
    always @(posedge clk)begin
        if(!resetn)begin
            tmp <= 4'h0;
        end
        else begin
            tmp <= {in,tmp[3:1]};
        end
    end
    
endmodule

n位 移位寄存器

在这里插入图片描述

module top_module (
    input [3:0] SW,
    input [3:0] KEY,
    output [3:0] LEDR
); 

    MUXDFF u_MUXDFF0 (KEY[0], KEY[3], SW[3],KEY[1],KEY[2],LEDR[3]);
    MUXDFF u_MUXDFF1 (KEY[0], LEDR[3], SW[2],KEY[1],KEY[2],LEDR[2]);
    MUXDFF u_MUXDFF2 (KEY[0], LEDR[2], SW[1],KEY[1],KEY[2],LEDR[1]);
    MUXDFF u_MUXDFF3 (KEY[0], LEDR[1], SW[0],KEY[1],KEY[2],LEDR[0]);
 endmodule

module MUXDFF (
    input clk,
    input W,R,E,L,
    output Q
);
    wire tmp;
    assign tmp = E ? W : Q;
    always @(posedge clk)begin
        Q <= L? R : tmp;
    end

endmodule

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 
); 
    reg [7:0] Q;

    always @ (posedge clk)begin
        if(enable)begin
            Q <= {Q[6:0],S}; 
        end
        else
            Q <= Q;
    end
    assign Z = Q[{A,B,C}];
endmodule

Rule90

在每个时间步长中,每个单元的下一状态是此时当前单元相邻两单元(左右)的异或

在该电路中,创建一个512单元系统(q(511:0)),并在每个时钟周期中前进一个时间步长。加载(load)表明系统的状态data[511:0],假设边界q[0]和q[512] 都为零在这里插入图片描述
该题目中 center就相当于Q[511:0]
Left就相当于左移{1‘b0,Q[511:0]}
Right就相当于右移{Q[511:0],1‘b0}

module top_module(
    input clk,
    input load,
    input [511:0] data,
    output [511:0] q ); 

    always @(posedge clk)begin
        if(load)begin
            q <= data;
        end
        else begin
            q <= {1'b0,q[511:1]}^{q[510:0],1'b0}; //当前单元为相邻两单元的异或,左^右
        end
    end
    
endmodule

Rule 100

在每个时间步长中,每个单元格的状态都会发生变化。在规则 110 中,根据下表,每个单元的下一个状态仅取决于自身及其两个相邻单元.(前一题目取决于左右相邻单元)在这里插入图片描述
要想得到下一状态的值,那么就要找到它与自身center以及左右相邻单元的关系,可以将上面表转化成卡诺图。
在这里插入图片描述
得到

q = ( q & ~right) | (~left & right )| (~q & right )

module top_module(
    input clk,
    input load,
    input [511:0] data,
    output [511:0] q //center
); 
    wire [511:0] left ;
    wire [511:0] right ;
    
    assign left = {1'b0,q[511:1]};
    assign right = {q[510:0],1'b0};

    always @ (posedge clk)begin
        if(load)begin
            q <= data;
        end
        else begin
            q <= (q&(~right) | ((~left)&right | ((~q)&right)));
        end
    end
    
endmodule

第三个真难

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Fighting_FPGA

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值