HDLBits: 在线学习 SystemVerilog(十七)-Problem 106-114(移位寄存器)

HDLBits: 在线学习 SystemVerilog(十七)-Problem 106-114(移位寄存器)HDLBits是一组小型电路设计习题集,使用Verilog/SystemVerilog硬件描述语言(HDL)练习数字硬件设计~网址如下:https://hdlbits.01xz.net/关于HDLBits的Verilog实现可以查看下面专栏:https://www.zhihu.com/column/c_1131528588117385216缩略词索引:SV:SystemVerilog从今…

4bccb354b24441aa6b470aaf27e29ed5.jpeg

HDLBits 是一组小型电路设计习题集,使用 Verilog/SystemVerilog 硬件描述语言 (HDL) 练习数字硬件设计~

网址如下:

https://hdlbits.01xz.net/

关于HDLBits的Verilog实现可以查看下面专栏:

https://www.zhihu.com/column/c_1131528588117385216

缩略词索引:

  • SV:SystemVerilog

从今天开始新的一章-时序电路,包括触发器、计数器、移位寄存器、状态机等。

今天更新移位寄存器,移位寄存器在乘法、除法以及各种矩阵操作中非常重要,熟练使用移位寄存器是基本技能。

移位运算符

虽然移位运算和本系列没什么太大关系,但是还是回顾一下:

<SystemVerilog-移位运算符>

Problem 106-Shift4

题目说明

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

  • areset:将移位寄存器重置为零。

  • 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);

题目解析

这是一个基本移位寄存器示例。移位过程在ena控制下,实现q[3]q[2]q[1]q[0] —> 0 q[3]q[2]q[1]—> 0 0 q[3]q[2]

因为这题增加了很多控制信号,所以只能使用时序电路进行描述。

module top_module(
    input logic clk,
    input logic areset,  // async active-high reset to zero
    input logic load,
    input logic ena,
    input logic [3:0] data,
    output logic [3:0] q ); 
    
    always_ff@(posedge clk or posedge areset) begin
        if(areset)       q <= '0 ;
        else if (load)   q <= data ;
        else if (ena)    q <= {1'd0,q[3:1]} ;
        else             q <= q ;
    end

endmodule

a75350ddfaf77dc2d4c49ef97997ba2a.png

点击Submit,等待一会就能看到下图结果:

28fb8f749f538557d293907f1169a540.png

注意图中的Ref是参考波形,Yours是你的代码生成的波形,网站会对比这两个波形,一旦这两者不匹配,仿真结果会变红。

这一题就结束了。

Problem 107-Rotate100

题目说明

设计一个100bit的可左移或右移的移位寄存器,附带同步置位和左移或右移的使能信号。本题中,移位寄存器在左移或右移时,不同于Problem106的补0和直接舍弃某一bit位,本题是要求在100bit内循环移动,不舍弃某一位同时也不补0。

比如说左移1bit,在Problem106就是补0和丢弃q[0]。而在本题中左移1bit为{q[0], q[99:1]}。

load:load信号将data[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);

题目解析

本题是一个桶型移位寄存器,题目的解答就是:{q[0], q[99:1]}。

module top_module(
    input logic clk,
    input logic load,
    input logic [1:0] ena,
    input logic [99:0] data,
    output logic [99:0] q); 
    
    always_ff@(posedge clk) begin
        if(load)             q <= data ;
        else begin
            case(ena)
                2'b00,2'b11: q <= q ;
                2'b01      : q <= {q[0],q[99:1]} ;
                2'b10      : q <= {q[98:0],q[99]};
            endcase
        end
    end

endmodule

b98199735a09d3f2b2fb289c1c8d2227.png

点击Submit,等待一会就能看到下图结果:

0eb117f531d4cf446b73adcc42848ec5.png

注意图中无波形。

这一题就结束了。

Problem 108-Shift18

先补充一下算术移位寄存器和按位移位寄存器:

SystemVerilog具有按位和算术移位运算符。

按位移位只是将向量的位向右或向左移动指定的次数,移出向量的位丢失。移入的新位是零填充的。例如,操作8’b11000101 << 2将产生值8’b00010100。按位移位将执行相同的操作,无论被移位的值是有符号的还是无符号的。

算术左移位对有符号和无符号表达式执行与按位右移位相同的操作。算术右移位对“无符号”和“有符号”表达式执行不同的运算。如果要移位的表达式是无符号的,算术右移位的行为与按位右移相同,即用零填充输入位。如果表达式是有符号的,则算术右移将通过用符号位的值填充每个输入位来保持值的有符号性。

具体如下:

764fa2df401273f62a0b945becf3d835.png

题目说明

构建一个具有同步加载功能的 64 位算术移位寄存器。移位器可以左右移动,移动 1 位或 8 位,由amount选择。

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

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

  • load :用数据 [63:0]加载移位寄存器而不是移位。

  • ena:选择是否移动。

  • amount:选择移动的方向和移动量。

2’b00:左移一位。

2’b01:左移 8 位。

2’b10:右移一位。

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

题目解析

module top_module(
    input logic clk,
    input logic load,
    input logic ena,
    input logic [1:0] amount,
    input logic [63:0] data,
    output logic [63:0] q); 
    
    always_ff@(posedge clk) begin
        if(load)           q <= data ;
        else if(ena)
        begin
            case(amount)
                2'b00:     q <= {q[62:0],1'd0} ;
                2'b01:     q <= {q[55:0],8'd0} ;
                2'b10:     q <= {q[63],q[63:1]};
                2'b11:     q <= {
   
   {8{q[63]}},q[63:8]};
            endcase
        end
    end

