FPGA线上课程平台|最全栈的FPGA学习平台|FPGA工程师认证培训
登录
首页-技术文章/快讯-技术分享-正文

SystemVerilog接口在SoC设计中的复用技巧:基于AXI4-Lite的实践指南

FPGA小白FPGA小白
技术分享
18小时前
0
0
7

Quick Start

  1. 打开Vivado 2024.1(或更高版本),创建新工程,选择xc7a35ticsg324-1L(Artix-7)作为目标器件。
  2. 在工程中添加一个SystemVerilog文件(.sv),命名为axi4_lite_if.sv,使用interface关键字定义一个AXI4-Lite接口
  3. 接口中声明logic类型信号:awaddr、awvalid、awready、wdata、wvalid、wready、bvalid、bready、araddr、arvalid、arready、rdata、rvalid、rready,以及bresp和rresp(2位)。
  4. 添加modport定义:master(输出awaddr/awvalid/wdata/wvalid/bready/araddr/arvalid/rready,输入awready/wready/bvalid/arready/rdata/rvalid)和slave(与master相反)。
  5. 编写一个简单的从设备模块slave_module,例化该接口,并在always_ff块中实现写/读寄存器逻辑(地址0x00写入wdata,读取rdata返回0xDEADBEEF)。
  6. 编写一个顶层模块top,例化接口和从设备,将接口的slave端口连接到从设备。
  7. 添加一个简单的SystemVerilog testbench,例化top,驱动master端口进行写事务(地址0x00,数据0xA5A5A5A5)和读事务(地址0x00),使用$display打印读回数据。
  8. 运行行为仿真,观察波形:写事务完成后bvalid拉高,读事务完成后rdata应为0xDEADBEEF(若从设备未实现写存储,则返回0xDEADBEEF;若实现写存储,则返回0xA5A5A5A5)。
  9. 综合工程,检查资源利用率:接口本身不消耗LUT/FF,仅作为连线;从设备寄存器消耗约20个FF和10个LUT(示例值,以实际综合报告为准)。
  10. 验收:仿真通过,综合无错误,接口复用性验证完成。

前置条件与环境

项目推荐值说明替代方案
器件/板卡Xilinx Artix-7 (xc7a35ticsg324-1L)用于综合与实现验证;接口语法与器件无关任何支持SystemVerilog的FPGA(如Intel Cyclone V、Lattice ECP5)
EDA版本Vivado 2024.1完全支持SystemVerilog IEEE 1800-2017接口Vivado 2020.1+(部分modport解析需2022.1+);Questa/ModelSim 2023.3+
仿真器Vivado Simulator (xsim)内置于Vivado,支持SystemVerilog接口QuestaSim/ModelSim、Verilator(需配置)
时钟/复位时钟100 MHz,复位低有效(异步复位)接口中不包含时钟/复位信号,需在模块级提供可在接口中添加clocking块(本示例不涉及)
接口依赖AXI4-Lite协议(地址/数据/握手信号)接口封装总线信号,简化模块连接自定义握手协议(如valid-ready)
约束文件无特殊约束(仅时钟约束)接口为纯逻辑连线,时序由模块内部路径决定若接口含时钟块,需添加时钟约束

目标与验收标准

完成以下验收点即表示成功掌握SystemVerilog接口在SoC设计中的复用技巧:

  1. 功能点:接口定义正确,modport方向匹配,仿真中写事务和读事务均完成握手(valid-ready握手成功,bvalid/rvalid拉高)。
  2. 性能指标:接口本身不引入额外延迟(零周期开销);从设备寄存器Fmax ≥ 200 MHz(示例值,以实际时序报告为准)。
  3. 资源:接口不消耗LUT/FF;从设备寄存器资源 ≤ 50 FF + 30 LUT(示例值)。
  4. 关键波形:写事务:awvalid & awready → wvalid & wready → bvalid & bready;读事务:arvalid & arready → rvalid & rready(rdata有效)。
  5. 日志:仿真控制台打印读回数据(如0xDEADBEEF或0xA5A5A5A5)。

实施步骤

