verilog与数字系统仿真——generate批量控制代码生成

        generate语法在verilog中用于控制部分代码的生成,下面以1位全加器级联生成多位加法器的案例,介绍generate for的用法。

        模块full_adder_1bit描述了1位全加器:

module full_adder_1bit(
    input   ai,
    input   bi,
    input   ci,
    output  so,
    output  co
);

assign so = ai ^ bi ^ ci;
assign co = ((ai ^ bi) & ci) | (ai & bi);

endmodule

        模块full_adder描述了多位加法器,通过参数控制加法器的位数:

module full_adder #(
    parameter WIDTH= 8
)
(
    input [WIDTH-1:0] a,
    input [WIDTH-1:0] b,
    output [WIDTH:0]s
);

wire [WIDTH-1:0] ci;
wire [WIDTH-1:0] co;
genvar i;
generate 
    for(i=0;i<WIDTH;i=i+1) begin :gen_adder
        full_adder_1bit full_adder_1bit_inst(   
            .ai(a[i]),
            .bi(b[i]),
            .ci(ci[i]),
            .so(s[i]),
            .co(co[i])
        );
    end
endgenerate

genvar j;
generate
    for(j=1;j<WIDTH;j=j+1) begin : co2ci
        assign ci[j] = co[j-1];
    end
endgenerate
assign ci[0] = 1'd0;

assign s[WIDTH] = co[WIDTH-1];

endmodule

        上述例子中,有两个generate语句块,第一个语句块用于批量生成一位全加器,第二个语句块用于将前级的进位值连接至后级的输入,从而级联出多位加法器。

        generate生成代码块时,请注意以下几点:

        1、循环变量必须由genvar生成;

        2、此例中“full_adder_1bit”是模块名,“gen_adder”是循环的名字,在modelsim仿真中此名字生成实例名,见下图,关于“full_adder_1bit_inst”,笔者目前尚不明确该名字的含义,欢迎读者评论区指出。“: gen_adder”可以省略,省略后仍然可以综合出相同的电路,但系统会自动起实例名。建议还是不省略,方便在软件报错时定位问题。

        

        3、对于“co2ci”,此名同样是循环名字,同样可以省略,注意,省略时前方的“:”也要去掉。

        仿真测试代码如下:

`timescale 1ns/1ns

module test_sim ;

reg [7:0] a;
reg [7:0] b;
wire [8:0] s;
initial begin
    a = 8'd0;
    b = 8'd0;
    repeat(2**8) begin
        repeat(2**8) begin
            #10 a = a + 8'd1;
        end
        b = b + 8'd1;
    end
    $stop;
end

full_adder #(
    .WIDTH(8)
)
full_adder_inst
(
    .a(a),
    .b(b),
    .s(s)
);

 
endmodule

        波形图:

        本文参考了以下文章:

【Verilog编程】generate for、generate if、generate case的用法 - 知乎 (zhihu.com)

        generate if 和generate case,其作用与预编译命令`ifdef-`endif相似,这里不再赘述。关于混合使用的例子,这里给出generate for与generate if的案例:

        以下模块中,参数MODE=0时为加法器;MODE=1时,data_out[WIDTH-1:0]=a&b,data_out[WIDTH]恒为0:


module logic_demo #(
    parameter WIDTH = 8,
    parameter MODE = 0
)
(
    input [WIDTH-1:0] a,
    input [WIDTH-1:0] b,
    output [WIDTH:0] data_out
);

wire [WIDTH-1:0] ci;
wire [WIDTH-1:0] s;
wire [WIDTH-1:0] co;
wire [WIDTH-1:0] dout;
genvar i;
generate 
    if(MODE == 0) begin
        for(i=0;i<WIDTH;i=i+1) begin :gen_adder
            full_adder_1bit full_adder_1bit_inst(   
                .ai(a[i]),
                .bi(b[i]),
                .ci(ci[i]),
                .so(s[i]),
                .co(co[i])
            );
        end
    end
    else begin
        for(i=0;i<WIDTH;i=i+1) begin :gen_and_gate
            and_gate and_gate_inst(   
                .a(a[i]),
                .b(b[i]),
                .dout(dout[i])
            );
        end
    end
endgenerate


genvar j;
generate
    if(MODE == 0) begin
        for(j=1;j<WIDTH;j=j+1) begin : co2ci
            assign ci[j] = co[j-1];
        end
        assign ci[0] = 1'd0;
        assign data_out = {co[WIDTH-1],s};
    end
    else begin
        assign data_out = {1'd0,dout};
    end
endgenerate

endmodule

        与门模块:

module and_gate
(
    input a,
    input b,
    output dout
);

assign dout = a & b;

endmodule

        测试代码:

`timescale 1ns/1ns

module test_sim ;

reg [7:0] a;
reg [7:0] b;
wire [8:0] data_out;
initial begin
    a = 8'd0;
    b = 8'd0;
    repeat(2**8) begin
        repeat(2**8) begin
            #10 a = a + 8'd1;
        end
        b = b + 8'd1;
    end
    $stop;
end

logic_demo #(
    .WIDTH(8),
    .MODE(1)
)
logic_demo_inst
(
    .a(a),
    .b(b),
    .data_out(data_out)
);

 
endmodule

        波形图:

        1、MODE=0时,加法器:

        2、MODE=1时,8输入与门:

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值