Verilog基础语法(7)之generate块

这篇具有很好参考价值的文章主要介绍了Verilog基础语法(7)之generate块。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

verilog中的generate块可以称为生成块,所谓生成,可以理解为复制。如果不太好理解,下面我们继续使用generate块。

generate块应用的场合通常是对模块进行批量例化,或者有条件的例化,使用参数进行控制对哪些模块进行例化,或者例化多少。
不仅限于模块例化,当同一个操作或模块实例需要多次重复,或者某些代码需要根据给定的Verilog参数有条件地包含时,这些语句特别方便。

generate块可以分为generate for和generate if或者generate case。

generate for

介绍generate for 之前,先介绍for循环:
for循环,必须在always块里使用。对应的,always块内的变量要声明成reg类型。

for(表达式1;表达式2;表达式3),执行时对表达式1、2、3和C语言中一样:

(1)执行表达式1,一般是循环变量赋初值;

(2)执行表达式2,若结果为真则执行for里面的内容,否则结束for语句;

(3)执行完for里面的语句,执行表达式3,一般是循环变量自增、自减、移位等操作,回到(2);

verilog的for和C语言的for的不同点;

C语言的for里面的语句是串行顺序执行,而verilog的for内的语句实际是并行的,只是为了写代码方便才用for对多个同样的结构赋值。

比如:实现移位寄存器:

integer i;
always @ (posedge clk)
begin
    data_reg[0] <= data_in;
    for(i = 0; i < 4; i = i+1) begin
        data_reg[i+1] <= data_reg[i];
    end
end

等效于:

always @ (posedge clk)
begin
    data_reg[0] <= data_in;
    data_reg[1] <= data_reg[0];
    data_reg[2] <= data_reg[1];
    data_reg[3] <= data_reg[2];
    data_reg[4] <= data_reg[3];
end

当相同结构的赋值语句较多时,使用for语句能够简化代码,并不会影响实际综合后的电路结构。

generate for 用于批量处理某些赋值等行为。例如:
半加器模块:

module add(
	input a,
	input b,
	output sum
	output cout
);

assign sum  = a ^ b;
assign cout = a & b;
endmodule

当需要多次进行加法运算时,设置一个可控制加发次数的模块

module exam
#
(
	parameter N = 2
)
(
	input [N-1:0]a,
	input [N-1:0]b,
	output [N-1:0]sum,
	output [N-1:0]cout
);
genvar i;
generate 
	for(i = 0; i < N; i = i + 1)begin:addN
		add u0(.a(a[i]), .b(b[i]), .sum(sum[i]), .cout(cout[i]));
	end
endgenerate

作用上:和for是一样的;

区别

(1)generate for的循环变量必须用genvar声明,for的变量可以用reg、integer整数等多种类型声明;

(2)for只能用在always块里面,generate for可以做assign赋值,用always块话,always写在generate for里;

(3)generate for后面必须给这个循环起一个名字,for不需要;

(4)generate for还可以用于例化模块;

generate if

generate if中的条件必须是参数,这是很重要的一点,初学者容易误用,例如将generate if(),括号内给一个变量,根据其值选择执行哪一块语句。
例子:
先给出两个待选择模块:

module mux_assign ( input a, b, sel,
                   output out);
  assign out = sel ? a : b;

  initial
  	$display ("mux_assign is instantiated");
endmodule
module mux_case (input a, b, sel,
                 output reg out);
  always @ (a or b or sel) begin
  	case (sel)
    	0 : out = a;
   	 	1 : out = b;
  	endcase
  end
  
  initial
    $display ("mux_case is instantiated");
endmodule

使用generate if语句来选择例化上述哪一个模块:

module my_design (	input a, b, sel,
         			output out);
  parameter USE_CASE = 0;

  generate
  	if (USE_CASE)
      mux_case mc (.a(a), .b(b), .sel(sel), .out(out));
    else
      mux_assign ma (.a(a), .b(b), .sel(sel), .out(out));
  endgenerate

endmodule

USE_CASE就是一个参数,根据参数的值来选择例化哪一个模块。
仿真文件:

