吴明

Systemverilog下interface的一种用法,突破传统思维。(内有源码)

1
阅读(9235)

    以前的文章中,我经常提到 sv interface的黑魔法。现在我就来聊一聊,systemverilog区别于hdl,到底可以带来什么样的思路。

    从实际应用出发吧(本来本文的代码就是已经应用于实际项目的),设计《一个SPI配置FPGA内部逻辑寄存器的方案》。

    这个还是很常用的功能,传统的设计,对于增减寄存器数量,只读寄存器,读写寄存器修改并不是很友好。有时候可以算“牵一发动全身”。

Github代码链接

-----------------------------------------------------------------------------------------------------------------

    具体的实现方式及各个参数说明,请参考github的ReadMe,这里不特别说明。

    下面为systemverilog代码

//-----------------这里的部分基本不需要修改--------------------------------
//——————————————————————————————————————————————————————————————————————-
localparam CFG_NUM = 12;       //寄存器数量

spi_cfg_interface #(           // 例化寄存器接口
   .ASIZE      (15),           // 寄存器地址宽   MAX 15
   .DSIZE      (16)            // 寄存器数据宽   MAX 16
)cfg_inf [CFG_NUM-1:0] (       //---<<<关键点【1】定义成数组>>>----
/*    input   bit   */  .clock      (clk_100M      ),
/*    input   bit   */  .rst_n      (rst_n         )
);

spi_ctrl_master #(
   .CFG_NUM            (CFG_NUM),
   .PHASE              (1),
   .ACTIVE             (1)
)spi_ctrl_master(
/*    input         */  .clock                  (clk_100M       ),
/*    input         */  .rst_n                  (rst_n          ),
//-->> SPI INTERFACE <<---
/*    input         */  .sck                    (mcu_spi_clk    ),
/*    input         */  .cs_n                   (mcu_spi_cs     ),
/*    output        */  .miso                   (mcu_spi_do     ),
/*    input         */  .mosi                   (mcu_spi_di     ),
/*    spi_cfg_interface.master  */  .cfg_inf    (cfg_inf        )//[CFG_NUM-1:0] 这行关键
); //---<<<关键点【2】interface数组 port>>>----
//======================================================================================
//---------------------------下面的部分用于随意的添加,修改--------------------------------
//——————————————————————————————————————————————————————————————————————————————————————
logic [15:0]        reg0;
logic [15:0]        reg1;

//--下面为例化不同寄存器--
//------------------------------------------------
//                         使用哪个接口   || 寄存器地址  ||  寄存器数据  
//                         哪个并不重要, ||            ||                  
//                         单必须是独占的 ||            ||                                 
spi_read_only_reg year_reg (cfg_inf[0],         0,        16'h2017); //只读寄存器 标识年
spi_read_only_reg date_reg (cfg_inf[1],         1,        16'h0326); //只读寄存器 标识日期
// 下面为读写寄存器                                                 || 寄存器默认值
spi_general_reg rd_wr_reg0 (cfg_inf[2],         2,        reg0,       32'h0000_0000);
spi_general_reg rd_wr_reg1 (cfg_inf[3],         3,        reg1,       32'h0000_0000);
//=======================================================================================
/*
例化寄存器的数量可以小于CFG_NUM
*/

如果想增加一个读写寄存器,只用例化一个 spi_general_reg 就行了,基本上只用修改一行代码。大大提高友好性。


systemverilog设计影响点:

  1.     spi_cfg_inerface 定义成一个可以parameter控制的interface数组。

  2.    模块接受一个interface数组的port 

  3.    控制信号全部封装进interface,根本不用表露


--@--Young--@--