0% found this document useful (0 votes)
337 views13 pages

I2c Bus VHDL

This document contains VHDL source code for an I2C bus controller core designed for FPGA. It includes two modules: 1) i2c_top module which defines the logic and interfaces for the overall controller and 2) i2c_core module which contains the state machine logic to generate the I2C protocol timing. The i2c_top module interfaces with external memory and contains registers for configuration, transmission, reception and status. The i2c_core module generates the I2C bus signals SCL and SDA according to the defined state machine states for start, stop, read and write operations.
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
337 views13 pages

I2c Bus VHDL

This document contains VHDL source code for an I2C bus controller core designed for FPGA. It includes two modules: 1) i2c_top module which defines the logic and interfaces for the overall controller and 2) i2c_core module which contains the state machine logic to generate the I2C protocol timing. The i2c_top module interfaces with external memory and contains registers for configuration, transmission, reception and status. The i2c_core module generates the I2C bus signals SCL and SDA according to the defined state machine states for start, stop, read and write operations.
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
You are on page 1/ 13

2.

(2665)《基于 FPGA 的 I2C 总线控制核设计》P23


I2C 控制核的 VHDL 源码如下:
.附录:VHDL源代码
1. i2c_top 模块逻辑代码
entity i2c_top is
port( eclk: in std_logic;
nReset: in std_logic;
--asram interface signal of EMIF
nAoe: in std_logic;
nAwe: in std_logic;
nAre: in std_logic;
-- Ardy: out std_logic;
nCs: in std_logic;--i2c control core seleted, address decoder output this signal to i2c_top module
-- edat_i:in std_logic_vector(7 downto 0);--EMIF data bus low 8bit in, for test
-- edat_o:out std_logic_vector(7 downto 0); --EMIF data bus low 8bit out, for test
edat :inout std_logic_vector(7 downto 0);
eadd:in std_logic_vector(4 downto 2); --EMIF low address bus
eint: out std_logic;
--i2c interface signal
SCL : inout std_logic;
SDA : inout std_logic );
end entity i2c_top;
signal prer : std_logic_vector(7 downto 0); -- clock prescale register 000wr
signal ctr : std_logic_vector(7 downto 0); -- control register 010wr
signal txr : std_logic_vector(7 downto 0); -- transmit register 011w 101r
signal rxr : std_logic_vector(7 downto 0); -- receive register 011r
signal cr : std_logic_vector(7 downto 0); -- command register 100w 110r
signal sr : std_logic_vector(7 downto 0); -- status register 100
--eclk/8
signal clk8 :std_logic;
-- generate i2c module frequency
process(nReset, eclk)is
begin
if(nReset='0')then
clk8<='0';
div8_cnt<="000";
elsif rising_edge(eclk) then
if( div8_cnt = prer(7 downto 5) )then
clk8<=not clk8;
div8_cnt<="000";
else
div8_cnt<=div8_cnt+'1';
end if;
end if;
end process;

gen_regs: process(nReset, nCs, nAwe,clk8)


