0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

generate的用法与结构

OpenFPGA 来源:OpenFPGA 作者:OpenFPGA 2022-09-27 09:02 次阅读

Verilog我思我用】-generate

在使用xilinx官方例程《XAPP585》实现CameraLink接口发送或者接收数据时,有个程序还是值得学习的,下面把这段程序截出来:

genvari;
genvarj;

generate
for(i=0;i<= (N-1) ; i = i+1)
begin : loop0

serdes_7_to_1_diff_sdr #(
       .D   (D),
       .DATA_FORMAT  (DATA_FORMAT))
dataout (
 .dataout_p    (dataout_p[D*(i+1)-1:D*i]),
 .dataout_n    (dataout_n[D*(i+1)-1:D*i]),
 .clkout_p    (clkout_p[i]),
 .clkout_n    (clkout_n[i]),
 .txclk      (txclk),
 .pixel_clk      (pixel_clk),
 .reset     (reset),
 .clk_pattern    (clk_pattern),
 .datain    (datain[(D*(i+1)*7)-1:D*i*7]));  
end
endgenerate 

主要是generate的用法,整个文件的功能是实现可选多通道数据发送,我们知道Cameralink中对于多通道传输时有一部分功能代码时相同的,只不过需要多通道复用,我们知道generate有一个功能就是重复操作多个模块的实例引用,当然就适合本例程。

下面我们先讲一讲generate的用法再结合代码简单讲解一下,对于generate其实很好理解,只不过写出来比较难。

generate用法

关键字generate和endgenerate(和begin / end类似)作为使用语法的起点,有三种衍生结构,分别为:

generate - for 语句结构

generate - if 语句结构

generate - case 语句结构

使用generate的情况主要如下:

使用 for 循环对模块进行多次相似实例化

使用参数更改模块的结构或设计

使用带有断言语句进行功能和形式验证

e1e816aa-3dfc-11ed-9e49-dac502259ad0.png

在这里我们思考一下,generate是在运行中构造重复模块吗??

答案是否定的,generate语句不是运行时构造。如果你想一想,这个generate结构实际上是在创建一个重复电路,我们不能即时添加或删除硬件电路,所以generate在综合过程中其实是重复构造相似电路,而不是在运行时构造。

下面先按照generate结构分别举例,然后举例几个常用案例。

generate - for语句结构

在使用generate - for语句之前,我们需要先声明一个变量genvar,用于for循环语句进行判断。

下面举两个不同应用的例子:

e20e0716-3dfc-11ed-9e49-dac502259ad0.png


e229bcae-3dfc-11ed-9e49-dac502259ad0.png

上面两个模块功能一样,第一个是对always 块进行了循环;第二个则是对实例化时的模块进行了循环。xorLoop 是 generate 语句模块名,目的是通过它对循环语句进行层次化引用,所以在上面栗子中的 xorLoop 模块相对层次名为 xorLoop[0].u_xor(后面会举例说明)

这里在对比两个常见的例子:

e254afae-3dfc-11ed-9e49-dac502259ad0.png

上面的例子功能也一样,一个使用generate...for语句一个使用for语句,关于这两者区别我会在文章最后总结里说明,大家可以自己先思考。

generate - if语句结构

generate -if 语句结构比较宽松,即不需要对不需要对generate语句进行命名(generate...for主要是对循环语句进行层次化引用) ,也不需要变量genvar。由于 generate - if 语句结构是通过判断语句执行代码块,这就决定了每次最多执行一个代码块,这种情况下,可以对各个代码块使用相同命名是合法的,且有助于保持对代码的层次化引用。

需要注意的一点是,在 generate 块中的判断条件必须是常量!

e2729a82-3dfc-11ed-9e49-dac502259ad0.png

generate - case

generate - case 语句和 generate - if 语句核心思想都是进行条件判断,用法基本一致。

和 generate - if 语句一样,case 判断条件必须是常量。

e2aadde8-3dfc-11ed-9e49-dac502259ad0.png

下面按照应用场景举例:

循环生成构造

循环生成构造提供了一种简单而简洁的方法来创建模块项的多个实例,例如模块实例、分配语句、断言、接口实例等。你可以把它想象成一台“克隆机”。

本质上,它是一种特殊类型的for循环,其循环索引变量为 datatype genvar。这是一个有趣的事实- genvar它是一个整数数据类型,仅在综合时存在并在运行时消失。

