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

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

3天内不再提示

怎么用emac实现Verilog自动连线呢?

sanyue7758 来源:江湖一叶漂 2024-01-24 10:03 次阅读

大型Verilog代码快速连线

我们在编写一些比较复杂的Verilog代码时,通常需要进行大量的手动连线工作,这种工作十分容易出错,并且在代码模块的嵌套层级较多时,更改里层的一个代码,可能就需要更改其外部一系列模块的端口信息等,因此,使用emacs工具能快速实现大批量的、复杂的Verilog模块之间的连线操作

emacs安装

在Ubuntu系统下,直接使用apt安装即可:

sudoaptinstallemacs

大小大概有170MB左右,安装完成后不需要进行其他设置操作。

示例工程下载

为了方便演示emacs的Verilog自动连线的强大功能,这里我提供了一个国内的Git仓库,方便直观的进行理解和使用,首先下载该仓库:

gitclonehttps://gitee.com/xlgforever/emacs_verilog.git

该仓库的README.md文件提供了一个简单的操作介绍。下面将详细演示和解释emacs的连线功能。

该仓库下主要存在以下文件:

(base)xlg@xlg16p:~/wrk/emacs_verilog$tree-L2
.
├──Makefile
├──README.md
├──src
│├──model1.v
│├──top_ori2.v
│├──top_ori3.v
│├──top_ori.v
│└──top.v
└──src2
└──model2.v

2directories,8files

•model1.v和model2.v是需要在顶层模块top.v中实例化的两个模块,这两个模块位于不同的文件夹中,以模拟多处Verilog源码文件的分布;此外model2还具有parameter,这两个模块的内容如下(因为仅用来示范连线功能,因此功能为空):

modulemodel1(
inputclk,
inputrst,
input[7:0]in_data1,
outputreg[7:0]out_data1,
outputregto_model2
);

endmodule//model1
modulemodel2#(
parameterLEN=8
)(
inputclk,
inputrst,
input[LEN-1:0]in_data2,
outputreg[LEN-1:0]out_data2,
inputfrom_model1
);

endmodule//model2

‍而我们的需求是,在顶层模块top.v中实例化这两个模块

情况一:基础用法

直接通过代码讲解,top_ori.v的代码如下:

moduletop(
/*autoarg*/
);

parameterLEN=8;
/*AUTOINPUT*/

/*AUTOOUTPUT*/

/*AUTOWIRE*/

/*model1AUTO_TEMPLATE(
.to_model2(from_model1_to_model2[]),
);
*/

model1u_model1(/*autoinst*/
);

/*model2AUTO_TEMPLATE(
.from_model1(from_model1_to_model2[]),
);
*/

model2#(/*autoinstparam*/)u_model2(/*autoinst*/
);


endmodule

//LocalVariables:
//verilog-auto-inst-param-value:t
//verilog-library-directories:(".""../src2/")
//End:

其中:

•/*autoarg*/用于自动将子模块之间未使用的信号作为父模块的端口信号,例如如果子模块有个信号,名为unuse_signal1,并且该信号没有连接到top模块的其他子模块,那么unuse_signal1就会出现在该指令的下方;

•/*AUTOINPUT*/和/*AUTOOUTPUT*/配合/*autoarg*/,自动为端口信号指定输入输出方向;

•/*AUTOWIRE*/用于自动为子模块之间的互联信号生成wire定义,并且只有子模块端口名称不相同的情况下才会生成;(后续会进行解释)

•AUTO_TEMPLATE,为该子模块的自动连线指定模板,如果不指定,则会自动生成与子模块端口名相同的信号以在顶层模块中使用;

•上述代码中,model1子模块指定to_model2所连接到信号名称为from_model1_to_model2,model2同理;

•此外,由于from_model1_to_model2这个信号与其两端所连接的端口名不一致,因此在/*AUTOWIRE*/下会自动生成该信号的wire定义;

