板间通讯avalon总线转16bit并行总线用于通用寄存器读写

news/2024/12/15 17:21:27/

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波形
在这里插入图片描述


http://www.ppmy.cn/news/1555353.html

相关文章

聊聊Oracle自适应查询优化

成也AQO败也AQO 因为工作的原因&#xff0c;我们接触到的客户大部分是金融和运营商行业&#xff0c;这些客户有个最大的特点是追求稳定&#xff0c;对于使用数据库新特性持保守的态度&#xff0c;不会轻易尝试某些可能会导致生产系统不稳定的新特性。上线前通常都会将一些新特…

Python爬虫获取商品销量详情

在这个数据驱动的时代&#xff0c;获取商品销量详情已经不再是简单的点击和浏览。我们需要的是速度、效率&#xff0c;还有一点点的...偷偷摸摸。没错&#xff0c;今天我们要聊的是如何使用Python爬虫来“偷窥”商品销量详情。别担心&#xff0c;我们保证一切都是合法合规的&am…

C++ 中多态性在实际项目中的应用场景有哪些?C++ 中面向对象编程如何实现数据隐藏?

1&#xff09;C 中多态性在实际项目中的应用场景有哪些&#xff1f; 在 C中&#xff0c;多态性主要通过虚函数来实现&#xff0c;它允许以统一的方式处理不同类型的对象&#xff0c;在实际项目中有很多重要的应用场景。 一、面向对象设计 1. 封装不同实现细节 在图形绘制系统中…

NDRCContextUnmarshall断点函数分析之I_RpcBindingCopy函数的作用

NDRCContextUnmarshall断点函数分析之I_RpcBindingCopy函数的作用 第一部分&#xff1a; void RPC_ENTRY NDRCContextUnmarshall ( // process returned context OUT NDR_CCONTEXT PAPI *phCContext,// stub context to update IN RPC_BINDING_HANDLE hRPC, …

STM32 ADC 配置

ADC&#xff08;模数转换器&#xff09;用于将模拟信号转换为数字信号&#xff0c;以便单片机处理。 模数转换器&#xff08;Analog-to-Digital Converter, ADC&#xff09;是电子系统中不可或缺的一部分&#xff0c;它负责将现实世界中的连续物理量&#xff0c;如温度、声音、…

Python鼠标轨迹算法(游戏防检测)

一.简介 鼠标轨迹算法是一种模拟人类鼠标操作的程序&#xff0c;它能够模拟出自然而真实的鼠标移动路径。 鼠标轨迹算法的底层实现采用C/C语言&#xff0c;原因在于C/C提供了高性能的执行能力和直接访问操作系统底层资源的能力。 鼠标轨迹算法具有以下优势&#xff1a; 模拟…

meta llama 大模型一个基础语言模型的集合

LLaMA 是一个基础语言模型的集合&#xff0c;参数范围从 7B 到 65B。我们在数万亿个 Token 上训练我们的模型&#xff0c;并表明可以专门使用公开可用的数据集来训练最先进的模型&#xff0c;而无需诉诸专有的和无法访问的数据集。特别是&#xff0c;LLaMA-13B 在大多数基准测试…

【html网页页面011】html+css+js制作香菇品牌食品网页含视频、轮播特效(5页面附效果及源码)

食品主题美食品牌网页制作 &#x1f964;1、写在前面&#x1f367;2、涉及知识&#x1f333;3、网页效果完整效果(5页)&#xff1a;代码目录结构&#xff1a;page1、首页page2、关于我们page3、经Y产品page4、近期活动page5、新品上新 &#x1f308;4、网页源码4.1 html4.2 CSS…