我们看到的《XAPP585》的例程就是这种运行结构,下面再举例看下该语句的特点:

/**Example1*/
/**
*16inputmux
*
*ExampleofhowtouseLoopGenerateConstruct
*/
modulemux_16(
inputlogic[0:15][127:0]mux_in,
inputlogic[3:0]select,
outputlogic[127:0]mux_out
);

logic[0:15][127:0]temp;

//Thefor-loopcreates16assignstatements
genvari;
generate
for(i=0;i< 16; i++) begin
            assign temp[i] = (select == i) ? mux_in[i] : 0;
        end
    endgenerate

    assign mux_out = temp[0] | temp[1] | temp[2] | temp[3] |
                     temp[4] | temp[5] | temp[6] | temp[7] |
                     temp[8] | temp[9] | temp[10] | temp[11] |
                     temp[12] | temp[13] | temp[14] | temp[15];
endmodule: mux_16

仿真文件如下:

`timescale1ns/1ps
/**
*Testbenchtoexercisethemux_16module.
*Hereweinstantiatethemux4times.Eachinstanceis
*fedadifferentinputwithdifferentinput`select`and
*theoutputisobserved.
*/
moduletb_mux_16;

logicclk;
logic[0:15][127:0]test_in[4];
logic[3:0]test_select[4];
logic[127:0]test_out[4];

inti,j,k;

initialbegin
clk=0;
forever#1nsclk=~clk;
end

initialbegin
//Setinputs
for(i=0;i< 4; i++) begin
        for (j=0; j < 16; j++) begin
            test_in[i][j] = 127'habcd_0000 + (i << 8) + j;
        end
        test_select[i] = i;
    end
    #2ns;
    // Print outputs
    for(k=0; k < 4; k++) begin
        $display("test_out[%0d] = 0x%x", k, test_out[k]);
    end
    #2ns;

    // Change input select 
    for (i=0; i < 4; i++) begin
        test_select[i] = 10 + i;
    end
    #2ns;
    // Print outputs again
    for(k=0; k < 4; k++) begin
        $display("test_out[%0d] = 0x%x", k, test_out[k]);
    end
    #10ns;
    $finish;
end

genvar m;
generate
    for (m=0; m < 4; m++) begin: MUX
       mux_16 imux_16 (
           .mux_in(test_in[m]),
           .select(test_select[m]),
           .mux_out(test_out[m])
       ); 
    end
endgenerate
endmodule: tb_mux_16

我们还可以嵌套generate...for 循环。只需确保genvars将外部循环和内部循环分开使用,并在嵌套的 for 循环中引用这些变量时要小心,这是一个经常犯错误的地方。

条件生成构造

条件生成构造允许根据在模块实例化期间传递的参数值更改设计结构。这在为设计创建参数化通用 RTL 模块时非常有用。

一个简单的例子:

/**Example2.1*/
/**
*Asimplegenerateexample.ThisparamerterOPERATION_TYPE,
*passedwhenthismoduleisinstantiated,isusedtoselect
*theoperationbetweeninputs`a`and`b`.
*/
moduleconditional_generate
#(parameterOPERATION_TYPE=0)
(
inputlogic[31:0]a,
inputlogic[31:0]b,
outputlogic[63:0]z
);

//Thegenerate-endgeneratekeywordsareoptional.
//Itistheactofdoingaconditionaloperation
//onaparameterthatmakesthisagenerateblock.
generate
if(OPERATION_TYPE==0)begin
assignz=a+b;
end
elseif(OPERATION_TYPE==1)begin
assignz=a-b;
end
elseif(OPERATION_TYPE==2)begin
assignz=(a<< 1) + b; // 2a+b
        end
        else begin
            assign z = b - a;
        end
    endgenerate
endmodule: conditional_generate

另一个例子 - 我们需要创建一个通用 CRC 生成器的任务。团队中的其他设计人员应该能够在 3 个多项式中选择 1 个进行 CRC 计算。

这是一种方法 - 提供一个名为 CRC_SEL 的参数,该参数在此模块实例化时使用,此CRC_SEL参数用来选择在模块中生成哪个 CRC 函数。通过使用generate而不是简单的多路复用器,可以节省一堆门电路和触发器,因为不需要的 CRC 函数不会被实例化。

e2d490ca-3dfc-11ed-9e49-dac502259ad0.png

完整代码如下:

/**
*CRCgeneratormodule.Selectthedesiredpolynomial
*usingtheCRC_SELparameter.
*
*Defaultpolynomial:x^16+x^15+x^2+1
*CRC_SEL=0:x^16+x^1+1
*CRC_SEL=1:x^16+x^12+x^5+1
*
*USAGE:
*+Strobe`start`whendrivingthefirstvalidbyte
*+Strobe`done`oneclkafterdrivingthelastvalidbyte
*+ThefinalCRCisavailable1clkafterthelastvalidbyte
*isdriven.Thisisthesamecycleyou'lldrive`done`.
*
*/
modulecrc_gen
#(parameterCRC_SEL=0)
(
inputlogicclk,
inputlogicrst,
inputlogicstart,
inputlogicdone,
inputlogic[7:0]data_in,
inputlogic[15:0]crc_in,
outputlogic[15:0]crc_out
);

logic[7:0]data_in_d;
logic[15:0]crc_in_d;

assigncrc_in_d=(start|done)?16'd0:crc_in;
assigndata_in_d=(done)?8'd0:data_in;
always_ff@(posedgeclk)begin
if(rst)begin
crc_out<= 'd0;
        end
        else begin
            // Generate blocks are always assigned a name. If
            // you don't name the generate block, it will be
            // given a default auto generated name.
            //
            // To invoke a function within a generate block,
            // hierarchically call it 
            // .
crc_out<= crc_poly.nextCRC16_D8(data_in_d, crc_in_d);
        end
    end

    // Once again the generate-endgenerate keywords are optional
    // It is the act of using a parameter, CRC_SEL, in the case
    // statement that makes it a generate block
    //
    // Also notice how all the generate blocks are given the same
    // name `crc_poly` and all the function names are the same
    // `nextCRC16_D8`. This is correct because only one of the
    // function declarations is compiled in during elaboration
    // phase.
    generate
    case (CRC_SEL)
        0: 
        begin: crc_poly
            // polynomial: x^16 + x^1 + 1
            // data width: 8
            // convention: the first serial bit is D[7]
            function automatic [15:0] nextCRC16_D8;
            
                input [7:0] Data;
                input [15:0] crc;
                reg [7:0] d;
                reg [15:0] c;
                reg [15:0] newcrc;

                d = Data;
                c = crc;
                
                newcrc[0] = d[0] ^ c[8];
                newcrc[1] = d[1] ^ d[0] ^ c[8] ^ c[9];
                newcrc[2] = d[2] ^ d[1] ^ c[9] ^ c[10];
                newcrc[3] = d[3] ^ d[2] ^ c[10] ^ c[11];
                newcrc[4] = d[4] ^ d[3] ^ c[11] ^ c[12];
                newcrc[5] = d[5] ^ d[4] ^ c[12] ^ c[13];
                newcrc[6] = d[6] ^ d[5] ^ c[13] ^ c[14];
                newcrc[7] = d[7] ^ d[6] ^ c[14] ^ c[15];
                newcrc[8] = d[7] ^ c[0] ^ c[15];
                newcrc[9] = c[1];
                newcrc[10] = c[2];
                newcrc[11] = c[3];
                newcrc[12] = c[4];
                newcrc[13] = c[5];
                newcrc[14] = c[6];
                newcrc[15] = c[7];
                nextCRC16_D8 = newcrc;
            endfunction
        end
        1:
        begin: crc_poly
            // polynomial: x^16 + x^12 + x^5 + 1
            // data width: 8
            // convention: the first serial bit is D[7]
            function automatic [15:0] nextCRC16_D8;
            
                input [7:0] Data;
                input [15:0] crc;
                reg [7:0] d;
                reg [15:0] c;
                reg [15:0] newcrc;

                d = Data;
                c = crc;
                
                newcrc[0] = d[4] ^ d[0] ^ c[8] ^ c[12];
                newcrc[1] = d[5] ^ d[1] ^ c[9] ^ c[13];
                newcrc[2] = d[6] ^ d[2] ^ c[10] ^ c[14];
                newcrc[3] = d[7] ^ d[3] ^ c[11] ^ c[15];
                newcrc[4] = d[4] ^ c[12];
                newcrc[5] = d[5] ^ d[4] ^ d[0] ^ c[8] ^ c[12] ^ c[13];
                newcrc[6] = d[6] ^ d[5] ^ d[1] ^ c[9] ^ c[13] ^ c[14];
                newcrc[7] = d[7] ^ d[6] ^ d[2] ^ c[10] ^ c[14] ^ c[15];
                newcrc[8] = d[7] ^ d[3] ^ c[0] ^ c[11] ^ c[15];
                newcrc[9] = d[4] ^ c[1] ^ c[12];
                newcrc[10] = d[5] ^ c[2] ^ c[13];
                newcrc[11] = d[6] ^ c[3] ^ c[14];
                newcrc[12] = d[7] ^ d[4] ^ d[0] ^ c[4] ^ c[8] ^ c[12] ^ c[15];
                newcrc[13] = d[5] ^ d[1] ^ c[5] ^ c[9] ^ c[13];
                newcrc[14] = d[6] ^ d[2] ^ c[6] ^ c[10] ^ c[14];
                newcrc[15] = d[7] ^ d[3] ^ c[7] ^ c[11] ^ c[15];
                nextCRC16_D8 = newcrc;
            endfunction
        end
        default: 
            begin: crc_poly
            // polynomial: x^16 + x^15 + x^2 + 1
            // data width: 8
            // convention: the first serial bit is D[7]
            function automatic [15:0] nextCRC16_D8;
            
                input [7:0] Data;
                input [15:0] crc;
                reg [7:0] d;
                reg [15:0] c;
                reg [15:0] newcrc;

                d = Data;
                c = crc;
                
                newcrc[0] = d[7] ^ d[6] ^ d[5] ^ d[4] ^ d[3] ^ d[2] ^ d[1] ^ d[0] ^ c[8] ^ c[9] ^ c[10] ^ c[11] ^ c[12] ^ c[13] ^ c[14] ^ c[15];
                newcrc[1] = d[7] ^ d[6] ^ d[5] ^ d[4] ^ d[3] ^ d[2] ^ d[1] ^ c[9] ^ c[10] ^ c[11] ^ c[12] ^ c[13] ^ c[14] ^ c[15];
                newcrc[2] = d[1] ^ d[0] ^ c[8] ^ c[9];
                newcrc[3] = d[2] ^ d[1] ^ c[9] ^ c[10];
                newcrc[4] = d[3] ^ d[2] ^ c[10] ^ c[11];
                newcrc[5] = d[4] ^ d[3] ^ c[11] ^ c[12];
                newcrc[6] = d[5] ^ d[4] ^ c[12] ^ c[13];
                newcrc[7] = d[6] ^ d[5] ^ c[13] ^ c[14];
                newcrc[8] = d[7] ^ d[6] ^ c[0] ^ c[14] ^ c[15];
                newcrc[9] = d[7] ^ c[1] ^ c[15];
                newcrc[10] = c[2];
                newcrc[11] = c[3];
                newcrc[12] = c[4];
                newcrc[13] = c[5];
                newcrc[14] = c[6];
                newcrc[15] = d[7] ^ d[6] ^ d[5] ^ d[4] ^ d[3] ^ d[2] ^ d[1] ^ d[0] ^ c[7] ^ c[8] ^ c[9] ^ c[10] ^ c[11] ^ c[12] ^ c[13] ^ c[14] ^ c[15];
                nextCRC16_D8 = newcrc;
            endfunction
        end
    endcase
    endgenerate

endmodule: crc_gen

下面是仿真文件及结果:

`timescale1ns/1ps
/**
*Testbenchtoexercisethemux_16module.
*Hereweinstantiatethemux4times.Eachinstanceis
*fedadifferentinputwithdifferentinput`select`and
*theoutputisobserved.
*/
moduletb_mux_16;

