实验报告 · 本节笔记
课程:中级 | FPGA工程师实战精进课程(送板卡+证书) · 第一部分 进阶接口设计篇
发布自课程云笔记 · FPGA 实验证据骨架
【本节要点】
ARP RX接收端代码
ARP 顶层
【疑问/坑点】
【可复用的代码/思路】
ARP_RX接口
`timescale 1ns / 1ps
module ARP_RX(
input wire rst_n ,
input wire arp_rxc ,
input wire arp_rxv ,
input wire [7:0] arp_rxd ,
output reg [47:0] pc_mac ,
output reg [31:0] pc_ip ,
output wire arp_rx_op ,
output wire arp_rx_done
);
parameter FPGA_MAC = 48'h00_11_22_33_44_55 ;
parameter FPGA_IP = 32'hC0_A8_00_03 ;
localparam IDLE = 1 ,//空闲
PREAMBL = 2 ,//前导码 6字节 0~6
SFD = 3 ,//帧起始界定符 1字节 6~7
ETH_MAC0 = 4 ,//目的PC MAC 6字节 8~13
ETH_MAC_S = 5 ,//源FPGA MAC 6字节 14~19
ARP_START0 = 6 ,//长度|类型 2字节 20~21
ARP_START1 = 7 ,//硬件类型 2字节 22~23
ARP_START2 = 8 ,//协议类型 2字节 24~25
ARP_START3 = 9 ,//硬件地址长度6 1字节 26
ARP_START4 = 10 ,//协议地址长度6 1字节 27
OP = 11 ,//arp协议类型 2字节 28~29
ETH_MAC_S1 = 12 ,//源FPGA MAC 6字节 30~35
ETH_IP_S1 = 13 ,//源FPGA IP 4字节 36~39
ETH_MAC1 = 14 ,//目的MAC PC 6字节 40~45
ETH_IP1 = 15 ,//目的IP PC 4字节 46~49
ARP_START5 = 16 ,//18字节00占位 18字节 50~67
CRC = 17 ;//CRC32校验 4字节 68~71
reg [4:0] cur_s ;//现态
reg [4:0] nex_s ;//次态
reg [6:0] cnt_byte ;//字节计数
reg error ;//错误信号
reg [15:0] op ;
reg [47:0] eth_mac ;//目的mac
reg [31:0] eth_ip ;//目的ip
reg [47:0] eth_mac_s ;//源mac
reg [31:0] eth_ip_s ;//源ip
always @(posedge arp_rxc)
begin
if(!rst_n)
cur_s <= IDLE ;
else
cur_s <= nex_s ;
end
always @(*)
begin
case (cur_s)
IDLE :
begin
if(arp_rxv && arp_rxd == 8'h55)
nex_s = PREAMBL ;
else
nex_s = cur_s ;
end
PREAMBL :
begin
if(error)
nex_s = IDLE ;
else if(cnt_byte == 5)
nex_s = SFD ;
else
nex_s = cur_s ;
end
SFD :
begin//nex_s = ETH_MAC0 ; //只有一个字节也可以直接跳变到下个状态
if(error)
nex_s = IDLE ;
else if(cnt_byte == 6)
nex_s = ETH_MAC0 ;
else
nex_s = cur_s ;
end
ETH_MAC0 :
begin
if(error)
nex_s = IDLE ;
else if(cnt_byte == 12)//8~13
nex_s = ETH_MAC_S ;
else
nex_s = cur_s ;
end
ETH_MAC_S :
begin
if(error)
nex_s = IDLE ;
else if(cnt_byte == 18)//14~19
nex_s = ARP_START0 ;
else
nex_s = cur_s ;
end
ARP_START0 :
begin
if(error)
nex_s = IDLE ;
else if(cnt_byte == 20)//20~21
nex_s = ARP_START1 ;
else
nex_s = cur_s ;
end
ARP_START1 :
begin
if(error)
nex_s = IDLE ;
else if(cnt_byte == 22)//22~23
nex_s = ARP_START2 ;
else
nex_s = cur_s ;
end
ARP_START2 :
begin
if(error)
nex_s = IDLE ;
else if(cnt_byte == 24)//24~25
nex_s = ARP_START3 ;
else
nex_s = cur_s ;
end
ARP_START3 :
begin//nex_s = ARP_START4 ;//只有一个字节也可以直接跳变到下个状态
if(error)
nex_s = IDLE ;
else if(cnt_byte == 25)
nex_s = ARP_START4 ;
else
nex_s = cur_s ;
end
ARP_START4 :
begin//nex_s = OP ;//只有一个字节也可以直接跳变到下个状态
if(error)
nex_s = IDLE ;
else if(cnt_byte == 26)
nex_s = OP ;
else
nex_s = cur_s ;
end
OP :
begin
if(error)
nex_s = IDLE ;
else if(cnt_byte == 28)//28~29
nex_s = ETH_MAC_S1 ;
else
nex_s = cur_s ;
end
ETH_MAC_S1 :
begin
if(error)
nex_s = IDLE ;
else if(cnt_byte == 34)//30~35
nex_s = ETH_IP_S1 ;
else
nex_s = cur_s ;
end
ETH_IP_S1 :
begin
if(error)
nex_s = IDLE ;
else if(cnt_byte == 38)//36~39
nex_s = ETH_MAC1 ;
else
nex_s = cur_s ;
end
ETH_MAC1 :
begin
if(error)
nex_s = IDLE ;
else if(cnt_byte == 44)//40~45
nex_s = ETH_IP1 ;
else
nex_s = cur_s ;
end
ETH_IP1 :
begin
if(error)
nex_s = IDLE ;
else if(cnt_byte == 48)//46~49
nex_s = ARP_START5 ;
else
nex_s = cur_s ;
end
ARP_START5 :
begin
if(error)
nex_s = IDLE ;
else if(cnt_byte == 66)//50~67
nex_s = CRC ;
else
nex_s = cur_s ;
end
CRC :
begin
if(error)
nex_s = IDLE ;
else if(cnt_byte == 70)//68~71
nex_s = IDLE ;
else
nex_s = cur_s ;
end
default : nex_s = IDLE ;
endcase
end
//字节计数器
always @(posedge arp_rxc)
begin
if(!rst_n)
cnt_byte <= 0 ;
else if(cur_s == IDLE)
cnt_byte <= 0 ;
else
cnt_byte <= cnt_byte + 1 ;
end
//error
always @(posedge arp_rxc)
begin
if(!rst_n)
error <= 0 ;
else
case (cur_s)
IDLE : error <= 0 ;
PREAMBL :
begin
if(cnt_byte < 6 && arp_rxd != 8'h55)
error <= 1 ;
else
error <= 0 ;
end
SFD :begin
if(cnt_byte == 6 && arp_rxd != 8'h55)
error <= 1 ;
else
error <= 0 ;
end
ETH_MAC0 :error <= 0 ;
ETH_MAC_S :error <= 0 ;
ARP_START0 :begin
if((cnt_byte == 19 && arp_rxd != 8'h08)||(cnt_byte == 20 && arp_rxd != 8'h06))
error <= 1 ;
else
error <= 0 ;
end
ARP_START1 :begin
if((cnt_byte == 21 && arp_rxd != 8'h00)||(cnt_byte == 22 && arp_rxd != 8'h01))
error <= 1 ;
else
error <= 0 ;
end
ARP_START2 :begin
if((cnt_byte == 23 && arp_rxd != 8'h08)||(cnt_byte == 24 && arp_rxd != 8'h00))
error <= 1 ;
else
error <= 0 ;
end
ARP_START3 :begin
if(cnt_byte == 25 && arp_rxd != 8'h06)
error <= 1 ;
else
error <= 0 ;
end
ARP_START4 :begin
if(cnt_byte == 26 && arp_rxd != 8'h04)
error <= 1 ;
else
error <= 0 ;
end
OP :begin
if((cnt_byte == 27 && arp_rxd != 8'h00)||(cnt_byte == 28 && arp_rxd != 8'h01 && arp_rxd != 8'h02))
error <= 1 ;
else
error <= 0 ;
end
ETH_MAC_S1 :error <= 0;
ETH_IP_S1 :error <= 0;
ETH_MAC1 :begin
if(cnt_byte == 44 && op == 16'h0002 && eth_mac != FPGA_MAC)
error <= 1 ;
else
error <= 0 ;
end
ETH_IP1 :error <= 0 ;
ARP_START5 :begin
if(cnt_byte == 49 && eth_ip != FPGA_IP)
error <= 1 ;
else
error <= 0 ;
end
CRC :error <= 0 ;
default :error <= 0 ;
endcase
end
//op
always @(posedge arp_rxc)
begin
if(!rst_n)
op <= 0 ;
else if(cur_s == OP)
op <= {op[7:0],arp_rxd} ;
end
//eth_mac
always @(posedge arp_rxc)
begin
if(!rst_n)
eth_mac <= 0 ;
else if(cur_s == ETH_MAC0)
eth_mac <= {eth_mac[39:0],arp_rxd} ;
end
//eth_ip
always @(posedge arp_rxc)
begin
if(!rst_n)
eth_ip <= 0 ;
else if(cur_s == ETH_IP1)
eth_ip <= {eth_ip[23:0],arp_rxd} ;
end
//eth_mac_s
always @(posedge arp_rxc)
begin
if(!rst_n)
eth_mac_s <= 0 ;
else if(cur_s == ETH_MAC_S1)
eth_mac_s <= {eth_mac_s[39:0],arp_rxd} ;
end
//eth_ip_s
always @(posedge arp_rxc)
begin
if(!rst_n)
eth_ip_s <= 0 ;
else if(cur_s == ETH_IP_S1)
eth_ip_s <= {eth_ip_s[23:0],arp_rxd} ;
end
//pc_mac
always @(posedge arp_rxc)
begin
if(!rst_n)
pc_mac <= 0 ;
else if(op == 16'h0002 && CRC)
pc_mac <= eth_mac_s ;
end
//pc_ip
always @(posedge arp_rxc)
begin
if(!rst_n)
pc_ip <= 0 ;
else if(op == 16'h0002 && CRC)
pc_ip <= eth_ip_s ;
end
assign arp_rx_op = op[0] ;//01,02:1:请求包、0:应答包
assign arp_rx_done = (cur_s == CRC && cnt_byte == 70)?1:0 ;
endmodule
`timescale 1ns / 1ps
module ARP(
input wire rst_n ,//复位
//TX
input wire arp_txc ,//时钟
output wire [7:0] arp_txd ,//数据
output wire arp_txv ,//有效信号
//RX
input wire arp_rxc ,
input wire arp_rxv ,
input wire [7:0] arp_rxd ,
//控制
input wire arp_tx_en ,//arp发送使能信号
input wire arp_tx_op ,//arp发送数据包的类型:请求|应答
//目的
output wire [47:0] pc_mac ,
output wire [31:0] pc_ip ,
output wire arp_rx_op ,
output wire arp_rx_done
);
//tx
wire crc_e ;
wire crc_init ;
wire arp_tx_done ;
//CRC
wire [31:0] crc_data ;
wire [31:0] crc_next ;
ARP_TX ARP_TX_u(
.arp_txc (arp_txc ),//时钟
.rst_n (rst_n ),//复位
.arp_tx_en (arp_tx_en ),//arp发送使能信号
.arp_tx_op (arp_tx_op ),//arp发送数据包的类型:请求|应答
.des_mac (pc_mac ),//接收到请求包(源mac),发送应答包(目的mac)
.des_ip (pc_ip ),//接收到请求包
.arp_txd (arp_txd ),//数据
.arp_txv (arp_txv ),//有效信号
.arp_tx_done (arp_tx_done),//结束信号
.crc_d (crc_d ),//crc32校验数据
.crc_e (crc_e ),//开始校验的使能
.crc_init (crc_init ) //初始化信号
);
ARP_RX ARP_RX_u(
.rst_n (rst_n ),
.arp_rxc (arp_rxc ),
.arp_rxv (arp_rxv ),
.arp_rxd (arp_rxd ),
.pc_mac (pc_mac ),
.pc_ip (pc_ip ),
.arp_rx_op (arp_rx_op ),
.arp_rx_done (arp_rx_done)
);
crc32_data crc32_data_u(
.clk (arp_txc ),
.rst_n (rst_n ),
.data (arp_txd ),
.crc_en (crc_en ),
.crc_clr (crc_init),
.crc_data (crc_data),
.crc_next (crc_next)
);
endmodule【FPGA·实验证据】
【实验目标】
本节要验证什么?预期现象是什么?
【波形/截图】
用工具栏插入波形图、仿真界面或示波器照片
【仿真 log】
粘贴关键仿真输出或报错原文
【上板现象】
板卡现象、按键/数码管/接口实测结果
【结论与待改】
结论、坑点与下一步修改
评论 0