微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > FPGA,CPLD和ASIC > 请问一个verilog 的case statement的非常奇怪的问题

请问一个verilog 的case statement的非常奇怪的问题

时间:10-02 整理:3721RD 点击:

鄙人最近正在研究mips processor.用verilog写,之前一直在用vhdl的,但是最近发现一个问题,下面我贴一下代码

  1. always @(*)
  2.         begin
  3.                 casex({aluop_ex, funct})
  4.                         6'b000? : alu_ctrl <= 0000;
  5.                         6'b010000 : alu_ctrl <= 0000;
  6.                         6'b010001 : alu_ctrl <= 0001;
  7.                         6'b010010 : alu_ctrl <= 0010;
  8.                         6'b010011 : alu_ctrl <= 0011;
  9.                         6'b010100 : alu_ctrl <= 0100;
  10.                         6'b010101 : alu_ctrl <= 0101;
  11.                         6'b010110 : alu_ctrl <= 0110;
  12.                         6'b010111 : alu_ctrl <= 0111;
  13.                         6'b011000 : alu_ctrl <= 1000;
  14.                         6'b011001 : alu_ctrl <= 1001;
  15.                         6'b100? : alu_ctrl <= 1010;
  16.                         6'b110? : alu_ctrl <= 1011;
  17.                         6'b111? : alu_ctrl <= 1100;
  18.                         default          : alu_ctrl <= 1111;
  19.                 endcase
  20.         end

复制代码


下面是testbench....我在每个延迟10ns的时候控制aluop_ex跟funct的输入的值,就是上面case语句从上到下的值。然后在仿真结果上得到相应的时间也就是alu_ctrl前面的数字,同时得到alu_ctrl的值。

  1. initial begin
  2.                 // Initialize Inputs
  3.                 funct = 0;
  4.                 aluop_ex = 0;
  5.                 #10
  6.                 funct = 0;
  7.                 aluop_ex = 2;
  8.                 #10
  9.                 funct = 1;
  10.                 aluop_ex = 2;
  11.                 #10
  12.                 funct = 2;
  13.                 aluop_ex = 2;
  14.                 #10
  15.                 funct = 3;
  16.                 aluop_ex = 2;
  17.                 #10
  18.                 funct = 4;
  19.                 aluop_ex = 2;
  20.                 #10
  21.                 funct = 5;
  22.                 aluop_ex = 2;
  23.                 #10
  24.                 funct = 6;
  25.                 aluop_ex = 2;
  26.                 #10
  27.                 funct = 7;
  28.                 aluop_ex = 2;
  29.                 #10
  30.                 funct = 0;
  31.                 aluop_ex = 3;
  32.                 #10
  33.                 funct = 3;
  34.                 aluop_ex = 4;
  35.                 #10
  36.                 funct = 1;
  37.                 aluop_ex = 5;
  38.                 #10
  39.                 funct = 2;
  40.                 aluop_ex = 6;
  41.                 #10
  42.                 funct = 0;
  43.                 aluop_ex = 7;
  44.                 // Wait 100 ns for global reset to finish
  45.                 #700;
  46.        $stop;
  47.                 // Add stimulus here

  48.         end
  49.         
  50.         initial begin
  51.                
  52.                         $monitor($time, "alu_ctrl=%b", alu_ctrl);
  53.         end
  54.       

复制代码


下面是结果,我用Isim 仿真的:

  1.                    0alu_ctrl=0000
  2.                   20alu_ctrl=0001
  3.                   30alu_ctrl=1010
  4.                   40alu_ctrl=1011
  5.                   50alu_ctrl=0100
  6.                   60alu_ctrl=0101
  7.                   70alu_ctrl=1110
  8.                   80alu_ctrl=1111
  9.                   90alu_ctrl=1000
  10.                  100alu_ctrl=0010
  11.                  110alu_ctrl=0111
  12.                  120alu_ctrl=0011
  13.                  130alu_ctrl=1100

复制代码


奇怪的结果我用bolder 标识出来了。
但结果应该是:
30alu_ctrl=0010
40alu_ctrl=0011
70alu_ctrl=0110
80alu_ctrl=0111

我用别的simulator 也试过了,比如iverilog结果是一样的。一开始我以为是Bug的问题,但现在觉得可能是我语句哪里有不对的地方、
有知道的大神请指点一下
非常感谢~!

