在分析了《深层次浅出轻松玩FPGA》的串口编码和IIC操纵器编码、xilinx官方网的xilinx的iic操纵器(参照书《FPGACPLD设计方案专用工具──Xilinx ISE应用详细说明》)、《片上系统软件设计方案观念与源码剖析》一书里含有wishbone插口的iic操纵器后,文中试着对之上做一些小结,并剖析不一样的iic操纵器的完成差别。 上一讲,大家剖析了权利的iic操纵器的完成,这一讲将再次另2种含有系统总线插口和更充足完成iic协议书的事例。下一讲下谈一谈SOC构架中的wishbone系统总线构架及外设挂载,及其一些硬软件融合的最底层的物品,关键参照《自身动手能力写cpu》一书及有关的网页页面材料等,烦请希望。
2、IIC操纵器 2.2 xilinx的iic操纵器 该操纵器关键是参照《FPGACPLD设计方案专用工具──Xilinx ISE应用详细说明》第一0章和官方网编码,材料连接见文末得出的免费下载连接详细地址。iic协议书的专业知识一样已不过多阐释,仅仅提几个方面上一讲中沒有或不用关心的地区: 1、I2C系统总线通讯时,起止位后的第一个字节数用以寻址方式,该字节数包括7比特的从机详细地址和1比特的读写能力标示比特, 一般来讲,从机详细地址由一个固定不动一部分和一个可程序编写一部分组成。 2、复合型文件格式中,这时服务器持续对从机开展数次读写能力实际操作,因而在造成起止位、收取和发送数据信息、造成终止位的全部传送全过程中,数据信息的方位产生数次更改,传送更改方位时,服务器会再次传出反复起止位和从机详细地址(上一讲中为何读的步骤要繁杂些的缘故)。 3、I2C系统总线在一个時刻只有有一个服务器,当I2C系统总线同时有2个或大量的器件想变成服务器时,就必须开展诉讼,数字时钟同歩全过程的目地是为诉讼出示一个明确的数字时钟。SCL 线低电平常间在于低电平常间最多的服务器,高电平常间在于高电平常间最少的服务器。服务器总是在 I2C 系统总线空余时造成起止位,可是在起止位的维持時间 tHD;STA内将会有2个或之上的服务器造成起止位,最后系统总线上的起止位由他们中间的线与计算决策,诉讼在接着 SDA 网上推送的比特中开展。假如一个服务器具备从机作用,那麼当它丧失诉讼时,务必马上转换到从机情况,由于它将会已经被别的服务器寻址方式。 4、如图所示 说完了这种有关iic协议书的点再次下边的一部分. I2C系统总线操纵器的关键功效是出示UC(Microcontroller,微操纵器或片式机)和I2C系统总线中间的插口,为二者中间的通讯出示物理学层协议书的变换。这种I2C协议书的器件,也不能立即和片式机外场系统总线相接,这种器件能够挂在一套I2C系统总线上,再根据I2C系统总线操纵器和 C连起來,如图所示所显示。在SOC设计方案中相近的协议书变换控制模块用到十分多。 I2C 系统总线操纵器包括2个关键一部分,一是微操纵器插口,通称 C插口,二是 I2C Master/Slave 插口,即I2C插口,根据这2个插口,I2C系统总线操纵器完成了微操纵器外场系统总线和 I2C 系统总线的联接。那麼这儿的微操纵器插口是哪样操纵器?是不是是哪样系统总线协议书,依据readme文档能够发觉原先是 MC68307片式机,是一款集成化的多系统总线解决器。 讲明楚了基本原理,大家看来看实际设计方案: This zip file contains the following folders: 能看到五个文档。uc_interface_blk_ver.v 完成了一些寄放器及其对下一层控制模块的操纵数据信号,shift8_blk_ver.v是串行通信收取和发送,t4_blk_ver.v是4位电子计数器,i2c_blk_ver.v 是高层,例化了uc_interface_blk_ver和i2c_control_blk_ver。i2c_control_blk_ver则完成了诉讼,start等收取和发送步骤情况机等。总体构架以下图: 全部构思還是很清晰的。插口处关键是一些寄放器,寄放器的数据信号到iic中控台制最底层的运行。 C 插口关键包括情况寄放器MBSR、操纵寄放器MBCR、详细地址寄放器MADR、数据信息寄放器MBDR 和详细地址译码/系统总线插口控制模块。情况寄放器标示I2C系统总线操纵器确当前情况,如传输是不是进行、系统总线是不是忙等信息内容,操纵寄放器是 C操纵I2C系统总线操纵器的关键方式,根据置0/置1能够进行I2C系统总线操纵器使能、终断使能、Master/Slave方式挑选、造成起止位等实际操作。详细地址寄放器储存着I2C系统总线操纵器做为Slave时的详细地址。数据信息寄放器用以储存接受或者待推送的数据信息。 下边剖析源码,因为源码诸多,只有摘出一部分,整理关键构思和关键数据信号线,大伙儿能够免费下载我注解的编码。 i2c_blk_ver.v 高层文档:
module i2c_blk (sda, scl, addr_bus, data_bus, as, ds, r_w, dtack, irq, mcf, clk, reset); parameter I2C_ADDRESS = 16 b0000; // I2C bus signals inout sda; inout scl; // uC interface signals input [23:0] addr_bus; inout [7:0] data_bus; input as; // address strobe, active low input ds; // data strobe, active low input r_w; // read/write output dtack; // data transfer acknowledge 给解决器的,表明数据信息是不是提前准备好啦 output irq; // interrupt request inout mcf; // temporary output for testing 给解决器,表明传送是不是完毕 // clock and reset input clk; input reset;这一是高层的键入輸出,并不是甚么独特的系统总线构造,较为好了解,pdf中有详尽的汉语表述每一个数据信号的含意。
接下去是一些wire型,具体上便是这些寄放器中有含意的每一名,即各种各样操纵数据信号线,有利于例化的 i2c_control I2C_CTRL与 uC_interface #(I2C_ADDRESS) uC_CTRL控制模块间的插口互连。 接下去从高层向下,uC_interface控制模块:
// Internal I2C Bus Registers // Address Register (Contains slave address) inout [7:0] madr; // Control Register inout men; // I2C Enable bit inout mien; // interrupt enable inout msta; // Master/Slave bit inout mtx; // Master read/write inout txak; // acknowledge bit inout rsta; // repeated start output mbcr_wr; // indicates that the control reg has been written // Status Register input mcf; // end of data transfer input maas; // addressed as slave input mbb; // bus busy input mal; // arbitration lost input srw; // slave read/write input mif; // interrupt pending input rxak; // received acknowledge output mal_bit_reset; // indicates that the MAL bit should be reset output mif_bit_reset; // indicates that the MIF bit should be reset input msta_rst; // resets the MSTA bit if arbitration is lost // Data Register inout [7:0] mbdr_micro; input [7:0] mbdr_i2c; output mbdr_read;能看到具体上这一控制模块的许多輸出数据信号便是这种寄放器的位,操纵更最底层的怎样完成。能够参照pdf查寻实际的寄放器(八位)的某一名是啥含意。例如情况寄放器全是input型,由于他关键意见反馈给uc当今情况,错误最底层的情况机操纵。数据信息寄放器中mbdr_micro是inout型,表明是uc系统总线那一端的,mbdr_i2c是input型,表明是以iic接受到的那一端的。
// State Machine Signals `define STATE_TYPE_IDLE 2 d0 `define STATE_TYPE_ADDR 2 d1 `define STATE_TYPE_DATA_TRS 2 d2 `define STATE_TYPE_ASSERT_DTACK 2 d3 // Constant Declarations parameter RESET_ACTIVE = 1 // Base Address for I2C Module (addr_bus[23:8]) parameter MBASE = UC_ADDRESS; // Register Addresses (5 Total): // Address Register (MBASE + 8Dh) `define MADR_ADDR 8 b // Control Register (MBASE + 91h) `define MBCR_ADDR 8 b // Status Register (MBASE + 93h) `define MBSR_ADDR 8 b // Data I/O Register (MBASE + 95h) `define MBDR_ADDR 8 buc一部分的情况机, C和 I2C系统总线操纵器中间的互动要采用 I2C系统总线操纵器內部的寄放器,寄放器的详细地址是24位的,在其中高16比特为I2C系统总线操纵器的基址,低八位用以差别不一样寄放器。接下去界定了10好几个wire型的正中间自变量,这种事情况机中造成的控制操纵情况机的。因为wire型自变量不可以再always中取值,因此后边又用这类方法界定一个相对的reg型自变量。
// Address match wire address_match; reg visual_0_address_match; assign address_match = visual_0_address_match; 再加了visual_0的作为前缀,那样做的益处?我觉得一是数字时钟同歩,reg数据信号由clock打一拍同歩,也有利于除去毛刺,由于assign数据信号立即相接,稍有颤动就会有毛刺,reg数据信号打拍子能够防止这类难题。二是能够一些数据信号做相近案子检验一样的消抖,举例说明:
51 input as; 221 begin visual_0_as_int //这儿又有一个数字时钟的延迟时间一拍 visual_0_as_int_d1 //历经一个数字时钟的延迟时间一拍,以便检验到恰当的降低沿而沒有颤动的影响 visual_0_ds_int = ds; if ((!as as_int_d1 addr_bus[23:8] == MBASE)) //低八位是差别哪个寄放器 visual_0_address_match = 1 else visual_0_address_match = 1 end 135 reg visual_0_as_int; assign as_int = visual_0_as_int; 138 reg visual_0_as_int_d1; assign as_int_d1 = visual_0_as_int_d1;
能看见从221行刚开始,获得as键入,历经好多个正中间自变量的资金周转,在if中通快递过!as as_int_d1来做到相近案子去抖的实际效果。此外一些自变量是对外开放輸出的,也需变为reg型。 这一部分的具体工作中步骤如图所示: ![]() // Wait for falling edge of as if (as_int_d1 !as) //as表明键入详细地址合理数据信号,低合理,这儿的as_int_d1具体上是一个相近功能键去抖的实际效果,延迟时间了2拍,跟踪数据信号便可以发觉 // falling edge of AS visual_0_next_state = `STATE_TYPE_ADDR; `STATE_TYPE_ADDR : // ---------- ADDR State (01) -------------- // Check that this module is being address if (address_match) //225行由键入的bus决策,也是打过一拍,保证数字时钟同歩 // Wait for ds to be asserted, active low if (!ds_int) //由键入的ds决策 visual_0_next_state = `STATE_TYPE_DATA_TRS; else visual_0_next_state = `STATE_TYPE_ADDR; else // this module is not being addressed visual_0_next_state = `STATE_TYPE_IDLE; `STATE_TYPE_DATA_TRS : begin // -------- DATA_TRS State (10) ------------ // Read or write from enabled register visual_0_next_state = `STATE_TYPE_ASSERT_DTACK; //衔接态,以便得出oe的数据信号,內部操纵线 visual_0_dtack_oe = 1 //前边被置为0了的 `STATE_TYPE_ASSERT_DTACK : begin // ------ ASSERT_DTACK State (11) ---------- // Assert dtack to uProcessor = 1 //前边被置为1了的 visual_0_dtack_oe = 1 // Wait for rising edge of as and ds if ((!as_int_d1) (!ds_int)) //锁存实际操作,直到DTACK合理,乃至能够剖析锁存了好多个数字时钟? visual_0_next_state = `STATE_TYPE_ASSERT_DTACK; else if ((as_int_d1) (ds_int)) visual_0_next_state = `STATE_TYPE_IDLE; endcase end /pre pre code_snippet_id= 1669606 snippet_file_name= blog__10_3192142 name= code > 因此sda具体上经过sda_out_reg,visual_0_sda_out_reg,sda_out,visual_0_sda_out操纵,即下面的图情况机中的visual_0_sda_out具体意味着了sda,一样scl也一样。 |