opebet体育app

IP核之初——FIFO添加以太网MAC头部。IP核之新——FIFO添加以太网MAC头部。

十一月 17th, 2018  |  opebet体育app

  本文设计思路源自明德扬至简设计法。在事先的几乎首博文被,由于设计比较简单,所有的效用还是因此verilogHDL代码编写实现的。我们设学会站于巨人的肩头上,这时候就该IP核登场了!

  本文设计思路源自明德扬至简设计法。在之前的几篇博文中,由于设计比较简单,所有的力量还是因此verilogHDL代码编写实现之。我们只要学会站在巨人的肩头上,这时候就该IP核登场了!

  说白了,IP核就是人家做好了的硬件模块,提供整体的用户接口及验证文档,更复杂的还有示例工程,你只要能够就此好之IP核,设计都完成一半了。说起来容易,从长的英文文档和网上各个非标准教程被得出所要,并灵活运用还是用下一番功夫的。

  说白了,IP核就是别人做好了之硬件模块,提供整体的用户接口和说明文档,更扑朔迷离的还有示例工程,你要能因此好这IP核,设计曾到位一半了。说起来容易,从长的英文文档和网上各个非标准教程被得出所欲,并灵活运用还是需要下一番功力之。

  我当里最要害的几接触如下:

  我认为其中最重点的几碰如下:

  1)
提供给IP核正确的钟和复位条件;

  1)
提供于IP核正确的钟表和复位条件;

  2) 明确各个重要用户接口功能;

  2) 明确各个重要用户接口功能;

  3) 掌握所用指令的操作时序;

  3) 掌握所急需指令的操作时序;

  4)
知道里面寄存器地址与功能跟布置方式、顺序;

  4)
知道里面寄存器地址和力量和配备方式、顺序;

  5)
会从官方示例工程中学会IP核正确使用方法;

  5)
会从官示例工程中学会IP核正确运用方式;

  今天来讲说一个太常用之IP核,FIFO。可以说它是FPGA能这么灵活处理数据的根基,常用来异步时钟域处理、位富有转换和需要多少缓存的场合。先来说明下,对于新家和正好接触一个IP核的丁的话,不要过分关注IP核的各国一个参数和机能,更从未必要知道里面的现实性组织和工作规律(还没有忘之前运用的ILA吧,反正自己是未懂得具体怎么规划出的)只需要控制最常用的及无限要之,把IP核用起来便非常功告成了。先从生成IP核开始吧:

  今天来讲说一个最为常用之IP核,FIFO。可以说其是FPGA能如此灵活处理数据的根底,常用来异步时钟域处理、位富有转换和用多少缓存的场地。先来说明下,对于新家及刚沾一个IP核的人吧,不要过度关注IP核的诸一个参数和功效,更无必要知道其中的现实组织及行事规律(还无忘之前以的ILA吧,反正自己是勿亮具体怎么统筹出来的)只需要控制最常用的与极其根本之,把IP核用起来就是非常功告成了。先由生成IP核开始吧:

opebet体育app 1

opebet体育app 2

  配置向导中率先页中是选取FIFO的接口模式与落实方式。这里我们就此原始的接口方式。箭头处是促成方式,如果需要异步时钟域处理选择读写独立钟模式。

  配置向导中首先页中凡是挑选FIFO的接口模式和实现方式。这里我们所以旧之接口方式。箭头处是兑现方式,如果欲异步时钟域处理选择读写独立钟模式。

opebet体育app 3

opebet体育app 4

  第二页中得特地强调的是朗诵模式之挑选。其实这里的First
Word Fall Through对应之就算是Altera FPGA中FIFO IP核读模式遭遇的Show
ahead模式嘛,换个名而已。这个读模式之性状是当宣读而能立竿见影之前,即把FIFO中第一个数据从读数据端口不断送出。在这种模式下,读而能信号倒像是“读清”信号,把上一样不好的数码清除掉,让FIFO送出下一个多少。这样做的处是吻合dout
和dout_vld相匹配的出口信号方式。

  第二页中得专门强调的是朗诵模式之挑三拣四。其实这里的First
Word Fall Through对应的就算是Altera FPGA中FIFO IP核读模式遭遇之Show
ahead模式嘛,换个名字而已。这个读模式之风味是当朗诵而能立竿见影之前,即把FIFO中第一个数据由读数据端口不断送出。在这种模式下,读而能信号倒像是“读清”信号,把上平等不良的数据清除掉,让FIFO送出下一个数额。这样做的处于是合dout
和dout_vld相配合的出口信号方式。

