FPGA|CPLD|ASIC论坛
直播中

runileking

10年用户 301经验值
擅长:可编程逻辑 MEMS/传感技术
私信 关注
[经验]

关于FPGA中IF和CASE的区别


         经常在写程序的时候纠结同样的功能到底用if实现还是case实现,用if的时候是ifelse if接连写还是if else嵌套写,书上有看到过但是自己没探索过,印象不深刻,经常还是会犯迷糊,这里写了简单的程序,对同一功能不同代码综合出来的电路做了对比,希望自己能对这块的东西有更深入的了解,也希望能够分享出来和大家进行探讨和交流,有不对的或者需要补充的地方欢迎大家批评指正。
         本次实例所实现的功能是在计数器等于四个特定值的时候将四个不同的输入值分别赋给输出。计数器为八位,从0255循环计数。特点是计数器的值大于需要条件判断的数量,在计数器数值不满足判断条件的时候不执行操作。
         第一种情况,用ifelse if来实现,Verilog代码如下:
module IF_CASE(
         inputclk,
         inputreset,
         input[15:0]data_in1,
         input[15:0]data_in2,
         input[15:0]data_in3,
         input[15:0]data_in4,
         outputreg [15:0]data
   );
         
         reg[7:0]counter;
         always@(posedge clk or negedge reset)
                   begin
                            if(!reset)
                                     begin
                                     counter<=0;
                                     end
                            else
                                     begin
                                               if(counter==8'hff)
                                                        begin
                                                        counter<=0;
                                                        end
                                               else
                                                        begin
                                                        counter<=counter+8'd1;
                                                        end
                                     end
                   end
         
         always@(posedge clk or negedge reset)
                   begin
                            if(!reset)
                                     begin
                                     data<=0;
                                     end
                            else
                                     begin
                                               if(counter==8'd1)
                                                        begin
                                                        data<=data_in1;
                                                        end
                                               elseif(counter==8'd10)
                                                        begin
                                                        data<=data_in2;
                                                        end
                                               elseif(counter==8'd20)
                                                        begin
                                                        data<=data_in3;
                                                        end
                                               elseif(counter==8'd30)
                                                        begin
                                                        data<=data_in4;
                                                        end
                                     end
                   end
endmodule
         第二种情况采用ifelse的嵌套方式实现,由于计数器代码一样,整个外部接口代码也一样,这里只是列出输出值赋值的always块,其Verilog代码如下:
         always@(posedge clk or negedge reset)
                   begin
                            if(!reset)
                                     begin
                                     data<=0;
                                     end
                            else
                                     begin
                                               if(counter==8'd1)
                                                        begin
                                                        data<=data_in1;
                                                        end
                                               else
                                                        begin
                                                                 if(counter==8'd10)
                                                                           begin
                                                                           data<=data_in2;
                                                                           end
                                                                 else
                                                                           begin
                                                                                    if(counter==8'd20)
                                                                                             begin
                                                                                             data<=data_in3;
                                                                                             end
                                                                                    else
                                                                                             begin
                                                                                             if(counter==8'd30)
                                                                                                       begin
                                                                                                       data<=data_in4;
                                                                                                       end
                                                                                             else
                                                                                                       begin
                                                                                                       end
                                                                                             end
                                                                           end
                                                        end
                                     end
                                                        
                   end
         这两种情况所占用的逻辑资源和综合后的RTL级电路都是完全一样的,分别如图1和图2所示: source1.png
1

source5.png


                                                   图2




         电路图可能看不清,简单介绍一下,开始有两个选择器和8输入与门电路构成计数器,然后查找表判断四个条件,如果满足条件输出1,更具查找表的输出控制选择器和使能D触发器,来实现对应的值的输出。上面两种情况对比说明在类似这种功能的电路中,代码形式为if else if平铺式或者if else嵌套式对应的电路是一致的,个人推荐使用if else if平铺式,这样便于代码阅读,写代码也不容易出错,嵌套太多看花眼。
         第三种情况采用case语句实现,这里同样只列出输出幅值的代码,如下:
         always @(posedge clk or negedge reset)
                   begin
                            if(!reset)
                                     begin
                                     data<=0;
                                     end
                            else
                                     begin
                                               case(counter)
                                               8'd1:data<=data_in1;
                                               8'd10:data<=data_in2;
                                               8'd20:data<=data_in3;
                                               8'd30:data<=data_in4;
                                               default:begin
                                                        end
                                               endcase
                                     end
                   end
         对上述代码进行综合,最后使用资源列表和RTL级电路如图3和图4所示:
1.png
3
2.png
4
         由资源列表可以看出采用case语句多用了17个查找表,所以类似本实例的情况,使用case结构实现耗费资源更多,电路图最大的区别就是case结构在选择输出数据的时候采用门级电路完成,这块应该用去了更多的查找表资源,而if else结构综合出的电路使用选择器来选出输出数据。因此类似本实例的情况推荐大家用if else语句实现。

回帖(3)

as493428735

2016-12-16 00:57:41
看的挺费劲,以后有机会再看,先留了
举报

runileking

2016-12-16 15:16:20
图二和图三的位置放反了,抱歉。
举报

郭润生

2018-7-25 20:51:12
不管咋说很流弊
举报

更多回帖

发帖
×
20
完善资料,
赚取积分