logicclk;
logic[0:15][127:0]test_in[4];
logic[3:0]test_select[4];
logic[127:0]test_out[4];

inti,j,k;

initialbegin
clk=0;
forever#1nsclk=~clk;
end

initialbegin
//Setinputs
for(i=0;i< 4; i++) begin
        for (j=0; j < 16; j++) begin
            test_in[i][j] = 127'habcd_0000 + (i << 8) + j;
        end
        test_select[i] = i;
    end
    #2ns;
    // Print outputs
    for(k=0; k < 4; k++) begin
        $display("test_out[%0d] = 0x%x", k, test_out[k]);
    end
    #2ns;

    // Change input select 
    for (i=0; i < 4; i++) begin
        test_select[i] = 10 + i;
    end
    #2ns;
    // Print outputs again
    for(k=0; k < 4; k++) begin
        $display("test_out[%0d] = 0x%x", k, test_out[k]);
    end
    #10ns;
    $finish;
end

genvar m;
generate
    for (m=0; m < 4; m++) begin: MUX
       mux_16 imux_16 (
           .mux_in(test_in[m]),
           .select(test_select[m]),
           .mux_out(test_out[m])
       ); 
    end
endgenerate
endmodule: tb_mux_16
Footer
 2022 GitHub, Inc.
Footer navigation
Terms
Privacy
Security
Status
Docs
Cont
e3cfa3a2-3dfc-11ed-9e49-dac502259ad0.png

