SystemVerilog中结合interface实现输出数据总线的功能(1)
来源:互联网 发布:高仿古驰男鞋淘宝店 编辑:程序博客网 时间:2024/04/28 23:09
前言
在经典的硬件设计中,众多设备可以用分时复用的方案共享同一组数据总线,这大大简化了设备间的通信接口设计,同时还能很容易的实现设备间一对多或者多对一的通信。在FPGA的HDL程序设计中,有时我们也希望能够应用数据总线方案以降低设计难度并充分利用这一方案的便利性。
在应用Verilog或者SystemVerilog编程时,映射于FPGA外部管脚的接口连线可以通过/CS、/RE、/WE等信号配合模块实现数据总线的读/写控制,在模块未取得数据总线的控制权前,模块一般向连向数据总线的输出接口赋值高阻态:'z
。然而在FPGA内部一般高阻态的赋值是不被允许的,即使编译综合通过,高阻态的赋值也会被综合器综合成0
或者1
,这会对连接在同一数据总线上的不同设备产生冲突。
为了解决这一冲突,在FPGA内部模块之间的数据总线必须使用选择器(mux)来实现.
Verilog应用选择器实现数据总线功能
所谓的选择器,实际上就是根据不同的输入选通信号选择不同模块的输出数据接口连接至数据总线。
为了应用选择器选择特定模块的输出到数据总线,需要为每个模块分配一个选通信号,这里我们约定选通信号的值为1时表示模块选通,为0时则表示模块未选通。
示例代码如下:
module dbus_module #( parameter DATAOUT)( output wire[31:0] o_data); assign o_data = 32'(DATAOUT);endmodulemodule tb_verilog_dbus( input wire[2:0] ics, output wire[31:0] odata); wire[31:0] odata_sel[2:0] dbus_module #(.DATAOUT(0)) dm_0(.o_data(odata_sel[0])); dbus_module #(.DATAOUT(1)) dm_1(.o_data(odata_sel[1])); dbus_module #(.DATAOUT(2)) dm_2(.o_data(odata_sel[2])); assign odata = ics[0] ? odata_sel[0] : ics[1] ? odata_sel[1] : ics[2] ? odata_sel[2] : 32'hFFFFFFFF;endmodule
应用SystemVerilog的interface简化数据总线的实现
观察上面的代码可见,上面的verilog代码虽然实现了数据总线的功能,但如果要增加或减少挂载至数据总线的模块,就不得不更改数据总线模块的代码。虽然可以使用parameter来参数化模块数量,但仍然缺少一些必要的灵活性,比如:挂载输出相同类型数据的不同类型的模块至数据总线,这使得数据总线模块tb_verilog_dbus的代码不得不根据需求更改。
SystemVerilog语言提供的interface恰好可以解决这一问题,interface可以添加verilog代码,且可以作为module的端口参数传递,因此我们可以将与数据总线相关的选择器和选通信号归纳至interface中,并将module的数据输出端口连接至interface的待选数据连线。示例代码如下:
interface if_dbus #( parameter LINKED_MDL_CNT) ( output logic[31:0] odbus); logic[LINKED_MDL_CNT-1:0] ocs; wire[31:0] data2sel[LINKED_MDL_CNT-1:0]; always_comb begin odbus = '0; for (int i = 0; i < LINKED_MDL_CNT; i++) begin if (ocs[i]) odbus = data2sel[i]; end endendinterface
应用if_dbus
示例代码如下:
module dbus_mdl1 #( parameter DATAOUT)( output wire[31:0] o_data); assign o_data = 32'(DATAOUT);endmodulemodule dbus_mdl2 #( parameter DATAOUT)( output wire[31:0] data_o); assign data_o = 32'(DATAOUT);endmodulemodule tb_if_dbus; wire[31:0] dbus2exam; if_dbus #( .LINKED_MDL_CNT(5) ) dbus_ifi( .odbus(dbus2exam) ); genvar i; generate for (i= 0; i < 3; i++) begin:MDL1_GEN dbus_mdl1 #( .DATAOUT(i) ) im( .o_data(dbus_ifi.data2sel[i]) ); end for (i = 3; i < 5; i++) begin:MDL2_GEN dbus_mdl2 #( .DATAOUT(i) ) im2( .o_data(dbus_ifi.data2sel[i]) ); end endgenerate // 测试总线输出数据的代码,查看dbus2exam reg clk; initial begin clk = 0; end always #1 clk = ~clk; reg[2:0] idxcntr; initial begin idxcntr = '0; end always_ff @(posedge clk) begin idxcntr = idxcntr + 1; end always_comb begin dbus_ifi.ocs = '0; if (idxcntr < 5) dbus_ifi.ocs[i] = 1'b1; endendmodule
进阶:使用参数化的interface适配不同数据位宽的数据总线
SystemVerilog的interface是可以参数化的,这给了我们做泛化编程的机会。将数据总线所传输数据的位宽以参数的形式在interface中体现,即可用同一个模块定义来适配不同数据位宽的总线。示例代码为:
interface if_dbus #( parameter DATA_BITW, parameter LINKED_MDL_CNT) ( output logic[DATA_BITW:0-1] odbus); logic[LINKED_MDL_CNT-1:0] ocs; wire[DATA_BITW-1:0] data2sel[LINKED_MDL_CNT-1:0]; always_comb begin odbus = '0; for (int i = 0; i < LINKED_MDL_CNT; i++) begin if (ocs[i]) odbus = data2sel[i]; end endendinterface
应用if_dbus
示例代码则变更如下:
module dbus_mdl1 #( parameter DATAOUT)( output wire[31:0] o_data); assign o_data = 32'(DATAOUT);endmodulemodule dbus_mdl2 #( parameter DATAOUT)( output wire[31:0] data_o); assign data_o = 32'(DATAOUT);endmodulemodule tb_if_dbus; wire[31:0] dbus2exam; if_dbus #( .DATA_BITW(32), // 增加对参数DATA_BITW的实例化 .LINKED_MDL_CNT(5) ) dbus_ifi( .odbus(dbus2exam) ); genvar i; generate for (i= 0; i < 3; i++) begin:MDL1_GEN dbus_mdl1 #( .DATAOUT(i) ) im( .o_data(dbus_ifi.data2sel[i]) ); end for (i = 3; i < 5; i++) begin:MDL2_GEN dbus_mdl2 #( .DATAOUT(i) ) im2( .o_data(dbus_ifi.data2sel[i]) ); end endgenerate // 测试总线输出数据的代码,查看dbus2exam reg clk; initial begin clk = 0; end always #1 clk = ~clk; reg[2:0] idxcntr; initial begin idxcntr = '0; end always_ff @(posedge clk) begin idxcntr = idxcntr + 1; end always_comb begin dbus_ifi.ocs = '0; if (idxcntr < 5) dbus_ifi.ocs[i] = 1'b1; endendmodule
- SystemVerilog中结合interface实现输出数据总线的功能(1)
- SystemVerilog中结合interface实现输出数据总线的功能(2)
- systemverilog interface
- systemverilog的数据隐藏特性
- ListView结合DataPager实现分页的功能(数据绑定时)
- Systemverilog中对象的复制
- something about the systemverilog--- interface
- systemverilog中关于事件的那些事
- systemverilog中$value$plusargs的用法
- SystemVerilog中有关class类的基础知识
- systemverilog中logic变量的使用
- PCI总线数据输出板驱动程序的开发
- extremetable+hibernate实现分页 关于结合hibernate后台数据分页和eXtremeTable分页功能的使用
- extremetable+hibernate实现分页 关于结合hibernate后台数据分页和eXtremeTable分页功能的使用
- ASP.NET中利用DataGrid的自定义分页功能和存储过程结合实现高效分页
- ASP.NET中利用DataGrid的自定义分页功能和存储过程结合实现高效分页
- ASP.NET中利用DataGrid的自定义分页功能和存储过程结合实现高效分页
- ASP.NET中利用DataGrid的自定义分页功能和存储过程结合实现高效分页
- 【华为oj】扑克牌比较
- cocoa touch——UIView——draw
- UIView——动画
- 图像高斯分布生成
- thinkphp3.2.3无法加载新建控制器:User
- SystemVerilog中结合interface实现输出数据总线的功能(1)
- TortoiseSVN服务器ip地址修改后如何使用
- 标准IO与文件IO 的区别
- Oracle -- 索引
- pdf2swf 转换时报错
- Servlet 转发实例
- UIView——手势
- 通过Web浏览并控制Tiny6410上的摄像头
- 自定义数据结构的基于范围的for循环 range-based for loop