提要求IP核准确的机械机械钟和重置条件,  二) 分明种种首要用户接口功用

  本文设计思路源自明德扬至简设计法。在头里的几篇博文中,由于规划相比简单,全数的功效都是用verilogHDL代码编写落成的。大家要学会站在受人珍爱的人的双肩上,那时候就该IP核上台了!

  本文设计思路源自明德扬至简设计法。在事先的几篇博文中,由于设计相比简单,所有的功效都以用verilogHDL代码编写达成的。大家要学会站在贤人的双肩上,那时候就该IP核上台了!

  说白了,IP核便是人家做好了的硬件模块,提供完整的用户接口和表明文书档案,更扑朔迷离的还有示例工程,你假设能用好这么些IP核,设计已经成功五成了。谈起来轻便,从冗长的英文文书档案和互连网各样非标准教程中得出所需,并灵活运用依然需求下壹番素养的。

  说白了,IP核就是人家做好了的硬件模块,提供完整的用户接口和验证文书档案,更扑朔迷离的还有示例工程,你一旦能用好那一个IP核,设计已经到位伍分之3了。谈起来轻便,从冗长的英文文书档案和网络各种非规范教程中汲取所需,并灵活运用还是必要下1番武术的。

  作者认为个中最要害的几点如下:

  小编以为个中最根本的几点如下:

  一)
提要求IP核准确的机械钟和重新恢复设置条件;

  1)
提供给IP核正确的石英钟和重新复苏设置条件;

  二) 鲜明种种显要用户接口功效;

  二) 鲜明各种首要用户接口作用;

  三) 明白所需指令的操作时序;

  三) 通晓所需指令的操作时序;

  四)
知道里面寄存器地址及效能和安顿情势、顺序;

  4)
知道里面寄存器地址及效用和布署格局、顺序;

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

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

  前几天来讲讲二个最常用的IP核,FIFO。能够说它是FPGA能如此灵活处理数据的根基,常用来异步时钟域管理、位宽转变以及须要多少缓存的场合。先来说明下,对于初学者和刚接触3个IP核的人的话,不要过分关心IP核的每3个参数和功能,更没需求知道里面的切实可行协会和行事规律(还没忘从前运用的ILA吧,反正笔者是不精晓具体怎么统一计划出来的)只需调节最常用的和最重大的,把IP核用起来就水到渠成了。先从生成IP核发轫吧:

  明天来讲讲1个最常用的IP核,FIFO。能够说它是FPGA能这么灵活管理数据的基础,常用来异步挂钟域管理、位宽调换以及需求多少缓存的场馆。先来评释下,对于初学者和刚接触1个IP核的人的话,不要过于关切IP核的每八个参数和功力,更没要求知道里面包车型客车现实协会和行事规律(还没忘在此之前运用的ILA吧,反正小编是不知情具体怎么规划出来的)只需调整最常用的和最珍视的,把IP核用起来就马到成功了。先从生成IP核起先吧:

图片 1

图片 2

  配置向导中率先页中是选择FIFO的接口方式和贯彻情势。那里大家用原始的接口情势。箭头处是落到实处情势,要是要求异步石英钟域处理采取读写独即小时方式。

  配置向导中首先页中是选拔FIFO的接口格局和完结方式。那里大家用原始的接口方式。箭头处是兑现方式,假设供给异步时钟域管理选拔读写独即时辰情势。

图片 3

图片 4

  第3页中需求越发强调的是读形式的选用。其实那里的First
Word Fall Through对应的即是Altera FPGA中FIFO IP核读方式中的Show
ahead情势嘛,换个名字而已。那些读情势的特点是在读使能立见成效从前,即把FIFO中第1个数据从读数据端口不断送出。在那种情势下,读使能非频域信号倒像是“读清”复信号,把上1遍的多少清除掉,让FIFO送出下三个数额。那样做的处是相符dout
和dout_vld匹同盟的出口复信号形式。

  第三页中需求专门重申的是读形式的选取。其实那里的First
Word Fall Through对应的便是Altera FPGA中FIFO IP核读情势中的Show
ahead方式嘛,换个名字而已。这一个读格局的表征是在读使能使得在此以前,即把FIFO中第一个数据从读数据端口不断送出。在那种形式下,读使能时域信号倒像是“读清”功率信号,把上三遍的数目清除掉,让FIFO送出下贰个数码。这样做的处是适合dout
和dout_vld相称合的出口复信号形式。

