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编辑器