opebet体育app 5

opebet体育app 6

  第三页是部署有可是挑选的标志位,可以因需要巧实现有标志位和抓手特性(我是从来没有因此过)。

  第三页是部署部分只是挑选的标志位,可以依据需要巧实现部分标志位和抓手特性(我是从来没因此了)。

opebet体育app 7

opebet体育app 8

  第四页可选FIFO内缓存数据量计数器,由于自身起来选的凡异步FIFO模式,所以是处来半点个计数器分别跟读侧和写侧时钟上升沿同。注意一点:这片只计数器均代表FIFO缓存数据量,只不过在钟上有点偏差,切不可错误理解也凡摹写副了或者读来了略微个数据。

  第四页可选FIFO内缓存数据量计数器,由于自起摘的凡异步FIFO模式,所以是处来些许个计数器分别跟读侧和写侧时钟上升沿同。注意一点:这简单只计数器均代表FIFO缓存数据量,只不过在钟上稍偏差,切不可错误理解吧凡写副了或者读来了小个数据。

opebet体育app 9

opebet体育app 10

  最后总结页,把前面的参数和部署汇总下。没有问题得以点击OK了!

  最后总结页,把前面的参数与配置汇总下。没有问题得以点击OK了!

  IP核生成好了,接下去要科学用起来。我们将为太网接口数据传作为案例背景,通常来说是FPGA逻辑+MAC
IP核+外部PHY芯片的架构。若想被MAC
IP核正确接收待发送数据,需要用数据开展封包并投入MAC头部信息。

  IP核生成好了,接下要科学用起来。我们管为太网接口数据传作为案例背景,通常来说是FPGA逻辑+MAC
IP核+外部PHY芯片的架构。若想为MAC
IP核正确接收待发送数据,需要拿数据进行封包并投入MAC头部信息。

opebet体育app 11

opebet体育app 12

  也简化设计,先就考虑针对封包后数添加MAC头部的职能,也就是说此时输入的多少就凡是长符合以太网规范,且拥有数据包格式的数据。由于当数码有输出前加额外的信息,所以先使缓存输入的数目直到MAC头输出完成还将写副数据发送出,因此需要因此FIFO缓存数据。进一步分析,经过封包后底多少格式如下:

  也简化设计,先只考虑针对封包后数添加MAC头部的作用,也就是说此时输入的数额就是是长符合以太网规范,且具备数据包格式的多寡。由于在多少有输出前加额外之音,所以先要缓存输入的数量直到MAC头输出完成还用写副数据发送出,因此待因此FIFO缓存数据。进一步分析,经过封包后的数额格式如下:

opebet体育app 13

opebet体育app 14

  其中sop和eop分别是包头,包尾指示信号,data_vld是数码中指示信号。由于数量位富有此处是32号,而数的尽小单元是字节,所以每个32各项数据不必然带有4单字节有效数据,使用data_mod指示出无效字节数。为了吃该模块输出端知道何时输出了一个数据包,要拿eop信号和数据信号拼接写副FIFO中,这样输出端发出eop时上新一轮循环。如果冲写副sop信号来作为开头发送MAC头部和数目有的标志,试想当一个短包紧跟着一个添加管写上FIFO中时,输出端正在送出落得亦然长管剩下的几乎单数据,无法响应短包的sop信号指示,那么短包即受“丢弃”了。为了避免丢包现象,需要满足“读写隔离规则”,即FIFO读操作和描写操作两者不克依据同样正的情景来控制其他一样在的所作所为。进一步引出“双FIFO架构”,使用数据FIFO缓存数据,而信息FIFO保留指示信息,这样说写侧的指示信号写副信息FIFO中,数据FIFO可以根据信息FIFO读侧的信来判断读之一言一行,也就算满足了读写隔离规则。

  其中sop和eop分别是包头,包尾指示信号,data_vld是数额中指示信号。由于数量位富有此处是32号,而数的绝小单元是字节,所以每个32各项数据未自然带有4独字节有效数据,使用data_mod指示出无效字节数。为了给该模块输出端知道何时输出了一个数据包,要将eop信号与数据信号拼接写副FIFO中,这样输出端发出eop时入新一轱辘循环。如果根据写副sop信号来当开发送MAC头部和数量有的表明,试想当一个短包紧跟着一个增长包写上FIFO中时,输出端正在送出高达同长包剩下的几只数据,无法响应短包的sop信号指示,那么短包即受“丢弃”了。为了避免丢包现象,需要满足“读写隔离规则”,即FIFO读操作与描绘操作两者不可知因同样在的状态来支配另外一样着的所作所为。进一步引出“双FIFO架构”,使用数据FIFO缓存数据,而信息FIFO保留指示信息,这样说写侧的指令信号写副信息FIFO中,数据FIFO可以依据信息FIFO读侧的消息来判断读的表现,也不怕满足了读写隔离规则。

