发布时间:2024-02-02 12:00
在verilog语言中有两个系统任务$readmemb,$readmemh可以用来从文件中读取数据到存储器中。这两个任务可以在仿真的任何时刻被执行使用,其使用方法如下:
1,$readmemb("<数据文件名(路径地址和文件名)>",<存储器名>);
2, $readmemb("<数据文件名>",<存储器名>,<起始地址(存储器的地址)>);
3, $readmemb("<数据文件名>",<存储器名>,<起始地址>,<结束地址>);
4,$readmemh("<数据文件名(路径地址和文件名)>",<存储器名>);
5, $readmemh("<数据文件名>",<存储器名>,<起始地址(存储器的地址)>);
5, $readmemh("<数据文件名>",<存储器名>,<起始地址>,<结束地址>);
1,存储器的空间要足够,如设定[7:0] remember[0:15];即是初始化了一个16个字长为8位的存储器;
2,文件中的数据是一次读到寄存器中的,仿真中通常使用数据文件来做信号源。并且读数据总是从文件起始地址读到结束地址结束,存储器容量要足够;
3,文件应为标准数据文件,常用*.mif, *.mem文件。
4,文件若只写文件名需要将文件放置在默认文件路径下,可以通过modelsim->file->changedirectory来更改。
写任务用$fopen和$fdisplay两个系统任务完成,其中前者用来得到文件句柄,所谓句柄就是用来打开这个文件的读写通道,
在modelsim环境下一旦用$fopen打开文件就会将文件清空。因此要读文件最好用$readmemb/$readmemh任务,写文件再用$fopen,注意最好新建个新文件来写,以免重要数据被清空。
目标为搭建上面的仿真环境,traffic_gen 负责产生碎片数据,长度随机;然后经过DUT模块,DUT数据处理位宽为512bit,将碎片拼接成完整数据,传送回来。
这里用发包软件生成一个长度为3000byte的UDP报文,然后用主机网卡发送出去,用wireshark抓取报文,网卡自动将报文切分成3个子报文。用wireshark将3个子报文按照hex dump 复制出来,保存为 *.mem文件。
module traffic_gen(
user_clk ,
user_rstn ,
trig_in ,
frag_last ,
sop ,
eop ,
data ,
valid ,
mty ,
rec_sop ,
rec_eop ,
rec_valid ,
rec_data
);
//--------------- port definition ---------------------
input user_clk ;
input user_rstn ;
input trig_in ;
output reg sop ;
output reg eop ;
output reg [511:0] data ;
output reg [5:0] mty ;
output reg valid ;
output reg frag_last ;
input rec_sop ;
input rec_eop ;
input rec_valid ;
input [511:0] rec_data ;
//----------------wire & reg --------------------------
parameter FRAG_NUM = 8'd3 ; //原始报文长度为3000,分片后切分成3个报文
parameter FRAG1_LEN = 1514 ;
parameter FRAG2_LEN = (1514 - 34) ;
parameter FRAG3_LEN = (82-34) ;
reg [7:0] frag1 [0:(FRAG1_LEN-1)] ; //第1个分片,报文长度1518
reg [7:0] frag2 [0:(FRAG2_LEN-1)] ; //第2个分片,报文长度1518 - 34 , 报文头部信息(da+sa+type+ip)无用
reg [7:0] frag3 [0:(FRAG3_LEN-1)] ; //第3个分片,报文长度82 -34 ,报文头部信息无用
integer fg ;
initial fg = $fopen("recombine_pkt.out", "w");
//fg1 = $fopen("udp_frag1.txt","r");
initial $readmemh("udp_frag1.mem",frag1);
initial $readmemh("udp_frag2.mem",frag2);
initial $readmemh("udp_frag3.mem",frag3);
//------------------main code -------------------------
task frag_init ;
begin
sop = 1'b0 ;
eop = 1'b0 ;
valid = 1'b0 ;
data = 'd0 ;
mty = 6'h3f ;
frag_last = 1'b0 ;
repeat(1)@(posedge user_clk);
end
endtask
task frag_send ;
integer i,j,k ;
begin
;//send frag1,frag2,frag3
end
endtask
always @(posedge user_clk) begin
if(rec_valid)
$fdisplay(fg,"%h",rec_data);
end
initial begin
frag_init ;
wait(user_rstn);
// #1000;
$display("frag send start>>>>");
frag_send ;
if(rec_eop)
$display("frag recombine compelete >>>>");
$stop ;
end
endmodule
1.报错 open readmem file "frag1.txt" in read mode. 文件格式不对,改为.mem格式正常。
2.*mem文件需要放在仿真目录下。