赞
踩
今天我们继续向前大步迈进,把待验证的DUT加入到环境中来!为此我写了一个非常复杂的模块~~主要的功能把输入的数据打两拍然后送出去。。。。当然这只是level1.0版本,后续在添加reference module时,我一定会补充更加复杂的场景代码的!其实急着把DUT放进来主要是为了下一个博客——验证环境module与program中的time slot做准备。
闲话不多说了,先来看看我的待验证DUT模块。目前功能实在是太简单了,我就不多说啥了,最后的三个fb接口是为之后预留的,可以先不管他们。那么从代码上要连接这个dut只需要两组接口,数据输入interface和数据输出interface。
`ifndef FLOW_PROC_V
`define FLOW_PROC_V
module flow_proc #(
parameter DATA_WIDTH = 8
)(
input clk ,
input rst_n ,
input data_in_vld ,
input sop_in_vld ,
input eop_in_vld ,
input [DATA_WIDTH-1:0] data_in ,
output reg data_out_vld ,
output reg sop_out_vld ,
output reg eop_out_vld ,
output reg [DATA_WIDTH-1:0] data_out ,
output fb_vld ,
output fb_eop ,
output fb_cnt
);
reg data_out_vld_ff1 ;
reg sop_out_vld_ff1 ;
reg eop_out_vld_ff1 ;
reg [DATA_WIDTH-1:0] data_out_ff1 ;
always @(posedge clk) begin
if(rst_n == 1'b0)begin
data_out_vld_ff1 <= 1'b0;
sop_out_vld_ff1 <= 1'b0;
eop_out_vld_ff1 <= 1'b0;
data_out_ff1 <= {DATA_WIDTH{1'b0}};
end
else begin
data_out_vld_ff1 <= data_in_vld;
sop_out_vld_ff1 <= sop_in_vld;
eop_out_vld_ff1 <= eop_in_vld;
data_out_ff1 <= data_in;
end
end
always @(posedge clk) begin
if(rst_n == 1'b0)begin
data_out_vld <= 1'b0;
sop_out_vld <= 1'b0;
eop_out_vld <= 1'b0;
data_out <= {DATA_WIDTH{1'b0}};
end
else begin
data_out_vld <= data_out_vld_ff1;
sop_out_vld <= sop_out_vld_ff1;
eop_out_vld <= eop_out_vld_ff1;
data_out <= data_out_ff1;
end
end
endmodule
`endif
?那我们来改造下验证环境,把DUT加入验证环境中。
改造1.用interface pkt_in_bus和pkt_out_bus分别连接DUT的入口和出口;
改造2.用in_mon采集pkt_in_bus上的信号,out_mon采集pkt_out_bus上的信号,转化为pkt格式traction;
改造3.chk不再与gen相连接,改为与in_mon和out_mon通过channnel连接;
改造4.in_mon的pkt包作为预期,out_mon的包为实际处理结果,由于DUT没有做逻辑处理因此暂时不需要RM;
改造后的验证环境如下图所示。
根据我们设计的验证环境,我们开始轰轰烈烈的改造工程。
首先来组织一下interface,可以预见到我们的模块后面的接口肯定会越来越多,那么我们不能每次加一个接口就从顶层一直加到env里面去,这种方式实在是太费力了,因此我将已有的pkt_if又封装了一层代码如下:
`include "pkt_if.sv"
`ifndef PKT_INTERFACE_SV
`define PKT_INTERFACE_SV
interface pkt_if_pack(
input logic clk,
input logic rst_n
);
pkt_if pkt_in_bus (clk, rst_n);
pkt_if pkt_out_bus (clk, rst_n);
endinterface : pkt_if_pack
//class pkt_interface;
// virtual pkt_if pkt_in_bus = pkt_if_pack.pkt_in_bus;
// virtual pkt_if pkt_out_bus = pkt_if_pack.pkt_out_bus;
//endclass : pkt_interface
`endif
(注释掉的class部分可以暂时不用关注,本来是一种通过virtual来更简洁的做法但是不知道为啥modelsim编译可以过仿真时候会报错,看来我还是要早点把虚拟机里的VCS用起来才是正道。)
把两个pkt_in_bus和pkt_out_out封装在这里,之后进行例化和传递时会简单很多。
封装好interface后我们就可以把DUT例化到环境中了,直接将DUT例化在top顶层即可,这里还想吐槽下modelsim,为啥我想include rtl_link文件也要报错呢,是我不会用么?不多说了,下面是在top中的例化代码,完整代码附在最后面。
//`include “rtl_link”
//part1
wire data_in_vld ;
wire sop_in_vld ;
wire eop_in_vld ;
wire [8 -1:0] data_in ;
wire data_out_vld ;
wire sop_out_vld ;
wire eop_out_vld ;
wire [8 -1:0] data_out ;
wire fb_vld ;
wire fb_eop ;
wire fb_cnt ;
//part2
pkt_if_pack pkt_bus(clk, rst_n);
//part3
flow_proc #(.DATA_WIDTH(8))
U_flow_proc(
.clk (clk) ,
.rst_n (rst_n) ,
.data_in_vld (data_in_vld) ,
.sop_in_vld (sop_in_vld) ,
.eop_in_vld (eop_in_vld) ,
.data_in (data_in) ,
.data_out_vld (data_out_vld) ,
.sop_out_vld (sop_out_vld) ,
.eop_out_vld (eop_out_vld) ,
.data_out (data_out) ,
.fb_vld (fb_vld) ,
.fb_eop (fb_eop) ,
.fb_cnt (fb_cnt)
);
//part4
assign data_in_vld = pkt_bus.pkt_in_bus.vld ;
assign sop_in_vld = pkt_bus.pkt_in_bus.sop ;
assign eop_in_vld = pkt_bus.pkt_in_bus.eop ;
assign data_in = pkt_bus.pkt_in_bus.data ;
assign pkt_bus.pkt_out_bus.vld = data_out_vld ;
assign pkt_bus.pkt_out_bus.sop = sop_out_vld ;
assign pkt_bus.pkt_out_bus.eop = eop_out_vld ;
assign pkt_bus.pkt_out_bus.data = data_out ;
//part5
test u_test(pkt_bus);
例化分为四个部分,part1定义wire信号,part2例化interface(与例化module方式一致),part3例化DUT,part4将interface与module相连接,part5将interface作为接口传参传入test,实现验证环境与DUT的互连。
当然每个人有自己的代码风格,这里我写的比较繁琐,主要是这样用惯了。
继续进行,接下来是最大的改动点env(test new()也有改动,看最后的代码好啦)。
改动1.if例化改为例化一份pkt_if_pack bus(之后所有的接口增减都到pkt_if_pack里面去做),例化两份mom,channel也对应的修改下;
virtual pkt_if_pack bus;
pkt_gen gen;
pkt_drv drv;
pkt_mon in_mon;
pkt_mon out_mon;
pkt_chk chk;
env_cfg cfg;
mailbox gen2drv_chan;
mailbox in_mon2chk_chan;
mailbox out_mon2chk_chan;
改动2.new函数微调下;
function environment::new(input virtual pkt_if_pack bus);
$display("At %0t, [ENV NOTE]: environment::new() start!", $time);
this.bus = bus;
this.cfg = new();
gen2drv_chan = new(1);
in_mon2chk_chan = new(1);
out_mon2chk_chan = new(1);
endfunction
改动3.bulid()中改变组件的连接方式,gen减少一个gen2chk channel传参,最终连接与图示一致;
task environment::build();
$display("At %0t, [ENV NOTE]: environment::build() start!", $time);
gen = new(cfg, gen2drv_chan);
drv = new(cfg, this.bus.pkt_in_bus, gen2drv_chan);
in_mon = new(cfg, this.bus.pkt_in_bus, this.in_mon2chk_chan);
out_mon = new(cfg, this.bus.pkt_out_bus, this.out_mon2chk_chan);
chk = new(cfg, in_mon2chk_chan, out_mon2chk_chan);
endtask
再对照一下这个图;
改动4.微调run(),主要涉及in_mon和out_mon;
好的至此主要改动基本完成,不过别忘记调整pkt_gen内部代码,毕竟少了一个通道嘛。
最终的编译文件和编译顺序如下图:
编译完成后,run个100000ns啥的发100个包
看看波形和打印log:
太完美了!附上截至目前为止的代码,睡觉~~~
附目前为止所有文件
`include "pkt_dec.sv"
module top();
logic clk;
logic rst_n;
initial begin
#0ns clk = 0;
forever #5ns clk = ~clk;
end
initial begin
#0ns rst_n = 0;
#225ns rst_n = 1;
end
//`include “rtl_link”
wire data_in_vld ;
wire sop_in_vld ;
wire eop_in_vld ;
wire [8 -1:0] data_in ;
wire data_out_vld ;
wire sop_out_vld ;
wire eop_out_vld ;
wire [8 -1:0] data_out ;
wire fb_vld ;
wire fb_eop ;
wire fb_cnt ;
pkt_if_pack pkt_bus(clk, rst_n);
flow_proc #(.DATA_WIDTH(8))
U_flow_proc(
.clk (clk) ,
.rst_n (rst_n) ,
.data_in_vld (data_in_vld) ,
.sop_in_vld (sop_in_vld) ,
.eop_in_vld (eop_in_vld) ,
.data_in (data_in) ,
.data_out_vld (data_out_vld) ,
.sop_out_vld (sop_out_vld) ,
.eop_out_vld (eop_out_vld) ,
.data_out (data_out) ,
.fb_vld (fb_vld) ,
.fb_eop (fb_eop) ,
.fb_cnt (fb_cnt)
);
assign data_in_vld = pkt_bus.pkt_in_bus.vld ;
assign sop_in_vld = pkt_bus.pkt_in_bus.sop ;
assign eop_in_vld = pkt_bus.pkt_in_bus.eop ;
assign data_in = pkt_bus.pkt_in_bus.data ;
assign pkt_bus.pkt_out_bus.vld = data_out_vld ;
assign pkt_bus.pkt_out_bus.sop = sop_out_vld ;
assign pkt_bus.pkt_out_bus.eop = eop_out_vld ;
assign pkt_bus.pkt_out_bus.data = data_out ;
test u_test(pkt_bus);
endmodule
`ifndef PKT_DATA_SV
`define PKT_DATA_SV
class pkt_data;
rand bit [7:0] payload_q[$];
rand int interval;
rand int pkt_len;
bit send_over;
bit [10:0] data[$];
constraint data_size_cons{
payload_q.size() == pkt_len;
};
constraint pkt_len_cons{
pkt_len inside {[1:50]};
//pkt_len == 5;
};
constraint interval_cons{
interval inside {[3:6]};
};
extern function new();
extern virtual function string psprintf(string preset = "");
extern virtual function bit compare(pkt_data to);
extern virtual function void pack();
extern virtual function void unpack();
extern virtual function pkt_data copy(pkt_data to=null);
endclass
function pkt_data::new();
endfunction
function bit pkt_data::compare(pkt_data to);
bit match = 1;
if(this.pkt_len != to.pkt_len) match = 0;
foreach(payload_q[i]) if(this.payload_q[i] != to.payload_q[i])
match = 0;
return match;
endfunction:compare
function void pkt_data::pack();
foreach (this.payload_q[i]) begin
if (i==0 & i==pkt_len-1) //modify!!!!!
this.data.push_back({1'b1, 1'b1, 1'b1, payload_q[i]});
else if (i==0)
this.data.push_back({1'b1, 1'b1, 1'b0, payload_q[i]});
else if (i==pkt_len-1)
this.data.push_back({1'b1, 1'b0, 1'b1, payload_q[i]});
else
this.data.push_back({1'b1, 1'b0, 1'b0, payload_q[i]});
end
for(int i=0; i this.data.push_front({'0});
end
endfunction
function string pkt_data::psprintf(string preset = "");
psprintf = {preset, $psprintf("pkt_len = %0d", pkt_len)};
foreach(payload_q[i])
psprintf = {psprintf, ",", $psprintf("payload[%0d] = 'h%0h", i, payload_q[i])};
endfunction
function pkt_data pkt_data::copy(pkt_data to=null);
pkt_data tmp;
if (to == null)
tmp = new();
else
$cast(tmp, to);
tmp.interval = this.interval;
tmp.pkt_len = this.pkt_len;
tmp.send_over= this.send_over;
foreach(this.payload_q[i])begin
tmp.payload_q.push_back(this.payload_q[i]);
end
return tmp;
endfunction
function void pkt_data::unpack();
this.pkt_len = payload_q.size();
endfunction
`endif
`ifndef ENV_CFG_SV
`define ENV_CFG_SV
class env_cfg;
bit chk_idle;
bit gen_idle;
bit drv_idle;
bit mon_idle;
int env_wait_pkt_time = 10000;
int mon_wait_pkt_time = 1000;
int drv_wait_pkt_time = 1000;
int chk_wait_pkt_time = 1000;
endclass:env_cfg
`endif
`include "pkt_if.sv"
`include "environment.sv"
program automatic test(pkt_if_pack bus);
environment env;
initial begin
env = new(bus);
env.build();
env.gen.send_num = 100;
env.run();
$display("At %0t, [TESt NOTE]: simulation finish~~~~~~~~~~~~~~~~~~", $time);
$finish;
end
endprogram
`ifndef ENV_SV
`define ENV_SV
`include "pkt_gen.sv"
`include "pkt_drv.sv"
`include "pkt_mon.sv"
`include "pkt_chk.sv"
`include "pkt_if.sv"
`include "env_cfg.sv"
`include "pkt_if_pack.sv"
class environment;
virtual pkt_if_pack bus;
pkt_gen gen;
pkt_drv drv;
pkt_mon in_mon;
pkt_mon out_mon;
pkt_chk chk;
env_cfg cfg;
mailbox gen2drv_chan;
mailbox in_mon2chk_chan;
mailbox out_mon2chk_chan;
int send_pkt_num;
//for finish fimu
int wait_time;
extern function new(input virtual pkt_if_pack bus);
extern virtual task build();
extern virtual task run();
extern virtual task report();
endclass
function environment::new(input virtual pkt_if_pack bus);
$display("At %0t, [ENV NOTE]: environment::new() start!", $time);
this.bus = bus;
this.cfg = new();
gen2drv_chan = new(1);
in_mon2chk_chan = new(1);
out_mon2chk_chan = new(1);
endfunction
task environment::build();
$display("At %0t, [ENV NOTE]: environment::build() start!", $time);
gen = new(cfg, gen2drv_chan);
drv = new(cfg, this.bus.pkt_in_bus, gen2drv_chan);
in_mon = new(cfg, this.bus.pkt_in_bus, this.in_mon2chk_chan);
out_mon = new(cfg, this.bus.pkt_out_bus, this.out_mon2chk_chan);
chk = new(cfg, in_mon2chk_chan, out_mon2chk_chan);
endtask
task environment::run();
fork
drv.run();
gen.run();
in_mon.run();
out_mon.run();
chk.run();
join_none
#100;
fork
//$display("At %0t, [ENV NOTE]: wait for end............", $time);
begin
wait(cfg.gen_idle);
wait(cfg.drv_idle);
wait(cfg.mon_idle);
wait(cfg.chk_idle);
$display("At %0t, [ENV NOTE]: normal finish", $time);
end
begin
while(1)begin
@(negedge top.clk);
if(this.bus.pkt_in_bus.vld) wait_time = 0;
else wait_time++;
if(wait_time > this.cfg.env_wait_pkt_time) break;
end
$display("At %0t, [ENV ERROR]: time out!!!!!", $time);
end
join_any
#1000;
report();
endtask
task environment::report();
$display("At %0t, [ENV NOTE]: report start", $time);
repeat(100) @top.clk;
chk.report();
$display("At %0t, [ENV NOTE]: report over", $time);
endtask
`endif
`ifndef PKT_GEN_SV
`define PKT_GEN_SV
`include "pkt_data.sv"
`include "env_cfg.sv"
class pkt_gen;
env_cfg cfg;
mailbox gen2drv_chan;
pkt_data pkt;
int send_num;
extern function new(env_cfg cfg, mailbox gen2drv_chan);
extern virtual task run();
endclass
function pkt_gen::new(env_cfg cfg, mailbox gen2drv_chan);
this.cfg = cfg;
this.gen2drv_chan = gen2drv_chan;
this.pkt = new();
endfunction
task pkt_gen::run();
pkt_data send_pkt;
pkt_data chk_pkt;
$display("At %0t, [GEN NOTE]: send_num = %0d", $time, send_num);
repeat(send_num) begin
assert(pkt.randomize());
$cast(send_pkt, pkt.copy());
$cast(chk_pkt, pkt.copy());
gen2drv_chan.put(send_pkt);
end
this.cfg.gen_idle = 1;
//$display("At %0t, [GEN NOTE]: gen over pkt", $time);
endtask
`endif
`ifndef PKT_DRV_SV
`define PKT_DRV_SV
`include "pkt_data.sv"
`include "pkt_if.sv"
`include "env_cfg.sv"
class pkt_drv;
env_cfg cfg;
mailbox gen2drv_chan;
vdrv dif;
//for finish simu
int idle_cnt;
int get_num;
extern function new(env_cfg cfg,
vdrv dif,
mailbox gen2drv_chan
);
extern virtual task run();
extern virtual task my_run();
extern virtual task rst_sig();
extern virtual task pkt_send(input pkt_data pkt);
extern virtual task set_idle();
endclass
function pkt_drv::new(env_cfg cfg,
vdrv dif,
mailbox gen2drv_chan
);
this.cfg = cfg;
this.dif = dif;
this.gen2drv_chan = gen2drv_chan;
this.get_num = 0;
endfunction
task pkt_drv::run();
fork
my_run();
set_idle();
join_none
endtask
task pkt_drv::my_run();
pkt_data send_pkt;
//$display("At %0t, [DRV NOTE]: pkt_drv run start!", $time);
rst_sig();
//$display("At %0t, [DRV NOTE]: after rst_n", $time);
while(1) begin
gen2drv_chan.peek(send_pkt);
//$display("At %0t, [DRV NOTE]: get no.%0d pkt from gen", $time, this.get_num++);
send_pkt.pack();
pkt_send(send_pkt);
gen2drv_chan.get(send_pkt);
rst_sig();
end
endtask:my_run
task pkt_drv::rst_sig();
wait(top.rst_n == 1'b1);
@(posedge top.clk);
this.dif.vld <= '0;
this.dif.sop <= '0;
this.dif.eop <= '0;
this.dif.data<= '0;
endtask
task pkt_drv::pkt_send(input pkt_data pkt);
foreach(pkt.data[i]) begin
@(posedge top.clk);
this.dif.vld <= pkt.data[i][10];
this.dif.sop <= pkt.data[i][9];
this.dif.eop <= pkt.data[i][8];
this.dif.data<= pkt.data[i][7:0];
end
endtask
task pkt_drv::set_idle();
while(1)begin
@(negedge top.clk);
if(this.dif.vld == 1) idle_cnt = 0;
else idle_cnt++;
if(idle_cnt > this.cfg.drv_wait_pkt_time) this.cfg.drv_idle = 1;
else this.cfg.drv_idle = 0;
end
endtask:set_idle
`endif
`ifndef PKT_MON_SV
`define PKT_MON_SV
`include "pkt_data.sv"
`include "pkt_if.sv"
`include "env_cfg.sv"
class pkt_mon;
env_cfg cfg;
vmon mif;
mailbox mon2chk_chan;
bit rec_status;//0:wait sop, 1:wait eop
int wait_pkt_time = 1000;
extern function new(env_cfg cfg,
vmon mif,
mailbox mon2chk_chan);
extern virtual task run();
extern virtual task send_chk(pkt_data pkt);
endclass
function pkt_mon::new(env_cfg cfg,
vmon mif,
mailbox mon2chk_chan
);
this.cfg = cfg;
this.mif = mif;
this.mon2chk_chan = mon2chk_chan;
this.wait_pkt_time = cfg.mon_wait_pkt_time;
this.rec_status = 0;
endfunction : new
task pkt_mon::run();
pkt_data rec_pkt;
int wait_time;
int i = 0;
//$display("At %0t, [MON NOTE]: run start!", $time);
while(1) begin
while(1) begin
@(posedge top.clk);
if(mif.vld == 1)begin
wait_time = 0;
if(rec_status == 0) begin//wait sop
rec_pkt = new();
if(mif.sop == 0) begin
$display("At %0t, [MON ERROR]: ERROR! The first pkt cycle is not sop!", $time);
break;
end
else begin
rec_pkt.payload_q.push_back(mif.data);
if(mif.eop == 1) begin
rec_status = 0;
//$display("At %0t, [MON NOTE]: get no.%0d pkt!", $time, i++);
send_chk(rec_pkt);
end
else
rec_status = 1;
end
end
else if(rec_status == 1) begin//wait eop
if(mif.sop == 1) begin
$display("At %0t, [MON ERROR]: ERROR! SOP????", $time);
break;
end
else begin
rec_pkt.payload_q.push_back(mif.data);
if(mif.eop == 1) begin
rec_status = 0;
//$display("At %0t, [MON NOTE]: get no.%0d pkt!", $time, i++);
send_chk(rec_pkt);
end
else
rec_status = 1;
end
end
end
else begin
wait_time++;
if(wait_time <= wait_pkt_time) begin
wait_time++;
end
else break;
end
end
this.cfg.mon_idle = 1;
//$display("At %0t, [MON NOTE]: mon run over!", $time);
break;
end
endtask : run
task pkt_mon::send_chk(pkt_data pkt);
pkt.unpack();
mon2chk_chan.put(pkt);
endtask : send_chk
`endif
`ifndef PKT_CHK_SV
`define PKT_CHK_SV
`include "pkt_data.sv"
`include "env_cfg.sv"
class pkt_chk;
env_cfg cfg;
pkt_data expect_q[$];
int in_expect, in_actual;
int match, not_match;
mailbox gen2chk_chan;
mailbox mon2chk_chan;
//for finish simu
int idle_cnt;
extern function new(env_cfg cfg,
mailbox gen2chk_chan,
mailbox mon2chk_chan);
extern virtual task run();
extern virtual task expect_gain();
extern virtual task actual_gain();
extern virtual task set_idle();
extern virtual function report();
endclass:pkt_chk
function pkt_chk::new(env_cfg cfg,
mailbox gen2chk_chan,
mailbox mon2chk_chan);
this.cfg = cfg;
this.gen2chk_chan = gen2chk_chan;
this.mon2chk_chan = mon2chk_chan;
endfunction:new
task pkt_chk::run();
fork
expect_gain();
actual_gain();
set_idle();
join_none
endtask:run
task pkt_chk::expect_gain();
pkt_data expect_data;
while(1) begin
gen2chk_chan.get(expect_data);
this.expect_q.push_back(expect_data);
in_expect++;
idle_cnt = 0;
//$display("At %0t, [CHK NOTE]: get a expect pkt", $time);
end
endtask:expect_gain
task pkt_chk::actual_gain();
pkt_data expect_data;
pkt_data actual_data;
while(1) begin
mon2chk_chan.get(actual_data);
in_actual++;
idle_cnt = 0;
if(this.expect_q.size == 0) $display("At %0t, [CHK ERROR]: expect_q==0???", $time);
else begin
expect_data = expect_q[0];
if(!expect_data.compare(actual_data)) begin
$display("At %0t, [CHK ERROR]: no match, \nexpect data:%s \nactual data:%s ", $time, expect_data.psprintf(), actual_data.psprintf());
expect_q.pop_front();
not_match++;
end
else begin
expect_q.pop_front();
//$display("At %0t, [CHK NOTE]: match, \nexpect data:%s \nactual data:%s ", $time, expect_data.psprintf(), actual_data.psprintf());
match++;
end
end
end
endtask:actual_gain
task pkt_chk::set_idle();
while(1)begin
@(negedge top.clk);
idle_cnt++;
if(idle_cnt > this.cfg.chk_wait_pkt_time) this.cfg.chk_idle = 1;
else this.cfg.chk_idle = 0;
end
endtask:set_idle
function pkt_chk::report();
$display("----------------------------------------------------------------------------------------------------");
$display("[CHECKER REPORT]expect pkt_num=%0d, actual pkt_num=%0d, match pkt_num=%0d, not match pkt_num=%0d", in_expect, in_actual, match, not_match);
$display("----------------------------------------------------------------------------------------------------");
endfunction:report
`endif
`ifndef PKT_IF_SV
`define PKT_IF_SV
interface pkt_if(input clk, rst_n);
logic [7:0] data;
logic sop;
logic eop;
logic vld;
clocking drv @(posedge clk);
output data;
output sop, eop, vld;
endclocking : drv
modport pkt_drv (clocking drv);
clocking mon @(posedge clk);
input data;
input sop, eop, vld;
endclocking : mon
modport pkt_mon (clocking mon);
endinterface
typedef virtual pkt_if.drv vdrv;
typedef virtual pkt_if.mon vmon;
`endif
`ifndef FLOW_PROC_V
`define FLOW_PROC_V
module flow_proc #(
parameter DATA_WIDTH = 8
)(
input clk ,
input rst_n ,
input data_in_vld ,
input sop_in_vld ,
input eop_in_vld ,
input [DATA_WIDTH-1:0] data_in ,
output reg data_out_vld ,
output reg sop_out_vld ,
output reg eop_out_vld ,
output reg [DATA_WIDTH-1:0] data_out ,
output fb_vld ,
output fb_eop ,
output fb_cnt
);
reg data_out_vld_ff1 ;
reg sop_out_vld_ff1 ;
reg eop_out_vld_ff1 ;
reg [DATA_WIDTH-1:0] data_out_ff1 ;
always @(posedge clk) begin
if(rst_n == 1'b0)begin
data_out_vld_ff1 <= 1'b0;
sop_out_vld_ff1 <= 1'b0;
eop_out_vld_ff1 <= 1'b0;
data_out_ff1 <= {DATA_WIDTH{1'b0}};
end
else begin
data_out_vld_ff1 <= data_in_vld;
sop_out_vld_ff1 <= sop_in_vld;
eop_out_vld_ff1 <= eop_in_vld;
data_out_ff1 <= data_in;
end
end
always @(posedge clk) begin
if(rst_n == 1'b0)begin
data_out_vld <= 1'b0;
sop_out_vld <= 1'b0;
eop_out_vld <= 1'b0;
data_out <= {DATA_WIDTH{1'b0}};
end
else begin
data_out_vld <= data_out_vld_ff1;
sop_out_vld <= sop_out_vld_ff1;
eop_out_vld <= eop_out_vld_ff1;
data_out <= data_out_ff1;
end
end
endmodule
`endif
`include "pkt_if.sv"
`ifndef PKT_INTERFACE_SV
`define PKT_INTERFACE_SV
interface pkt_if_pack(
input logic clk ,
input logic rst_n
);
pkt_if pkt_in_bus (clk, rst_n);
pkt_if pkt_out_bus (clk, rst_n);
endinterface : pkt_if_pack
//class pkt_interface;
// virtual pkt_if pkt_in_bus = pkt_if_pack.pkt_in_bus;
// virtual pkt_if pkt_out_bus = pkt_if_pack.pkt_out_bus;
//endclass : pkt_interface
`endif
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。