三种条件判断方法"a?b:c", if , case综合出来居然一样?
写了几段代码做比较,vivado RTL电路图看 a?b:c 和if结果一样复杂一些,case语句生成的电路最简单。但是,然而,综合后的电路图居然都一样,都是LUT查表就没了,真值表都一样。那么,差别呢?差别哪去了?
另外,比较了一下:
如果用always @(posedge clk) 会用到FDRE,多浪费一点资源。
用always输出z必须是reg, 而a?b:c判断就不需要,生成的电路却一样,这点怎么解释?
- module MyTest(
- input clk,
- input [3:0] keys,
- output [3:0] leds
- );
-
- (* dont_touch="true" *) IfTest if_test(clk, keys[0],keys[3:2],leds[0]);
- // (* dont_touch="true" *) CaseTest case_test(clk, keys[0],keys[3:2],leds[1]);
- (* dont_touch="true" *) IfTest1 if_test1(clk, keys[1:00],keys[3:0],leds[2]);
- // (* dont_touch="true" *) CaseTest1 case_test1(clk, keys[1:0],keys[3:0],leds[3]);
- (* dont_touch="true" *) WireTest wire_test(clk, keys[1:00],keys[3:0],leds[1]);
- (* dont_touch="true" *) WireTest1 wire_test1(clk, keys[1:00],keys[3:0],leds[3]);
- endmodule
- module IfTest(input clk, input x, input [1:0] y, output reg z);
- //always @(posedge clk) begin
- always @(*) begin
- if (x == 0)
- z <= y[0];
- else
- z <= y[1];
- end
- endmodule
- module CaseTest(input clk, input x, input [1:0] y, output reg z);
- //always @(posedge clk) begin
- always @(*) begin
- case (x)
- 0: z <= y[0];
- 1: z <= y[1];
- endcase
- end
- endmodule
- module IfTest1(input clk, input [1:0] x, input [3:0] y, output reg z);
- //always @(posedge clk) begin
- always @(*) begin
- if (x == 0)
- z <= y[0];
- else if (x==1)
- z <= y[1];
- else if (x==2)
- z <= y[2];
- else
- z <= y[3];
- end
- endmodule
- module CaseTest1(input clk, input [1:0] x, input [3:0] y, output reg z);
- //always @(posedge clk) begin
- always @(*) begin
- case (x)
- 0: z <= y[0];
- 1: z <= y[1];
- 2: z <= y[2];
- 3: z <= y[3];
- endcase
- end
- endmodule
- module WireTest(input clk, input [1:0] x, input [3:0] y, output z);
- assign z = x==0? y[0]: y[1];
- endmodule
- module WireTest1(input clk, input [1:0] x, input [3:0] y, output z);
- assign z = x==0? y[0]: (x==1? y[1]: (x==2? y[2]: y[3]));
- endmodule
因为 a?b:c电路和if完全一致,图省掉。
综合后的电路图,没用时钟:

综合后的电路图,使用时钟:

综合前电路图,没用时钟。看着很复杂,综合后居然一样:

综合前电路图,用时钟:
首先,可综合风格的代码里,有用always描述组合逻辑的写法。很显然你这几段都被综合成组合逻辑了(哪怕你定义的是reg型)。既然也是描述组合逻辑,显然综合出来和用assign是一样的。
其次,用always@(*)描述组合逻辑,要使用阻塞赋值。个人没见过你这种写法。
还有,你的case段写得也有毛病,没有default项,容易产生latch,这在RTL级设计里是不允许的。
小编,网上有一个文档,叫做《**可综合风格verilog**》,这是个好东西,可以快速上手RTL级设计,事半功倍。
不建议在不可综合风格的verilog语法上耗费太多精力。
个人建议哈~
非常感谢,@(posedge clk)我也测试了,四张图里面两张是有时钟的。代码是后面测试组合逻辑修改后的,等下我加上去,避免误会。有时钟的话多一个FDRE器件。
网上那个文章拜读过,感觉有些不对,在github上有个项目ip-cores项目,@(posedge)下面用阻塞非阻塞赋值的项目都有,感觉是都可以用,只要风格一致。效率上讲非阻塞要高,但是写复杂逻辑是不是需要要阻塞赋值?
下面是个阻塞赋值的例子:
https://github.com/steevenlee/ip-cores/blob/communication_controller_documented_verilog_uart/uart.v
非常感谢,@(posedge clk)我也测试了,四张图里面两张是有时钟的。代码是后面测试组合逻辑修改后的,等下我加上去,避免误会。有时钟的话多一个FDRE器件。
网上那个文章拜读过,感觉有些不对,在github上有个项目ip-cores项目,@(posedge)下面用阻塞非阻塞赋值的项目都有,感觉是都可以用,只要风格一致。效率上讲非阻塞要高,但是写复杂逻辑是不是需要要阻塞赋值?
下面是个阻塞赋值的例子:
https://github.com/steevenlee/ip-cores/blob/communication_controller_documented_verilog_uart/uart.v
没注意到这里,谢谢~
一开始是用时序逻辑写的,后来改成组合逻辑,发现结果一模一样。代码就是最后的
其实不管你怎么设计,如果功能一样,那么综合工具综合出来的东西理论上都是一样电路,这就是综合工具的作用。
同样的设计用不同的描述方式,一个原因是为了可读性。
always@(*)可读性更好,能设计更复杂的组合逻辑,在设计状态机的时候都是用这个。
assign完全能实现上述功能,但要让别人看明白,费时费力。
建议先把这些东西区分看,理解综合的含义。