图片 5

图片 6

  第一页是安插部分可选的标识位,可以依照供给灵活落成部分标识位和抓手天性(作者是一贯没用过)。

  第贰页是布局地分可选的标识位,能够依靠需求灵活落成部分标识位和抓手性格(笔者是一向没用过)。

图片 7

图片 8

  第四页可选FIFO内缓存数据量计数器,由于本人起头采纳的是异步FIFO格局,所以此处有多个计数器分别与读侧和写侧石英钟上涨沿同步。注意一点:那五个计数器均代表FIFO缓存数据量,只不过在石英钟上稍稍错误,切不可错误精通为是写入了依然读出了有个别个数据。

  第4页可选FIFO内缓存数据量计数器,由于作者起来采用的是异步FIFO形式,所以此处有八个计数器分别与读侧和写侧时钟上涨沿同步。注意一点:那四个计数器均表示FIFO缓存数据量,只不过在时钟上稍稍偏差,切不可错误明白为是写入了或许读出了有点个数据。

图片 9

图片 10

  最终总结页,把后面包车型大巴参数和布局汇总下。寻常能够点击OK了!

  最终计算页,把前边的参数和布置汇总下。没不常常能够点击OK了!

  IP核生成好了,接下去要科学用起来。大家把以太网接口数据传输作为案例背景,常常来讲是FPGA逻辑+MAC
IP核+外部PHY芯片的架构。若想让MAC
IP核准确接受待发送数据,供给将数据开始展览封包并投入MAC尾部音讯。

  IP核生成好了,接下去要科学用起来。大家把以太网接口数据传输作为案例背景,平日来说是FPGA逻辑+MAC
IP核+外部PHY芯片的框架结构。若想让MAC
IP核精确接受待发送数据,须求将数据开始展览封包并到场MAC底部音讯。

图片 11

图片 12

  为简化设计,先只思考对封包后数据增多MAC尾部的效率,也正是说此时输入的多少就是长度符合以太网标准,且具备数据包格式的多寡。由于在数据部分输出前加额外的信息,所以先要缓存输入的数量直到MAC头输出实现再将写入数据发送出来,因而需求用FIFO缓存数据。进一步分析,经过封包后的数码格式如下:

  为简化设计,先只思考对封包后数据加多MAC尾部的法力,约等于说此时输入的多少即是长度符合以太网标准,且有着数据包格式的多寡。由于在数额部分输出前加额外的消息,所以先要缓存输入的数据直到MAC头输出完结再将写入数据发送出来,因而需求用FIFO缓存数据。进一步分析,经过封包后的数码格式如下:

图片 13

图片 14

  当中sop和eop分别是邢台,包尾提醒时限信号,data_vld是多少有效提示非确定性信号。由于数量位宽此处是三拾1人,而数据的蝇头单元是字节,所以各样三10位数据不肯定带有多少个字节有效数据,使用data_mod提醒出无效字节数。为了让该模块输出端知道哪一天输出完多个数据包,要把eop数字信号和数据非信号拼接写入FIFO中,那样输出端发出eop时进入新1轮循环。假设遵照写入sop确定性信号来作为开端发送MAC底部和数目部分的注明,试想当3个短包紧跟着3个长包写进FIFO中时,输出摆正在送出上1长包剩下的多少个数据,不可能响应短包的sop复信号提示,那么短包即被“抛弃”了。为了幸免丢包现象,须要满足“读写隔绝规则”,即FIFO读操作和写操作两者不能够根据一方的意况来调节另1方的一坐一起。进一步引出“双FIFO框架结构”,使用数据FIFO缓存数据,而消息FIFO保留提醒音信,那样讲写侧的提示非确定性信号写入音讯FIFO中,数据FIFO能够根据消息FIFO读侧的新闻来推断读的表现,也就满意了读写隔断规则。

  在那之中sop和eop分别是桂林,包尾提醒信号,data_vld是数码有效提示非确定性信号。由于数量位宽此处是34人,而数据的纤维单元是字节,所以每个三十六个人数据不自然带有多少个字节有效数据,使用data_mod提示出无效字节数。为了让该模块输出端知道哪天输出完二个数据包,要把eop功率信号和数据确定性信号拼接写入FIFO中,那样输出端发出eop时进入新1轮循环。要是遵照写入sop时域信号来作为开首发送MAC尾部和多少部分的表明,试想当贰个短包紧跟着一个长包写进FIFO中时,输出摆正在送出上一长包剩下的多少个数据,不能够响应短包的sop功率信号提醒,那么短包即被“甩掉”了。为了防止丢包现象,需求满意“读写隔断规则”,即FIFO读操作和写操作两者不可能依据一方的情况来决定另1方的作为。进一步引出“双FIFO架构”,使用数据FIFO缓存数据,而音信FIFO保留提醒音信,那样讲写侧的指示实信号写入音信FIFO中,数据FIFO能够根据音信FIFO读侧的新闻来决断读的一言一动,也就满足了读写隔开规则。