begin
if (nReset = '0') then
prer <= (others => '1');-- '0' for stimulate fast; '1' only for real system
ctr <= (others => '0');
txr <= (others => '0');
elsif rising_edge(nAwe) then
if( nCs = '0') then --nAwe='0'
case eadd is
when "000" => prer( 7 downto 0) <= edat;--edat_i;
when "010" => ctr <= edat;--edat_i;
when "011" => txr <= edat;--edat_i;--data write to slave
-- illegal cases, for simulation only
when others =>
prer <=prer;
ctr <= ctr;
txr <= txr;
end case;
end if;
end if;
end process gen_regs;
-- decode control register
core_en <= ctr(7);--i2c core enable bit
ien <= ctr(6);--interrupt enable bit
-- generate command register
gen_cr: process(nReset, nAwe, clk8, core_en, nCs,done)
begin
if (nReset = '0' or done='1') then
cr <= (others => '0');
elsif rising_edge(nAwe) then
if ( nCs= '0') then --nAwe = '0' and
if ( core_en = '1' and eadd = "100" ) then
-- only take new commands when i2c core enabled
-- pending commands are finished
cr <= edat;--edat_i;
end if;
else
cr(2 downto 1) <= "00";--(others => '0'); -- reserved bits, always '0'
cr(0) <= '0'; -- clear IRQ_ACK bit
end if;
end if;
end process gen_cr;
-- decode command register
start_r <= cr(7);
stop_r <= cr(6);
rd_r <= cr(5);
wr_r <= cr(4);
ack_r <= cr(3);-- '0'表示确认
iack_r <= cr(0);-- 中断响应位
assign_edato : process(nCs,nAre,nAoe,eadd,prer, ctr, rxr, sr, txr, cr)
variable dat_o:std_logic_vector(7 downto 0);
begin
if(nCs = '0' and nAre ='0' and nAoe='0')then
case eadd is
when "000" => dat_o := prer(7 downto 0);
when "010" => dat_o := ctr;
when "011" => dat_o := rxr; -- write is transmit register TxR
when "100" => dat_o := sr; -- write is command register CR
when "111" => dat_o := "10011101";--(others => '0'); for test
when others => dat_o := "ZZZZZZZZ";
end case;
else
dat_o := "ZZZZZZZZ";
end if;
edat <= dat_o;
end process assign_edato;
-- interrupt request signal
gen_irq: process (clk8, nReset)
begin
if (nReset = '0') then
int <= '0';
elsif (clk8'event and clk8 = '1') then
-- interrupt signal is only generated when IEN (interrupt enable bit) is set
int <= irq_flag and ien;
end if;
end process gen_irq;
eint<= int when (ien = '1') else 'Z';--利用中断使能信号 ien 实现 EINT 的共享
end architecture rtl;

2. i2c 时序状态机模块代码
entity i2c_core is
port ( clk : in std_logic;
nReset : in std_logic;
cmd_ack : out std_logic;
clk_cnt : in std_logic_vector(4 downto 0);
cmd : in std_logic_vector(2 downto 0);
Din : in std_logic;
Dout : out std_logic;
busy : out std_logic;
SCL : inout std_logic;
SDA : inout std_logic );
end entity i2c_core;
architecture structural of i2c_core is
begin
slave_wait <= '1' when ((SCLo = '1') and (SCL = '0')) else '0';
-- generate clk enable signal
gen_clken: process(clk, nReset)
begin
if (nReset = '0') then
cnt <= (others => '0');
clk_en <= '1'; --'0';
elsif (clk'event and clk = '1') then
if (cnt = "00000") then
clk_en <= '1';
cnt <= clk_cnt;
else
if (slave_wait = '0') then
cnt <= cnt -'1';
end if;
clk_en <= '0';
end if;
end if;
end process gen_clken;
-- generate statemachine
nxt_state_decoder : process (clk, nReset, state, cmd, SDA, din)
variable nxt_state : cmds;
variable icmd_ack, ibusy : std_logic;
begin
nxt_state := state;
icmd_ack := '0'; -- default no acknowledge
ibusy := '1'; -- default busy
store_sda <= '0';
if (nReset = '0') then
state <= idle;
cmd_ack <= '0';
busy <= '0';
Dout <= '0';
elsif (clk'event and clk = '1') then
if (clk_en = '1') then
state <= nxt_state;
busy <= ibusy;
if (store_sda = '1') then
Dout <= SDA;
end if;
end if;
cmd_ack <= icmd_ack and clk_en;
end if;
case (state) is
when idle =>
case cmd is
when CMD_START =>
nxt_state := start_a;
icmd_ack := '1'; -- command completed
when CMD_STOP =>
nxt_state := stop_a;
icmd_ack := '1';
when CMD_WRITE =>
nxt_state := wr_a;
icmd_ack := '1';
when CMD_READ =>
nxt_state := rd_a;
icmd_ack := '1';
when others =>
nxt_state := idle;
icmd_ack := '1';
ibusy := '0';
end case;
when start_a =>
nxt_state := start_b;
when start_b =>
nxt_state := start_c;
when start_c =>
nxt_state := start_d;
when start_d =>
nxt_state := start_e;
when start_e =>
nxt_state := start_f;
when start_f =>
nxt_state := idle;
ibusy := '0'; -- not busy when idle
when stop_a =>
nxt_state := stop_b;
when stop_b =>
nxt_state := stop_c;
when stop_c =>
nxt_state := stop_d;
when stop_d =>
nxt_state := stop_e;
when stop_e =>
nxt_state := stop_f;
when stop_f =>
nxt_state := idle;
ibusy := '0'; -- not busy when idle
when rd_a =>
nxt_state := rd_b;
when rd_b =>
nxt_state := rd_c;
when rd_c =>
nxt_state := rd_d;
when rd_d =>
nxt_state := rd_e;
store_sda <= '1';
when rd_e =>
nxt_state := idle;
ibusy := '0'; -- not busy when idle
when wr_a =>
nxt_state := wr_b;
when wr_b =>
nxt_state := wr_c;
when wr_c =>
nxt_state := wr_d;
when wr_d =>
nxt_state := wr_e;
when wr_e =>
nxt_state := idle;
ibusy := '0'; -- not busy when idle
end case;
end process nxt_state_decoder;
SCL <= '0' when (SCLo = '0') else 'Z';
SDA <= '0' when (SDAo = '0') else 'Z';
end architecture structural;
3 .i2c 命令状态机模块代码

entity i2c is
port ( clk : in std_logic;
ena : in std_logic;
nReset : in std_logic;
cmd_ack : out std_logic;
ack_out : out std_logic;
busy :out std_logic;
clk_cnt : in std_logic_vector(4 downto 0);
start,stop,read,write,ack_in : in std_logic;
Din : in std_logic_vector(7 downto 0);
Dout : out std_logic_vector(7 downto 0);
SCL : inout std_logic;
SDA : inout std_logic );
end entity i2c;
architecture structural of i2c is
signal core_cmd : std_logic_vector(2 downto 0);
signal core_ack, core_busy, core_txd, core_rxd : std_logic;
signal sr : std_logic_vector(7 downto 0); -- 8bit shift register
signal shift, ld ,go, host_ack: std_logic;
begin
ack_out <= core_rxd;
go <= ( read or write) and not host_ack;
-- sgo <= go;--for simulation
-- assign Dout output to shift-register (7 downto 0)
Dout <= sr;
-- generate host-command-acknowledge
cmd_ack <= host_ack;
busy<=core_busy;
-- generate shift register
shift_register: process(clk)
begin
if (clk'event and clk = '1') then
if (ld = '1') then
sr <= din;--load data to sr
elsif (shift = '1') then
sr <= (sr(6 downto 0) & core_rxd);--shift to left a bit
end if;
end if;
end process shift_register;

statemachine : block
type states is (st_idle, st_start, st_read, st_write, st_ack, st_stop);
signal state : states;
signal dcnt : unsigned(2 downto 0);-- use to indicate 8 databits of a byte
begin
nxt_state_decoder: process(clk, nReset, state,dcnt, core_txd, core_cmd, go, start, read, core_ack, sr(7),
ack_in, stop)
variable nxt_state : states;
variable idcnt : unsigned(2 downto 0);--use to 指示字节的 8 个节拍
variable ihost_ack : std_logic;
variable icore_cmd : std_logic_vector(2 downto 0);
variable icore_txd : std_logic;-- store transmit data bit
variable ishift, iload : std_logic;
begin
-- 8 databits (1byte) of data to shift-in/out
idcnt := dcnt;
-- no acknowledge (until command complete)
ihost_ack := '0';
-- keep current databit transmit to i2c_core
icore_txd := core_txd;
icore_cmd := core_cmd;
ishift := '0';
iload := '0';
nxt_state := state; -- keep current state;
if (nReset = '0') then
core_cmd <= CMD_NOP;
core_txd <= '0';
shift <= '0';
ld <= '0';
dcnt <= "111";
host_ack <= '0';
state <= st_idle;
elsif (clk'event and clk = '1') then
if (ena = '1') then
state <= nxt_state;
dcnt <= idcnt;
shift <= ishift;
ld <= iload;
core_cmd <= icore_cmd;
core_txd <= icore_txd;
host_ack <= ihost_ack;
end if;
end if;
-- state machine
case state is
when st_idle => -- States change in st_idle.
if (go = '1') then
if (start = '1') then
nxt_state := st_start;
icore_cmd := CMD_START;
elsif (read = '1') then --sequenc read
nxt_state := st_read;
icore_cmd := CMD_READ;
idcnt := "111"; --set 8 databits
else --sequent write
nxt_state := st_write;
icore_cmd := CMD_WRITE;
idcnt := "111"; --set 8 databits
iload := '1'; --allow to load data, which will be sent out!
end if;
end if;
when st_start =>
if (core_ack = '1') then --has already interpretted the start command
if (read = '1') then --read follow start
nxt_state := st_read;
icore_cmd := CMD_READ;
idcnt := "111";
else --write follow start
nxt_state := st_write;
icore_cmd := CMD_WRITE;
idcnt := "111";
iload := '1';
end if;
end if;
when st_write =>
if (core_ack = '1') then --has already interpretted the write command
idcnt := dcnt -1; -- count down Data_counter
icore_txd := sr(7); --send out the bit7 to core
if (dcnt = 0) then --already send 8 bits data
nxt_state := st_ack; --change state to st_ack
icore_cmd := CMD_READ; --read the ack bit from slave
else
ishift := '1';
end if;
end if;
when st_read =>
if (core_ack = '1') then
idcnt := dcnt -1; -- count down Data_counter
ishift := '1';
if (dcnt = 0) then --already read 8 bits data
nxt_state := st_ack; -- change state to st_ack
icore_cmd := CMD_WRITE; --write a ack bit to the slave
icore_txd := ack_in; --发送确认位到 Slave
end if;
end if;
when st_ack => --8bits read or write command has completed, wait for
acknowledge.
if (core_ack = '1') then
ihost_ack := '1';
ishift := '1'; --shift the 9 bit= slave ack bit.
if (stop = '1') then
nxt_state := st_stop;
icore_cmd := CMD_STOP;
else
nxt_state := st_idle;
icore_cmd := CMD_NOP;
end if;
end if;
when st_stop =>
if (core_ack = '1') then
nxt_state := st_idle;
icore_cmd := CMD_NOP;
end if;
when others => -- illegal states
nxt_state := st_idle;
icore_cmd := CMD_NOP;
end case;
end process nxt_state_decoder;
end block statemachine;
end architecture structural;

. 基于 RAM 的文件系统的实现 vxworks

如果的系统上安装有硬盘,则在 BSP 中装载你的硬盘驱动即可。如果没有,建议建立基于 RAM 的


文件系统。建立 RAM 文件系统的方式如下:

#ifndef RAMDISK_VERSION
#define RAMDISK_VERSION '1.0 built by [email protected]'
#endif // RAMDISK_VERSION

#include <vxWorks.h>
#include <stdio.h>
#include <ramDrv.h>
#include <iosLib.h>
#include <dosFsLib.h>
#include <alloc.h>
/**********************************************************************

Function: Create a ram disk device
Parameters:
name -> device name, such as 'ramdisk0:'.
size -> block device size.
Returned:
The actualy disk size. Or ERROR.

**********************************************************************/

STATUS CreateRamDisk(char * name,int size)
{
int nBlock = NULL 
BLK_DEV * pBlkDev = NULL 
DOS_VOL_DESC * pVolDesc = NULL 

// the disksize should be integral multiple of the blocksize.

size = size - size%512 
nBlock = size/512 

// You can simultaneously open 20 files

dosFsInit(20) 

// Create a ram-disk.
// The base address is the return value of alloc.
// The block size is 512.
// nBlock blocks per track
// Total nBlock blocks.
// The base address offset is 0.

pBlkDev = ramDevCreate(0,512,nBlock,nBlock,0) 
if (NULL==pBlkDev)
{
fprintf(stderr,'Can not create ram block device.\n') 
return ERROR 
}

// Make DOSFS by a ram block device.
pVolDesc = dosFsMkfs(name,pBlkDev) 
if (NULL==pVolDesc)
{
fprintf(stderr,'Can not create ram-dos-fs.\n') 
return ERROR 
}

// The size is actualy disk size.

return size 
}

/**********************************************************************

Function: Delete a ram disk device
Parameters:
name -> device name, such as 'ramdisk0:'.
Returned:
Return OK if the device is removed successfuly.
Otherwise return ERROR.

**********************************************************************/

STATUS DeleteRamDisk(char * name)
{
DEV_HDR * pDevHdr = NULL 

// Find ram-disk device by name

if ( NULL==(pDevHdr=iosDevFind(name,NULL)) )
{
fprintf(stderr,'Can not find device (%s).\n',name) 
return ERROR 
}

// Delete the device and free the alloced memory

iosDevDelete(pDevHdr) 
free(pDevHdr) 

return OK 
}
/**********************************************************************

Function: Create a ram disk device & set is as default path.
Parameters:
name -> device name, such as 'ramdisk0:'.
size -> block device size.
Returned:
The actualy disk size. Or ERROR.

**********************************************************************/

STATUS InitRamFsEnv(char * name,int size)
{
STATUS iReturn = CreateRamDisk(name,size) 

if (ERROR!=iReturn) ioDefPathSet(name) 

return iReturn 
}

You might also like