opebet体育app 15

opebet体育app 16

  于拖欠模块中,可以于写侧出现sop信号时写副信息FIFO一个指示信息,所以当信息FIFO非空即表示来一个数据包正在进入,此时发送MAC头信息,随之读取数据FIFO中缓存数据,当读侧出现eop信号则读清信息FIFO,循环往复完成了加加头部信息之行事。

  于该模块中,可以以写侧出现sop信号时写副信息FIFO一个指令信息,所以当信息FIFO非空即表示来一个数据包正在进入,此时发送MAC头信息,随之读取数据FIFO中缓存数据,当读侧出现eop信号则读清信息FIFO,循环往复完成了补加头部信息之干活。

  MAC头部信息呢14字节,而数据位宽是32各,即同潮发送四个字节,所以一定给头部也老三单半数目。因此于发送第三只头部数常常,低16号如为此数据有填充,后止的数码为要就移动。如此走操作后,数据有就是晚了同等相撞输出最后16个。如果最终这16员数据中起有效字节,那么mac_data_vld当前节奏也要中,且mac_data_eop和mac_data_mod跟着晚同猛击输出;如果任凭有效字节,则按照正规情形输出。在代码中自我动用end_normal和end_lag信号来区分上述两栽情况。需要特别注意的凡,在移动操作后数包中包含的无效字节个数也会见发生变化。为了理清思路和时序,画出中心信号时先后图:

  MAC头部信息为14字节,而数位宽是32个,即一律次于发送四个字节,所以一定给头也老三只半数码。因此当发送第三独头部数经常,低16各类而就此多少有填充,后止的数量也要是跟着走。如此走操作后,数据有即后了千篇一律冲撞输出最后16员。如果最终就16位数据被有管用字节,那么mac_data_vld当前节奏也如中,且mac_data_eop和mac_data_mod跟着晚同碰碰输出;如果任由有效字节,则随常规情形输出。在代码中自己使用end_normal和end_lag信号来区分上述两种植状态。需要特别注意的凡,在走操作后数包中包含的不算字节个数也会发生变化。为了理清思路和时序,画有中心信号时先后图:

opebet体育app 17

opebet体育app 18

opebet体育app 19