module tb;
  reg a, b, sel;
  wire out;
  integer i;

  my_design #(.USE_CASE(1)) u0 ( .a(a), .b(b), .sel(sel), .out(out));

  initial begin
  	a <= 0;
    b <= 0;
    sel <= 0;

    for (i = 0; i < 5; i = i + 1) begin
      #10 a <= $random;
      	  b <= $random;
          sel <= $random;
      $display ("i=%0d a=0x%0h b=0x%0h sel=0x%0h out=0x%0h", i, a, b, sel, out);
    end
  end
endmodule

结果:
USE_CASE代入参数为1,因此,应该例化的是mux_case 被执行。

// When USE_CASE = 1
mux_case is instantiated
i=0 a=0x0 b=0x0 sel=0x0 out=0x0
i=1 a=0x0 b=0x1 sel=0x1 out=0x1
i=2 a=0x1 b=0x1 sel=0x1 out=0x1
i=3 a=0x1 b=0x0 sel=0x1 out=0x0
i=4 a=0x1 b=0x0 sel=0x1 out=0x0

generate case

generate case语句和generate if语句用法无异,和普通的if与case一致,if具有优先级,case没有优先级。
例子:
给出半加器和全加器设计:
半加器:

module halfadd (input a, b,
           output reg sum, cout);
  always @ (a or b)
  {cout, sum} = a + b;

  initial
    $display ("Half adder instantiation");
endmodule

全加器:

module falladd (input a, b, cin,
           output reg sum, cout);
  always @ (a or b or cin)
  {cout, sum} = a + b + cin;

    initial
      $display ("Full adder instantiation");
endmodule

顶层使用generate case来选调用半加器和全加器,通过参数为ADDER_TYPE 值进行区分:

module my_adder (input a, b, cin,
                 output sum, cout);
  parameter ADDER_TYPE = 1;

  generate
    case(ADDER_TYPE)
      0 : halfadd u0 (.a(a), .b(b), .sum(sum), .cout(cout));
      1 : falladd u1 (.a(a), .b(b), .cin(cin), .sum(sum), .cout(cout));
    endcase
  endgenerate
endmodule

仿真文件:

module tb;
  reg a, b, cin;
  wire sum, cout;

  my_adder #(.ADDER_TYPE(0)) u0 (.a(a), .b(b), .cin(cin), .sum(sum), .cout(cout));

  initial begin
    a <= 0;
    b <= 0;
    cin <= 0;

    $monitor("a=0x%0h b=0x%0h cin=0x%0h cout=0%0h sum=0x%0h",
             a, b, cin, cout, sum);

    for (int i = 0; i < 5; i = i + 1) begin
      #10 a <= $random;
      b <= $random;
      cin <= $random;
    end
  end
endmodule

仿真结果:
仿真中ADDER_TYPE = 0,选择了半加器:文章来源地址https://www.toymoban.com/news/detail-639980.html

Half adder instantiation
a=0x0 b=0x0 cin=0x0 cout=00 sum=0x0
a=0x0 b=0x1 cin=0x1 cout=00 sum=0x1
a=0x1 b=0x1 cin=0x1 cout=01 sum=0x0
a=0x1 b=0x0 cin=0x1 cout=00 sum=0x1

