verilog语法实例学习(5)

子电路模块

子电路模块的使用

     一个verilog模块能够作为一个子电路包含在另一个模块中。采用这种方式,所有的模块都必须定义在一个文件中,那么verilog编译器就必须被告知每个模块的所属。模块例化的通用形式和门例化语句类似。

      modulename [#(parameter overrides)] instance_name(

         port_name([expression]) {,port_name([expression])});

      instance_name可以是任何合法的verilog标识符,端口连接指定了模块之间的连接方式。在一个设计中,相同的模块可以多次例化,但每个例化名字必须是唯一的。[#(parameter overrides)] 是用来传入子模块内部参数值的,这个在前面讲过。port_name对应子模块的一个端口名,每个expression指定了端口的连接。port_name可以使例化语句列表中的信号顺序不必与子电路模块中的端口顺序一致,在verilog中,这叫做名称端口连接。如果端口排序与子电路相同,那个.port_name就可以省略,这种连接就叫顺序端口连接

复制代码
module fulladd(cin, x, y, s, cout);
   input cin;//carry in bit
	input x;
	input y;

	output s;
	output cout;//carryout bit

	assign s = x^y^cin;
	assign cout = (x&y)|(x&cin)|(y&cin);

endmodule
复制代码


复制代码
/*
  通过实例化全加器模块实现四位加法的功能。
  输入:cin,进位
       x, y 被加数和加数
		 s 和
		 cout 进位
*/
module adder4(cin, x, y,s,cout);

  input cin;
  input [3:0] x;
  input [3:0] y;

  output [3:0] s;
  output cout;
  wire [3:1] c; //内部线网类型信号c,用来存储串行进位

  fulladd stage0(.cin(cin),.x(x[0]),.y(y[0]),.s(s[0]),.cout(c[1]));
  fulladd stage1(.cin(c[1]),.x(x[1]),.y(y[1]),.s(s[1]),.cout(c[2]));
  fulladd stage2(.cin(c[2]),.x(x[2]),.y(y[2]),.s(s[2]),.cout(c[3]));
  fulladd stage3(.cin(c[3]),.x(x[3]),.y(y[3]),.s(s[3]),.cout(cout));

endmodule
复制代码

在上面四位加法器的模块中,我们例化了一位全加器模块四次,每次例化都有不同的例化名字。


子电路的参数

当子电路包含参数时候,参数的默认值可以在例化语句中修改。具体参照下面链接中:verilog中的参数

https://www.cnblogs.com/mikewolf2002/p/10183150.html


生成块

如果要在循环语句中例化模块,则需要使用generate 结构,它的语法如下:

generate

  [for loops]

  [if-else statements]

  [case statements]

  [instantiate statements]

endgenerate

    这种结构提高了verilog模块的灵活度,因为它允许例化语句包含在for循环和if-else语句内部。如果某一个for循环包含在generate块内,则循环变量必须声明为genvar类型。genvar类似于integer,但是它只能使正数,且只能用在generate块内。

    下面的代码中,我们在generate块中用for循环例化了32个全加器子模块。每个for循环中产生的实例名都是一个唯一的由编译器产生的例化名:addbits[0].stage,…,addbits[n-1].stage

    generate块中可hi包括并行语句和过程语句,但是它的主要优点在于for循环内与if-else语句内的门例化和模块例化。


复制代码
module fulladd(cin, x, y, s, cout);
   input cin;//carry in bit
	input x;
	input y;

	output s;
	output cout;//carryout bit

	assign s = x^y^cin;
	assign cout = (x&y)|(x&cin)|(y&cin);

endmodule
复制代码
复制代码
module addern_2(x, y, s, cout);
  parameter n=32;
  input [n-1:0] x;
  input [n-1:0] y;
  output [n-1:0] s;
  output  cout;

  wire [n:0] c;
  genvar k;
  assign c[0]=0;
  assign cout=c[n];

  generate
	 for(k = 0; k <= n-1; k = k + 1) begin:addbit
       fulladd stage(c[k],x[k],y[k],s[k],c[k+1]);
	 end
  endgenerate

endmodule
复制代码







posted on   迈克老狼2012  阅读(2170)  评论(0编辑  收藏  举报

编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· Vue3状态管理终极指南:Pinia保姆级教程
历史上的今天:
2012-12-27 D3D10/11中的遮挡查询的使用

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示