opebet体育app 20

 

 

 

 

 

 

 

 

 

 

   

   

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  有了档次求,设计思路后肯定模块接口列表:

  有矣类别需求,设计思路后显然模块接口列表:

 opebet体育app 21

 opebet体育app 22

 

 

  开始修代码了:

  开始编制代码opebet体育app了:

  1 `timescale 1ns / 1ps
  2 
  3 module add_mac_head(
  4     input clk,
  5     input rst_n,
  6     input [31:0] app_data,
  7     input app_data_vld,
  8     input app_data_sop,
  9     input app_data_eop,
 10     input [1:0] app_data_mod,//无效字节数
 11 
 12     input mac_tx_rdy,//MAC IP发送准备就绪信号
 13     output reg [31:0] mac_data,
 14     output reg mac_data_vld,
 15     output reg mac_data_sop,
 16     output reg mac_data_eop,
 17     output reg [1:0] mac_data_mod
 18     );
 19     
 20     reg [34:0] wdata;
 21     reg wrreq,rdreq;
 22     reg wdata_xx;
 23     reg wrreq_xx,rdreq_xx;
 24     reg [1:0] head_cnt;
 25     reg head_flag,head_tmp,rd_flag,rd_flag_tmp;
 26     reg [34:0] q_tmp;
 27     
 28     wire [31:0] data_shift;
 29     wire add_head_cnt,end_head_cnt;
 30     wire head_neg;
 31     wire [34:0] q;
 32     wire rdempty_xx;
 33     wire sop_in;
 34     wire [2:0] head_len;
 35     wire [111:0] mac_head;
 36     wire [47:0] des_mac,sour_mac;
 37     wire [15:0] pack_type;
 38     wire rd_neg;
 39     
 40     fifo_generator_0 fifo_data (
 41   .clk(clk),      // input wire clk
 42   .din(wdata),      // input wire [34 : 0] din
 43   .wr_en(wrreq),  // input wire wr_en
 44   .rd_en(rdreq),  // input wire rd_en
 45   .dout(q),    // output wire [34 : 0] dout
 46   .full(),    // output wire full
 47   .empty()  // output wire empty
 48 );
 49 
 50     fifo_generator_1 fifo_message (
 51   .clk(clk),      // input wire clk
 52   .din(wdata_xx),      // input wire [0 : 0] din
 53   .wr_en(wrreq_xx),  // input wire wr_en
 54   .rd_en(rdreq_xx),  // input wire rd_en
 55   .dout(),    // output wire [0 : 0] dout
 56   .full(),    // output wire full
 57   .empty(rdempty_xx)  // output wire empty
 58 );
 59     
 60     //数据fifo写数据
 61     always@(posedge clk or negedge rst_n)begin
 62         if(!rst_n)
 63             wdata <= 0;
 64         else if(app_data_vld)    
 65             wdata <= {app_data_eop,app_data_mod,app_data};
 66     end
 67     
 68     always@(posedge clk or negedge rst_n)begin
 69         if(!rst_n)
 70             wrreq <= 0;
 71         else if(app_data_vld)
 72             wrreq <= 1;
 73         else 
 74             wrreq <= 0;
 75     end
 76     
 77     always@(posedge clk or negedge rst_n)begin
 78         if(!rst_n)
 79             wdata_xx <= 0;
 80         else if(sop_in)
 81             wdata_xx <= 1;
 82         else 
 83             wdata_xx <= 0;
 84     end
 85     
 86     assign sop_in = app_data_vld && app_data_sop;
 87     
 88     //当写侧出现sop时表明有一个数据包正在写入,此时写信息FIFO任意数据告知读侧开始发送MAC头部信息
 89     always@(posedge clk or negedge rst_n)begin
 90         if(!rst_n)
 91             wrreq_xx <= 0;
 92         else if(sop_in)
 93             wrreq_xx <= 1;
 94         else 
 95             wrreq_xx <= 0;
 96     end
 97     
 98     //MAC头部有14个字节 数据位宽是32位,即一个数据4个字节,需要发送4个数据(最后一个数据只有2个字节是头部)
 99     always@(posedge clk or negedge rst_n)begin
100         if(!rst_n)
101             head_cnt <= 0;
102         else if(add_head_cnt)begin
103             if(end_head_cnt)
104                 head_cnt <= 0;
105             else 
106                 head_cnt <= head_cnt + 1'b1;
107         end
108     end
109     
110     assign add_head_cnt = head_flag && mac_tx_rdy;
111     assign end_head_cnt = add_head_cnt && head_cnt == head_len - 1 - 1;
112     assign head_len = 4;
113     
114     //发送MAC头部标志位
115     always@(posedge clk or negedge rst_n)begin
116         if(!rst_n)
117             head_flag <= 0;
118         else if(end_head_cnt)
119             head_flag <= 0;
120         else if(!rdempty_xx && !rd_flag)
121             head_flag <= 1;
122     end
123     
124     //读数据FIFO标志位
125     always@(posedge clk or negedge rst_n)begin
126         if(!rst_n)
127             rd_flag <= 0;
128         else if(end_head_cnt)
129             rd_flag <= 1;
130         else if(rd_eop)
131             rd_flag <= 0;
132     end
133     
134     assign rd_eop = rdreq && q[34];
135     
136     always@(*)begin
137         if(rd_flag && mac_tx_rdy)
138             rdreq <= 1;
139         else
140             rdreq <= 0;
141     end
142     
143     //读侧出现eop读取完整版报文,此时读清信息FIFO
144     always@(*)begin
145         if(rd_eop)
146             rdreq_xx <= 1;
147         else
148             rdreq_xx <= 0;
149     end
150     
151     //寄存头部标志位找出下降沿
152     always@(posedge clk or negedge rst_n)begin
153         if(!rst_n)
154             head_tmp <= 0;
155         else 
156             head_tmp <= head_flag;
157     end
158     
159     assign head_neg = head_flag == 0 && head_tmp == 1;
160     
161     //寄存q用于移位操作
162     always@(posedge clk or negedge rst_n)begin
163         if(!rst_n)
164             q_tmp <= 0;
165         else 
166             q_tmp <= q;
167     end
168     
169     assign data_shift = {q_tmp[15:0],q[31:16]};
170     
171     //MAC头 14字节
172     assign mac_head  = {des_mac,sour_mac,pack_type};
173     assign des_mac        = 48'hD0_17_C2_00_E5_40  ;//目的MAC PC网卡物理地址
174     assign sour_mac       = 48'h01_02_03_04_05_06  ;//源MAC地址为01_02_03_04_05_06
175     assign pack_type      = 16'h0800               ;//IP数据报
176     
177     always@(posedge clk or negedge rst_n)begin
178         if(!rst_n)
179             rd_flag_tmp <= 0;
180         else 
181             rd_flag_tmp <= rd_flag;
182     end
183     
184     assign rd_neg = rd_flag == 0 && rd_flag_tmp == 1;
185     
186     //数据输出
187     always@(posedge clk or negedge rst_n)begin
188         if(!rst_n)
189             mac_data_sop <= 0;
190         else if(add_head_cnt && head_cnt == 0)
191             mac_data_sop <= 1;
192         else 
193             mac_data_sop <= 0;
194     end
195     
196     always@(posedge clk or negedge rst_n)begin
197         if(!rst_n)
198             mac_data_eop <= 0;
199         else if(end_normal || end_lag)
200             mac_data_eop <= 1;
201         else 
202             mac_data_eop <= 0;
203     end
204     
205     assign end_normal = rd_eop && q[33:32]      > 2'd1;
206     assign end_lag    = rd_neg && q_tmp[33:32] <= 2'd1;
207     
208     always@(posedge clk or negedge rst_n)begin
209         if(!rst_n)
210             mac_data <= 0;
211         else if(add_head_cnt)//由于MAC不是32位数据的整数倍,需要对数据进行移位
212             mac_data <= mac_head[111 - head_cnt*32 -: 32];
213         else if(head_neg)
214             mac_data <= {mac_head[15:0],q[31:16]};
215         else 
216             mac_data <= data_shift;
217     end
218     
219     always@(posedge clk or negedge rst_n)begin
220         if(!rst_n)
221             mac_data_vld <= 0;
222         else if(head_flag || rd_flag || end_lag)
223             mac_data_vld <= 1;
224         else 
225             mac_data_vld <= 0;
226     end
227     
228     //输出无效字节个数 由于输出端进行了数据移位,导致无效数据个数发生变化
229     always@(posedge clk or negedge rst_n)begin
230         if(!rst_n)
231             mac_data_mod <= 0;
232         else if(end_normal)
233             mac_data_mod <= q[33:32] - 2;
234         else if(end_lag && q_tmp[33:32] == 2'd1)
235             mac_data_mod <= 1;
236         else if(end_lag && q_tmp[33:32] == 0)
237             mac_data_mod <= 2;
238         else 
239             mac_data_mod <= 0;
240     end
241     
242 endmodule
  1 `timescale 1ns / 1ps
  2 
  3 module add_mac_head(
  4     input clk,
  5     input rst_n,
  6     input [31:0] app_data,
  7     input app_data_vld,
  8     input app_data_sop,
  9     input app_data_eop,
 10     input [1:0] app_data_mod,//无效字节数
 11 
 12     input mac_tx_rdy,//MAC IP发送准备就绪信号
 13     output reg [31:0] mac_data,
 14     output reg mac_data_vld,
 15     output reg mac_data_sop,
 16     output reg mac_data_eop,
 17     output reg [1:0] mac_data_mod
 18     );
 19     
 20     reg [34:0] wdata;
 21     reg wrreq,rdreq;
 22     reg wdata_xx;
 23     reg wrreq_xx,rdreq_xx;
 24     reg [1:0] head_cnt;
 25     reg head_flag,head_tmp,rd_flag,rd_flag_tmp;
 26     reg [34:0] q_tmp;
 27     
 28     wire [31:0] data_shift;
 29     wire add_head_cnt,end_head_cnt;
 30     wire head_neg;
 31     wire [34:0] q;
 32     wire rdempty_xx;
 33     wire sop_in;
 34     wire [2:0] head_len;
 35     wire [111:0] mac_head;
 36     wire [47:0] des_mac,sour_mac;
 37     wire [15:0] pack_type;
 38     wire rd_neg;
 39     
 40     fifo_generator_0 fifo_data (
 41   .clk(clk),      // input wire clk
 42   .din(wdata),      // input wire [34 : 0] din
 43   .wr_en(wrreq),  // input wire wr_en
 44   .rd_en(rdreq),  // input wire rd_en
 45   .dout(q),    // output wire [34 : 0] dout
 46   .full(),    // output wire full
 47   .empty()  // output wire empty
 48 );
 49 
 50     fifo_generator_1 fifo_message (
 51   .clk(clk),      // input wire clk
 52   .din(wdata_xx),      // input wire [0 : 0] din
 53   .wr_en(wrreq_xx),  // input wire wr_en
 54   .rd_en(rdreq_xx),  // input wire rd_en
 55   .dout(),    // output wire [0 : 0] dout
 56   .full(),    // output wire full
 57   .empty(rdempty_xx)  // output wire empty
 58 );
 59     
 60     //数据fifo写数据
 61     always@(posedge clk or negedge rst_n)begin
 62         if(!rst_n)
 63             wdata <= 0;
 64         else if(app_data_vld)    
 65             wdata <= {app_data_eop,app_data_mod,app_data};
 66     end
 67     
 68     always@(posedge clk or negedge rst_n)begin
 69         if(!rst_n)
 70             wrreq <= 0;
 71         else if(app_data_vld)
 72             wrreq <= 1;
 73         else 
 74             wrreq <= 0;
 75     end
 76     
 77     always@(posedge clk or negedge rst_n)begin
 78         if(!rst_n)
 79             wdata_xx <= 0;
 80         else if(sop_in)
 81             wdata_xx <= 1;
 82         else 
 83             wdata_xx <= 0;
 84     end
 85     
 86     assign sop_in = app_data_vld && app_data_sop;
 87     
 88     //当写侧出现sop时表明有一个数据包正在写入,此时写信息FIFO任意数据告知读侧开始发送MAC头部信息
 89     always@(posedge clk or negedge rst_n)begin
 90         if(!rst_n)
 91             wrreq_xx <= 0;
 92         else if(sop_in)
 93             wrreq_xx <= 1;
 94         else 
 95             wrreq_xx <= 0;
 96     end
 97     
 98     //MAC头部有14个字节 数据位宽是32位,即一个数据4个字节,需要发送4个数据(最后一个数据只有2个字节是头部)
 99     always@(posedge clk or negedge rst_n)begin
