前言
当fpga开发者需要做rtl和c/c++联合仿真的时候,一些常用的方法包括使用microblaze软核,或者使用qemu仿真zynq的ps部分。
此教程介绍一种通过systemc做rtl/c/c++联合仿真的方法,所有的bfms(bus function module)都是通过systemc完成。
文中所涉及的所有代码均在vivado和modelsim/questasim上做了验证。
简介
systemc基础
systemc是标准c/c++语言的延伸,即可以描述硬件,也具有c/c++的特性。这个特点让systemc特别适合做系统级别的设计、建模以及验证。
systemc是周期精确的,其主要的组包括
信号,用来连接两个或者多个模块,提供了传输系统间传输与交流数据的通道。
端口,模块的输入、输出接口。
模块,类似vhdl里面的entity和敏感列表。
主函数(sc_main),与c/c++一致,函数的入口。
在systemc中实例化一个rtl的实体
在systemc中实例化一个rtl的实体很直观,你只需要为其rtl实体手写一个对应的systemc的外部模块,之后这个模块就可以在systemc的环境被被其它类调用。
下面将举例说明如果在systemc中构建一个vhdl的实体
示例 vhdl的设计
entity counter isport(clk : in std_logic;reset: in std_logic;count: std_logic_vector(7 downto 0));end;architecture rtl of counter is…end rtl;
对应的systemc模块
class counter : public sc_foreign_module {public:sc_in clk;sc_in reset;sc_out > count;counter(sc_module_name nm) : sc_foreign_module(nm, work.counter),clk(clk),reset(reset),count(count) {}};
需要注意的是,你还可以通过modelsim/questasim提供的scgenmod工具自动生成vhdl、verilog对应的systemc的模块。
用systemc设计bfms
因为sytemc是通过时钟驱动的, 在systemc里面写bfms就变得很直接在systemc中实现axi4-lite的读操作可以如下,
u32 xil_in32(uintptr addr) {u32 data;if (aresetn_i.read() == sc_logic_0) {awaddr.write(0);awvalid.write(sc_logic_0);wdata.write(0);wvalid.write(sc_logic_0);bready.write(sc_logic_1);araddr.write(0);arvalid.write(sc_logic_0);rready.write(sc_logic_1);}else {sc_core::wait(aclk_i.posedge_event());araddr.write(addr);arvalid.write(sc_logic_1);uint32_t num_clocks = 0;while (arready.read() != sc_logic_1) {sc_core::wait(aclk_i.posedge_event());num_clocks++;if (num_clocks == m_timeout_clks) {arvalid.write(sc_logic_0);return -1;}}arvalid.write(sc_logic_0);num_clocks = 0;while (rvalid.read() != sc_logic_1) {sc_core::wait(aclk_i.posedge_event());num_clocks++;if (num_clocks == m_timeout_clks) {return -1;}}data = rdata.read().to_uint();}return data;}
在systemc中实现axi4-lite的写操作可以如下
void xil_out32(uintptr addr, u32 value) {if (aresetn_i.read() == sc_logic_0) {awaddr.write(0);awvalid.write(sc_logic_0);wdata.write(0);wvalid.write(sc_logic_0);bready.write(sc_logic_1);araddr.write(0);arvalid.write(sc_logic_0);rready.write(sc_logic_1);}else {sc_core::wait(aclk_i.posedge_event());awaddr.write(addr);awvalid.write(sc_logic_1);wdata.write(value);wvalid.write(sc_logic_1);uint32_t num_clocks = 0;bool m_awready = false;bool m_wready = false;while ((!m_awready) || (!m_wready)) {sc_core::wait(aclk_i.posedge_event());if (awready.read() == sc_logic_1) {m_awready.write(true);awvalid.write(sc_logic_0);}if (wready.read() == sc_logic_1) {m_wready.write(true);wvalid.write(sc_logic_0);}num_clocks++;if (num_clocks == m_timeout_clks) {awvalid.write(sc_logic_0);wvalid.write(sc_logic_0);return;}}num_clocks = 0;while (bvalid.read() != sc_logic_1) {sc_core::wait(aclk_i.posedge_event());num_clocks++;if (num_clocks == m_timeout_clks) {return;}}}}
系统设计框图
完整的系统框图如下所示。清楚的展示是systemc /dut之间的调用关系。
软件需求
在教程中,需要以下设计工具
vivado design suite
modelsim/questasim
预先编译的vivado ip的仿真库
示例工程
打开vivado,创建一个空的工程。
在vivado里面,打开create and package new ip wizard,选择create a new axi4 peripheral,之后create an axi4 peripheral using the default template。
使用scgenmod指令创建systemc的外部模块。
重写xil_io.c文件,其实现是通过上面介绍的systemc完成bfms的方法。
编译,连接。最后运行vsim。
测试结果
以下是questasim的仿真结果,通过打印的信息可以看到 rtl和c/c++的联合仿真功能的运行。
# vsim -t 1ps xil_defaultlib.env xil_defaultlib.glbl -onfinish stop -l xpm -l unisims_ver -l secureip -l unimacro_ver -l xil_defaultlib -l simlog.txt -assertdebug# ******************************# * user peripheral self test# ******************************# user logic slave module test...## - slave register write/read passed## ** note: (vsim-6574) systemc simulation stopped by user.
电子纸显示技术分析
诺基亚8什么时候上市:诺基亚3、诺基亚5、诺基亚6、诺基亚3310已上市,骁龙835诺基亚8还会远吗?
小米6最新消息:鲁大师曝光小米6跑分,这个分数满意吗?
一文看懂嵌入式总线技术的原理和分类及技术指标
将环境传感器用于传感器融合中和NIMS
介绍一种通过SystemC做RTL/C/C++联合仿真的方法
固态继电器开关电路,Solid state relay sw
连接器UL 1977有哪些检测项目?
博世的半导体业务明星产品
迪士尼想出售游戏业务放弃做电子游戏方面
通信工程企业中通国脉发布2022第一季度报告
用示波器显示齐纳(稳压)二极管的特性曲线
MTK联发科4G安卓主板的性能特点
什么是轮圈的PCD
ChatGPT的核心要点
富唯智能机器人集成了协作机器人、移动机器人和视觉引导技术
5G及特高压对镀锌铁塔企业的消费与需求
压力检测的方法有哪些
微软谷歌相继强调“AI”,苹果却强调Siri的深度学习是否要落伍了?
电桥拓扑结构中的有源元件