systemverilog 过程编程分配、任务和功能、模块和层次结构、Modports

本文详细介绍了SystemVerilog中的条件语句(if-else,case,casex/casez),各种循环结构(for,repeat,foreach,while,do-while),任务和功能的声明与区别,以及模块的连接、接口的使用和modport的定向。通过实例演示了如何在设计中运用这些关键概念。

过程编程分配

条件if-else语句

条件if-else语句的语法为:

if (expression)
command1;
else
command2;

其他是可选的,并根据是否存在时钟语句。还可以支持具有多个if和else条目的代码,如中所示以下示例:

If (expression1)
Command1;
elsif (expression2)
command2;
elsif (expression3)
command3;
else
command4;

此示例被合成为优先级if语句。

•如果发现第一个表达式为TRUE,则不计算其他表达式。

•如果使用了唯一或优先级If else语句,Vivado synthesis将其视为parallel_case和full_case。

案例说明

case语句的语法为:

case (expression)
value1: statement1;
value2: statement2;
value3: statement3;
default: statement4;
endcase

case语句中的默认语句是可选的。这些值是按顺序计算的,因此如果value1和value3都为true,则执行语句1。除了case,还有casex和casez语句。这些语句让您handle不关心值(casex)或值(casez)中的三态条件。如果使用了唯一或优先级事例语句,Vivado合成会将这些语句视为parallel_case和full_ case。

循环语句

Vivado synthesis和SystemVerilog中支持的几种类型的循环。其中一个最常见的是for循环。以下是语法:

for (initialization; expression; step) statement;

for循环从初始化开始并计算表达式。如果表达式计算到0时,它停止并执行;否则,如果计算结果为1,则继续执行该语句。什么时候这是用语句完成的,它执行step函数。

•重复循环通过执行指定次数的函数来工作。以下是语法:

repeat (expression) statement;

此语法将表达式求值为数字,并执行指定的语句次数。

•for each循环为数组中的每个元素执行一条语句。

•while循环获取一个表达式和一条语句,并执行该语句,直到表达式为false。

•do-while循环执行与while循环相同的功能,但它测试语句后的表达式。

•永久循环始终执行。要避免无限循环,请将其与break一起使用语句以退出循环。

任务和功能

任务

任务声明的语法为:

task name (ports); [optional declarations]; statements;
endtask

以下是两种类型的任务:

•静态任务:下次调用任务时,声明将保留以前的值。

•自动任务:声明不保留以前的值。

小心!使用这些任务时要小心;Vivado合成将所有任务视为自动任务。如果没有指定静态或自动,许多模拟器默认为静态任务,因此存在模拟不匹配的可能性。将任务指定为自动或静态的方法是下列的

task automatic my_mult... //or
task static my_mult ...

功能(自动和静态)

函数与任务类似,但返回一个值。函数的格式为:

function data_type function_name(inputs);
declarations;
statements;
endfunction : function_name

最后的function_name是可选的,但确实使代码更易于阅读。

因为函数返回一个值,所以它必须有一个return语句或特定的状态

函数名称:

function_name = ....

与任务一样,功能也可以是自动的或静态的。

小心!Vivado合成将所有功能视为自动功能。然而,一些模拟器可能会表现出不同地将这些功能与第三方模拟器一起使用时要小心。

模块和层次结构

在SystemVerilog中使用模块与Verilog非常相似,并包括以下附加功能如以下小节所述。

连接模块

实例化和连接模块主要有三种方式:

•前两个是按顺序列表和名称排列的,如Verilog中所示。

•第三种是通过命名端口。

如果模块的端口名称与实例化模块,下层模块可以按名称挂起。例如

module lower ( output [4:0] myout; input clk;
input my_in;
input [1:0] my_in2;
... ...
endmodule
//in the instantiating level.
lower my_inst (.myout, .clk, .my_in, .my_in2);

使用通配符端口连接模块

连接模块时可以使用通配符。例如,从前面的示例来看:

// in the instantiating module lower my_inst (.*);

只要上层模块具有正确的名称和类型。

此外,这些可以混合和匹配。例如

lower my_inst (.myout(my_sig), .my_in(din), .*);

这将myout端口连接到名为my_sig的信号,my_in端口连接到一个名为din的信号并且clk和my_ in2被连接到clk和my_。

接口

接口提供了一种指定块之间通信的方法。接口是一组将网络和变量分组在一起以建立连接模块之间更易于编写。基本接口的语法为:

interface interface_name; parameters and ports; items;
endinterface : interface_name

末尾的interface_name是可选的,但使代码更易于阅读。例如,

请参阅以下代码:

module bottom1 ( input clk,
input [9:0] d1,d2, input s1,
input [9:0] result, output logic sel,
output logic [9:0] data1, data2, output logic equal);
//logic// endmodule
module bottom2 ( input clk, input sel,
input [9:0] data1, data2, output logic [9:0] result);
//logic// endmodule
module top ( input clk, input s1,
input [9:0] d1, d2, output equal);
logic [9:0] data1, data2, result; logic sel;
bottom1 u0 (clk, d1, d2, s1, result, sel, data1, data2, equal); bottom2 u1
(clk, sel, data1, data2, result);
endmodule

前面的代码片段实例化了两个较低级别的模块,其中一些信号是两者通用。这些常见信号都可以通过接口指定:

interface my_int
logic sel;
logic [9:0] data1, data2, result;
endinterface : my_int
在两个底层模块中,您可以更改为:
module bottom1 (
my_int int1,
input clk,
input [9:0] d1, d2,
input s1,
output logic equal);
and
module bottom2 (
my_int int1,
input clk);

在模块内部,您还可以更改访问sel、data1、data2和result的方式。根据模块的说法,这是因为没有这些名称的端口。相反,有一个名为my_int的端口。这需要进行以下更改:

if (sel)
result <= data1;
to:
if (int1.sel)
int1.result <= int1.data1;

最后,在顶层模块中,必须实例化接口,并且实例引用界面:

module top(
input clk,
input s1,
input [9:0] d1, d2,
output equal);
my_int int3(); //instantiation
bottom1 u0 (int3, clk, d1, d2, s1, equal);
bottom2 u1 (int3, clk);
endmodule

Modports

在前面的例子中,接口内部的信号不再表示为输入或输出。在添加接口之前,端口sel是bottom1的输出和输入底部2。添加接口后,这一点不再清晰。事实上,Vivado合成引擎并没有发出警告,这些端口现在被视为双向端口,并且在生成的网表中通过层次结构,这些被定义为inouts。这不是生成的逻辑的问题,但它可能会令人困惑。要指定方向,请使用modport关键字,如以下代码片段所示:

interface my_int;
logic sel;
logic [9:0] data1, data2, result;
modport b1 (input result, output sel, data1, data2);
modport b2 (input sel, data1, data2, output result);
endinterface : my_int
In the bottom modules, use when declared:
module bottom1 (
my_int.b1 int1,

这样可以正确地将输入和输出关联起来。

其他接口功能

除了信号,接口内部还可以有任务和功能。这让你创建特定于该接口的任务。接口可以参数化。在前面的例子中,data1和data2都是10位矢量,但您可以将这些接口修改为任何大小取决于所设置的参数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cckkppll

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值