• VL5 位拆分与运算


    写在前面

    1. 这个专栏的内容记录的是牛客的Verilog题库刷题,附带RTL\TestBench,并进行覆盖率收集
    2. 牛客算是一个Verilog宝藏刷题网站了,网站提供在线仿真环境,不用自己找题(点击直达),<刷题记录>专栏,持续打卡中…


    一、题目

    (1)题目描述

    现在输入了一个压缩的16位数据,其实际上包含了四个数据[3:0][7:4][11:8][15:12],现在请按照sel选择输出四个数据的相加结果,并输出valid_out信号(在不输出时候拉低)


    (2) 状态转换

    seloutvalidout
    0:不输出且只有此时的输入有效0
    1输出[3:0]+[7:4]1
    2输出[3:0]+[11:8]1
    3输出[3:0]+[15:12]1

    (3)信号示意图

    在这里插入图片描述


    (4)波形示意图

    在这里插入图片描述


    (5)端口描述

    信号方向类型位宽描述
    clkinputwire1时钟,周期为5ns
    rstinputwire1同步复位,低电平有效
    dinputwire16输入的16bit数据
    validoutoutputreg1有效输出时为1,否则为0
    outoutputreg5输出结果

    二、分析

      题意可知,模块采用同步复位且复位信号在低电平有效;可以使用时序逻辑对输入数据d进行锁存到data_buff;输出信号out和validout可使用组合逻辑输出,输出信号根据sel的变化进行变化。


    三、RTL

    module data_cal(
    input             clk     ,
    input             rst     ,
    input      [15:0] d       ,
    input      [1 :0] sel     ,
    
    output reg [4:0]  out     ,
    output reg        validout
    );
    
    reg [15:0] data_buff;
    
    //*************code***********//
    
    always @ (posedge clk) begin
      if (!rst) begin
        data_buff <= 16'b0;
        out <= 5'b0;
        validout <= 1'b0;
      end
      else begin
        data_buff <= d;
      end
    end
    
    
    always @ (*) begin
      if(sel)begin
        validout = 1'b1;
      end
      else begin
        validout = 1'b0;
      end
    end
    
    always @ (*) begin
      case(sel)
        2'd0:out = 5'b0;
        2'd1:out = data_buff[3:0] + data_buff[7 :4 ];
        2'd2:out = data_buff[3:0] + data_buff[11:8 ];
        2'd3:out = data_buff[3:0] + data_buff[15:12];
        default:out = 5'b0;
      endcase
    end
    //*************code***********//
    endmodule
    

    四、Testbench

    `timescale 1ps/1ps
    module tb_data_cal;
    
      reg         clk      ;
      reg         rst      ;
      reg  [15:0] d        ;
      reg  [ 4:0] sel      ;
      
      wire [4 :0] out      ;
      
      wire        validout ;
    
    //-- debug signal
    
    /*-----------------------------------------------\
     --    --
    \-----------------------------------------------*/
    
    initial begin
      clk   = 1     ;
      rst   = 1     ;
      d     = 16'd0 ;
      #1000 rst  = 0;
      #4001 rst  = 1;
             d_case(d,16'd0                  );
      #5000  d_case(d,16'b1000_0100_0010_0001);
      #20000 d_case(d,16'b1000_0100_0010_0011);
      #25000 d_case(d,16'b1000_0100_0010_0111);
      #5000  d_case(d,16'b1000_0100_0010_1111);
      #5000  d_case(d,16'b1000_0100_0011_1111);
      #5000  d_case(d,16'b1000_0100_0111_1111);
      #5000  d_case(d,16'b1000_0100_1111_1111);
      #5000  d_case(d,16'b1000_0101_1111_1111);
      #5000  d_case(d,16'b1000_0111_1111_1111);
      #5000  d_case(d,16'b1000_1111_1111_1111);
      #5000  d_case(d,16'b1001_1111_1111_1111);
      #5000  d_case(d,16'b1011_1111_1111_1111);
      #5000  d_case(d,16'b1111_1111_1111_1111);
      #20000 ;
      repeat(10000)begin
      #5000  d_case(d,{$random}%8'hFF);
      end
    end
    
    
    /*-----------------------------------------------\
     -- sigal var T*5000ps     --
    \-----------------------------------------------*/
    initial begin
             sel_case(sel,0);
      #15000 sel_case(sel,2);
      #15000 sel_case(sel,2);
      #15000 sel_case(sel,1);
      #5000  sel_case(sel,0);
      #25000 sel_case(sel,3);
      repeat(10000)begin
        #5000 sel_case(sel,{$random}%4);
      end
    end
    
    /*-----------------------------------------------\
     --  task of d_case and sel_case  --
    \-----------------------------------------------*/
    task d_case;
      output  [15:0] a;
      input   [15:0] b;
    
      a = b;
    
    endtask
    
    task sel_case;
      output [1:0] s  ;
      input  [1:0] b  ;
    
      begin
        s = b;
      end
    endtask
    
    /*-----------------------------------------------\
     --  clock period is 5ns  --
    \-----------------------------------------------*/
    always begin
      #2500 clk = ~clk;
    end
    
    
    /*-----------------------------------------------\
     --  display  --
    \-----------------------------------------------*/
    always @ (data_cal.data_buff)begin
      if(sel == 2'd0)begin
        if((out != 0) || (validout != 0))begin
          $display($realtime,",true = %d,out = %d,validout = %d",data_cal.data_buff,out,validout);
        end
        else begin
        end
      end
      else if(sel == 2'd1) begin
        if((out != data_cal.data_buff[3:0] +  data_cal.data_buff[7:4]) || (validout != 1'b1))begin
          $display($realtime,",true = %d,out = %d,validout = %d",data_cal.data_buff[3:0] +  data_cal.data_buff[7:4],out,validout);
        end
        else begin
        end
      end
      else if(sel == 2'd2) begin
        if((out != data_cal.data_buff[3:0] +  data_cal.data_buff[11:8]) || (validout != 1'b1))begin
          $display($realtime,",true = %d,out = %d,validout = %d",data_cal.data_buff[3:0] +  data_cal.data_buff[11:8],out,validout);
        end
        else begin
        end
      end
    else if(sel == 2'd3) begin
        if((out != data_cal.data_buff[3:0] +  data_cal.data_buff[15:12]) || (validout != 1'b1))begin
          $display($realtime,",true = %d,out = %d,validout = %d",data_cal.data_buff[3:0] +  data_cal.data_buff[15:12],out,validout);
        end
        else begin
        end
      end
    
    end
    
    data_cal u_data_cal(
                       .clk       (clk     ),
                       .rst       (rst     ),
                       .d         (d       ),
                       .out       (out     ),
                       .sel       (sel     ),
                       .validout  (validout)
                  );
    
    initial #60000000 $finish;
    initial begin
      $fsdbDumpfile("data_cal.fsdb");
      $fsdbDumpvars            ;
      $fsdbDumpMDA             ;
    end
    endmodule
    
    

    五、结果分析

    (1)TB结果

    在这里插入图片描述
    在这里插入图片描述


    (2)波形图

    在这里插入图片描述

    由波形图可tb可以确定,输出符合预期结果


    (3)覆盖率

    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述

    可以看到总覆盖率只有93.92%,受行覆盖率和分支覆盖率的影响。查看信息可以看到主要是case语句的default语句没有被执行到。


    ✍✍☛ 题库入口
      经过一段时间的沉淀,发现入行IC行业,自己的底子还是很差,写的文章质量参差不齐,也没能解答大家的疑问。决定还是要实打实从基础学起,由浅入深。因此决定通过补充/完善基础知识的同时,通过题库刷题不断提高自己的设计水平,题库推荐给大家(点击直达),<题库记录>栏目不定期更新,欢迎前来讨论。


    作者:xlinxdu
    版权:本文版权归作者所有
    转载:未经作者允许,禁止转载,转载必须保留此段声明,必须在文章中给出原文连接。

  • 相关阅读:
    如何在PHP应用中处理跨域请求?
    二刷力扣--二叉树(2)
    ESP32-C3入门教程 基础篇⑫——量产烧写设备配置和序列号, NVS partition分区确认, NVS 分区生成程序, csv转bin
    初探JVM
    WPF元素绑定
    网络运维与网络安全 学习笔记2023.11.21
    护眼台灯进入销售旺季,企业如何利用APS高级排产扩产增效?
    【Linux】Crontab、Shell、Linux、Git
    机器学习笔记(二)回归
    自然人如何在浙江法院网上完成诉讼——具体流程
  • 原文地址:https://blog.csdn.net/qq_43244515/article/details/126960273