到了这里,关于Verilog基础语法(7)之generate块的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • VSCODE-Verilog开发插件/(代码格式化+Verilog文件树显示+一键例化+UCF转XDC+代码错误检查+语法高亮)

    VSCODE插件,可实现功能: 变量对齐 逗号对齐 括号对齐 快捷键:CTRL + L 例化的代码自动复制到剪切板 快捷键:ctrl+shift+p :输入 Convert_instance 正常顺序转换 可实现序号的从小到大的排列 快捷键:ctrl+shift+p :输入 Convert UCF to XDC NORMAL ORDER 或 Convert UCF to XDC SORT ORDER ucf, xdc, do, tcl 语法

    2024年03月10日
    浏览(50)
  • Verilog基础语法(7)之generate块

    verilog中的generate块可以称为生成块,所谓生成,可以理解为复制。如果不太好理解,下面我们继续使用generate块。 generate块应用的场合通常是对模块进行批量例化,或者有条件的例化,使用参数进行控制对哪些模块进行例化,或者例化多少。 不仅限于模块例化,当同一个操作

    2024年02月13日
    浏览(33)
  • Verilog 学习笔记(一)模块例化

        1.单个模块的例化 verilog中模块的例化有两种方式,一种是基于端口位置来例化模块,另一种则是根据端口名称来例化。首先介绍第一种基于端口位置来例化。在此之前,我们先给出一个简单的模块如下:  上图中的mod_a模块声明如下: module mod_a ( output, output, input, input,

    2024年02月13日
    浏览(45)
  • FPGA | Verilog基础语法

    菜鸟教程连接 举例(\\\"//\\\"符号后的内容为注释文字): initial $dumpfile (“myfile.dump”); //指定VCD文件的名字为myfile.dump,仿真信息将记录到此文件 可以指定某一模块层次上的所有信号,也可以单独指定某一个信号。 典型语法为$dumpvar(level, module_name); 参数level为一个整数,用于指

    2024年02月05日
    浏览(52)
  • FPGA_学习_04_Verilog基础语法和Modelsem仿真

    前言:对于以前学过C/C++/C#的作者来讲,Verilog的基础语法算是 特别简单 的。本文主要介绍Verilog的基础语法和Modelsem仿真。 FPGA开发是以模块为基础的,每个可 综合 的.v文件都是一个模块,模块由 module 和 endmodule 来声明。在这两个的内部,完成模块功能的实现。 在Vi

    2024年02月05日
    浏览(47)
  • FPGA学习笔记:verilog基础代码与modelsim仿真(六)——vga显示模块

    VGA显示 目标:实现屏幕红、橙、黄、绿、青、蓝、紫、黑、白、灰条形显示 1. 模块框图与波形图 vga_colorbar是实现目标功能的总体模块框图,为了实现对应的输出,我们使用三个具体功能模块实现功能。 (1) clk_gen——使用pll锁相环实现时钟分频 (2)vga_ctrl——图像控制与输出模

    2024年02月04日
    浏览(42)
  • 【FPGA学习记录3-1】Verilog语法之Verilog的数据类型

    写在前面 本科时学过FPGA的相关课程,因此对于Verilog相关语法的学习重在回顾。 1.Verilog的数据类型 Verilog 最常用的 2 种数据类型就是 线(wire)与寄存器(reg) ,其余类型可以理解为这两种数据类型的扩展或辅助。 1.1wire类型 wire 类型表示硬件单元之间的物理连线,由其连接

    2024年02月02日
    浏览(46)
  • FPGA模块使用Verilog调用另一个Verilog模块

    FPGA模块使用Verilog调用另一个Verilog模块 在FPGA设计中,常常需要将一个大的模块分解成多个子模块来实现。而这些子模块通常由Verilog代码编写而成。在设计中,我们需要通过调用这些子模块来实现整体的功能。本文将介绍如何使用Verilog调用另一个Verilog模块。 为了说明这个过

    2024年02月07日
    浏览(47)
  • 【FPGA协议篇】UART通信及其verilog实现(代码采用传参实现模块通用性,适用于快速开发)

    ​ 即通用异步收发器(Universal Asynchronous Receiver/Transmitter),是一种 串行、异步、全双工 的通信协议。特点是通信线路简单,适用于远距离通信,但传输速度慢。 数据传输速率:波特率(单位:baud,波特) 常见波特率有:1200、2400、4800、19200、38400、57600等,最常用的是9600和11520

    2024年02月05日
    浏览(50)
  • 1、verilog语法——模块的结构

    目录 前言 一、什么是模块 二、模块的内容 1.I/O声明的格式 2.内部信号的声明 3.功能定义 三、模块的调用(例化) 要点注意 本次的学习内容是verilog的基本设计单元:模块(module) 模块(module)是verilog设计基本单元。一共由两部分组成:一部分是描述接口,另一部分描述逻辑

    2024年02月08日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包