由于之间就用过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程序驱动起来这个控制器。