endmodule

d667085671cea4a8408ce8b7fa28131e.png

点击Submit,等待一会就能看到下图结果:

96762b980ef17e1503c1570e0af3dda2.png

注意图中的Ref是参考波形,Yours是你的代码生成的波形,网站会对比这两个波形,一旦这两者不匹配,仿真结果会变红。

这一题就结束了。

Problem 109-Lfsr5

题目说明

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

下图显示了一个 5 位最大长度的 Galois LFSR,在位置 5 和 3 处有抽头。(抽头位置通常从 1 开始编号)。请注意,为了保持一致性,我在位置 5 处绘制了 XOR 门,但其中一个 XOR 门输入为 0。

2c0a446d987db2302af92fcf679c0342.png图片来自HDLBits

构建这个 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 logic clk,
    input logic reset,    // Active-high synchronous reset to 5'h1
    output logic [4:0] q
); 
    always_ff@(posedge clk) begin
        if(reset)         q <= 5'h1 ;
        else begin
        q[4] <= 1'd0 ^ q[0] ;
        q[3] <= q[4];
        q[2] <= q[3] ^ q[0] ;
        q[1] <= q[2] ;
        q[0] <= q[1] ;
        end
    end
        
endmodule

8b687500e607d19ff1543b73298915a4.png

点击Submit,等待一会就能看到下图结果:

4403234067d0563b6151e968cd2e381a.png

注意图中的Ref是参考波形,Yours是你的代码生成的波形,网站会对比这两个波形,一旦这两者不匹配,仿真结果会变红。

这一题就结束了。

Problem 110-Mt2015_lfsr

题目说明

5e0f7c26f75d1972353408724a1aca0c.png图片来自HDLBits

编写此时序电路的 Verilog 代码(可以使用子模块进行构建,但顶层要命名为 top_module)。

模块端口声明

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

题目解析

本题的解答思路是将三个触发器的输出端 Q,输入端 D,组合成一个 3bit 宽度的向量进行设计,使用一个 always 块实现寄存器组。与之相对的是思路是例化三个选择器+触发器的电路,分别连接三个部分的输入输出。

根据选择器的 select 端的电平,触发器组的输入分别为外部输入 SW 或者触发器组输出序列的组合逻辑,这里用:{LEDR[1]^LEDR[2],LEDR[0],LEDR[2]} 表示。

其他信号根据题目的要求连接。

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

006d00ba7029388d51a69e9096c91244.png

点击Submit,等待一会就能看到下图结果:

674cf60cfcdfe9ddc6a34c4f3ed48261.png

注意图中无波形。

这一题就结束了。

Problem 111-Lfsr32

题目说明

参考109题中的 5bit LFSR,实现一个 32bit LFSR,

抽头点为32,22,2,1。

提示:32bit 的 LFSR 最好使用向量实现,而不是例化 32 个触发器。

模块端口声明

module top_module(
    input clk,
    input reset,    // Active-high synchronous reset to 32'h1
    output [31:0] q
);

题目解析

module top_module(
    input clk,
    input reset,    // Active-high synchronous reset to 32'h1
    output [31:0] q
); 
    
    reg [31:0] q_next;
    always_comb begin
        q_next = {q[0], q[31:1]};
        q_next[21] = q[0] ^ q[22];
        q_next[1] = q[0] ^ q[2];
        q_next[0] = q[0] ^ q[1];
    end
    
    always_ff@(posedge clk)begin
        if(reset)
            q <= 32'h1;
        else begin
            q <= q_next;
        end
    end
 
endmodule

13941d355feada7c69540f63b64767b8.png

点击Submit,等待一会就能看到下图结果:

9160005380417258bddd6b10868416df.png

注意图中无波形。

这一题就结束了。

Problem 112-m2014_q4k

题目说明

实现下图中的电路

f72647fc4c4b7526eb62addd1386bfa2.png图片来自HDLBits

模块端口声明

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

题目解析

实现一个带有异步复位的移位寄存器。

module top_module (
    input logic clk,
    input logic resetn,   // synchronous reset
    input logic in,
    output logic out);
    
    var logic [3:0] Q ;
    
    always_ff@(posedge clk) begin
        if(!resetn)     Q <= '0 ;
        else            Q <= {in,Q[3:1]} ;
    end
    
    assign out = Q[0] ;

endmodule

