system verilog 三段式状态机和interface

1.结构体和C语言类似,system verilog定义的package,也是一个sv文件,需要被工程当作文件一样添加。如果是inclue的文件,要在工程中设置搜索路径,否则在引用时要用相对工程启动文件的路径。在其他sv文件中,"import dma_define::*;"在最前面添加即可。

package dma_define;
//M9K max  256*36   72bit

//130bit
typedef struct packed {
    logic        sop ;
    logic        eop ;
    logic [63:0] data;
    logic [ 7:0] ptr ;  
    logic [15:0] len ;
    logic [39:0] addr;
} DMA_ST;

//66bit
//typedef struct packed {
//    logic        sop ;
//    logic        eop ;
//    logic [ 7:0] ptr ;  
//    logic [15:0] len ;
//    logic [39:0] addr;
//} BD_ST;


endpackage

import dma_define::*;

module cyclone_dma_if (
    input                    clk              ,
    input                    rst              ,
    //pcie avmm
    output reg  [23:0]       txs_address    =0, //                txs.address
    output reg               txs_chipselect =0, //                   .chipselect
    output wire [ 7:0]       txs_byteenable   , //                   .byteenable
    input       [63:0]       txs_readdata     , //                   .readdata
    output reg  [63:0]       txs_writedata  =0, //                   .writedata
    output reg               txs_read       =0, //                   .read
    output reg               txs_write      =0, //                   .write
    output reg  [ 6:0]       txs_burstcount =0, //                   .burstcount
    input                    txs_readdatavalid, //                   .readdatavalid
    input                    txs_waitrequest  , //                   .waitrequest
    //pcie write  写bd finish 和写数据到cpu
    output                   pcie_wcmdq_ren   ,
    input  DMA_ST            pcie_wcmdq_dat   ,
    input                    pcie_wcmdq_empty ,
    //pcie read  下行
    output wire              pcie_rcmdq_ren   ,
    input  DMA_ST            pcie_rcmdq_dat   ,
    input                    pcie_rcmdq_empty ,
    //pcie 返回数据
    output reg               pcie_recvd_wen   ,
    output DMA_ST            pcie_recvd_dat   , //下行无法反压
    output wire [ 4:0][31:0] debug
);

2.三段式状态机,用枚举的方法定义状态,方便仿真和代码阅读。

    typedef enum bit [2:0] {
        FSM_IDLE,
        FSM_READ,
        FSM_WAIT_READ,
        FSM_WRITE,
        FSM_WAIT_WRITE,
        FMS_NOP
    }FSM_STATE;

    FSM_STATE         fsm_curr,fsm_next;

    always@(posedge clk)begin
        if(rst)
            fsm_curr <= FSM_IDLE;
        else
            fsm_curr <= fsm_next;
    end

    always@(*)begin
        case (fsm_curr)
            FSM_IDLE:
            FSM_READ:
            FSM_WAIT_READ:
            FSM_WRITE:
            FSM_WAIT_WRITE:
            FMS_NOP:
            default
        endcase
    end

    always@(posedge clk)begin
        case(fsm_curr)

            default:;
        endcase
    end

3.interface。使用上和结构体的最大区别就是它有modport,可以区分方向。结构体一定是单向的,一般结构体都是和wen afull,或者ren和empty作为fifo的前后传递信号用。interface也是定义在一个sv文件中,一个sv可以用interface和endinterface定义多个接口。当成工程文件引用,不必在其他模块中声明就可以使用该接口。


interface AVALON_MM #(
    parameter DATA_W = 32,
    parameter ADDR_W = 8
)();
    logic                write;
    logic   [DATA_W-1:0] writedata;
    logic                read;
    logic   [ADDR_W-1:0] address;
    logic   [DATA_W-1:0] readdata;
    logic                readdatavalid;
    logic                waitrequest;
    modport Slave(input write,writedata,read,address,output readdata,readdatavalid,waitrequest);
    modport Master(output write,writedata,read,address,input readdata,readdatavalid,waitrequest);
endinterface

