移植OPENCORES上的I2C MASTER到AXI接口处理器层面实现驱动 之一

59 篇文章 4 订阅
46 篇文章 8 订阅




由于之间就用过OPENCORES上的I2C MASTER,所以对他的接口时序以及处理器方面的驱动非常了解。这里主要做的工作是移植。





这个IP核来自www.opencores.org 是经过OPENCORES认证的IP核。




这个IP是采用了WISHBONE互联总线标准,是最简单最基本的互联总线,因此很容易移植上AXI_LITE接口。以下代码是我以前做的一个项目的例化代码,


 /*
 i2c_master_top U1(
	wb_clk_i ( ), 
	wb_rst_i ( ), 
	arst_i ( ), 
	wb_adr_i ( ), 
	wb_dat_i ( ), 
	wb_dat_o ( ),
	wb_we_i ( ), 
	wb_stb_i ( ), 
	wb_cyc_i ( ), 
	wb_ack_o ( ), 
	wb_inta_o ( ),


	.scl_pad_i ( ), 
	.scl_pad_o ( ), 
	.scl_padoen_o ( ), 
	.sda_pad_i ( ), 
	.sda_pad_o ( ), 
	.sda_padoen_o( )
	);
	*/

我们看到非常简单,下面做的工作就是直接简历AXI_LITE外设实现实例化此模块并将接口处理好。


下面做的主要工作就是接口的转换,将WISHBONE接口转成AXI LITE 接口。

1,WISHBONE只读写地址是一个,而AXI_LITE接口的读写地址是两个分开。这点要对I2C MASTER进行修改。

2,这里I2C_MASTER的WISHBONE用三位地址长度,所以我们也用三位的AXI_LITE地址总线。

3,这里I2C_MASTER的WISHBONE数据位长度是8位,而AXI_LITE 总线是32位数据长度。

4,对于I2C_MASTER来说不会挂起总线,任何时候的读和写都是READY的,因此就简单处理好读写时序就可以。

5,写寄存器时,地址,数据以及写信号同时出现在时钟的上升边缘,就完成写操作,所以我们做接口转换时候找到数据,地址,和写信号就行。

6,读数据的时候,我们加进去读地址,数据在下一周期出现在WB_DOUT。

7,I2C接口的 scl_pad_i, scl_pad_o, scl_padoen_o, sda_pad_i, sda_pad_o, sda_padoen_o 信号直接引出来到顶层处理。

8,wb_stb_i, wb_cyc_i, 两个原来的WISHBONE信号直接接1就可以。


简单修改一下原来WISHBONE接口的顶层文件,加上读寄存器地址,去掉多余的控制信号,接口成:

module i2c_master_top(
	wb_clk_i, wb_rst_i, 
	//arst_i,
	wb_adr_i_wr,wb_adr_i_rd, wb_dat_i, wb_dat_o,
	wb_we_i, 
	//wb_stb_i, wb_cyc_i, 
	//wb_ack_o, 
	wb_inta_o,
	scl_pad_i, scl_pad_o, scl_padoen_o, sda_pad_i, sda_pad_o, sda_padoen_o );

我们直接编写AXI LITE外设,步骤在我给大家的视频已经详细提过,这里注意设置8个寄存器。按照模板生产,之后加入做了简单修改后的2C_MASTER控制代码:

	// Add user logic here
i2c_master_top  u1(
        .wb_clk_i( S_AXI_ACLK  ), 
        .wb_rst_i( ~S_AXI_ARESETN ), 
        .wb_adr_i_wr( axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] ),
        .wb_adr_i_rd( axi_araddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] ), 
        .wb_dat_i(  S_AXI_WDATA[7:0]), 
        .wb_dat_o( axi_rdata ),
        .wb_we_i( slv_reg_wren  ), 
        .wb_inta_o(  ),
        .scl_pad_i(  scl_pad_i), 
        .scl_pad_o( scl_pad_o ), 
        .scl_padoen_o( scl_padoen_o ), 
        .sda_pad_i( sda_pad_i ), 
        .sda_pad_o( sda_pad_o ), 
        .sda_padoen_o (sda_padoen_o  ) 
        );
	// User logic ends
封装好以后就是现在的样子。


我们看到非常简介明了。这里没有引出中断,如果要引出并使用的画,要在I2C MASTER里面读明白中断是否保持,从而选择是边缘触发还是电平触发。我不是很倾向于使用中断,因为会将整个系统搞得不好预测,尤其是中断的丢失有时候危害是致命的。有些场合必须中断比如使用LWIP协议,就需要有中断来处理数据,如果用户再加上一个或多个中断,如果添加进来的中断优先级高,可能造成LWIP中断地址,如果添加进来的优先级低,可能造成用户优先级降低。另外中断一般很难在线调试,很多问题在实验没有出现,到用户现场就出现了。所以不是偶发时间或者是用轮询能及时处理的,不建议使用中断。(中断说得有点多哈)。



这样IP核做好了,下步就是调用这个IP并编写C程序驱动起来这个控制器。








  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值