您实在是写的太不清楚了
aluop_ex 和 funct 各是几位?
“30alu_ctrl=0010” 又是啥意思?



   不好意思,aluop_ex跟funct各是3位,然后alu_ctrl前面的数字指的是时间比如前面的30指的是第30ns

这个是随aluop_ex跟funct的值变化的,而不是时间。ps:我也是菜鸟 仅供参考



   我可能没说清楚,我没有贴出我testbench~我在testbench上面控制哪一个时间输入aluop_ex跟funct的值,然后在这一时间 就会输出对应的aluctrl。



    要不你把testbench也贴出来吧?

组合逻辑电路为什么要用非阻塞赋值语句呢



   你好,testbench已经在上面编辑出来了



   即使不用非阻塞幅值结果也是一样的



   不用了,跟你解释我代码的时间我已经处理完了。
           anyway, thx for your time.

小编你没把两个变量各是三位表示出来 你用12345678这样表示没指明位数。
建议写成****=3‘b***



   anyway,很奇怪的我即使用最简单的形式,比如:

  1. always @(*)
  2. begin
  3. casex( funct)
  4. 3'b000 : alu_ctrl = 0000;
  5. 3'b001 : alu_ctrl = 0001;
  6. 3'b010 : alu_ctrl = 0010;
  7. 3'b011 : alu_ctrl = 0011;
  8. 3'b100 : alu_ctrl = 0100;
  9. 3'b101 : alu_ctrl = 0101;
  10. 3'b110 : alu_ctrl = 0110;
  11. 3'b111 : alu_ctrl = 0111;
  12. default : alu_ctrl = 1101;
  13. endcaseend

复制代码


结果跟上面是一样一样的。
更奇怪的是,我如果这么写:

  1. always @(*)
  2. begin
  3. casex( funct)
  4. 3'b000 : alu_ctrl = 0000;
  5. 3'b001 : alu_ctrl = 0001;
  6. 3'b010 : alu_ctrl = 1010;
  7. 3'b011 : alu_ctrl = 1011;
  8. 3'b100 : alu_ctrl = 0100;
  9. 3'b101 : alu_ctrl = 0101;
  10. 3'b110 : alu_ctrl = 1110;
  11. 3'b111 : alu_ctrl = 1111;
  12. default : alu_ctrl = 1101;
  13. endcase
  14. end

复制代码



结果就正确了。我用的是xilinx ise14.2
如果你也有ise的话也可以试试。
我反正是没招了



    咕(╯﹏╰) 不好意思 我刚没说清楚,是testbench里面的那两个激励*****和***,貌似默认是8位?



    咦 不是endmodule吗?还有你把 endcase和end写成endcaseend肯定错了,居然没出错

没用过ISE 不过应该可以看波形吧 看看两个变量各是几位的?还有各个时间点上的变化和你testbench里写的是否一致。



   这个我可能复制代码的时候刚才有点弄乱了

不要用casex

你altctrl几位的。?monitor那边用二进制,casex那边用十进制

小编请记住,不指定格式的数字会被认为是32位的十进制数。
例如30ns的那个,case语句返回的确实是0010,但它是32位的十进制数,转换成二进制,取低4位就是1010。
其它没出错的小编可以换算一下,都是纯属巧合。
小编的case语句等号右边都该写成4'b....,也就是指定它是4比特二进制数,就对了。

    看了一下,的确和21L说的一样。verilog代码里面的十进制数转变为二进制后,符合你仿真的结果。

解决这类问题有2个重要的方法
1.用硬件的表达形式写代码,不要图省事,很多写verilog的容易犯这个错误
2.觉得波形和代码对应不上,请看仿真/综合出来的电路是否是自己想要的

这个是随aluop_ex跟funct的值变化的



   多谢前辈。我写上那个4'b之后就对了。原谅我的无知
大谢!



LZ言过了,大家互相学习交流嘛,不能说“无知”,更不存在“原谅”不原谅的。
我会知道是因为我也是这么错过来的。


1. 要使用阻塞赋值,但可能这个问题不会影响仿真结果
2. 0001, 0010等数据前面加 n'bxxxx,你应该要表达的是2进制 的数,同时注意你的$display,里面是不是也是用%b,而不是%d,%h等。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top