d2b2324afb199e6f08f856d7cb5f4c97.png

点击Submit,等待一会就能看到下图结果:

dc743e3dbe1ce708c424330d252fe35d.png

注意图中无波形。

这一题就结束了。

Problem 113-2014_q4b

题目说明

实现下图中的 n bit 移位寄存器电路,这题希望使用例化的方式,例化 4 个选择器+触发器模块实现一个 4bit 移位寄存器。另外还要进行一些连线工作。

9c7715998cb4707a8cdbe610c499ffd5.png
c0886836f060f892d903cfe9061df871.png图片来自HDLBits

模块端口声明

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

题目解析

MUXDFT 模块之前已经实现了,复制过来即可,剩下的就是例化。

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

    MUXDFF u1_MUXDFF(
        .clk    (KEY[0] ),       
        .w  (KEY[3] ),
        .R  (SW[3] ),
        .E  (KEY[1] ),
        .L  (KEY[2] ),
        .Q  (LEDR[3])
    );
    MUXDFF u2_MUXDFF(
        .clk (KEY[0] ),
        .w  (LEDR[3]),
        .R  (SW[2] ),
        .E  (KEY[1] ),
        .L  (KEY[2] ),
        .Q  (LEDR[2])
    );
    MUXDFF u3_MUXDFF(
        .clk (KEY[0] ),
        .w  (LEDR[2]),
        .R  (SW[1] ),
        .E  (KEY[1] ),
        .L  (KEY[2] ),
        .Q  (LEDR[1])
    );
    MUXDFF u4_MUXDFF(
        .clk (KEY[0] ),
        .w  (LEDR[1]),
        .R  (SW[0] ),
        .E  (KEY[1] ),
        .L  (KEY[2] ),
        .Q  (LEDR[0])
    );
                           
endmodule

module MUXDFF (
    input logic clk,
    input logic w, R, E, L,
    output logic Q
);
    always_ff@(posedge clk) begin
        casex({E,L})
            2'b00: Q <= Q ;
            2'bx1: Q <= R ;
            2'b10: Q <= w ;
        endcase
    end

endmodule

1e7d5451d7ed144d768f3d47b3bebdba.png

点击Submit,等待一会就能看到下图结果:

a644ceeb54e0a519aec91f222c87ef66.png

注意图中无波形。

这一题就结束了。

Problem 114-ece241_2013_q12

题目说明

本题中实现的是一个和 8×1 结构的存储体相关的电路。存储的输入通过移入比特进行,存储的读取类似于传统 RAM 中的随机读取,即可以指定读出比特的位置,通过 3 个输入端口指定读取位置。

首先通过 8 个触发器实现一个 8bit 深的移位寄存器。8个寄存器的输出依次为 Q[0]…Q[7]。移位寄存器的输入为 S,输入首先会填充到 MSB(最高位),Q[0]。当 enable 信号控制移位,当其有效时输入数据并移位。此外,该电路有三个输入端口 A,B,C 以及输出端口 Z。工作的功能如下:当 ABC = 000 时,Z = Q[0],当 ABC = 001 时,Z = Q[1],以此类推。你的电路中只能包括一个 8bit 移位寄存器以及一个多路选择器。(这就是个三输入查找表 LUT 电路)

模块端口声明

module top_module (
    input clk,
    input enable,
    input S,
    input A, B, C,
    output Z );

题目解析

module top_module (
    input logic clk,
    input logic enable,
    input logic S,
    input logic A, B, C,
    output logic Z ); 
    
    var logic [7:0] Q ;
    
    always_ff@(posedge clk) begin
        if(enable)  Q <= {Q[6:0],S} ;
    end
    
    always_comb begin
        case({A, B, C})
            3'b000:begin
                Z = Q[0];
            end
            3'b001:begin
                Z = Q[1];
            end
            3'b010:begin
                Z = Q[2];
            end
            3'b011:begin
                Z = Q[3];
            end
            3'b100:begin
                Z = Q[4];
            end
            3'b101:begin
                Z = Q[5];
            end
            3'b110:begin
                Z = Q[6];
            end
            3'b111:begin
                Z = Q[7];
            end
        endcase
    end


endmodule

0e06a5dbbbee3fd63d5a9df23f4aa629.png

点击Submit,等待一会就能看到下图结果:

1ff6636c73dd4e902f104db735cdeb1a.png

注意图中的Ref是参考波形,Yours是你的代码生成的波形,网站会对比这两个波形,一旦这两者不匹配,仿真结果会变红。

这一题就结束了。

总结

今天的几道题就结束了,对于移位寄存器的使用以及算术/按位移位的理解还是有益处的。

最后我这边做题的代码也是个人理解使用,有错误欢迎大家批评指正,祝大家学习愉快~

代码链接:

https://github.com/suisuisi/SystemVerilog/tree/main/SystemVerilogHDLBits

今天的文章HDLBits: 在线学习 SystemVerilog(十七)-Problem 106-114(移位寄存器)分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/12594.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注