【牛客网刷题系列 之 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.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.5 仿真波形

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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值