在仿真环境使用两个UDP实体实现全栈仿真的方法:实验设置

66 篇文章 22 订阅
28 篇文章 11 订阅

书接上篇。

这个仿真第一个实验就是要做实体A发送数据给实体B,顶层的verilog代码如下:


module tb_top ;
 
wire [31:0]my_a_ip ={8'd192,8'd168,8'd0,8'HAA} ;
wire [47:0]my_a_mac =48'HA1A2A3A4A5A6;
wire [31:0]my_a_udp_port = 'h1234 ;

wire [31:0]my_b_ip ={8'd192,8'd168,8'd0,8'HBB} ;
wire [47:0]my_b_mac =48'hB1B2B3B4B5B6;
wire [31:0]my_b_udp_port = 'h2345 ;
 
reg rst = 0 ,clk = 0 ;
always #5 clk = ~clk ;

integer i; initial begin 
$dumpfile("tb_top.vcd");
$dumpvars;
rst = 1;
@(posedge clk) ;@(posedge clk) ;
rst = 0; 
@(posedge clk) ;
for(i=0;i<( test_len + 2048 );i=i+1)@(posedge clk);
$finish ;
end 

wire [15:0] test_len = 18;  
reg [11:0]  c;always @(posedge clk) if (rst) c<=0; else c<=(c==(1000-1))?0:c+1; // system counter for debug  
reg [7:0] st  = 0 ;
reg [7:0] r;

always @(posedge clk) if (rst)st<=0; else  case (st)
0:st<=10;
10:if(s_udp_tx_busy==0)st<=20;
20:st<=30;
30:if(r==test_len)st<=40;
40:st<=10;
default st<=0; 
endcase 

reg s_udp_tx_start=0;
always @(posedge clk)  if (rst){s_udp_tx_start,r}<=0; else case (st)
20:begin  r<=0;s_udp_tx_start <=1; end 
30:begin r<=r+1; s_udp_tx_start <=0; end 
default  begin r<=0;s_udp_tx_start <=0;end  
endcase 

wire [7:0] a2b_u8 ,b2a_u8  ;
wire a2b_en,b2a_en;

 udp_top  a(
.clk (clk), 
.rst(rst) , 
.s_udp_dst_ip(my_b_ip),
.s_udp_src_port(my_a_udp_port),
.s_udp_dst_port (my_b_udp_port),
.s_udp_tx_valid (),
.s_udp_tx_busy(s_udp_tx_busy),
.s_udp_tx_len(test_len),
.s_udp_tx_dat(r),
.s_udp_ip_id('hb3fe),
.s_udp_tx_start(s_udp_tx_start),
  
.phy_tx_dout(a2b_u8) ,
.phy_tx_err(),
.phy_tx_en(a2b_en),
.phy_rx_din(b2a_u8),
.phy_rx_dv(b2a_en),

.cfg_my_ip(my_a_ip),
.cfg_my_mac(my_a_mac)

);
  
   
 udp_top  b(
.clk (clk), 
.rst(rst) , 

.s_udp_dst_ip(my_b_ip),
.s_udp_src_port(my_b_udp_port),
.s_udp_dst_port (my_a_udp_port),
.s_udp_tx_valid (1'b1), //?
.s_udp_tx_busy(),
.s_udp_tx_len(),
.s_udp_tx_dat(),
.s_udp_ip_id('hb3fe),
.s_udp_tx_start(1'b0),
 
.phy_tx_dout(b2a_u8) ,
.phy_tx_err(),
.phy_tx_en(b2a_en),
.phy_rx_din(a2b_u8),
.phy_rx_dv(a2b_en),

.cfg_my_ip(my_b_ip),
.cfg_my_mac(my_b_mac)

);
  
  


endmodule 

这里首先规定了实体A和B的IP地址以及MAC地址,还有各自端口号。

wire [31:0]my_a_ip ={8'd192,8'd168,8'd0,8'HAA} ;
wire [47:0]my_a_mac =48'HA1A2A3A4A5A6;
wire [31:0]my_a_udp_port = 'h1234 ;

wire [31:0]my_b_ip ={8'd192,8'd168,8'd0,8'HBB} ;
wire [47:0]my_b_mac =48'hB1B2B3B4B5B6;
wire [31:0]my_b_udp_port = 'h2345 ;

为了能在波形界面直接看出来的这些数据我们用了区别度很高的数值。

比如下图以太网总线上出现的A1,A2....A6序列我们就一眼看出是实体的A的mac地址。

 在PHY总线上,A和B的接收和发送交叉起来

时钟和复位部分比较简洁:

reg rst = 0 ,clk = 0 ;
always #5 clk = ~clk ;


wire [15:0] test_len = 18;
integer i; initial begin 
$dumpfile("tb_top.vcd");
$dumpvars;
rst = 1;
@(posedge clk) ;@(posedge clk) ;
rst = 0; 
@(posedge clk) ;
for(i=0;i<( test_len + 2048 );i=i+1)@(posedge clk);
$finish ;
end 

跑上2000多个周期也就够了,之后停止仿真。

测试激励部分,我们发送UDP的内容是0,1,2,... TEST_LEN-1 这些字节内容。只要在实体A段试图一直发送(只要实体的UDP端口不是BUSY就一直生成报文控制start给实体A做激励)。

reg [7:0] st  = 0 ;
reg [7:0] r;

always @(posedge clk) if (rst)st<=0; else  case (st)
0:st<=10;
10:if(s_udp_tx_busy==0)st<=20;
20:st<=30;
30:if(r==test_len)st<=40;
40:st<=10;
default st<=0; 
endcase 

reg s_udp_tx_start=0;
always @(posedge clk)  if (rst){s_udp_tx_start,r}<=0; else case (st)
20:begin  r<=0;s_udp_tx_start <=1; end 
30:begin r<=r+1; s_udp_tx_start <=0; end 
default  begin r<=0;s_udp_tx_start <=0;end  
endcase 

另外我还做了一个全局的计数器,每周期不断累计,显示范围是0-999,到达999后从新归零继续累加。这个主要是为了出现在仿真波形上,别的波形好用对照数周期数。比如下图:

我们数tx_data数据总线出现的0的个数,直接278-271=7 就OK 。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值