•[]方括号的意思是,如果该信号的位宽不固定为1,则会自动在wire定义和端口引出处添加位宽;

•/*autoinst*/,如果只是指定了模板,而不使用该指令,也不会自动实例化该子模块;使用该命令来自动按照所设置的TEMPLATE生成端口连接;

•/*autoinstparam*/,自动将子模块内部定义为parameter的变量添加在此处,**注意如果不想让该命令添加的参数,应该设置为localparam**;

•endmodule后面的四行代码用于指定所需要实例化的子模块应该在那些目录中查找其对应的源代码文件

•parameter LEN = 8;等和参数相关的代码最好放在靠前的位置,不然等下自动生成的、使用了该参数的代码将会报错,因为该参数需要事先声明;

在仓库根目录执行make emacs -s,上述top.v模块将自动实例化为以下代码:

moduletop(
/*autoarg*/
//Outputs
out_data2,out_data1,
//Inputs
rst,in_data2,in_data1,clk
);

parameterLEN=8;
/*AUTOINPUT*/
//Beginningofautomaticinputs(fromunusedautoinstinputs)
inputclk;//Tou_model1ofmodel1.v,...
input[7:0]in_data1;//Tou_model1ofmodel1.v
input[LEN-1:0]in_data2;//Tou_model2ofmodel2.v
inputrst;//Tou_model1ofmodel1.v,...
//Endofautomatics

/*AUTOOUTPUT*/
//Beginningofautomaticoutputs(fromunusedautoinstoutputs)
output[7:0]out_data1;//Fromu_model1ofmodel1.v
output[LEN-1:0]out_data2;//Fromu_model2ofmodel2.v
//Endofautomatics

/*AUTOWIRE*/
//Beginningofautomaticwires(forundeclaredinstantiated-moduleoutputs)
wirefrom_model1_to_model2;//Fromu_model1ofmodel1.v
//Endofautomatics

/*model1AUTO_TEMPLATE(
.to_model2(from_model1_to_model2[]),
);
*/

model1u_model1(/*autoinst*/
//Outputs
.out_data1(out_data1[7:0]),
.to_model2(from_model1_to_model2),//Templated
//Inputs
.clk(clk),
.rst(rst),
.in_data1(in_data1[7:0]));

/*model2AUTO_TEMPLATE(
.from_model1(from_model1_to_model2[]),
);
*/

model2#(/*autoinstparam*/
//Parameters
.LEN(LEN))u_model2(/*autoinst*/
//Outputs
.out_data2(out_data2[LEN-1:0]),
//Inputs
.clk(clk),
.rst(rst),
.in_data2(in_data2[LEN-1:0]),
.from_model1(from_model1_to_model2));//Templated


endmodule

//LocalVariables:
//verilog-auto-inst-param-value:t
//verilog-library-directories:(".""../src2/")
//End:

可以发现:

•/*autoarg*/将两个子模块之间没有互联的信号自动添加到了顶层端口的信号;

•/*AUTOINPUT*/和/*AUTOOUTPUT*/配合/*autoarg*/,进一步为顶层端口的信号指明了输入输出方向,并且包含了信号的宽度信息;

•/*AUTOWIRE*/仅自动生成了一个信号from_model1_to_model2,因为该信号既不与model1的to_model2端口名相同,也不与model2的from_model1端口名相同;

情况二:匹配模板匹配

打开top_ori2.v文件,其与top_ori.v代码的区别主要如下:

/*model1AUTO_TEMPLATE(
.to_model2(from_model1_to_model2),
.out_(.*)1(in_12),
.in_(.*)1(out_12),
);
*/

•.out_(.*)1 (in_12),的意思是,将model1的以out_开头、1结尾的端口,连接到以in_开头、2结尾的信号;其效果就是,将model1的out_data1端口,连接到in_data2信号,而in_data2正好是model2的同名端口,且model2的TEMPLATE中没有指定in_data2的信号连接,即默认连接到与端口同名的信号;