使用时要注意方向。最经典的应用就是一个模块内声明,类似于wire,一个模块输入,一个输出。可以大大节约代码行数。interface就类似一个模块,还是用generate的语法去生成和索引,很是灵活。

    AVALON_MM#(32,8)   dma_csr()                ;
    AVALON_MM#(32,8)   gtx_csr()                ;
    wire [ 5:0][31:0]  prase_rd_debug           ;
    wire [ 2:0][31:0]  sch_wr_debug             ;
    wire [ 4:0][31:0]  dma_if_debug             ;

    pcie_dma inst_pcie_dma (
        .clk                           (pcie_clk             ),
        .rst                           (dma_rst              ), //input 
        .txs_address                   (txs_address          ),
        .txs_chipselect                (txs_chipselect       ),
        .txs_byteenable                (txs_byteenable       ),
        .txs_readdata                  (txs_readdata         ),
        .txs_writedata                 (txs_writedata        ),
        .txs_read                      (txs_read             ),
        .txs_write                     (txs_write            ),
        .txs_burstcount                (txs_burstcount       ),
        .txs_readdatavalid             (txs_readdatavalid    ),
        .txs_waitrequest               (txs_waitrequest      ),
        .igress_ren                    (igress_ren           ), //pcie_clk 
        .igress_rdata                  (igress_rdata         ),
        .igress_empty                  (igress_empty         ),
        .ig_bd_usedw                   (ig_bd_usedw          ),
        .eg_rspda_wen                  (eg_rspda_wen         ), //pcie_clk
        .eg_rspda_dat                  (eg_rspda_dat         ),
        .eg_rspda_afull                (eg_rspda_afull       ),
        .prase_rd_debug                (prase_rd_debug       ),
        .sch_wr_debug                  (sch_wr_debug         ),
        .dma_if_debug                  (dma_if_debug         ),
        .avmm                          (dma_csr              )  //slave 8bit symbol
    );

    gtx inst_gtx(
        .clk                           (clk                  ),
        .gtx_csr                       (gtx_csr.Slave        )
    );
   
    avmm_conv inst_avmm_conv (
        .pcie_clk                      (pcie_clk             ), //input
        .pcie_rstn                     (pcie_rstn            ), //input
        .i_bar_address                 (bar0_address         ), //input       [19:0]
        .i_bar_byteenable              (bar0_byteenable      ), //input       [03:0]
        .i_bar_read                    (bar0_read            ), //input
        .i_bar_readdata                (bar0_readdata        ), //output reg  [31:0]
        .i_bar_readdatavalid           (bar0_readdatavalid   ), //output reg
        .i_bar_write                   (bar0_write           ), //input
        .i_bar_writedata               (bar0_writedata       ), //input       [31:0]
        .i_bar_waitrequest             (bar0_waitrequest     ), //output wire
        .cra_chipselect                (cra_chipselect       ), //output reg
        .cra_address                   (cra_address          ), //output reg  [11:0]
        .cra_byteenable                (cra_byteenable       ), //output wire [ 3:0]
        .cra_read                      (cra_read             ), //output reg
        .cra_readdata                  (cra_readdata         ), //input       [31:0]
        .cra_write                     (cra_write            ), //output reg
        .cra_writedata                 (cra_writedata        ), //output reg  [31:0]
        .cra_waitrequest               (cra_waitrequest      ), //input
        .gtx_csr                       (gtx_csr.Master       ),
        .dma_write                     (dma_csr.write        ),
        .dma_writedata                 (dma_csr.writedata    ),
        .dma_read                      (dma_csr.read         ),
        .dma_address                   (dma_csr.address      ),
        .dma_readdata                  (dma_csr.readdata     ),
        .dma_readdatavalid             (dma_csr.readdatavalid),
        .dma_waitrequest               (dma_csr.waitrequest  )  //这里故意写成这样,方便理解
    );      

system verilog的标准上都写明了interface等语法的用法,更多的用法是应用在仿真中。但仅仅学习了一些最基本的,也可以将代码写得更加简洁。

4.$fopen函数。

我们可以用以下代码创建一个文件句柄,在仿真中把打印内容写到txt文本中。

integer  fw;
initial begin
    fw = $fopen("run.txt","w+");
end

always@(posedge clk)begin
    $fwrite(fw,"%t : test[%d] is running!\n",$time,0);
end

可以看到$fwrite最末尾添加了换行符,也是和display的区别,后者会自己加换行符。

但当我们有N个重复例化的模块时,我们相应地也要例化N个log文件,最笨的方法是例化N次,给fopen传递不同的run_0.txt,run_1.txt等。可以用$sformatf拼接字符串,用generate来创建和写入。

integer  fw[8];
string   fw_str[8];
reg [7:0]  test_id = 8'd0;

genvar i;
generate 
    for(i=0;i<8;i=i+1)begin
        initial begin
            fw_str[i] = $sformatf("run_%0d.txt",i);
            fw    [i] = $fopen(fw_str[i],"w+");
        end

        always@(posedge clk)begin
            $fwrite(fw[i],"%t : test[%d] is running!\n",$time,test_id[i]);
        end
    end
endgenerate

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值