使用SystemVerilog简化FPGA中的接口
FPGA工程师们应该都会吐槽Verilog的语法,相当的不友好,尤其是对于有很多接口的模块,像AXI4/AXI-Lite这种常用的总线接口,动不动就好几十根线,写起来是相当费劲。
当然现在Xilinx推荐使用纯bd文件的方式来设计FPGA,这样HDL代码就会少了很多。但我们大多数的工程还是无法避免使用HDL来连接两个module。所以本文就推荐使用SystemVerilog来简化FPGA中接口的连接方式。
也许很多FPGA工程师对SystemVerilog并不是很了解,因为以前的FPGA开发工具是不支持SystemVerilog的,导致大家都是用VHDL或者Verilog来开发,但现在Vivado对SystemVerilog的支持已经比较好了,完全可以使用SystemVerilog写出可综合的FPGA程序,而且FPGA开发中只会使用的SystemVerilog语法的一小部分,入门也很快,因此建议FPGA工程师学一下SystemVerilog。
本文中用到的logic
关键字的解释可以参考SystemVerilog教程之数据类型1
此次例程也比较简单,有两个模块module1
和module2
,module1
中输出a
和b
,在module2
中完成加法后再返还给module1
,最终输出的led=c | a
。
image-20200720203534072
首先用Verilog来实现,代码也比较简单,就简单解释一句:文件格式都是.sv
,这是因为SystemVerilog的语法都是包含Verilog的。
//top.sv
module top(
input clk,
input rst,
output [3:0] led
);
logic [3:0] a ;
logic [3:0] b ;
logic [3:0] c ;
module1 inst_module1(
.clk (clk ),
.rst (rst ),
.a (a),
.b (b),
.c (c),
.led (led)
);
module2 inst_module2(
.clk (clk ),
.rst (rst ),
.a (a),
.b (b),
.c (c)
);
endmodule
// module1.sv
module module1(
input clk,
input rst,
output logic [3:0] a,
output logic [3:0] b,
input logic [3:0] c,
output logic [3:0] led
);
assign led = c | a;
always @ ( posedge clk ) begin
if(rst) begin
a <= 4'd1;
b <= 4'd2;
end
else begin
a <= a + 1'b1;
b <= b + 1'b1;
end
end
endmodule
// module2.sv
module module2(
input clk,
input rst,
input logic [3:0] a,
input logic [3:0] b,
output logic [3:0] c
);
always @ ( posedge clk ) begin
if(rst)
c <= 4'd1;
else
c <= a + b;
end
endmodule
综合之后的Schematic如下图所示:(为了更好的表示电路结构,我将flatten_hierarchy
选为了none
)
image-20200720192328527
下面我们把程序稍作改动,将a/b/c三个接口使用SystemVerilog中的interface
来连接。
在工程中添加my_itf.sv
文件如下:
// my_itf.sv
interface my_itf;
logic [3:0] a, b, c;
modport mod1 (input c, output a, b);
modport mod2 (input a, b, output c );
endinterface : my_itf
关键字interface
就表示要创建一个接口模块,里面包含了3个接口:a/b/c。
modport
定义了这三个接口的方向,对于module1
来说,a和b是输出,c是输入;对于module2
来说,a和b是输入,c是输出。
注:也可以不使用modport
,Vivado会根据代码自动推断出接口的方向,但不建议这么做
修改module1.sv
如下,其中a/b/c端口换成了my_itf.mod1 itf_abc
,my_itf.mod1
就表示my_itf接口的方向按照mod1
中指定的,而且代码中的a、b、c要相应的换成itf_abc.a
、itf_abc.b
、itf_abc.c
.
// module1.sv
module module1(
input clk,
input rst,
my_itf.mod1 itf_abc,
output logic [3:0] led
);
assign led = itf_abc.c | itf_abc.a;
always @ ( posedge clk ) begin
if(rst) begin
itf_abc.a <= 4'd1;
itf_abc.b <= 4'd2;
end
else begin
itf_abc.a <= itf_abc.a + 1'b1;
itf_abc.b <= itf_abc.b + 1'b1;
end
end
endmodule
修改module2.sv
代码如下,原则跟上面是一样的,不再赘述。
// module2.sv
module module2(
input clk,
input rst,
my_itf.mod2 itf_abc
);
always @ ( posedge clk ) begin
if(rst)
itf_abc.c <= 4'd1;
else
itf_abc.c <= itf_abc.a + itf_abc.b;
end
endmodule
修改top.sv
如下,例化my_itf
接口,将itf_abc.mod1
传给module1
,将itf_abc.mod2
传给module2
.
// top.sv
module top(
input clk,
input rst,
output [3:0] led
);
logic [3:0] a ;
logic [3:0] b ;
logic [3:0] c ;
my_itf itf_abc();
module1 inst_module1(
.clk (clk ),
.rst (rst ),
.itf_abc (itf_abc.mod1),
.led (led)
);
module2 inst_module2(
.clk (clk ),
.rst (rst ),
.itf_abc (itf_abc.mod2)
);
endmodule
大功告成!!!
综合后Schematic如下,跟上面的图只是名字不同,电路是一样的。
image-20200720201342972
- 如果未来的 AI 拥有意识,你舍得不理它吗?
- 微信这家人脸智慧时尚店可以“刷脸”试衣、付款
- 北京允许无人驾驶路测 难道是为方便圣诞老人送礼?
- 小程序新增多项功能,优化100多个功能点,堪称重磅!
- 人工智能的回报率:对冲基金嵌入机器学习?
- “人工智能助力上海科创中心建设”国际高峰论坛圆满结束
- 纳米白与Pandas
- 人工智能来了!实体零售会变成什么样?
- 全国计算机等级考试重大改革!新增Python科目
- 福特:相比美国人中国人更欢迎自动驾驶未来
- Zzreal的大数据笔记-SparkDay03
- 一文读懂公有链、私有链、联盟链
- 你开车低头看个微信消息都能被拍的清清楚楚,因为有这些黑科技
- 开启程序员世界的Hello World
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- _countof和sizeof
- Flutter适配深色模式的方法(DarkMode)
- RecyclerView+SnapHelper实现无限循环筛选控件
- 详解Android 8.1.0 Service 中 弹出 Dialog的方法
- 短信收发类无错版JustinIO.cs
- Android快速实现无预览拍照功能
- RecyclerView+PagerSnapHelper实现抖音首页翻页的Viewpager效果
- android中使用react-native设置应用启动页过程详解
- 面试官问我单例模式真的安全吗?我懵逼了
- 详解Android使用CoordinatorLayout+AppBarLayout实现拉伸顶部图片功能
- Android自定义控制条效果
- Android使用MediaPlayer和TextureView实现视频无缝切换
- Android实现静默拍照功能
- Android实现动态体温计
- Android实现倾斜角标样式