转载:Verilog语法之generate for、generate if、generate case

本文转载自CSDN博主「孤独的单刀」的原创文章,原文链接:https://blog.csdn.net/wuzhikaidetb/article/details/128192810

0、前言

  Verilog-2005中有3个 generate 语句可以用来很方便地实现 重复赋值和例化(generate for)或 根据条件选择性地进行编译 generate if 和 generate case)等功能。接下来就一起看下这3个语句的应用场景和应用方法吧。


1、generate for

  假设我希望把2个输入 a[4:0] b[4:0] 做一个异或操作,但是顺序要颠倒,也就是这样:

module xor_test
(
    input    [4:0]    a,
    input    [4:0]    b,
    output   [4:0]    out
);
    
assign    out[4] = a[4] ^ b[0];
assign    out[3] = a[3] ^ b[1];
assign    out[2] = a[2] ^ b[2];
assign    out[1] = a[1] ^ b[3];
assign    out[0] = a[0] ^ b[4];
            
endmodule

  在 vivado 中分析出来是这样的:很简单就是两个输出的不同位做一个异或运算。

  vivado 综合出来是这样的:用了几个 LUT 来实现异或功能。


1.1、应用场景

  上面的例子限于篇幅只假设了输入为5bit的位宽,所以这样写并不会让人觉得有多麻烦,但是假想一下如果位宽变成10、20、100呢?那我手不写断去?

  当你需要进行一些重复性的工作时,比如多次例化同一模块、同一语句等,可以使用 generate for 语句来解放双手,节省工作量。当然你用脚本语言来生成或者直接用某些编辑器也能很快地实现这个功能,不过在这里我们就不提了。

  上面的例子用 generate for 语句写是这样的:

module xor_test(
    input    [4:0]    a,
    input    [4:0]    b,
    output   [4:0]    out
);
 
genvar i;                                            // 定义循环变量
 
generate
    for (i = 0; i < 5; i = i + 1)                    // 重复条件
        begin: XOR_INST                              // begin要起个名字
            assign    out[i] = a[i] ^ b[4-i];        // 需要重复的语句
        end
endgenerate
                
endmodule

  在 vivado 中分析出来是这样的:(与上面的方式一致)

  vivado 综合出来是这样的: (仍然与上面的方式一致)

  这样看, generate for 是个不错的提高效率的方案。当然,该语句不光可以对 assign 进行重复赋值,还适用以下场景:

(1)模块module;(2)用户定义原语UDP;(3)门级语句;(4)连续赋值语句assign;(5)initial和always块。


1.2、格式

  generate for 语句的一般用法:

genvar <var>;

generate
    for (<var>=0; <var> < <limit>; <var>=<var>+1)
    begin: <label>
        <instantiation>
    end
endgenerate

  如果你是一个基于 xilinx 的开发者,可以使用 vivado 自带的语法模板:

  (1)打开语法模板:

  (2)搜索 generate:

  (3)把上图右侧的语句复制到你自己的代码里边。


1.3、注意事项

关于 generate for 语句的使用需要注意:

  • generate for 语句必须使用 genvar 关键字定义 for 循环变量

  • generate for 循环必须加 begin…end , 哪怕只有一句

  • 不要使用 i++ 这种 C 语言式的自增语句( Verilog 没有 i++ 这个语法 ),而是使用 i = i + 1

  • generate 后不加 begin,里面的语法: for 循环、 if…else…、case 语句后面的 begin 后面一定要加名字,且名字唯一,否则会导致无法比对通过的问题

  • 过多的 generate 会导致收集覆盖率缓慢,要注意使用


2、generate if

  generate if 的使用场景和条件编译语句类似,比如你的代码中包含了一个加法模块和一个减法模块,对于2个输入 a 和 b ,希望使用 POL 来进行控制:如 POL=1 则进行加法,反之进行减法。

  代码是这样写的:

module xor_test(
    input    [4:0]    a,
    input    [4:0]    b,
    output   [4:0]    out
);
 
localparam  integer  POL = 1;        // 根据POL的值来生成对应的电路
 
generate
    if (POL == 1) begin: POL1
        assign    out = a + b;
    end else begin: POL0
        assign    out = a - b;
    end
endgenerate
                            
endmodule

  定义成 POL = 1 时会由 vivado 综合成一个加法器:

  定义成 POL = 0 时则会由 vivado 综合成一个减法器:

  假如不使用 generate if 语法,则代码是这样的:

module xor_test
(
    input    [4:0]    a,
    input    [4:0]    b,
    input             POL,
    output    reg    [4:0]    out
);
 
always@(*)begin
    if(POL == 1)
        out = a + b;
    else
        out = a - b;
end
                            
endmodule

  这样综合出来的就是加法电路和减法电路一起:

  使用 generate if 可以根据需要来灵活地生成对应电路,不会浪费资源,适用于某些根据特定需求来实现电路的场景。而不使用该语句则会把所有潜在的电路均综合出来,会使电路面积增大,但是灵活性却较高。

  这是 vivado 自带的语法模板:

generate
    if (<condition>) begin: <label_1>
        <code>;
    end else if (<condition>) begin: <label_2>
        <code>;
    end else begin: <label_3>
        <code>;
    end
endgenerate

3、generate case

  generate case 和 generate if 作用上是差不多的,都是 用于选择性综合电路,区别就是 if 语句和 case 语句的区别,如果你会用其中一个,那另一个也很简单,模板如下:

generate
    case (<constant_expression>)
        <value>: begin: <label_1>
            <code>
        end
        <value>: begin: <label_2>
            <code>
        end
        default: begin: <label_3>
            <code>
end
    endcase
endgenerate

  上面的例子照着改就是这样了:

module xor_test(
    input    [4:0]    a,
    input    [4:0]    b,
    output   [4:0]    out
);
 
localparam    integer    POL = 1;        // 根据POL的值来生成对应的电路
 
generate
    case(POL)
        1'b1: begin: POL1
                assign    out = a + b;
            end
        1'b0: begin: POL0
                assign    out = a - b;
            end
        default:begin:    DEFAULT end    
    endcase
endgenerate
                            
endmodule
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值