西安网站建设公司找哪家docker做网站
- 作者: 五速梦信息网
- 时间: 2026年03月21日 07:12
当前位置: 首页 > news >正文
西安网站建设公司找哪家,docker做网站,自考网站建设与管理,交流平台网站怎么做从零开始 verilog 以太网交换机#xff08;三#xff09;MAC发送控制器的设计与实现 #x1f508;声明#xff1a; #x1f603;博主主页#xff1a;王_嘻嘻的CSDN主页 #x1f9e8; 从零开始 verilog 以太网交换机系列专栏#xff1a;点击这里 #x1f511;未经作者允…从零开始 verilog 以太网交换机三MAC发送控制器的设计与实现 声明 博主主页王_嘻嘻的CSDN主页 从零开始 verilog 以太网交换机系列专栏点击这里 未经作者允许禁止转载侵权必删 关注本专题的朋友们可以收获一个经典交换机设计的全流程包括设计与验证FPGA以太网MAC的基础知识。新手朋友们还将获得一个具有竞争力的项目经历后续整个工程和代码下载链接也都会放在csdn和公众号内 本章将继续进行MAC发送端控制器的设计与实现交换机完整的架构可以参考从零开始 verilog 以太网交换机一架构分析。 1、MAC发送控制器功能 MAC发送控制器的功能和接收控制器对称负责以太网的MAC - PHY的数据交换将数据帧转换为MII接口形式的数据流并根据长度进行补零计算CRC校验等。 其功能包括以下5点 根据以太网规范先发送前导码再发送帧起始符关于前导符和帧起始符的基础知识在第二章中有介绍MAC接收控制器的设计与实现之后将Payload有效荷载从数据缓冲区读出并发送若数据过短需要填充数据‘0’使MAC帧长度符合要求将同步计算的CRC-32校验值发送当MAC全部发送结束后需要按照以太网规范插入帧间等待时间本工程中为24个cycle时钟周期 2、MAC发送控制器接口 与接收控制器正好相反MAC发送控制器一端连接数据缓冲区和状态缓冲区另一端连接标准MII接口具体接口如下。 需要注意的是系统时钟clk和MII发送端时钟tx_clk不同tx_dv和tx_d需要在tx_clk下控制。 3、MAC发送控制器实现细节 发送控制器需要根据数据帧生成CRC-32校验值通常CRC的多项式公式可以直接通过生成器来生成。CRC生成器将放在本号的资源栏中有需要的可以下载或者关注博主的公众号也有下载链接 AFIFO的格式和结构都与接受控制器的相同不了解的同学可以回看上一章内容从零开始 verilog 以太网交换机一架构分析。 3.1、功能细节分析 检查state_fifo是否为空若非空则从state_fifo中取出一个数据得到需要发送的MAC帧长度信息发送前导码’0101’本工程内重复6次和帧起始符4‘b1011;将data_fifo数据取出发送到MII接口并同步进行CRC-32的计算当长度过小时进行填充处理Payload发送完毕后将CRC-32的计算值一并发送MAC发送结束后等待帧间隔时间后继续发送下一帧 3.3、MAC发送器核心电路设计 由于MAC发送控制器需要制造前导码在帧尾填充数据将交换机内部的8-bits数据转换成MII接口的4-bits数据且系统时钟sys_clk和MII时钟tx_clk异步所以在该模块中设置了一级用AFIFO实现的中间队列既便于控制数据通路又能处理异步时钟域。 所以发送控制器的总体架构如下 前级队列控制状态机负责接收交换机处理完的数据帧并写入对应的中间队列internal_data_fifo和internal_state_fifo在设计中前级状态机分为5个状态R_IDLE、R_PRE、R_SEND、R_PAD和R_CRC后四个状态分别负责向internal_data fifo存储前导码、Payload、填充‘0’和CRC校验值。 根据每个状态需要的字节数cnt_r控制状态的跳转每当前级state fifo非空时发起一次接收数据帧的处理把封装好的完整帧存储在internal data fifo中并在最后一拍更新internal state fifo内容。 而当internal data fifo不足以存放一个最大帧时此最大帧需要包括前导码和CRC校验的字节数前级队列状态机会反压输入停止接收任何数据。 后级队列控制器负责将接收到的完整数据帧连续不断的发送到MII接口同样也是通过状态机的形式控制internal fifo的输出逻辑。 后级队列控制相对容易当internal state fifo非空时取出实际长度数据并按长度读取data fifo每拍发送一个4-bits data到MII接口发送完一个完整帧后停止一段时间后继续开始检测下一数据帧是否准备完成。 3.4、MAC发送器代码 控制器的设计并不复杂Verilog代码将放在下面Testbench就不展示了有需要的可以等专题结束后在资源中下载或者去我的公众号获得链接。 module mac_t( //system interface input clk, input rst_n, //MII interface input tx_clk, output reg tx_dv, output [3:0] tx_d, //mac-r - interface mux output reg data_fifo_rd, input [7:0] data_fifo_dout, output reg state_fifo_rd, input [15:0] state_fifo_dout, input state_fifo_empty);parameter BCNT_MAX 1518; parameter BCNT_MIN 64; parameter PRE_CNT 7; //前导码数量 parameter CRC_CNT 4; //4 byte crc code parameter FRAME_WAIT_CNT 24; //前级接收数据帧的状态机 localparam R_IDLE 5b00001; localparam R_PRE 5b00010; localparam R_SEND 5b00100; localparam R_PAD 5b01000; localparam R_CRC 5b10000;//缓存向MII发送数据帧的状态机 localparam T_IDLE 3b001; localparam T_SEND 3b010; localparam T_WAIT 3b100;reg [4:0] cur_sta_r; reg [4:0] next_sta_r;reg [10:0] cnt_r; //内部计数器 记录还有多少byte需要发送 最大2k//internal data fifo变量 reg [7:0] in_data_fifo_din; reg in_data_fifo_wr; reg in_data_fifo_rd; wire [7:0] in_data_fifo_dout; wire [11:0] in_data_fifo_wr_cnt;//internal state fifo变量 reg [15:0] in_state_fifo_din; reg in_state_fifo_wr; wire in_state_fifo_rd; wire [15:0] in_state_fifo_dout; wire in_state_fifo_full; wire in_state_fifo_empty;wire bp; //反压信号当internal fifo空间不够一个最大帧时反压上级拒绝接收一切数据//crc 变量 reg crc_init; wire crc_cal; wire crc_vld; wire [7:0] crc_dout; wire [7:0] crc_din;assign bp (in_data_fifo_wr_cnt[11:0] 4096-BCNT_MAX-PRE_CNT-1) | in_state_fifo_full;assign crc_din[7:0] in_data_fifo_din[7:0];//后级状态机变量 reg [2:0] cur_sta_t; reg [2:0] next_sta_t;reg [11:0] cnt_t; //以半字节为单位 reg in_state_fifo_empty_dly;//前级状态机 always (posedge clk or negedge rst_n)beginif(!rst_n)cur_sta_r[4:0] R_IDLE;elsecur_sta_r[4:0] next_sta_r[4:0]; endalways ()begincase(cur_sta_r[4:0])R_IDLE: next_sta_r4:0 ? R_PRE : R_IDLE; //IDLE态时 只有internal fifo空间足够 且 前级已有处理完的数据帧才能进入下一状态R_PRE: next_sta_r4:0 ? R_SEND : R_PRE; //发送完所有前导码和起始符后 进入下一状态R_SEND: next_sta_r4:0 ? ( state_fifo_dout[10:0] BCNT_MIN-CRC_CNT ) ? R_PAD : R_CRC : R_SEND; //发送完所有数据帧 进入下一状态 cnt每一状态都会更新R_PAD: next_sta_r4:0 ? R_CRC : R_PAD; //完成所有填充 进入下一状态R_CRC: next_sta_r4:0 ? R_IDLE: R_CRC; //CRC校验需要4 cycle 结束后将校验值填入 返回IDLE态default: next_sta_r[4:0] R_IDLE; endcase end//cnt采样 always (posedge clk or negedge rst_n)beginif(!rst_n)cnt_r[10:0] 11b0;else begincase(cur_sta_r[4:0])R_IDLE: cnt_r[10:0] PRE_CNT ;R_PRE: cnt_r[10:0] cnt_r[10:0] 11b1 ? cnt_r[10:0] - 11b1 : state_fifo_dout[10:0];R_SEND: cnt_r[10:0] cnt_r[10:0] 11b1 ? cnt_r[10:0] - 11b1 : (state_fifo_dout10:0) ? BCNT_MIN-CRC_CNT-state_fifo_dout[10:0] : CRC_CNT;R_PAD: cnt_r[10:0] cnt_r[10:0] 11b1 ? cnt_r[10:0] - 11b1 : CRC_CNT;R_CRC: cnt_r[10:0] cnt_r[10:0] - 11b1;default: cnt_r[10:0] 11b0;endcaseend end//crc var 控制 always (posedge clk or negedge rst_n)beginif(!rst_n)crc_init 1b0;else if(cur_sta_r[4:0]R_IDLE next_sta_r[4:0]R_PRE)crc_init 1b1;elsecrc_init 1b0; endassign crc_cal cur_sta_r[4:0]R_SEND | cur_sta_r[4:0]R_PAD; assign crc_vld cur_sta_r[4:0]R_SEND | cur_sta_r[4:0]R_PAD | cur_sta_r[4:0]R_CRC;// //out data fifo控制 always (posedge clk or negedge rst_n)beginif(!rst_n)data_fifo_rd 1b0;else if(cur_sta_r[4:0]R_PRE cnt_r[10:0]11b1)data_fifo_rd 1b1;else if(cur_sta_r[4:0]R_SEND cnt_r[10:0]11b1)data_fifo_rd 1b0; end//out state fifo控制 always (posedge clk or negedge rst_n)beginif(!rst_n)state_fifo_rd 1b0;else if(cur_sta_r[4:0]R_CRC cnt_r[10:0]11b1)state_fifo_rd 1b1;elsestate_fifo_rd 1b0; end//internal data fifo控制 always (posedge clk or negedge rst_n)beginif(!rst_n)in_data_fifo_wr 1b0;else if(cur_sta_r[4:0]R_IDLE)in_data_fifo_wr 1b0;else if(next_sta_r[4:0]R_PRE)in_data_fifo_wr 1b1; endalways (posedge clk or negedge rst_n)begin //TODOif(!rst_n)in_data_fifo_din[7:0] 8h0;else if(cur_sta_r[4:0]R_IDLE)in_data_fifo_din[7:0] 8h55;else if(cur_sta_r[4:0]R_PRE cnt_r[10:0]11d1)in_data_fifo_din[7:0] 8hd5;else if(cur_sta_r[4:0]R_SEND)in_data_fifo_din[7:0] data_fifo_dout[7:0];else if(cur_sta_r[4:0]R_PAD)in_data_fifo_din[7:0] 8h0;else if(cur_sta_r[4:0]R_CRC)in_data_fifo_din[7:0] crc_dout[7:0]; end//internal state fifo控制 always (posedge clk or negedge rst_n)beginif(!rst_n)in_state_fifo_wr 1b0;else if(cur_sta_r[4:0]R_CRC cnt_r[10:0]11b1)in_state_fifo_wr 1b1;elsein_state_fifo_wr 1b0; endalways (posedge clk or negedge rst_n)beginif(!rst_n)in_state_fifo_din[15:0] 16b0;else if(cur_sta_r[4:0]R_CRC cnt_r[10:0]11b1)in_state_fifo_din[15:0] state_fifo_dout[15:0];elsein_state_fifo_din[15:0] 16b0; end////后级状态机 always (posedge tx_clk or negedge rst_n)beginif(!rst_n)cur_sta_t[2:0] T_IDLE;elsecur_sta_t[2:0] next_sta_t[2:0]; endalways (posedge tx_clk or negedge rst_n)begin //打一拍 为了in state fifo read over, fsm enter next stateif(!rst_n)in_state_fifo_empty_dly 1b1;elsein_state_fifo_empty_dly in_state_fifo_empty; endalways ()begincase(cur_sta_t[2:0])T_IDLE: next_sta_t[2:0] !in_state_fifo_empty_dly ? T_SEND : T_IDLE;T_SEND: next_sta_t[2:0] cnt_t[11:0]12b1 ? T_WAIT : T_SEND;T_WAIT: next_sta_t[2:0] cnt_t[11:0]12b1 ? T_IDLE : T_WAIT;default:next_sta_t[2:0] T_IDLE;endcase end//发送状态时 cnt采样 always (posedge tx_clk or negedge rst_n)beginif(!rst_n)cnt_t[11:0] 12b0;else begincase(cur_sta_t[2:0])T_IDLE: cnt_t[11:0] !in_state_fifo_empty_dly ? (in_state_fifo_dout[10:0]PRE_CNTCRC_CNT)1b1 : 12b0;T_SEND: cnt_t[11:0] cnt_t[11:0]12b1 ? FRAME_WAIT_CNT : cnt_t[11:0] - 12b1;T_WAIT: cnt_t[11:0] cnt_t[11:0] - 12b1;default: cnt_t[11:0] 12b0;endcaseend end//internal state fifo 控制assign in_state_fifo_rd cur_sta_t[2:0]T_IDLE !in_state_fifo_empty;//internal data fifo 控制 always (posedge tx_clk or negedge rst_n)begin //fifo dout需要提前读取后dout上才有数据并不是数据先在总线上if(!rst_n)in_data_fifo_rd 1b0;else if( (cur_sta_t[2:0]T_IDLE !in_state_fifo_empty) | (cur_sta_t[2:0]T_SEND cnt_t[0]) )in_data_fifo_rd 1b1;elsein_data_fifo_rd 1b0; end//MII接口控制 always (posedge tx_clk or negedge rst_n)beginif(!rst_n)tx_dv 1b0;else if(cur_sta_t[2:0]T_SEND)tx_dv 1b1;elsetx_dv 1b0; endassign tx_d[3:0] cnt_t[0] ? in_data_fifo_dout[3:0] : in_data_fifo_dout[7:4];data_fifo x_internal_data_fifo(.rst(~rst_n),.wr_clk(clk),.rd_clk(tx_clk),.din(in_data_fifo_din[7:0]),.wr_en(in_data_fifo_wr),.rd_en(in_data_fifo_rd),.dout(in_data_fifo_dout[7:0]),.full(),.empty(),.rd_data_count(),.wr_data_count(in_data_fifo_wr_cnt[11:0]));state_fifo x_internal_state_fifo(.rst(~rst_n),.wr_clk(clk),.rd_clk(tx_clk),.din(in_state_fifo_din[15:0]),.wr_en(in_state_fifo_wr),.rd_en(in_state_fifo_rd),.dout(in_state_fifo_dout[15:0]),.full(in_state_fifo_full),.empty(in_state_fifo_empty)); crc32 x_crc32(.clk(clk),.rst_n(rst_n),.data(crc_din[7:0]),.init(crc_init),.cal(crc_cal),.vld(crc_vld),.crc_reg(),.crc(crc_dout[7:0])); endmodule搜索关注我的微信公众号【IC墨鱼仔】获取我的更多IC干货分享
- 上一篇: 西安网站建设公司排名免费网站后台模板
- 下一篇: 西安网站建设价格猎奇网站源码
相关文章
-
西安网站建设公司排名免费网站后台模板
西安网站建设公司排名免费网站后台模板
- 技术栈
- 2026年03月21日
-
西安网站建设公司 云阔厦门哪家做网站好
西安网站建设公司 云阔厦门哪家做网站好
- 技术栈
- 2026年03月21日
-
西安网站建设服务商十强新手建立企业网站流程
西安网站建设服务商十强新手建立企业网站流程
- 技术栈
- 2026年03月21日
-
西安网站建设价格猎奇网站源码
西安网站建设价格猎奇网站源码
- 技术栈
- 2026年03月21日
-
西安网站建设开发查派多媒体制作公司
西安网站建设开发查派多媒体制作公司
- 技术栈
- 2026年03月21日
-
西安网站建设哪家动漫设计专业好不好
西安网站建设哪家动漫设计专业好不好
- 技术栈
- 2026年03月21日