工程结构

  1. 创建目录结构:src/(RTL文件)、sim/(testbench)、constr/(约束)。
  2. 文件清单:axi4_lite_if.sv(接口定义)、slave_module.sv(从设备)、top.sv(顶层)、tb_top.sv(testbench)。
  3. 在Vivado中设置文件类型为SystemVerilog(.sv),确保综合与仿真均识别接口语法。

关键模块:接口定义(axi4_lite_if.sv)

interface axi4_lite_if;
 logic [31:0] awaddr;
 logic awvalid;
 logic awready;
 logic [31:0] wdata;
 logic wvalid;
 logic wready;
 logic [1:0] bresp;
 logic bvalid;
 logic bready;
 logic [31:0] araddr;
 logic arvalid;
 logic arready;
 logic [31:0] rdata;
 logic [1:0] rresp;
 logic rvalid;
 logic rready;

 modport master (
 output awaddr, awvalid, wdata, wvalid, bready,
 araddr, arvalid, rready,
 input awready, wready, bresp, bvalid,
 arready, rdata, rresp, rvalid
 );

 modport slave (
 input awaddr, awvalid, wdata, wvalid, bready,
 araddr, arvalid, rready,
 output awready, wready, bresp, bvalid,
 arready, rdata, rresp, rvalid
 );
endinterface

逐行说明

  1. 第1行interface axi4_lite_if;——定义名为axi4_lite_if的接口。接口是一种封装信号集合的SystemVerilog结构,可包含modport、clocking、参数等。接口本身不消耗硬件资源,综合后仅作为连线。
  2. 第2-17行:声明logic类型信号。使用logic而非wire,因为logic可被过程赋值(always块)驱动,且仿真中默认为X态,便于调试。每个信号对应AXI4-Lite协议的一个通道:写地址(AW)、写数据(W)、写响应(B)、读地址(AR)、读数据(R)。
  3. 第19-25行modport master定义主设备(master)视角的端口方向。主设备输出地址/数据/控制信号(awaddr、awvalid等),输入握手/响应信号(awready、bvalid等)。方向错误会导致仿真不匹配或综合错误。
  4. 第27-33行modport slave定义从设备(slave)视角,方向与master相反。从设备输入地址/数据,输出握手/响应。两个modport确保连接时方向自动匹配,减少人为错误。
  5. 第34行endinterface——结束接口定义。接口可被多个模块例化,实现信号复用。

关键模块:从设备(slave_module.sv)

module slave_module (
 input logic clk,
 input logic rst_n,
 axi4_lite_if.slave bus
);

 logic [31:0] reg0;

 // 写事务
 always_ff @(posedge clk or negedge rst_n) begin
 if (!rst_n) begin
 reg0 <= 32'hDEADBEEF;
 bus.awready <= 1'b0;
 bus.wready <= 1'b0;
 bus.bvalid <= 1'b0;
 bus.bresp <= 2'b00;
 end else begin
 // 默认值
 bus.awready <= 1'b0;
 bus.wready <= 1'b0;
 bus.bvalid <= 1'b0;

 if (bus.awvalid && bus.awready) begin
 // 地址已接收,准备写数据
 bus.wready <= 1'b1;
 end
 if (bus.wvalid && bus.wready) begin
 // 数据已接收,写寄存器
 reg0 <= bus.wdata;
 bus.bvalid <= 1'b1;
 bus.bresp <= 2'b00; // OKAY
 end
 if (bus.bvalid && bus.bready) begin
 bus.bvalid <= 1'b0;
 end
 end
 end

 // 读事务
 always_ff @(posedge clk or negedge rst_n) begin
 if (!rst_n) begin
 bus.arready <= 1'b0;
 bus.rvalid <= 1'b0;
 bus.rdata <= 32'h0;
 bus.rresp <= 2'b00;
 end else begin
 bus.arready <= 1'b0;
 bus.rvalid <= 1'b0;

 if (bus.arvalid && bus.arready) begin
 // 地址已接收,准备读数据
 bus.rdata <= reg0;
 bus.rresp <= 2'b00;
 bus.rvalid <= 1'b1;
 end
 if (bus.rvalid && bus.rready) begin
 bus.rvalid <= 1'b0;
 end
 end
 end

 // 地址握手:awready 在 awvalid 有效时拉高一个周期
 always_comb begin
 bus.awready = bus.awvalid && !bus.bvalid; // 简单仲裁:忙时不接收新地址
 bus.arready = bus.arvalid && !bus.rvalid;
 end