图片 15

图片 16

  在该模块中,可以在写侧出现sop非频域信号时写入音讯FIFO2个指令消息,所以当音信FIFO非空即表示有3个数据包正在进入,此时出殡MAC头音讯,随之读取数据FIFO中缓存数据,当读侧出现eop功率信号则读清消息FIFO,循环往复落成了增添尾部音信的干活。

  在该模块中,能够在写侧出现sop功率信号时写入音讯FIFO多个指示音讯,所以当新闻FIFO非空即表示有3个数据包正在进入,此时出殡MAC头音信,随之读取数据FIFO中缓存数据,当读侧出现eop信号则读清消息FIFO,循环往复实现了增多底部音讯的行事。

  MAC尾部音信为1四字节,而数据位宽是三玖个人,即1次发送八个字节,所以一定于底部为八个半多少。因而在发送第多少个尾部数据时,低13人要用数据部分填充,前边的数目也要跟着移动。如此移位操作后,数据部分就晚了一拍输出最终15个人。固然最终那1四个人数据中有卓有成效字节,那么mac_data_vld当前节奏也要得力,且mac_data_eop和mac_data_mod跟着晚一拍输出;假如无有效字节,则依据正规状态输出。在代码中本人动用end_normal和end_lag非确定性信号来区分上述三种景况。需求尤其注意的是,在运动操作后数据包中包涵的无效字节个数也会发生变化。为了理清思绪和时序,画出中央非确定性信号时序图:

  MAC底部消息为1四字节,而数据位宽是叁九人,即3回发送多个字节,所以一定于底部为多少个1/三码。因而在出殡和埋葬第捌个底部数据时,低十三位要用数据部分填充,前边的数目也要接着移动。如此移位操作后,数据部分就晚了一拍输出最终拾伍位。假使最后那十五个人数据中有有效字节,那么mac_data_vld当前节奏也要有效,且mac_data_eop和mac_data_mod跟着晚一拍输出;假设无有效字节,则依据常规情形输出。在代码中自个儿使用end_normal和end_lag能量信号来区分上述三种状态。要求越发注意的是,在运动操作后数据包中包括的不算字节个数也会发生变化。为了理清思绪和时序,画出中央实信号时序图:

图片 17

图片 18

图片 19

图片 20

 

 

 

 

 

 

 

 

 

 

   

   

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  有了种类必要,设计思路后鲜明模块接口列表:

  有了品种要求,设计思路后显著模块接口列表:

 图片 21

 图片 22

 

 

  初叶编制代码了:

  开端编写制定代码了:

  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职责就能够兑现全数差异尺寸,不一致无效字节个数的数据包。观看输出波形:

图片 23

图片 24

 mac侧输出多少个包文数据如下:

 mac侧输出多个包文数据如下:

图片 25

图片 26

 

 

 

 

 

 

图片 27

图片 28

图片 29

图片 30

 

 

 

 

 

 

   能够看看mac侧数据发送准确。本博文由于关键描述FIFO应用,那里只做骑行为仿真,读者能够灵活运用,增加在本身的花色中。

   能够看看mac侧数据发送准确。本博文由于关键讲述FIFO应用,那里只做骑行为仿真,读者能够灵活运用,增加在自个儿的门类中。

相关文章