原创
针对特权同学《深入浅出玩转FPGA》第31页if...else和case语句的一些补充
笔者是在看了特权同学玩转fpga入门视频之后,觉得不错,才拜读的他的《深入浅出玩转FPGA》这本书,在看到第31页对if..else和case语句进行分析时,觉得部分分析可能缺乏可比性,容易造成误解,斗胆在这里做一些讨论和补充。
该书中首先引用两段代码EX1和EX2说明if...else结构和case结构在verilog逻辑代码逻辑相同时,将导致RTL级视图不同,但最后映射资源利用和扇出却是相同的。
后来又举例两段读写控制代码,来说明case语句比if...else语句占用资源更少,但这两段代码其实没有可比性,或者说不应该像书中那样比较,因为容易导致误解。书中的两段代码如下:
第一段代码 EX3:
input clk;
input rst_n;
input close,wr,rd;
output [2:0]db;
reg[2:0]dbr;
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
dbr<=3'd0;
end
else begin
if(close)dbr<=3'b111;
else if(rd)dbr<=3'b101;
else if(wr)dbr<=3'b011;
else dbr<=3'd0;
end
end
assign db=dbr;
第二段代码EX4:
input clk;
input rst_n;
input close,wr,rd;
output [2:0]db;
reg[2:0]dbr;
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
dbr<=3'd0;
end
else begin
case({close,rd,wr})
3'b100:dbr<=3'b111;
3'b010:dbr<=3'b101;
3'b001:dbr<=3'b011;
default:dbr<=3'd0;
endcase
end
end
assign db=dbr;
书中直接对比以上两段代码的RTL视图,以及映射后的资源利用和扇出情况。但其实第二段代码,并没有将所有case列全,若想使两段代码逻辑一致,显然第二段代码需如下将所有case列出:
case({close,rd,wr})
3'b100:dbr<=3'b111;
3'b110:dbr<=3'b111;
3'b101:dbr<=3'b111;
3'b111:dbr<=3'b111;
3'b010:dbr<=3'b101;
3'b011:dbr<=3'b101;
3'b001:dbr<=3'b011;
default:dbr<=3'd0;
endcase
而如果第二段代码将所有case列出,则虽然RTL视图不同,但映射后的资源利用以及平均扇出其实仍是一致的。
很显然根据示例代码EX1~EX4,我们不难发现,在RTL级实现中,case语句一般是先经过译码器(decode),将所有可能的case情况译码出来,然后将最终输出相同的情况直接取或,而if-else结构的RTL级实现则与此不同,一般会采用选通器(MUX)互连的形式。
此外,最终映射优化的过程,其实类似于数字电路设计中的卡诺图优化,因此只要if...else和case的逻辑完整,其实映射后的资源利用和扇出应当是一致的,但是我们在设计中,往往有些信号或者说case情况其实是隐含不可能出现的,类似于数字电路中所说的约束项,例如上面的3'b110,3'b101,3'b111,3'b011这四种情况可能在实际中并不会出现,那么以上两段代码在功能上最终表现就会是相同的,但这隐含了以上四种情况实际上不会发生的约束。考虑到一般情况下,if...else结构较case结构可能隐含更多的约束项,因此可能导致更简化的最简逻辑表达式的产生,而一般逻辑表达式越简化,对细节的约束就越少,所使用的门也就相对要少,因而,一般所使用的逻辑资源也就少一些。
使用if...else结构,以及以上第二段完整的case语句结构,所产生的资源映射情况都将如该书中39页图2.7所示。
用户402158 2014-8-12 14:29