请问一个verilog 的case statement的非常奇怪的问题
鄙人最近正在研究mips processor.用verilog写,之前一直在用vhdl的,但是最近发现一个问题,下面我贴一下代码
- always @(*)
- begin
- casex({aluop_ex, funct})
- 6'b000? : alu_ctrl <= 0000;
- 6'b010000 : alu_ctrl <= 0000;
- 6'b010001 : alu_ctrl <= 0001;
- 6'b010010 : alu_ctrl <= 0010;
- 6'b010011 : alu_ctrl <= 0011;
- 6'b010100 : alu_ctrl <= 0100;
- 6'b010101 : alu_ctrl <= 0101;
- 6'b010110 : alu_ctrl <= 0110;
- 6'b010111 : alu_ctrl <= 0111;
- 6'b011000 : alu_ctrl <= 1000;
- 6'b011001 : alu_ctrl <= 1001;
- 6'b100? : alu_ctrl <= 1010;
- 6'b110? : alu_ctrl <= 1011;
- 6'b111? : alu_ctrl <= 1100;
- default : alu_ctrl <= 1111;
- endcase
- end
下面是testbench....我在每个延迟10ns的时候控制aluop_ex跟funct的输入的值,就是上面case语句从上到下的值。然后在仿真结果上得到相应的时间也就是alu_ctrl前面的数字,同时得到alu_ctrl的值。
- initial begin
- // Initialize Inputs
- funct = 0;
- aluop_ex = 0;
- #10
- funct = 0;
- aluop_ex = 2;
- #10
- funct = 1;
- aluop_ex = 2;
- #10
- funct = 2;
- aluop_ex = 2;
- #10
- funct = 3;
- aluop_ex = 2;
- #10
- funct = 4;
- aluop_ex = 2;
- #10
- funct = 5;
- aluop_ex = 2;
- #10
- funct = 6;
- aluop_ex = 2;
- #10
- funct = 7;
- aluop_ex = 2;
- #10
- funct = 0;
- aluop_ex = 3;
- #10
- funct = 3;
- aluop_ex = 4;
- #10
- funct = 1;
- aluop_ex = 5;
- #10
- funct = 2;
- aluop_ex = 6;
- #10
- funct = 0;
- aluop_ex = 7;
- // Wait 100 ns for global reset to finish
- #700;
- $stop;
- // Add stimulus here
- end
-
- initial begin
-
- $monitor($time, "alu_ctrl=%b", alu_ctrl);
- end
下面是结果,我用Isim 仿真的:
- 0alu_ctrl=0000
- 20alu_ctrl=0001
- 30alu_ctrl=1010
- 40alu_ctrl=1011
- 50alu_ctrl=0100
- 60alu_ctrl=0101
- 70alu_ctrl=1110
- 80alu_ctrl=1111
- 90alu_ctrl=1000
- 100alu_ctrl=0010
- 110alu_ctrl=0111
- 120alu_ctrl=0011
- 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,很奇怪的我即使用最简单的形式,比如:
- always @(*)
- begin
- casex( funct)
- 3'b000 : alu_ctrl = 0000;
- 3'b001 : alu_ctrl = 0001;
- 3'b010 : alu_ctrl = 0010;
- 3'b011 : alu_ctrl = 0011;
- 3'b100 : alu_ctrl = 0100;
- 3'b101 : alu_ctrl = 0101;
- 3'b110 : alu_ctrl = 0110;
- 3'b111 : alu_ctrl = 0111;
- default : alu_ctrl = 1101;
- endcaseend
结果跟上面是一样一样的。
更奇怪的是,我如果这么写:
- always @(*)
- begin
- casex( funct)
- 3'b000 : alu_ctrl = 0000;
- 3'b001 : alu_ctrl = 0001;
- 3'b010 : alu_ctrl = 1010;
- 3'b011 : alu_ctrl = 1011;
- 3'b100 : alu_ctrl = 0100;
- 3'b101 : alu_ctrl = 0101;
- 3'b110 : alu_ctrl = 1110;
- 3'b111 : alu_ctrl = 1111;
- default : alu_ctrl = 1101;
- endcase
- 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等。