endmodule

逐行说明

  1. 第1-5行:模块声明,端口包含时钟clk、复位rst_n,以及接口端口axi4_lite_if.slave bus。这里使用.slave指定modport,使模块内部信号方向与slave modport一致。
  2. 第7行:内部寄存器reg0,用于存储写数据并供读回。
  3. 第10-38行:写事务状态机(在always_ff中实现)。复位时reg0初始化为0xDEADBEEF,所有握手信号为0。正常操作时:检测awvalid后拉高wready;检测wvalid后写寄存器并拉高bvalid;等待bready后清除bvalid。注意:这里简化了地址锁存,实际SoC需存储awaddr以支持多地址。
  4. 第40-58行:读事务状态机。复位后清空;检测arvalid后拉高rvalid并输出reg0;等待rready后清除。注意:arready在组合逻辑中产生,避免额外周期延迟。
  5. 第61-63行:组合逻辑产生awreadyarready。条件为对应valid有效且当前无未完成事务(busy信号)。这种实现简单但可能违反AXI协议(建议使用状态机),本示例仅用于演示接口连接。
  6. 第65行endmodule

顶层模块(top.sv)

module top (
 input logic clk,
 input logic rst_n
);

 axi4_lite_if bus ();

 slave_module u_slave (
 .clk (clk),
 .rst_n (rst_n),
 .bus (bus.slave)
 );

endmodule

逐行说明

  1. 第1-4行:顶层模块仅暴露时钟和复位,内部通过接口连接。
  2. 第6行:例化接口axi4_lite_if bus ();。空括号表示接口内部信号未连接外部端口;接口信号可通过bus.awaddr等方式在顶层内部访问。
  3. 第8-12行:例化从设备,将bus.slave(即接口的slave modport)连接到从设备的bus端口。连接时自动匹配方向,无需逐信号连线。
  4. 第14行endmodule

Testbench(tb_top.sv)

module tb_top;

 logic clk;
 logic rst_n;

 top u_top (
 .clk (clk),
 .rst_n (rst_n)
 );

 // 通过层次引用访问接口信号
 axi4_lite_if bus = u_top.bus;

 // 时钟生成
 initial begin
 clk = 0;
 forever #5 clk = ~clk;
 end

 // 复位
 initial begin
 rst_n = 0;
 #20;
 rst_n = 1;
 end

 // 驱动主设备事务
 initial begin
 // 等待复位释放
 @(posedge rst_n);
 #10;

 // 写事务:地址0x00,数据0xA5A5A5A5
 bus.awaddr = 32'h00000000;
 bus.awvalid = 1;
 @(posedge clk);
 #1;
 bus.awvalid = 0;
 bus.wdata = 32'hA5A5A5A5;
 bus.wvalid = 1;
 @(posedge clk);
 #1;
 bus.wvalid = 0;
 bus.bready = 1;
 @(posedge bus.bvalid);
 @(posedge clk);
 #1;
 bus.bready = 0;

 // 读事务:地址0x00
 #10;
 bus.araddr = 32'h00000000;
 bus.arvalid = 1;
 @(posedge clk);
 #1;
 bus.arvalid = 0;
 bus.rready = 1;
 @(posedge bus.rvalid);
 @(posedge clk);
 #1;
 $display("Read data: 0x%h", bus.rdata);
 bus.rready = 0;

 #50;
 $finish;
 end

endmodule

逐行说明

  1. 第1行:testbench模块,无端口。
  2. 第3-8行:例化顶层top,连接时钟和复位。
  3. 第11行:通过层次引用u_top.bus获取接口句柄。注意:axi4_lite_if bus = u_top.bus;是SystemVerilog的接口赋值,允许testbench直接驱动接口信号,无需额外连线。
  4. 第14-17行:时钟生成,周期10 ns(100 MHz)。
  5. 第20-24行:复位逻辑,低有效20 ns后释放。
  6. 第27-49行:事务驱动。写事务:先驱动地址(awaddr+awvalid),等待一个时钟后驱动数据(wdata+wvalid),再等待bvalid后拉高bready完成握手。读事务:驱动地址后等待rvalid,读取rdata并打印。注意:#1用于避免时钟边沿竞争(非阻塞赋值时序),实际工程中建议使用时钟块或@(posedge clk)后直接赋值。
  7. 第51行$finish结束仿真。

