SystemVerilog课程笔记(三)


1. DUT——router功能概述

1.1管脚图

以router(路由器)为例

## 1.2输入输出信号 **左边**是输入:16位的din(数据输入)、16位的frame_n(数据帧有效,低电平有效)、16位的valid_n(有效信号,低电平有效)、reset_n(低电平复位)和clock(时钟) **右边**是输出:16位的dout(数据输出)、16位的dout(数据输出)、16位的frameo_n(数据帧输出有效)、16位的valido_n(输出有效信号,低电平有效) ## 1.3模块功能 16个输入的通道,选一个通道作为输入通道,同样的,16个输出的通道,也是选一个通道作为输出通道,数据是一bit一bit地传输。 例如,选择din[7]为数据的输入通道,所以frame_n[7]和valid_n[7]就是控制信号;选择dout[3]为数据的输出通道,所以frameo_n[3]和valido_n[3]就是控制信号。因此数据会从7号输入通道输入,然后从3号通道输出,路由器的功能就是这么简单。 ## 1.4输入信号协议
**din信号** 1.din[i]中的i表示从哪路输入,**din中的第一段4bit的数据表示输出地址(低位开始)**,从哪路输出 2.地址传输完毕后拉高进入隔离段 3.隔离段结束后开始传输数据(低位开始) **frame_n信号** 1.下降沿指示packet的第一位数据 2.上升沿指示packet的最后一位数据 **valid_n信号** 1.其在din的地址输入时间段可为任意值x 2.在隔离段pad拉高 3.其拉低时表示数据有效,因此在payload段若其拉高,则din数据无效 4.数据输入完毕后拉高 ## 1.5输出信号协议
输出信号时序图如上,比较简单,当valido_n和frameo_n均为低时数据有效,除了packet最后一位输出数据时frameo_n为高 。 ## 1.6复位信号协议
以上为其复位协议时序图,有以下几点需要注意: 1.复位时,reset_n为低电平,frame_n和valid_n为高电平 2.有效复位**至少保持1个clk** 3.复位后**至少等待15个时钟**周期后才可以发送数据

2. 实验代码

//********************************** stimulator **********************************//
module rt_stimulator(
  input clock
  ,input reset_n
  ,output logic [15:0] din
  ,output logic [15:0] frame_n
  ,output logic [15:0] valid_n
  ,input [15:0] dout
  ,input [15:0] valido_n
  ,input [15:0] busy_n
  ,input [15:0] frameo_n
);
//for debug purpose from waveform	//定义检测状态的变量
  typedef enum {DRV_RESET,DRV_IDLE,DRV_ADDR,DRV_PAD,DRV_DATA} drv_state_t;
  drv_state_t dbg_state;  
  byte unsigned dbg_din_chnl0_data; 

initial begin : drive_reset_proc //reset阶段,复位时,reset_n为低电平,frame_n和valid_n为高电平
  @(negedge reset_n);
  dbg_state <= DRV_RESET;
  din <= 0;
  frame_n <= 1;
  valid_n <= 1;
end

// drive chaannel 0 - chanel 15 (din[15:0])定义数据输出地址及数据
bit [3:0] addr;
byte unsigned data[];

initial begin : drive_chnl0_proc
  @(negedge reset_n);
  repeat(10) @(posedge clock);//延迟10个时钟周期
  addr = 3;		//从第3位输出
  data = '{8'h33,8'h77};	
    // drive address phase 输入地址位阶段
for(int i=0;i<4;i++)begin  //4 clock
  @(posedge clock);
  dbg_state <=DRV_ADDR;	
  din[0] <= addr[i];
  valid_n[0] <= $urandom_range(0,1);	//valid_n在din的地址输入时间段可为任意值x
  frame_n[0] <= 1'b0;	//frame_n需要为低
end
    // drive pad phase //隔离阶段
  for (int i=0;i<5;i++)begin  //5 clock
    @(posedge clock);
    dbg_state <=DRV_PAD;
    din[0] <= 1'b1;
    valid_n[0] <= 1'b1;	//valid_n需为高电平
    frame_n[0] <= 1'b0; //frame_n需为低电平
  end
    // drive data phase 传输数据阶段
  foreach(data[id])begin
    for(int i=0;i<8;i++)begin
     @(posedge clock);
      dbg_state <=DRV_DATA;
      dbg_din_chnl0_data <= data[id];
      din[0] <= data[id][i];
      valid_n[0] <=1'b0;
      frame_n <= (id == data.size()-1 && i == 7) ? 1'b1 : 1'b0;//packet最后一位输出数据时frameo_n为高
    end
  end
// drive idle phase 闲置(没有数据传输)阶段
  @(posedge clock);
  dbg_state <=DRV_IDLE;
  dbg_din_chnl0_data <= 0;
  din[0] <= 1'b0;
  valid_n[0] <= 1'b1;
  frame_n <= 1'b1;
end
endmodule

//********************************** tb **********************************//
module lab3tb;

bit clk,rstn;
logic [15:0] din, frame_n, valid_n;
logic [15:0] dout, valido_n, busy_n, frameo_n;

// 产生时钟,周期为10ns
initial 
    forever #5ns clk <= !clk;

// 产生复位信号
  initial begin
    #2ns rstn <= 1;
    #10ns rstn <= 0;
    #10ns rstn <= 1;
  end

//例化router为DUT
router dut(           
  .reset_n(rstn),
  .clock(clk),
  .*  //其余端口名称均相同
);

//例化stimulator
rt_stimulator stim(
  .reset_n(rstn),
  .clock(clk),
  .*
);
endmodule 

3. 仿真结果

另,关于vim编辑器

4. 初步TestBench平台概览


文章作者: DPH
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 DPH !
  目录