•(.*)这部分代码表示的是匹配任意长度的任意字符串;

•1表示是,与(.*)成功匹配的字符串;

•在该例子中,(.*)与data成功匹配,所以1代表的就是data;

•.in_(.*)1 (out_12),同理;

在仓库根目录执行make emacs2 -s,上述TEMPLATE生成的实例化代码如下:

model1u_model1(/*autoinst*/
//Outputs
.out_data1(in_data2[7:0]),//Templated
.to_model2(from_model1_to_model2),//Templated
//Inputs
.clk(clk),
.rst(rst),
.in_data1(out_data2[7:0]));//Templated

可以发现,model1的以out或者in开头信号军按照我们的规则进行了信号连接。

这种一般用于什么场景呢,想象一下有两个AXI接口的模块需要连接信号,Master的信号名可能是M00_AXI_xxxx,而Slave的信号名可能是S00_AXI_xxxx,那么我们在连接信号时,只需要在Master的TEMPLATE中使用.M00_AXI_(.*) (S00_AXI_1),一行命令,就能让emacs自动连接这两个模块。

情况三:使用TEMPLATE实例化多次不同信号连接的子模块

通常,我们可能需要将一个模块实例化多次,每个实例的端口所连接到信号会有所区别,这样,我们就需要在TEMPLATE中使用正则表达式。

modulemodel1(
inputclk,
inputrst,
input[7:0]in_data1,
outputreg[7:0]out_data1,
outputregto_model2
);

endmodule//model1

通过在TEMPLATE中使用正则表达式,我们可以实现将每个实例的实例名的一部分作为改实例的端口所连接的信号名的一部分,以区分不同实例的信号;

以top_ori3.v为例,我们将model1的TEMPLATE改为:

/*model1AUTO_TEMPLATE"_(.*)"(
.to_model2(from_model1_to_model2),
.out_(.*)1(in_1_@),
.in_(.*)1(@_out_1),
);
*/

model1u_model1_inst1(/*autoinst*/
);

model1u_model1_inst2(/*autoinst*/
);

此外,上述代码我们实例化了model1两次,每次使用了不同的实例名:

•"_(.*)"含义是,匹配实例名中第一个_字符后的后续所有字符;

•对于实例名u_model1_inst1来说,匹配的就是model1_inst1;

•.out_(.*)1 (in_1_@),中@的含义是,使用匹配到的实例名的部分替换@,组成最终的信号名;

执行make emacs2 -s,最终生成的实例的代码如下:

.in_data1(model1_inst2_out_data));//Templated

model1u_model1_inst1(/*autoinst*/
//Outputs
.out_data1(in_data_model1_inst1),//Templated
.to_model2(from_model1_to_model2),//Templated
//Inputs
.clk(clk),
.rst(rst),
.in_data1(model1_inst1_out_data));//Templated

