赞
踩
1.功能:两个fpga之间进行通讯的工具
2.区别: 8b/10b,axi_stream的数据位宽是32bit(我设置的)
64b/66b,axi_stream的数据位宽是64bit(我设置的)
为什么64b的比8b的好呢?
因为8b的浪费了20%的带宽(也就是速度慢了)
一般来说小数据量用8b就可以了,大数据量就得用64b了,具体还是要看项目的要求
另外界面就不放了,那俩保持默认,或者你想初学时想要时钟少一点就看看第三个界面的设置吧,我懒得搞了
话不多说,直接放程序(初学者,我就不放过fifo的了,这个不过fifo的程序接收数据的时候跳了一下,别直接用哦,好好研究一下吧
AURORA_TOP.V
module Aurora_TOP #( parameter DATA_LEN = 32 ,//这俩我是为了可以随时更改aurora的模式(8b或者64b的) parameter KEEP_LEN = 4 ) ( input usr_rst ,//系统复位信号 input usr_clk ,//系统时钟,这里使用是为了产生aurora需要的两个复位信号,和init_clk直接连到一起的 input i_gt_clk_p ,//gt差分时钟,125mhz的 input i_gt_clk_n , input i_init_clk ,//初始化时钟,50mhz的 output o_aurora_txp ,//看名字 output o_aurora_txn , input i_aurora_rxp ,//看名字 input i_aurora_rxn ); wire s_reset ; wire s_gt_reset ; wire s_user_clk ; wire [DATA_LEN-1:0] s_axi_tx_tdata ; wire [KEEP_LEN-1:0] s_axi_tx_tkeep ; wire s_axi_tx_tlast ; wire s_axi_tx_tvalid ; wire s_axi_tx_tready ; wire [DATA_LEN-1:0] s_axi_rx_tdata ; wire [KEEP_LEN-1:0] s_axi_rx_tkeep ; wire s_axi_rx_tlast ; wire s_axi_rx_tvalid ; wire s_channel_up ; wire s_lane_up ; wire s_hard_err ; wire s_soft_err ; wire s_frame_err ; //产生aurora需要的复位信号 AURORA_RST u_Aurora_rst( .usr_clk ( usr_clk ), .usr_rst ( usr_rst ), .o_reset ( s_reset ), .o_gt_reset ( s_gt_reset ) ); //很简单的一个axi的程序 AURORA_AXI u_Aurora_axi( .usr_clk ( s_user_clk ), .usr_rst ( usr_rst ), .i_channel_up ( s_channel_up ), .o_axi_tx_tdata ( s_axi_tx_tdata ), .o_axi_tx_tkeep ( s_axi_tx_tkeep ), .o_axi_tx_tlast ( s_axi_tx_tlast ), .o_axi_tx_tvalid ( s_axi_tx_tvalid ), .i_axi_tx_tready ( s_axi_tx_tready ), .i_axi_rx_tdata ( s_axi_rx_tdata ), .i_axi_rx_tkeep ( s_axi_rx_tkeep ), .i_axi_rx_tlast ( s_axi_rx_tlast ), .i_axi_rx_tvalid ( s_axi_rx_tvalid ) ); //初学时无关的输入都设置为0(我也是初学者,还不是很懂那些输入信号) aurora_8b10b_0 u_aurora_8b10b_0 ( .reset ( s_reset ), .gt_reset ( s_gt_reset ), .gt_refclk1_p ( i_gt_clk_p ), .gt_refclk1_n ( i_gt_clk_n ), .init_clk_in ( i_init_clk ), .drpclk_in ( i_init_clk ), //speed = 3.125,lane_width = 4 --> data_width = 32 //because 8b/10b,so data_width = 32*(10/8) = 40 //so o_user_clk = 3.125g/40 = 78.125mhz,输出的user时钟,给子模块当时时钟用的 .user_clk_out ( s_user_clk ), .channel_up ( s_channel_up ),//o .lane_up ( s_lane_up ),//o .s_axi_tx_tdata ( s_axi_tx_tdata ),//i .s_axi_tx_tkeep ( s_axi_tx_tkeep ),//i .s_axi_tx_tlast ( s_axi_tx_tlast ),//i .s_axi_tx_tvalid ( s_axi_tx_tvalid ),//i .s_axi_tx_tready ( s_axi_tx_tready ),//o .m_axi_rx_tdata ( s_axi_rx_tdata ),//o .m_axi_rx_tkeep ( s_axi_rx_tkeep ),//o .m_axi_rx_tlast ( s_axi_rx_tlast ),//o .m_axi_rx_tvalid ( s_axi_rx_tvalid ),//o .hard_err ( s_hard_err ),//o .soft_err ( s_soft_err ),//o .frame_err ( s_frame_err ),//o .rxp ( i_aurora_rxp ),//i .rxn ( i_aurora_rxn ),//i .txp ( o_aurora_txp ),//o .txn ( o_aurora_txn ),//o .sync_clk_out ( ), .gt_reset_out ( ), .gt_refclk1_out ( ), .loopback ( 3'b000), .drpaddr_in ( 'd0 ), .drpen_in ( 'd0 ), .drpdi_in ( 'd0 ), .drprdy_out ( ), .drpdo_out ( ), .drpwe_in ( 'd0 ), .power_down ( 1'b0 ), .tx_lock ( ), .tx_resetdone_out ( ), .rx_resetdone_out ( ), .link_reset_out ( ), .pll_not_locked_out ( ), .sys_reset_out ( ), .gt0_qplllock_out ( ), .gt0_qpllrefclklost_out ( ), .gt_qpllclk_quad2_out ( ), .gt_qpllrefclk_quad2_out( ) ); endmodule
AURORA_RST.V(这个是借鉴哪个博主的,忘了)
module AURORA_RST ( input usr_clk , input usr_rst , output o_reset , output o_gt_reset ); parameter GT_RESET_START = 128 ;//说了她最少得拉低128个时钟 parameter GT_RESET_END = 256 ;//另一个复位只要比上面长就行,256=128*2,就是凭心里咋舒服咋来 parameter RESET_MAX = GT_RESET_END + GT_RESET_START; reg r_reset ; reg r_gt_reset ; reg [10:0] r_start_cnt ; wire s_start ; reg [10:0] r_cnt ; assign s_start = (r_start_cnt < RESET_MAX - 1 && r_start_cnt > 'd0); always @ (posedge usr_clk or posedge usr_rst) begin if(usr_rst) begin r_start_cnt <= 'd0; end else begin if(r_start_cnt == RESET_MAX - 1) begin r_start_cnt <= r_start_cnt; end else begin r_start_cnt <= r_start_cnt + 1'b1; end end end always @ (posedge usr_clk or posedge usr_rst) begin if(usr_rst) begin r_cnt <= 'd0; end else if(s_start) begin if(r_cnt == RESET_MAX - 1) begin r_cnt <= 'd0; end else begin r_cnt <= r_cnt + 1'b1; end end else ; end always @ (posedge usr_clk or posedge usr_rst) begin if(usr_rst) begin r_gt_reset <= 1'b0; end else begin if(r_cnt == GT_RESET_START - 1) begin r_gt_reset <= 1'b1; end else if (r_cnt == GT_RESET_END - 1 || r_cnt == 0 ) begin r_gt_reset <= 1'b0; end end end assign o_gt_reset = r_gt_reset; always @ (posedge usr_clk) begin if (s_start) begin r_reset <= 1'b1; end else begin r_reset <= 1'b0; end end assign o_reset = r_reset; endmodule
AURORA_AXI.V,这个就不多介绍了,很简单的(当时学的时候主要是初始化有点烦)
module AURORA_AXI #( parameter DATA_LEN = 32 , parameter KEEP_LEN = 4 ) ( input usr_clk , input usr_rst , input i_channel_up , output [DATA_LEN-1:0] o_axi_tx_tdata , output [KEEP_LEN-1:0] o_axi_tx_tkeep , output o_axi_tx_tlast , output o_axi_tx_tvalid , input i_axi_tx_tready , input [DATA_LEN-1:0] i_axi_rx_tdata , input [KEEP_LEN-1:0] i_axi_rx_tkeep , input i_axi_rx_tlast , input i_axi_rx_tvalid ); localparam NUM = 63 ; localparam C_TXIDLE = 4'h0 ; localparam C_TXDATA = 4'h1 ; localparam C_TXEND = 4'hf ; localparam C_RXIDLE = 4'h0 ; localparam C_RXDATA = 4'h1 ; localparam C_RXEND = 4'hf ; reg [ 3:0] r_t_now ; reg [ 3:0] r_t_next ; reg [ 3:0] r_r_now ; reg [ 3:0] r_r_next ; reg [DATA_LEN-1:0] r_axi_tx_tdata ; reg [DATA_LEN-1:0] r_axi_rx_tdata ; reg [10:0] r_tx_cnt ; reg r_axi_tx_tlast ; reg r_axi_tx_tvalid ; assign o_axi_tx_tkeep = 4'hf; always @ (posedge usr_clk or posedge usr_rst) begin if(usr_rst) begin r_t_now <= C_TXIDLE; end else begin r_t_now <= r_t_next; end end always @ (*) begin r_t_next = C_TXIDLE; case (r_t_now) C_TXIDLE : begin if(i_channel_up) begin r_t_next = C_TXDATA; end else begin r_t_next = C_TXIDLE; end end C_TXDATA : begin if(o_axi_tx_tlast && o_axi_tx_tvalid && i_axi_tx_tready) begin r_t_next = C_TXEND; end else begin r_t_next = C_TXDATA; end end C_TXEND : begin r_t_next = C_TXIDLE; end default : r_t_next = C_TXIDLE; endcase end always @(posedge usr_clk or posedge usr_rst) begin if(usr_rst) begin r_axi_tx_tlast <= 1'b0; end else begin if(i_axi_tx_tready && o_axi_tx_tvalid) begin if(r_tx_cnt == 'd63) begin r_axi_tx_tlast <= 1'b1; end else begin r_axi_tx_tlast <= 1'b0; end end else ; end end assign o_axi_tx_tlast = r_axi_tx_tlast; always @(posedge usr_clk or posedge usr_rst) begin if(usr_rst) begin r_axi_tx_tvalid <= 1'b0; end else begin if(i_axi_tx_tready) begin if(r_t_next == C_TXDATA) begin r_axi_tx_tvalid <= 1'b1; end else begin r_axi_tx_tvalid <= 1'b0; end end else ; end end assign o_axi_tx_tvalid = r_axi_tx_tvalid; always @ (posedge usr_clk or posedge usr_rst) begin if(usr_rst) begin r_tx_cnt <= 'd0; end else begin if(r_t_next == C_TXDATA && i_axi_tx_tready) begin r_tx_cnt <= r_tx_cnt + 'd1; end else if(r_t_next == C_TXEND) begin r_tx_cnt <= 'd0; end end end always @ (posedge usr_clk or posedge usr_rst) begin if(usr_rst) begin r_axi_tx_tdata <= 'dz; end else begin if(r_t_next == C_TXDATA && i_axi_tx_tready) begin r_axi_tx_tdata <= r_axi_tx_tdata + 'd1; end else if(r_t_next == C_TXIDLE) begin r_axi_tx_tdata <= 'd0; end end end assign o_axi_tx_tdata = r_axi_tx_tdata; always @ (posedge usr_clk or posedge usr_rst) begin if(usr_rst) begin r_r_now <= C_RXIDLE; end else begin r_r_now <= r_r_next; end end always @ (*) begin r_r_next = C_RXIDLE; case (r_r_now) C_RXIDLE : begin if(i_axi_rx_tvalid) begin r_r_next = C_RXDATA; end else begin r_r_next = C_RXIDLE; end end C_RXDATA : begin if(i_axi_rx_tlast) begin r_r_next = C_RXEND; end else begin r_r_next = C_RXDATA; end end C_RXEND : begin r_r_next = C_RXIDLE; end default : r_r_next = C_RXIDLE; endcase end always @(posedge usr_clk or posedge usr_rst) begin if(usr_rst) begin r_axi_rx_tdata <= 'dz; end else begin if(i_axi_rx_tvalid) begin r_axi_rx_tdata <= i_axi_rx_tdata; end else begin r_axi_rx_tdata <= 'dz; end end end endmodule
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。