相关阅读
Verilog基础https://blog.csdn.net/weixin_45791458/category_12263729.html?spm=1001.2014.3001.5482
目录
五、生成块命名空间
六、端口命名空间
七、specify块命名空间
八、属性命名空间
Verilog有八个标识符命名空间:其中两个是全局的(定义命名空间和文本宏命名空间),六个是局部的(模块命名空间,块命名空间、生成块命名空间、端口命名空间、specify块命名空间、属性命名空间)。
五、生成块命名空间
生成块命名空间由生成块结构引入。它统一了其中的函数(function)、任务(task)、命名块(named block)、实例名(instance name)、嵌套的生成块名(generated block)、局部参数(local parameter)、命名事件(named event)、genvar声明、线网声明(net declaration)和变量声明(variable declaration)的标识符。
例8给出了一些生成块命名空间的标识符重名的例子。
// 例8 // 文件:generate.v module ExampleModule; wire [3:0] a, b; wire [3:0] out; genvar i; // 注意这个genvar的名字在模块命名空间中,而不是生成块命名空间 // 生成块命名空间中多个标识符重名 generate for (i = 0; i < 4; i = i + 1) begin : test // 注意这个生成块的名字在模块命名空间中,而不是生成块命名空间,只有generate for结构内的才是生成块命名空间 // 定义一个函数,名为"my_name" function [3:0] my_name; input [3:0] a, b; begin my_name = a + b; end endfunction // 定义一个任务,名为"my_name" task my_name; input [3:0] a; begin $display("Value: %d", a); end endtask // 定义一个命名块,名为"my_name" initial begin: my_name $display("This is a named block"); end // 实例名为"my_name" testmodule my_name(); // 定义一个嵌套的生成块,名为"my_name" if(1) begin: my_name testmodule a(); end // 定义一个局部参数,名为"my_name" localparam my_name = 1; // 定义一个命名事件,名为"my_name" event my_name; // 定义一个genvar,名为"my_name" genvar my_name; // 定义一个变量,名为"my_name" reg my_name; // 定义一个线网,名为"my_name" wire my_name; end endgenerate endmodule六、端口命名空间
端口命名空间由下面结构引入:模块、接口、原语和程序。它提供了一种从结构上定义位于两个不同命名空间中的两个对象之间的连接的方法,连接可以是单向的(输入或输出),也可以是双向的(输入或输出)。端口命名空间中的端口名称不能重复,如例9所示。在端口命名空间中引入的端口名称可以通过声明与端口名称同名的变量类型或线网类型在模块命名空间中重新声明,如例10所示。
// 例9 // 文件:port.v module FaultyModule( input wire clk, // 时钟信号 input wire reset, // 复位信号 output wire clk, // 错误:尝试再次使用'clk'作为输出 input wire dataIn // 数据输入 ); // 模块内容 endmodule// 例10 // 文件:port.v module FaultyModule( clk, // 时钟信号 reset, // 复位信号 data_in // 数据输入 data_out // 数据输出 ); input wire clk; // 重复声明 input wire reset; // 重复声明 input wire data_in; // 重复声明 output wire data_out; // 重复声明 endmodule七、specify块命名空间
specify块命名空间由specify结构引入,它统一了其中的spec参数,如例11所示。
// 例11 // 文件:specify.v `timescale 1ns/1ps `celldefine module example_with_specify ( output Q, input D, input CLK, input RN ); reg notifier; // 时序违例通知寄存器 // 例化时序 UDP 作为触发器内核 dff_udp u_dff (Q, CLK, D, RN, notifier); specify specparam t_CLK_Q = 0.12; specparam t_RN_Q = 0.10; (CLK => Q) = (t_CLK_Q, t_CLK_Q); (RN => Q) = (t_RN_Q, t_RN_Q); specparam tsetup = 0.10; specparam thold = 0.05; specparam twidth = 0.20; specparam tperiod = 0.40; specparam trecov = 0.08; specparam tremov = 0.06; $setup(D, posedge CLK, tsetup, notifier); $hold (posedge CLK, D, thold, notifier); $width (posedge CLK, twidth, 0, notifier); $period(posedge CLK, tperiod, notifier); $recovery(posedge RN, posedge CLK, trecov, notifier); $removal (posedge RN, posedge CLK, tremov, notifier); endspecify endmodule `endcelldefine primitive dff_udp ( Q, CLK, D, RN, notifier ); output Q; reg Q; input CLK, D, RN, notifier; table (01) 0 1 ? : ? : 0 ; (01) 1 1 ? : ? : 1 ; (0x) ? 1 ? : ? : - ; (x1) ? 1 ? : ? : - ; (1?) ? 1 ? : ? : - ; ? (??) 1 ? : ? : - ; ? ? 0 ? : ? : 0 ; ? ? (01) ? : ? : - ; ? ? 1 * : ? : x ; endtable endprimitive八、属性命名空间
属性命名空间是由附加到语言元素的(*和*)结构包围,这些结构用于指定SystemVerilog源代码中的对象、语句和语句组的属性,这些属性可由各种工具(包括仿真器)使用,以控制工具的操作或行为,如例12所示。属性名称只能在属性名称空间中定义和使用,也不能在此名称空间中定义任何其他类型的名称。
// 例12 // 文件:attributes module MyModule #( parameter DATA_WIDTH = 8 ) ( input wire clk, input wire reset, input wire [DATA_WIDTH-1:0] data_in, output wire [DATA_WIDTH-1:0] data_out ); // 使用属性指定寄存器优化 (* max_fanout = 10 *) reg [DATA_WIDTH-1:0] buffer; always @(posedge clk) begin if (reset) begin buffer <= 0; end else begin buffer <= data_in; end end assign data_out = buffer; endmodule至此介绍完了Verilog中的八个标识符命名空间:定义命名空间、文本宏命名空间、模块命名空间,块命名空间、生成块命名空间、端口命名空间、specify块命名空间、属性命名空间。注意,其中并未讨论访问性问题(即在哪里能访问到这些标识符),因为这属于标识符引用问题(包括标识符层次引用),另一篇文章进行解释。