断言和形式验证

generate - case 语句结构在编写断言时也非常有用,这反过来有助于形式验证。

如果对形式验证有任何经验,那么就会知道形式工具在尝试证明属性时很快就会遇到计算界限。因此,重要的是要保持属性简短而简单。

例如,如果有一个具有 8 个 REQquest 输入和 8 个 ACK 输出的仲裁器块,那么与其编写单个断言来覆盖所有 8 个 REQ/ACK 对,不如将其分解为具有 1 个 REQ/ACK 的 8 个单独的断言对。

/**Example3.1*/
genvark;
generate
for(k=0;k< 8; k++) begin
        req_a: assert property (req[k] |=>ack[k]);
end
endgenerate

分层访问生成块

绊倒人们的一件事是如何访问位于生成块内的模块项。

生成块有一个名字。如果不为其命名,编译器将自动分配一个通用名称,例如genblk01,genblk02通常必须转储 wave 并查看Visualizer工具以查看分配了哪些名称。

要访问生成块中的模块项,必须分层访问它.

这是来自 SystemVerilog LRM 1800-2012 的一个很好的示例(示例 4 第 27.5 节)。查看如何访问块中定义的任务和模块实例。

分层实例名称为:

memory.word16[3].p,memory.word16[2].p,
memory.word16[1].p,memory.word16[0].p,
/**Example4*/
moduledimm(addr,ba,rasx,casx,csx,wex,cke,clk,dqm,data,dev_id);
parameter[31:0]MEM_WIDTH=16,MEM_SIZE=8;
...
genvari;
case({MEM_SIZE,MEM_WIDTH})
{32'd8,32'd16}://8Megx16bitswide
begin:memory
for(i=0;i<4; i=i+1) begin:word16
                sms_08b216t0 p(.clk(clk), .csb(csx), .cke(cke),.ba(ba),
                    .addr(addr), .rasb(rasx), .casb(casx),
                    .web(wex), .udqm(dqm[2*i+1]), .ldqm(dqm[2*i]),
                    .dqi(data[15+16*i:16*i]), .dev_id(dev_id));
                // The hierarchical instance names are:
                // memory.word16[3].p, memory.word16[2].p,
                // memory.word16[1].p, memory.word16[0].p,
                // and the task memory.read_mem
            end
            task read_mem;
                input [31:0] address;
                output [63:0] data;
                begin // call read_mem in sms module
                    word[3].p.read_mem(address, data[63:48]);
                    word[2].p.read_mem(address, data[47:32]);
                    word[1].p.read_mem(address, data[31:16]);
                    word[0].p.read_mem(address, data[15: 0]);
                end
            endtask 
        end
    ...
    endcase
