HDLBits第十二章练习及答案

1、 4 位移位寄存器

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

  • areset:让寄存器复位为0
  • load:加载4bit数据到移位寄存器中,不移位
  • ena:使能右移
  • q:移位寄存器中的内容

代码实现:

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)
           q <= data;
       else if(ena)
           q <= q >> 1;
       else
           q <= q;
   end

endmodule

验证结果:
在这里插入图片描述
:左移运算符 << , 右移运算符 >> 。

运算过程是将左边(右边)的操作数向左(右)移,所移动的位数由右边的操作数来决定,然后用0来填补移出的空位。

2、左/右旋转器

构建一个100位的左右旋转器,同步load,左右旋转需使能。旋转器从另一端输入移位的位元,不像移位器那样丢弃移位的位元而以零位移位。如果启用,旋转器就会旋转这些位,而不会修改或丢弃它们。

  • load:加载100位的移位寄存器数据
  • ena[1:0]:2’b01 右转1bit; 2’b10 左转1bit;其他情况不转
  • 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)
          q <= data;
      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

方法二:

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]};
      else  q <= q;

  end

endmodule

验证结果:
在这里插入图片描述

3、算术移位寄存器

建立一个64位算术移位寄存器,同步加载。移位器可以左右移位,并按数量选择1位或8位的移位。

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

  • load:加载数据
  • 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)
            q <= data;
        else begin
            if(ena)begin
                case(amount)
                    2'b00: q <= q << 1;
                    2'b01: q <= q << 8;
                    2'b10: q <= {q[63],q[63:1]};
                    2'b11: q <= {{8{q[63]}},q[63:8]};
                    default: q <= q;
                endcase
            end
            else 
                q <= q;
        end
    end

endmodule

验证结果:
在这里插入图片描述在这里插入图片描述

4、5位线性反馈移位寄存器

线性反馈移位寄存器(LFSR)主要包括:

  • 伽罗瓦(内部LFSR),又称one-to-many
    在这里插入图片描述
  • 斐波那契(外部LFSR),又称many-to-one
    在这里插入图片描述其中,gn为反馈系数,取值只能为0或1,取为0时表明不存在该反馈之路,取为1时表明存在该反馈之路;这里的反馈系数决定了产生随机数的算法的不同。用反馈函数表示成
    y = a0x^0 + a1x + a2x^2…,反馈函数为线性的叫线性移位反馈序列,否则叫非线性反馈移位序列。

Q1、Q2、Q3、Qn为LFSR的输出,M(x)是输入的码字多项式,如M(x)=x^4+ x^1+ 1,表示输入端的输入顺序为11001,同样,LFSR的结构也可以表示为多项式G(x),称为生成多项式:
G(x) = gn*x^n+ …+g1*x^1+ g0

练习:

构造线性移位寄存器,reset应当使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)
            q <= 5'h1;
        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

验证结果:
在这里插入图片描述

5、3位线性反馈移位寄存器

为这个序列电路编写Verilog代码。假设你要在DE1-SoC板上实现这个电路。将R输入连接到SW开关,将时钟连接到密钥[0],将L连接到密钥[1],将Q输出连接到红灯LEDR上。
在这里插入图片描述
注:该电路是线性反馈移位寄存器(LFSR) 的一个示例。最大周期 LFSR 可用于生成伪随机数,因为它在重复之前循环 2 n -1 个组合。全零组合不会出现在此序列中。

代码实现:

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
        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

验证结果:
在这里插入图片描述

6、32位线性反馈移位寄存器

构建一个32位的Galois LFSR,其taps位置为32、22、2和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)
            q <=32'h1;
        else begin
            for(i=1'b0;i<32;i=i+1'b1) begin
                if(i==21||i==1||i==0)
                    q[i] <= q[i+1] ^ q[0];
                else if(i==31)
                    q[i] <= 1'b0 ^ q[0];
                else
                    q[i] <= q[i+1];
            end
       end         
    end

endmodule

验证结果:
在这里插入图片描述

7、移位寄存器1

实现如下电路图:
在这里插入图片描述
代码实现:

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

验证结果:
在这里插入图片描述

8、移位寄存器2

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

  • 输入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 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]),
      .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

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

endmodule

验证结果:
在这里插入图片描述

9、3 输入查找表 (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) 
            Q <= {Q[6:0],S};
        else
            Q <= Q;
    end

    assign Z = Q[{A,B,C}];

endmodule

验证结果:
在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值