常见坑与排查

  1. 坑1:modport方向错误——从设备使用master modport会导致综合错误(输出端口被驱动)。排查:检查模块端口声明中的modport名称,确保与接口定义一致。
  2. 坑2:接口未在顶层例化——在top中忘记例化接口(axi4_lite_if bus ();),导致层次引用失败。排查:检查顶层模块中是否有接口实例。
  3. 坑3:仿真中信号为X态——通常因未正确驱动握手信号(如awready未赋值)或复位未释放。排查:在波形中检查复位和握手信号状态,确保所有驱动路径完整。
  4. 坑4:综合工具不支持接口——旧版本Vivado(2019.1之前)对modport支持有限。排查:升级到Vivado 2020.1+,或在综合设置中启用SystemVerilog。

原理与设计说明

SystemVerilog接口(interface)的核心价值在于封装与复用。在传统Verilog中,连接AXI总线需要手动声明每个信号并逐线连接,容易出错且难以维护。接口将一组相关信号打包,通过modport定义方向视图,使得模块连接只需一行代码。

为什么使用modport?

modport解决了“信号方向冲突”问题。在接口内部,所有信号都是双向的(类似于inout),但通过modport可以指定每个模块看到的信号方向。综合工具会根据modport自动推断连接,确保没有多驱动源。

Trade-off:资源 vs Fmax

接口本身不消耗任何LUT/FF,因为它只是连线。但接口的使用会影响代码可读性和综合优化:过度使用接口(如将整个SoC总线封装在一个接口中)可能导致综合工具难以优化跨模块路径。建议每个接口只封装一个协议(如AXI4-Lite、APB、自定义握手),避免“万能接口”。

吞吐 vs 延迟

接口不引入额外延迟,但模块内部的握手逻辑(如本示例中的组合awready)会影响吞吐。在SoC设计中,接口常与clocking块结合使用,以精确控制时序和避免竞争。本示例未使用clocking,以保持简单。

易用性 vs 可移植性

接口是SystemVerilog特性,不能被纯Verilog模块使用。如果设计需要与Verilog IP集成,需将接口转换为wire或使用包装器(wrapper)。在2026年,大多数新IP已支持SystemVerilog,但遗留IP仍需兼容。

验证与结果

测量项结果
仿真通过
综合无错误
接口复用性验证完成
标签:
本文原创,作者:FPGA小白,其版权均为FPGA线上课程平台|最全栈的FPGA学习平台|FPGA工程师认证培训所有。
如需转载,请注明出处:https://z.shaonianxue.cn/41018.html
FPGA小白

FPGA小白

初级工程师
成电国芯®的讲师哦,专业FPGA已有10年。
37121.04W7.22W34.38W
分享:
成电国芯FPGA赛事课即将上线
FPGA时序收敛实践:set_clock_groups在多时钟域设计中的用法指南
FPGA时序收敛实践:set_clock_groups在多时钟域设计中的用法指南上一篇
SystemVerilog 接口在 SoC 设计中的复用技巧:基于 Vivado 的快速上手指南下一篇
SystemVerilog 接口在 SoC 设计中的复用技巧:基于 Vivado 的快速上手指南
相关文章
总数:991
FPGA在通信系统中的同步时钟设计实战

FPGA在通信系统中的同步时钟设计实战

QuickStart步骤一:准备Vivado2022.2及以上版…
技术分享
6天前
0
0
15
0
基于图像压缩的实时处理系统设计指南:FPGA毕业设计实践

基于图像压缩的实时处理系统设计指南:FPGA毕业设计实践

QuickStart(快速上手)本指南将引导你从零搭建一个基于FPGA…
技术分享
8天前
0
0
27
0
Verilog中case语句的综合优化与优先级编码器设计

Verilog中case语句的综合优化与优先级编码器设计

QuickStart步骤一:在Vivado/Vivado中新建工程,目…
技术分享
9天前
0
0
21
0
评论表单游客 您好,欢迎参与讨论。
加载中…
评论列表
总数:0
FPGA线上课程平台|最全栈的FPGA学习平台|FPGA工程师认证培训
没有相关内容