model1u_model1_inst2(/*autoinst*/
//Outputs
.out_data1(in_data_model1_inst2),//Templated
.to_model2(from_model1_to_model2),//Templated
//Inputs
.clk(clk),
.rst(rst),

我们这里举例的正则匹配,使用的都是(.*)中的.*规则,即万能匹配,可以匹配任意多的任意字符,通过修改该正则匹配的规则,可以实现自己想要的其他效果;

大型Verilog代码快速连线(2)

上面我们熟悉了三种情况下的emacs的连线用法,接下来进行一些进阶连线操作的举例。

正则表达式"([0-9]+)",即匹配至少一个数字,由于该匹配模式很常见,在使用时,可以直接使用@符号来表示。

•.pci_req([0-9]+)_1 (pci_req_jtag_[1])

等效于:

•.pci_req@_1 (pci_req_jtag_[1])。

使用AUTO_TEMPLATE匹配多个端口名/将输入端口赋值为相应宽度的0

在top_ori4.v中,我们分别设置model1和model2的TEMPLATE,并执行make emacs4 -s后,在top.v中得到如下所示结果:

/*model1AUTO_TEMPLATE(
.to_model2(from_model1_to_model2),
.out_(.*)@(in_1_2),
.in_(.*)@(out_1_2),
);
*/


//执行 make emacs4 -s 之后得到:
model1u_model1_inst1(/*autoinst*/
//Outputs
.out_data1(in_data_1),//Templated
.to_model2(from_model1_to_model2),//Templated
//Inputs
.clk(clk),
.rst(rst),
.in_data1(out_data_1));//Templated


/*model2AUTO_TEMPLATE(
.from_model1(from_model1_to_model2),
.in_(.*)({@"vl-width"{1'b0}}),
);
*/

model2#(/*autoinstparam*/
//Parameters
.LEN(LEN))u_model2(/*autoinst*/
//Outputs
.out_data2(out_data2[LEN-1:0]),
//Inputs
.clk(clk),
.rst(rst),
.in_data2({LEN{1'b0}}),//Templated
.from_model1(from_model1_to_model2));//Templated

对于model1:

•(.*)匹配的是model1的端口名中的data,而@等同于([0-9]+),所以,匹配的是1;

•所以根据该TEMPLATE,out_data1连接到了in_data_1,in_data1连接到了out_data_1;

对于model2:

•"vl-width"表示是该端口的位宽;@“vl-width”则表示获得该端口的位宽;

•所以根据该TEMPLATE,model2的in_data2端口被连接到了长度为LEN的0上;

除了vl-width,emacs的Verilog模式还有以下的内置变量

•vl-name:端口的名字部分,例如端口如果是port1[7:0],则vl-name代表的是port1;

•vl-bits:端口的宽度部分,例如端口如果是port1[7:0],则vl-bits代表的是[7:0];

•vl-dir:端口的方向,input/output/inout;

•vl-cell-type:Verilog模块的名称;

•vl-cell-name:Verilog模块的实例的名称;

这些内置变量的使用方法感兴趣的可以自己研究一下。

如何信号名全小写/如何将实例名包含到信号名中

执行make emacs5 -s,打开top.v文件,可以看到模板和生成的实例如下:

/*model1AUTO_TEMPLATE(
.to_model2(from_model1_to_model2),
.(.*)(@"(downcasevl-name)"[]),
);
*/

model1u_model1_inst1(/*autoinst*/
//Outputs
.out_data1(out_data1[7:0]),//Templated
.to_model2(from_model1_to_model2),//Templated
//Inputs
.clk(clk),//Templated
.rst(rst),//Templated
.in_data1(in_data1[7:0]));//Templated


/*model2AUTO_TEMPLATE(
.from_model1(from_model1_to_model2),
.in_(.*)(@"vl-cell-name"_i),
.out_(.*)(@"vl-cell-name"_o),
);
*/

model2#(/*autoinstparam*/
//Parameters
.LEN(LEN))u_model2(/*autoinst*/
//Outputs
.out_data2(u_model2_o),//Templated
//Inputs
.clk(clk),
.rst(rst),
.in_data2(u_model2_i),//Templated
.from_model1(from_model1_to_model2));//Templated

对于model1:

•.(.*) (@"(downcase vl-name)"[]),中,首先通过万能匹配(.*),匹配了全部的端口,然后使用vl-name内置变量将端口名全小写;

•由于本例中没有含有大写的端口名,所以看不出效果;

对于model2:

•.in_(.*) (@"vl-cell-name"_i),中,首先是针对所有以in_开头的端口名,都连接到"实例名" + "_1"的信号上(仅举例示范);

•.out_(.*) (@"vl-cell-name"_o),同理;

其他

除了某些内置变量,还支持普通的算术运算。例如有一个信号in,我们想要将该信号灯每8bit连接到同一个模块的不同实例的a端口上,则可以如下:

/*InstModuleAUTOTEMPLATE(
.a(@in[@"(+(*8@)7)":@"(*8@)"]),
);*/

InstModuleu_a0(/*AUTOINST*/
.a(in[7:0));//Templated
InstModuleu_a1(/*AUTOINST*/
.a(in[15:8));//Templated

从上述代码可以发现,运算符 操作数1 操作数2配合@可以实现很强大的功能:

•* 8 @,运算符为*,第一个操作数为8,第二个操作数为@,而@匹配的是实例名u_a0中的0,所以对u_a0来说,@为0,对u_a1来说,@为1;

•+ (* 8 @) 7,运算符为+,将(* 8 @)的结果作为第一个操作数,第二个操作数为7;

•@"(+ (* 8 @) 7)":将+号产生的结果,通过""号转换为字符;

详细资料见:https://www.veripool.org/verilog-mode/help

emacs在小型模块仿真中的使用技巧

相信很多人都有这种经历——想对某一个模块进行一些简单的仿真测试,但是这个模块端口很多,写一个tb文件的话工作量很大,这时候就可以使用emacs来快速生成仿真环境。

我们的需求如下

•为待测试的模块的所有INPUT生成reg类型的变量;

•为待测试的模块的所有OUTPUT生成wire类型的变量;

DUT

我们依然使用model1作为DUT,其端口如下:

modulemodel1(
inputclk,
inputrst,
input[7:0]in_data1,
outputreg[7:0]out_data1,
outputregto_model2
);

endmodule//model1

新建一个tb.v文件,代码如下:

moduletb();

/*AUTOREGINPUT*/

/*AUTOWIRE*/

/*model1AUTO_TEMPLATE(

);
*/

model1u_model1(/*autoinst*/
);

endmodule//tb

//LocalVariables:
//verilog-auto-inst-param-value:t
//verilog-library-directories:(".""../src2/")
//End:

•/*AUTOREGINPUT*/为模块的所有INPUT生成reg类型的变量

•/*AUTOWIRE*/,同上一节,为模块的所有OUTPUT生成wire类型的变量

执行:

emacs--batch./src/tb.v-fverilog-auto-fsave-buffer

生成的tb.v文件如下:

moduletb();

/*AUTOREGINPUT*/
//Beginningofautomaticreginputs(forundeclaredinstantiated-moduleinputs)
regclk;//Tou_model1ofmodel1.v
reg[7:0]in_data1;//Tou_model1ofmodel1.v
regrst;//Tou_model1ofmodel1.v
//Endofautomatics

/*AUTOWIRE*/
//Beginningofautomaticwires(forundeclaredinstantiated-moduleoutputs)
wire[7:0]out_data1;//Fromu_model1ofmodel1.v
wireto_model2;//Fromu_model1ofmodel1.v
//Endofautomatics

/*model1AUTO_TEMPLATE(

);
*/

model1u_model1(/*autoinst*/
//Outputs
.out_data1(out_data1[7:0]),
.to_model2(to_model2),
//Inputs
.clk(clk),
.rst(rst),
.in_data1(in_data1[7:0]));

endmodule//tb

//LocalVariables:
//verilog-auto-inst-param-value:t
//verilog-library-directories:(".""../src2/")
//End:

可以看到,emac自动为我们生成了待测试模块的输入端口的reg变量和输出端口的wire变量,然后我们只需要操作这些变量即可,无需手动生成这些信号。




审核编辑:刘清

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

    关注

    28

    文章

    1326

    浏览量

    109302
  • DUT
    DUT
    +关注

    关注

    0

    文章

    180

    浏览量

    11998
  • Ubuntu系统
    +关注

    关注

    0

    文章

    84

    浏览量

    3785
  • EMAC
    +关注

    关注

    0

    文章

    3

    浏览量

    3295

原文标题:干货!还不知道怎么用emac 实现Verilog自动连线?

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

收藏 人收藏

    评论

    相关推荐

    verilog语言实现电子钟

    各位大神求救啊verilog语言实现电子钟
    发表于 05-04 16:37

    连线问题

    大家好,我想问一下在程序框图中,两个连线点的距离超过了一个屏幕,该如何去连线呢?先谢谢大家了!
    发表于 05-04 21:48

    Verilog中用*实现乘法和乘法器ip核实现乘法的区别?

    Verilog中用*实现乘法和乘法器ip核实现乘法综合结果有哪些不同?
    发表于 03-18 09:35

    DM8168 的EMAC (Ethernet MACs )接口与EMAC 直接连接传输数据,是否支持?

    A芯片DM8168的EMAC 接口,与 B芯片DM8168的EMAC接口直接相连进行数据传输,中间不需使用PHY芯片, 请问: DM8168是否支持这样的应用? 如果可以支持,EMAC接口间
    发表于 05-15 07:17

    如何在OMAPL138双核系统上实现两个EMAC

    OMAPL138双核系统,目前只有一个EMAC ,现需要两个EMAC,如何实现呢?请教一下。
    发表于 07-10 09:06

    DSP/BIOS和EMAC通信怎么

    之类什么的,我的是TMS320C6747请问该如何配置?2)DSP开发板上有EMAC口,请问如何编程让DSP和PC之间能够通信,分别用什么方法怎么去编程?3)EMAC通信经常看到网上的文档说是在DSP
    发表于 04-17 09:58

    请问Verilog怎么实现UART/RS232/RS485收发自动校调功能?

    请问Verilog怎么实现UART/RS232/RS485收发自动校调功能,降低接收误码率?
    发表于 06-21 07:27

    Verilog实现8255芯片功能

    Verilog实现8255芯片功能
    发表于 11-03 17:06 144次下载

    数字系统设计:VERILOG实现

    数字系统设计:VERILOG实现 (第2版)
    发表于 11-30 10:21 0次下载

    Emac32_PCB学习好资料

    Emac32,PCB学习好资料,欢迎下载学习。
    发表于 03-24 10:42 0次下载

    LPC2368_EMAC源代码

    LPC2368_EMAC源代码,又需要的下来看看
    发表于 08-15 17:55 4次下载

    FPGA设计中DAC控制的Verilog实现

    FPGA设计中DAC控制的Verilog实现(单片机电源维修)-该文档为FPGA设计中DAC控制的Verilog实现资料,讲解的还不错,感兴趣的可以下载看看…………………………
    发表于 07-26 12:18 18次下载
    FPGA设计中DAC控制的<b class='flag-5'>Verilog</b><b class='flag-5'>实现</b>

    自动连线的神器——emacs verilog mode

    Verilog-mode是由Michael McNamara mac@verilog.com和Wilson Snyder wsnyder@wsnyder.org编写。难能可贵的是,这个verilog-mode保持着每月都有更新。
    的头像 发表于 03-29 14:56 4850次阅读
    <b class='flag-5'>自动</b><b class='flag-5'>连线</b>的神器——emacs <b class='flag-5'>verilog</b> mode

    六轴机器人五金冲压连线,助您实现冲压自动

    六轴机器人五金冲压连线,采用机器人自动上下料的方式代替人工完成繁重的体力劳动,增加设备的稳定性和可靠性,提供冲压上料整体解决方案,可实现快速部署,灵活应对产线变化。
    的头像 发表于 03-06 16:53 638次阅读
    六轴机器人五金冲压<b class='flag-5'>连线</b>,助您<b class='flag-5'>实现</b>冲压<b class='flag-5'>自动</b>化

    RTL顶层自动连线的秘密武器:Emacs verilog-mode介绍

    Verilog-mode.el 是用于 Emacs 的非常流行的免费 Verilog 模式,它提供上下文相关的突出显示、自动缩进,并提供宏扩展功能以大大减少 Verilog 编码时间。
    的头像 发表于 04-03 10:48 1679次阅读