• 【牛客网刷题系列 之 Verilog快速入门】~ 位拆分与运算


    0. 插眼

    vcs+verdi联合仿真传送门

    1. VL5 位拆分与运算

    1.1 题目描述

    现在输入了一个压缩的16位数据,其实际上包含了四个数据[3:0][7:4][11:8][15:12],

    现在请按照sel选择输出四个数据的相加结果,并输出valid_out信号(在不输出时候拉低)

    0: 不输出且只有此时的输入有效

    1:输出[3:0]+[7:4]

    2:输出[3:0]+[11:8]

    3:输出[3:0]+[15:12]

    1.1.1 信号示意图

    在这里插入图片描述

    1.1.2 波形示意图

    在这里插入图片描述

    1.1.3 输入描述

    输入信号 d, clk, rst
    类型 wire
    在testbench中,clk为周期5ns的时钟,rst为低电平复位

    1.1.4 输出描述

    输出信号 validout out
    类型 wire

    这里需要注意的是,官方给的类型是reg,当你提交的时候傻眼了,哈哈哈!!!

    1.2 解题思路

    和上一个题思路很像,就是保存下来一个数,对它进行相应的操作。

    1.3 代码实现

    module data_cal(
    input clk,
    input rst,
    input [15:0]d,
    input [1:0]sel,
    
    output [4:0]out,
    output validout
    );
    //*************code***********//
    
        reg [15:0] d_reg;
        reg [4:0] out_reg;
        reg validout_reg;
        
        always @ (posedge clk or negedge rst) begin
            if(!rst) begin
               out_reg <= 5'd0;
                validout_reg <= 1'b0;
            end
            else begin
                case (sel)
                    2'b00 : begin
                       validout_reg <= 1'b0;
                        d_reg <= d;
                        out_reg <= 5'd0;
                    end
                    2'b01 : begin
                       validout_reg <= 1'b1;
                        out_reg <= d_reg[3:0] + d_reg[7:4];
                    end
                    2'b10 : begin
                       validout_reg <= 1'b1;
                        out_reg <= d_reg[3:0] + d_reg[11:8];
                    end
                    2'b11 : begin
                       validout_reg <= 1'b1;
                        out_reg <= d_reg[3:0] + d_reg[15:12];
                    end
                    default : begin
                        validout_reg <= 1'b0;
                        out_reg <= 5'd0;
                    end
                endcase
            end
        end
    
        assign validout = validout_reg;
        assign out = out_reg;
    //*************code***********//
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    1.4 测试文件

    module data_cal_tb();                                                                           
      2     reg clk=0;
      3     reg rst;
      4     reg [15:0]d;
      5     reg [1:0]sel;
      6     wire [4:0]out;
      7     wire validout;
      8  
      9     always #5 clk = ~clk;  // Create clock with period=10
     10  
     11    initial begin
     12         #10 rst <= 0;
     13 //        repeat(10) @(posedge clk);
     14         #50 rst <= 1;
     15         #210 $finish;
     16     end
     17  
     18  data_cal dut(
     19     .clk(clk),
     20     .rst(rst),
     21     .d(d),
     22     .sel(sel),
     23     .out(out),
     24     .validout(validout)
     25 );
     26  
     27 initial begin
     28   d <= 16'h0000;
     29   @(posedge rst);
    30   repeat(1) @(posedge clk);
     31   d <= 16'b1000010000100001;
     32   repeat(4) @(posedge clk);
     33   d <= 16'b1000010000100011;
     34   repeat(5) @(posedge clk);
     35   d <= 16'b1000010000100111;
     36 end  
     37  
     38 initial begin 
     39   sel <= 2'd0;
     40   @(posedge rst);
     41   repeat(2) @(posedge clk);
     42   sel <= 2'd2;
     43   repeat(3) @(posedge clk);
     44   sel <= 2'd1;
     45   repeat(3) @(posedge clk);
     46   sel <= 2'd0;
     47   repeat(1) @(posedge clk);
     48   sel <= 2'd3;
     49 end      
     50  
     51 initial begin
     52     $fsdbDumpfile("tb.fsdb");
     53     $fsdbDumpvars;
     54 end
     55 endmodule                   
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    1.5 仿真波形

    在这里插入图片描述
    这个题,rtl代码倒是不难,但这测试文件写的我贼难受,而且仿真还出现了一些小问题,如下:
    在这里插入图片描述
    停在这里不动了,最后查资料说是代码中有死锁,我一查看,时钟出问题了,这里再次强调,时钟一定要给初始值,否则一切都白扯。

    重要的事情说三遍!!!
    时钟要给初始值!!!
    时钟要给初始值!!!
    时钟要给初始值!!!

    好了,这篇就先写到这里吧!!!
    一件三联不迷路===>

  • 相关阅读:
    SpringBoot 前端406 后端Could not find acceptable representation
    猿创征文| Unity高级开发面向对象编程知识总结
    reactor的原理与实现
    使用JacORB编译idl文件生成依赖的开发jar---Corba北向接口开发001
    endnote设置
    MySQL 清空分区表单个分区数据
    图解操作系统-cpu cache
    ssh 设置普通用户使用密钥登录
    double或Double取整或保留n位小数(后续如果有需要再整理其他小数类型)
    卫星影像如何插入到AutoCAD使用
  • 原文地址:https://blog.csdn.net/qq_40549426/article/details/125538088