1,本模块主要用于实现master端avalon总线转16bit并行总线,slave端恢复成avalon总线,实现板间通信。
板间总线接口如下:
output emif_clk ,output reg emif_wr_rd , //0-rd 1-wroutput reg emif_addr_data, //0-data 1-addroutput reg [7:0] emif_data_tx ,input [7:0] emif_data_rx
数据位宽可以根据需要扩展32bit、64bit
如果硬件支持的话也可以数据线用inout,省掉8跟线
2,master端avalon_to_16bit_no_addr.v
module avalon_to_16bit_no_addr (input clk ,input rst ,input [7:0] M_AVALON_address ,input M_AVALON_read ,output reg [31:0] M_AVALON_readdata ,output reg M_AVALON_readdatavalid ,// output reg M_AVALON_waitrequest ,input M_AVALON_write ,input [31:0] M_AVALON_writedata ,output emif_clk ,output reg emif_wr_rd , //0-rd 1-wroutput reg emif_addr_data, //0-data 1-addroutput reg [7:0] emif_data_tx ,input [7:0] emif_data_rx
);reg M_AVALON_write_delay ;reg M_AVALON_read_delay ;reg [15:0] M_AVALON_writedata_r ; //缓存数据reg [7:0] emif_data_rx_r0;reg [8:0] cur_state;reg [8:0] next_state;reg [2:0] delay_cnt = 3'b0;localparam IDLE = 9'b0_0000_0001;//001localparam WR_REG_WR_ADDR = 9'b0_0000_0010;//002localparam WR_REG_WR_DATA1 = 9'b0_0000_0100;//004localparam WR_REG_WR_DATA2 = 9'b0_0000_1000;//008localparam RD_REG_WR_ADDR = 9'b0_0001_0000;//010localparam RD_REG_RD_DELAY1 = 9'b0_0010_0000;//020// localparam RD_REG_RD_DELAY2 = 9'b0_0100_0000;//040localparam RD_REG_RD_DATA1 = 9'b0_1000_0000;//080localparam RD_REG_RD_DATA2 = 9'b1_0000_0000;//100assign emif_clk = clk;always@(posedge clk) beginM_AVALON_write_delay <= M_AVALON_write ;M_AVALON_read_delay <= M_AVALON_read ;end//上升沿跳变下降沿接收always @ (negedge clk )beginemif_data_rx_r0 <= emif_data_rx;endalways @ (posedge clk or posedge rst)beginif (rst) cur_state <= IDLE;else cur_state <= next_state;endalways@(*)begincase(cur_state) IDLE:begin if(M_AVALON_write_delay == 1'b0 && M_AVALON_write == 1'b1) //写寄存器next_state = WR_REG_WR_ADDR; else if(M_AVALON_read_delay == 1'b0 && M_AVALON_read == 1'b1) //读寄存器next_state = RD_REG_WR_ADDR; else next_state = IDLE; end /************************写寄存器***************************/WR_REG_WR_ADDR:begin next_state = WR_REG_WR_DATA1; endWR_REG_WR_DATA1:begin next_state = WR_REG_WR_DATA2; endWR_REG_WR_DATA2:begin next_state = IDLE; end
/************************读寄存器***************************/RD_REG_WR_ADDR:begin next_state = RD_REG_RD_DELAY1; endRD_REG_RD_DELAY1:begin if(delay_cnt == 3'd4) //读等待 //回读的相位差除了对端数据处理相位,还有隔离芯片引入的相位差,因此这里是个测量值。随隔离芯片性能调整next_state = RD_REG_RD_DATA1; else next_state = RD_REG_RD_DELAY1; endRD_REG_RD_DATA1:begin next_state = RD_REG_RD_DATA2; endRD_REG_RD_DATA2:begin next_state = IDLE; end/***************************************************/default:begin next_state = IDLE; endendcaseendalways@(posedge clk) beginif(cur_state == RD_REG_RD_DELAY1)delay_cnt <= delay_cnt + 3'b1;elsedelay_cnt <= 3'd0 ;endalways@(posedge clk or posedge rst)beginif(rst) beginemif_wr_rd <= 1'b0 ; //读状态emif_addr_data <= 1'b0 ; //数据状态 emif_data_tx <= 8'b0 ;M_AVALON_writedata_r <= 16'b0 ;endelse beginM_AVALON_writedata_r <= 16'b0 ;M_AVALON_readdatavalid <= 1'b0 ;case(cur_state) IDLE:begin emif_wr_rd <= 1'b0 ; //读状态emif_addr_data <= 1'b0 ; //数据状态 emif_data_tx <= 8'b0 ;M_AVALON_writedata_r <= 16'b0 ;M_AVALON_readdata <= 32'h0 ;end /************************写寄存器***************************/WR_REG_WR_ADDR:begin emif_wr_rd <= 1'b1 ; //写emif_addr_data <= 1'b1 ; //地址emif_data_tx <= M_AVALON_address ; //发送地址M_AVALON_writedata_r <= M_AVALON_writedata[15:0]; //缓存数据endWR_REG_WR_DATA1:begin emif_wr_rd <= 1'b1 ; //写emif_addr_data <= 1'b0 ; //数据emif_data_tx <= M_AVALON_writedata_r[7:0] ; //发送第一个8bitM_AVALON_writedata_r <= M_AVALON_writedata_r ; endWR_REG_WR_DATA2:begin emif_wr_rd <= 1'b1 ; //写emif_addr_data <= 1'b0 ; //数据emif_data_tx <= M_AVALON_writedata_r[15:8]; //发送第二个8bitM_AVALON_writedata_r <= 16'b0 ; end/************************读寄存器***************************/RD_REG_WR_ADDR:begin emif_wr_rd <= 1'b1 ; //写emif_addr_data <= 1'b1 ; //地址emif_data_tx <= M_AVALON_address ; //发送地址endRD_REG_RD_DELAY1:begin //等一拍 emif_wr_rd <= 1'b0 ; //读emif_addr_data <= 1'b0 ; //数据emif_data_tx <= 8'b0 ; //发送数据M_AVALON_readdata <= 32'h0 ; //先读低8bitendRD_REG_RD_DATA1:begin emif_wr_rd <= 1'b0 ; //读emif_addr_data <= 1'b0 ; //数据emif_data_tx <= 8'b0 ; //发送数据M_AVALON_readdata <= {8'b0, emif_data_rx_r0} ; //先读低8bitendRD_REG_RD_DATA2:begin emif_wr_rd <= 1'b0 ; //读emif_addr_data <= 1'b0 ; //数据emif_data_tx <= 8'b0 ; //发送数据M_AVALON_readdata <= {emif_data_rx_r0, M_AVALON_readdata[7:0]} ; //再读高8bitM_AVALON_readdatavalid <= 1'b1 ;end/***************************************************/default:begin emif_wr_rd <= 1'b0 ; //读状态emif_addr_data <= 1'b0 ; //数据状态 emif_data_tx <= 8'b0 ;M_AVALON_writedata_r <= 16'b0 ;endendcaseendendendmodule
3,slave端恢复avalon总线并读写寄存器
module reg_control (input rst ,output emif_clk_w , //emif_clkinput emif_clk ,input emif_wr_rd , //0-rd 1-wrinput emif_addr_data, //0-data 1-addrinput [7:0] emif_data_tx ,output reg [7:0] emif_data_rx ,//软件控制的GPIOoutput reg [15:0] pod_gpio_reg60 = 16'd0 ,output reg [15:0] pod_gpio_reg61 = 16'd3 ,input [15:0] pid_gpio_reg62 ,output reg [15:0] pod_gpio_reg63 = 16'd0 );parameter FPGA_VERSION = 16'd118 ;wire emif_clk_IBUFG;//通信总线进来以后首先打两拍reg emif_wr_rd_r0, emif_wr_rd_r1; //0-rd 1-wrreg emif_addr_data_r0, emif_addr_data_r1; //0-data 1-addrreg [7:0] emif_data_tx_r0, emif_data_tx_r1;reg [7:0] cur_state;reg [7:0] next_state;localparam IDLE = 8'b0000_0001;//001localparam STATE_2ST_BYTE = 8'b0000_0010;//002localparam STATE_3ST_BYTE_WR = 8'b0000_0100;//004localparam STATE_3ST_BYTE_RD = 8'b0000_1000;//008// localparam RD_REG_RD_DATA1 = 8'b0001_0000;//010// localparam RD_REG_RD_DATA2 = 8'b0010_0000;//020reg [7:0] reg_addr;reg [15:0] wr_reg_value;reg wr_reg_flag;reg rd_reg_flag; //一个脉冲,用于读清操作wire [15:0] rd_reg_value;reg [15:0] rd_reg_value_r; //记录rd_reg_value的值,防止打高8bit的时候值变了IBUFG CLK_U0(.I (emif_clk),.O (emif_clk_IBUFG));BUFG CLK_U1(.I (emif_clk_IBUFG),.O (emif_clk_w));/**************************总线转换****************************/
//上升沿跳变下降沿接收always @ (negedge emif_clk_w )beginemif_wr_rd_r0 <= emif_wr_rd;emif_wr_rd_r1 <= emif_wr_rd_r0;emif_addr_data_r0 <= emif_addr_data;emif_addr_data_r1 <= emif_addr_data_r0;emif_data_tx_r0 <= emif_data_tx;emif_data_tx_r1 <= emif_data_tx_r0;endalways @ (posedge emif_clk_w or posedge rst)beginif (rst) cur_state <= IDLE;else cur_state <= next_state;endalways@(*)begincase(cur_state) IDLE:begin if(emif_wr_rd_r0 == 1'b1 && emif_addr_data_r0 == 1'b1) //写地址,不区分是写操作的写地址还是读操作的写地址next_state = STATE_2ST_BYTE; else next_state = IDLE; end STATE_2ST_BYTE:begin if(emif_wr_rd_r0 == 1'b1 && emif_addr_data_r0 == 1'b0) //写数据next_state = STATE_3ST_BYTE_WR; else if(emif_wr_rd_r0 == 1'b0 && emif_addr_data_r0 == 1'b0) //读数据next_state = STATE_3ST_BYTE_RD; else //其它位为非法状态next_state = IDLE; end //写寄存器STATE_3ST_BYTE_WR:begin next_state = IDLE; end//读寄存器STATE_3ST_BYTE_RD:begin next_state = IDLE; enddefault:begin next_state = IDLE; endendcaseendalways@(posedge emif_clk_w or posedge rst)beginif(rst) beginreg_addr <= 8'b0 ;wr_reg_value <= 16'b0 ;wr_reg_flag <= 1'b0 ;rd_reg_flag <= 1'b0 ;emif_data_rx <= 8'b0 ;endelse beginrd_reg_flag <= 1'b0 ;case(cur_state) IDLE:begin reg_addr <= emif_data_tx_r0 ; //发过来的第一个字节是地址wr_reg_value <= 16'b0 ;wr_reg_flag <= 1'b0 ;emif_data_rx <= 8'b0 ;end STATE_2ST_BYTE:begin //不判断是读还是写操作wr_reg_value <= {8'b0, emif_data_tx_r0} ; //缓存发过来的第二byte,发过来的第二个字节是低8bit数据emif_data_rx <= rd_reg_value[7:0] ; //发送读数据的低8bitrd_reg_value_r <= rd_reg_value ; //记录rd_reg_value的值,防止打高8bit的时候值变了end //写寄存器STATE_3ST_BYTE_WR:begin wr_reg_value <= {emif_data_tx_r0, wr_reg_value[7:0]} ; //发过来的第二个字节是低8bit数据wr_reg_flag <= 1'b1 ;end//读寄存器STATE_3ST_BYTE_RD:begin emif_data_rx <= rd_reg_value_r[15:8] ;rd_reg_flag <= 1'b1 ;enddefault:begin emif_data_rx <= 8'b0 ;endendcaseendend/************************写寄存器***************************/
//读写寄存器需要保持一致always@(posedge emif_clk_w )beginif(wr_reg_flag) begincase(reg_addr) 8'h60 : pod_gpio_reg60 <= wr_reg_value ;8'h61 : pod_gpio_reg61 <= wr_reg_value ;8'h63 : pod_gpio_reg63 <= wr_reg_value ;default:begin endendcaseendend/************************读寄存器***************************/assign rd_reg_value = (reg_addr == 8'h01) ? FPGA_VERSION : //r FPGA版本号(reg_addr == 8'h60) ? pod_gpio_reg60 :(reg_addr == 8'h61) ? pod_gpio_reg61 :(reg_addr == 8'h62) ? pid_gpio_reg62 :(reg_addr == 8'h63) ? pod_gpio_reg63 :16'b0;endmodule
4,master端0x74寄存器写0x1234波形
5,master端0x74寄存器读到0x1234波形