100         if(!rst_n)
101             head_cnt <= 0;
102         else if(add_head_cnt)begin
103             if(end_head_cnt)
104                 head_cnt <= 0;
105             else 
106                 head_cnt <= head_cnt + 1'b1;
107         end
108     end
109     
110     assign add_head_cnt = head_flag && mac_tx_rdy;
111     assign end_head_cnt = add_head_cnt && head_cnt == head_len - 1 - 1;
112     assign head_len = 4;
113     
114     //发送MAC头部标志位
115     always@(posedge clk or negedge rst_n)begin
116         if(!rst_n)
117             head_flag <= 0;
118         else if(end_head_cnt)
119             head_flag <= 0;
120         else if(!rdempty_xx && !rd_flag)
121             head_flag <= 1;
122     end
123     
124     //读数据FIFO标志位
125     always@(posedge clk or negedge rst_n)begin
126         if(!rst_n)
127             rd_flag <= 0;
128         else if(end_head_cnt)
129             rd_flag <= 1;
130         else if(rd_eop)
131             rd_flag <= 0;
132     end
133     
134     assign rd_eop = rdreq && q[34];
135     
136     always@(*)begin
137         if(rd_flag && mac_tx_rdy)
138             rdreq <= 1;
139         else
140             rdreq <= 0;
141     end
142     
143     //读侧出现eop读取完整版报文,此时读清信息FIFO
144     always@(*)begin
145         if(rd_eop)
146             rdreq_xx <= 1;
147         else
148             rdreq_xx <= 0;
149     end
150     
151     //寄存头部标志位找出下降沿
152     always@(posedge clk or negedge rst_n)begin
153         if(!rst_n)
154             head_tmp <= 0;
155         else 
156             head_tmp <= head_flag;
157     end
158     
159     assign head_neg = head_flag == 0 && head_tmp == 1;
160     
161     //寄存q用于移位操作
162     always@(posedge clk or negedge rst_n)begin
163         if(!rst_n)
164             q_tmp <= 0;
165         else 
166             q_tmp <= q;
167     end
168     
169     assign data_shift = {q_tmp[15:0],q[31:16]};
170     
171     //MAC头 14字节
172     assign mac_head  = {des_mac,sour_mac,pack_type};
173     assign des_mac        = 48'hD0_17_C2_00_E5_40  ;//目的MAC PC网卡物理地址
174     assign sour_mac       = 48'h01_02_03_04_05_06  ;//源MAC地址为01_02_03_04_05_06
175     assign pack_type      = 16'h0800               ;//IP数据报
176     
177     always@(posedge clk or negedge rst_n)begin
178         if(!rst_n)
179             rd_flag_tmp <= 0;
180         else 
181             rd_flag_tmp <= rd_flag;
182     end
183     
184     assign rd_neg = rd_flag == 0 && rd_flag_tmp == 1;
185     
186     //数据输出
187     always@(posedge clk or negedge rst_n)begin
188         if(!rst_n)
189             mac_data_sop <= 0;
190         else if(add_head_cnt && head_cnt == 0)
191             mac_data_sop <= 1;
192         else 
193             mac_data_sop <= 0;
194     end
195     
196     always@(posedge clk or negedge rst_n)begin
197         if(!rst_n)
198             mac_data_eop <= 0;
199         else if(end_normal || end_lag)
200             mac_data_eop <= 1;
201         else 
202             mac_data_eop <= 0;
203     end
204     
205     assign end_normal = rd_eop && q[33:32]      > 2'd1;
206     assign end_lag    = rd_neg && q_tmp[33:32] <= 2'd1;
207     
208     always@(posedge clk or negedge rst_n)begin
209         if(!rst_n)
210             mac_data <= 0;
211         else if(add_head_cnt)//由于MAC不是32位数据的整数倍,需要对数据进行移位
212             mac_data <= mac_head[111 - head_cnt*32 -: 32];
213         else if(head_neg)
214             mac_data <= {mac_head[15:0],q[31:16]};
215         else 
216             mac_data <= data_shift;
217     end
218     
219     always@(posedge clk or negedge rst_n)begin
220         if(!rst_n)
221             mac_data_vld <= 0;
222         else if(head_flag || rd_flag || end_lag)
223             mac_data_vld <= 1;
224         else 
225             mac_data_vld <= 0;
226     end
227     
228     //输出无效字节个数 由于输出端进行了数据移位,导致无效数据个数发生变化
229     always@(posedge clk or negedge rst_n)begin
230         if(!rst_n)
231             mac_data_mod <= 0;
232         else if(end_normal)
233             mac_data_mod <= q[33:32] - 2;
234         else if(end_lag && q_tmp[33:32] == 2'd1)
235             mac_data_mod <= 1;
236         else if(end_lag && q_tmp[33:32] == 0)
237             mac_data_mod <= 2;
238         else 
239             mac_data_mod <= 0;
240     end
241     
242 endmodule

 编写测试激励验证功能:

 编写测试激励验证功能:

 1 `timescale 1ns / 1ps
 2 
 3 module add_mac_head_tb;
 4 
 5     
 6     reg clk,rst_n;
 7     reg [31:0] app_data;
 8     reg app_data_sop,app_data_eop,app_data_vld;
 9     reg [1:0] app_data_mod;
10     reg mac_tx_rdy;
11     
12     wire [31:0] mac_data;
13     wire mac_data_vld,mac_data_sop,mac_data_eop;
14     wire [1:0] mac_data_mod;
15 
16     add_mac_head add_mac_head(
17     .clk(clk),
18     .rst_n(rst_n),
19     .app_data(app_data),
20     .app_data_vld(app_data_vld),
21     .app_data_sop(app_data_sop),
22     .app_data_eop(app_data_eop),
23     .app_data_mod(app_data_mod),//无效字节数
24 
25     .mac_tx_rdy(mac_tx_rdy),//MAC IP发送准备就绪信号
26     .mac_data(mac_data),
27     .mac_data_vld(mac_data_vld),
28     .mac_data_sop(mac_data_sop),
29     .mac_data_eop(mac_data_eop),
30     .mac_data_mod(mac_data_mod)
31     );
32     
33     parameter CYC = 5,
34               RST_TIME = 2;
35               
36     integer i;
37               
38     initial begin
39         clk = 1;
40         forever #(CYC / 2.0) clk = ~clk;
41     end
42     
43     initial begin
44         rst_n = 1;
45         #1;
46         rst_n = 0;
47         #(CYC*RST_TIME);
48         rst_n = 1;
49     end
50     
51     initial begin
52         #1;
53         app_data = 0;
54         app_data_sop = 0;
55         app_data_eop = 0;
56         app_data_mod = 0;
57         app_data_vld = 0;
58         mac_tx_rdy = 1;
59         #(CYC*RST_TIME);
60         packet_gen(10,0);
61         packet_gen(5,0);
62         packet_gen(15,2);
63         #1000;
64         $stop;
65     end
66     
67     task packet_gen;
68         input [15:0] length;
69         input [1:0] invld_num;
70         begin
71             app_data_vld = 1;
72             app_data_sop = 1;
73             app_data = 32'h01020300;
74             for(i = 0;i < length;i = i + 1'b1)begin
75                 if(i == 1)
76                     app_data_sop = 0;
77                 else if(i == length - 1)begin
78                     app_data_mod = invld_num;
79                     app_data_eop = 1;
80                 end
81                 app_data = app_data +1'b1;
82                 #(CYC*1);
83             end
84             app_data_eop = 0;
85             app_data_vld = 0;
86             app_data_mod = 0;
87         end
88     endtask
89 
90 endmodule
 1 `timescale 1ns / 1ps
 2 
 3 module add_mac_head_tb;
 4 
 5     
 6     reg clk,rst_n;
 7     reg [31:0] app_data;
 8     reg app_data_sop,app_data_eop,app_data_vld;
 9     reg [1:0] app_data_mod;
10     reg mac_tx_rdy;
11     
12     wire [31:0] mac_data;
13     wire mac_data_vld,mac_data_sop,mac_data_eop;
14     wire [1:0] mac_data_mod;
15 
16     add_mac_head add_mac_head(
17     .clk(clk),
18     .rst_n(rst_n),
19     .app_data(app_data),
20     .app_data_vld(app_data_vld),
21     .app_data_sop(app_data_sop),
22     .app_data_eop(app_data_eop),
23     .app_data_mod(app_data_mod),//无效字节数
24 
25     .mac_tx_rdy(mac_tx_rdy),//MAC IP发送准备就绪信号
26     .mac_data(mac_data),
27     .mac_data_vld(mac_data_vld),
28     .mac_data_sop(mac_data_sop),
29     .mac_data_eop(mac_data_eop),
30     .mac_data_mod(mac_data_mod)
31     );
32     
33     parameter CYC = 5,
34               RST_TIME = 2;
35               
36     integer i;
37               
38     initial begin
39         clk = 1;
40         forever #(CYC / 2.0) clk = ~clk;
41     end
42     
43     initial begin
44         rst_n = 1;
45         #1;
46         rst_n = 0;
47         #(CYC*RST_TIME);
48         rst_n = 1;
49     end
50     
51     initial begin
52         #1;
53         app_data = 0;
54         app_data_sop = 0;
55         app_data_eop = 0;
56         app_data_mod = 0;
57         app_data_vld = 0;
58         mac_tx_rdy = 1;
59         #(CYC*RST_TIME);
60         packet_gen(10,0);
61         packet_gen(5,0);
62         packet_gen(15,2);
63         #1000;
64         $stop;
65     end
66     
67     task packet_gen;
68         input [15:0] length;
69         input [1:0] invld_num;
70         begin
71             app_data_vld = 1;
72             app_data_sop = 1;
73             app_data = 32'h01020300;
74             for(i = 0;i < length;i = i + 1'b1)begin
75                 if(i == 1)
76                     app_data_sop = 0;
77                 else if(i == length - 1)begin
78                     app_data_mod = invld_num;
79                     app_data_eop = 1;
80                 end
81                 app_data = app_data +1'b1;
82                 #(CYC*1);
83             end
84             app_data_eop = 0;
85             app_data_vld = 0;
86             app_data_mod = 0;
87         end
88     endtask
89 
90 endmodule

   连续输入三单长不同之报文,此处为设计重用,用而参数化的task对鼓舞报文进行打包。需要输入报文时单需要调用packet_gen任务即可兑现所有不同长度,不同无效字节个数的数据包。观察输出波形:

   连续输入三只长不同之报文,此处为筹重用,用而参数化的task对鼓舞报文进行打包。需要输入报文时只需要调用packet_gen任务即可实现有不同长短,不同无效字节个数的数据包。观察输出波形:

opebet体育app 23

opebet体育app 24

 mac侧输出三单包文数据如下:

 mac侧输出三独包文数据如下:

opebet体育app 25

opebet体育app 26

 

 

 

 

 

 

opebet体育app 27

opebet体育app 28

opebet体育app 29

opebet体育app 30

 

 

 

 

 

 

   可以看看mac侧数据发送正确。本博文由于关键描述FIFO应用,这里仅仅做出行为仿真,读者可灵活运用,添加于融洽之品类受到。

   可以见到mac侧数据发送正确。本博文由于主要描述FIFO应用,这里才做出行为仿真,读者可以灵活运用,添加于大团结之花色遭到。

相关文章

标签:, ,

Your Comments

近期评论

    功能


    网站地图xml地图