endmodule

总结

这篇文章是在阅读《XAPP585》代码时候看着generate语法极其方便,所以引出了该篇文章,下面说下generate...for和for的区别:

首先第二个代码时错误的!

只有当 for 循环在 generate 中时,才能将 always 放在 for 循环中!

generate for 循环和常规 for 循环之间的主要区别在于 generate for 循环是为每次迭代生成一个实例。这意味着在示例中将有 3 个 always 块(与常规循环情况下的 1 个块相反)。

一个更好的例子是:

moduleA();
..
endmodule;

moduleB();
parameterNUM_OF_A_MODULES=2;//shouldbeoverridenfromhigherhierarchy
genvari;
for(i=0i

在此示例中,常规 for 无法完成创建 NUM_OF_A_MODULES 实例的工作。

审核编辑:彭静
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 接口
    +关注

    关注

    33

    文章

    8442

    浏览量

    150704
  • 数据
    +关注

    关注

    8

    文章

    6800

    浏览量

    88731
  • 代码
    +关注

    关注

    30

    文章

    4720

    浏览量

    68211

原文标题:【Verilog我思我用】-generate

文章出处:【微信号:Open_FPGA,微信公众号:OpenFPGA】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    定时器/计数器的 Programmable pulse generate (PPG) mode,寻求详解!急!!!

    generate (PPG) mode 不懂,希望得到帮助。还有,希望能有好心人推荐一些详细介绍单片机硬件工作原理和用法的资料。 非常感谢!!!
    发表于 10-10 11:54

    Labview 事件结构中级用法 ,用户事件。

    Labview事件结构中级用法,用户事件。源代码如下,版本是2015
    发表于 09-14 08:23

    verilog中generate语句的用法分享

    、assign、always、task等语句或者模块进行复制。在generate语句中可以引入if-else和case语句,根据条件不同产生不同的实例化。在设计中,很多情况下需要编写很多结构相同但是参数
    发表于 12-23 16:59

    讲一讲generate用法

    ), .clk_pattern (clk_pattern), .datain (datain[(D*(i+1)*7)-1:D*i*7]));endendgenerate主要是generate用法,整个
    发表于 09-29 15:06

    Using References to Generate O

    This application report describes the process for using references to generate offsets forTexas Instrument’s TLC55XX family data converters.
    发表于 06-02 08:39 13次下载

    DAC and Op Amp Generate Variab

    Abstract: This design idea describes a simple circuit to generate a programmable negative control
    发表于 04-20 15:16 753次阅读
    DAC and Op Amp <b class='flag-5'>Generate</b> Variab

    How to Generate PWM Waveforms

    of microcontrollers to generate desired PWM waveforms. The action will require that the compare functionality be enabled. The note includes
    发表于 04-23 16:16 1282次阅读
    How to <b class='flag-5'>Generate</b> PWM Waveforms

    DAC and Op Amp Generate Variab

    Abstract: This design idea describes a simple circuit to generate a programmable negative control
    发表于 05-07 09:16 2015次阅读
    DAC and Op Amp <b class='flag-5'>Generate</b> Variab

    Typedef用法小结

    非常不错的文档有着基本数据类型结构体enum与函数指针等等的Typedef相关用法.
    发表于 11-02 11:36 19次下载

    Delphi资源生成器Delphi Resource Generate免费下载

    Delphi Resource Generate用来生成我们经常使用的资源文件。省去了去使用命令brcc32.exe的麻烦!提高效率很重要!
    发表于 12-12 14:54 1次下载
    Delphi资源生成器Delphi Resource <b class='flag-5'>Generate</b>免费下载

    Verilog generate语句的类型

    Generate 结构在创建可配置的RTL的时候很有用。Generate loop能够让语句实例化多次,通过index来控制。而conditional generate能够选择
    的头像 发表于 03-16 14:34 2.1w次阅读
    Verilog <b class='flag-5'>generate</b>语句的类型

    generate语句的基本概念与用法

    生成语句(GENERATE)是一种可以建立重复结构或者是在多个模块的表示形式之间进行选择的语句。由于生成语句可以用来产生多个相同的结构,因此使用生成语句就可以避免多段相同结构的VHDL
    的头像 发表于 11-21 07:08 5809次阅读

    C语言结构用法很多,但是坑也很多

    C语言结构用法很多,坑也很多
    的头像 发表于 01-13 16:06 1257次阅读

    Verilog语法之generate for、generate if、generate case

    Verilog-2005中有3个generate 语句可以用来很方便地实现重复赋值和例化(generate for)或根据条件选择性地进行编译(generate if和generate
    的头像 发表于 12-28 15:21 2620次阅读

    探究寄存机的电路结构以及惯常用法

    *本文将探究什么是寄存器,寄存器的电路结构,寄存器与内存的异同以及寄存器的惯常用法。* ```
    的头像 发表于 01-30 17:08 1045次阅读
    探究寄存机的电路<b class='flag-5'>结构</b>以及惯常<b class='flag-5'>用法</b>