1,本模块主要用于实现master端avalon总线转16bit并行总线,slave端恢复成avalon总线,实现板间通信。
板间总线接口如下:
output emif_clk ,
output reg emif_wr_rd , //0-rd 1-wr
output reg emif_addr_data, //0-data 1-addr
output 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-wr
output reg emif_addr_data, //0-data 1-addr
output 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;//001
localparam WR_REG_WR_ADDR = 9'b0_0000_0010;//002
localparam WR_REG_WR_DATA1 = 9'b0_0000_0100;//004
localparam WR_REG_WR_DATA2 = 9'b0_0000_1000;//008
localparam RD_REG_WR_ADDR = 9'b0_0001_0000;//010
localparam RD_REG_RD_DELAY1 = 9'b0_0010_0000;//020
// localparam RD_REG_RD_DELAY2 = 9'b0_0100_0000;//040
localparam RD_REG_RD_DATA1 = 9'b0_1000_0000;//080
localparam RD_REG_RD_DATA2 = 9'b1_0000_0000;//100
assign emif_clk = clk;
always@(posedge clk) begin
M_AVALON_write_delay <= M_AVALON_write ;
M_AVALON_read_delay <= M_AVALON_read ;
end
//上升沿跳变下降沿接收
always @ (negedge clk )begin
emif_data_rx_r0 <= emif_data_rx;
end
always @ (posedge clk or posedge rst)begin
if (rst)
cur_state <= IDLE;
else
cur_state <= next_state;
end
always@(*)begin
case(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;
end
WR_REG_WR_DATA1:begin
next_state = WR_REG_WR_DATA2;
end
WR_REG_WR_DATA2:begin
next_state = IDLE;
end
/************************读寄存器***************************/
RD_REG_WR_ADDR:begin
next_state = RD_REG_RD_DELAY1;
end
RD_REG_RD_DELAY1:begin
if(delay_cnt == 3'd4) //读等待 //回读的相位差除了对端数据处理相位,还有隔离芯片引入的相位差,因此这里是个测量值。随隔离芯片性能调整
next_state = RD_REG_RD_DATA1;
else
next_state = RD_REG_RD_DELAY1;
end
RD_REG_RD_DATA1:begin
next_state = RD_REG_RD_DATA2;
end
RD_REG_RD_DATA2:begin
next_state = IDLE;
end
/***************************************************/
default:begin
next_state = IDLE;
end
endcase
end
always@(posedge clk) begin
if(cur_state == RD_REG_RD_DELAY1)
delay_cnt <= delay_cnt + 3'b1;
else
delay_cnt <= 3'd0 ;
end
always@(posedge clk or posedge rst)begin
if(rst) begin
emif_wr_rd <= 1'b0 ; //读状态
emif_addr_data <= 1'b0 ; //数据状态
emif_data_tx <= 8'b0 ;
M_AVALON_writedata_r <= 16'b0 ;
end
else begin
M_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]; //缓存数据
end
WR_REG_WR_DATA1:begin
emif_wr_rd <= 1'b1 ; //写
emif_addr_data <= 1'b0 ; //数据
emif_data_tx <= M_AVALON_writedata_r[7:0] ; //发送第一个8bit
M_AVALON_writedata_r <= M_AVALON_writedata_r ;
end
WR_REG_WR_DATA2:begin
emif_wr_rd <= 1'b1 ; //写
emif_addr_data <= 1'b0 ; //数据
emif_data_tx <= M_AVALON_writedata_r[15:8]; //发送第二个8bit
M_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 ; //发送地址
end
RD_REG_RD_DELAY1:begin //等一拍
emif_wr_rd <= 1'b0 ; //读
emif_addr_data <= 1'b0 ; //数据
emif_data_tx <= 8'b0 ; //发送数据
M_AVALON_readdata <= 32'h0 ; //先读低8bit
end
RD_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} ; //先读低8bit
end
RD_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]} ; //再读高8bit
M_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 ;
end
endcase
end
end
endmodule
3,slave端恢复avalon总线并读写寄存器
module reg_control (
input rst ,
output emif_clk_w , //emif_clk
input emif_clk ,
input emif_wr_rd , //0-rd 1-wr
input emif_addr_data, //0-data 1-addr
input [7:0] emif_data_tx ,
output reg [7:0] emif_data_rx ,
//软件控制的GPIO
output 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-wr
reg emif_addr_data_r0, emif_addr_data_r1; //0-data 1-addr
reg [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;//001
localparam STATE_2ST_BYTE = 8'b0000_0010;//002
localparam STATE_3ST_BYTE_WR = 8'b0000_0100;//004
localparam 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;//020
reg [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 )begin
emif_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;
end
always @ (posedge emif_clk_w or posedge rst)begin
if (rst)
cur_state <= IDLE;
else
cur_state <= next_state;
end
always@(*)begin
case(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;
end
default:begin
next_state = IDLE;
end
endcase
end
always@(posedge emif_clk_w or posedge rst)begin
if(rst) begin
reg_addr <= 8'b0 ;
wr_reg_value <= 16'b0 ;
wr_reg_flag <= 1'b0 ;
rd_reg_flag <= 1'b0 ;
emif_data_rx <= 8'b0 ;
end
else begin
rd_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] ; //发送读数据的低8bit
rd_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 ;
end
default:begin
emif_data_rx <= 8'b0 ;
end
endcase
end
end
/************************写寄存器***************************/
//读写寄存器需要保持一致
always@(posedge emif_clk_w )begin
if(wr_reg_flag) begin
case(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
end
endcase
end
end
/************************读寄存器***************************/
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波形