⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wishbone_i2c_master.vhd

📁 -- WISHBONE revB2 compiant I2C master core -- -- author: Richard Herveille -- rev. 0.1 based on s
💻 VHD
📖 第 1 页 / 共 2 页
字号:
							nxt_state := st_ack;							icore_cmd := CMD_READ;						else							ishift := '1';--							icore_txd := sr(7);						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							nxt_state := st_ack;							icore_cmd := CMD_WRITE;							icore_txd := ack_in;						end if;					end if;							when st_ack =>					if (core_ack = '1') then						-- generate command acknowledge signal						ihost_ack := '1';						-- Perform an additional shift, needed for 'read' (store last received bit in shift register)						ishift := '1';						-- check for stop; Should a STOP command be generated ?						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;			-- generate registers			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 (rst = '1') then					core_cmd <= CMD_NOP;					core_txd <= '0';									shift <= '0';					ld <= '0';					dcnt <= "111";					host_ack <= '0';					state <= st_idle;				else					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;		end process nxt_state_decoder;	end block statemachine;end architecture structural;----------------------------------------- Bit controller section---------------------------------------- Translate simple commands into SCL/SDA transitions-- Each command has 5 states, A/B/C/D/idle---- start:	SCL	~~~~~~~~~~\____--	SDA	~~~~~~~~\______--		 x | A | B | C | D | i---- repstart	SCL	____/~~~~\___--	SDA	__/~~~\______--		 x | A | B | C | D | i---- stop	SCL	____/~~~~~~~~--	SDA	==\____/~~~~~--		 x | A | B | C | D | i----- write	SCL	____/~~~~\____--	SDA	==X=========X=--		 x | A | B | C | D | i----- read	SCL	____/~~~~\____--	SDA	XXXX=====XXXX--		 x | A | B | C | D | i---- Timing:		Normal mode	Fast mode------------------------------------------------------------------- Fscl		100KHz		400KHz-- Th_scl		4.0us		0.6us	High period of SCL-- Tl_scl		4.7us		1.3us	Low period of SCL-- Tsu:sta		4.7us		0.6us	setup time for a repeated start condition-- Tsu:sto		4.0us		0.6us	setup time for a stop conditon-- Tbuf		4.7us		1.3us	Bus free time between a stop and start condition--library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_arith.all;entity bit_ctrl is	port (		clk : in std_logic;		rst : in std_logic;		nReset : in std_logic;		clk_cnt : in unsigned(15 downto 0);		-- clock prescale value		ena : in std_logic;				-- core enable signal		cmd : in std_logic_vector(2 downto 0);		cmd_ack : out std_logic;		busy : out std_logic;		Din : in std_logic;		Dout : out std_logic;		-- i2c lines		SCLin : in std_logic;				-- I2C clock line		SCLout : out std_logic;		SDAin : in std_logic;				-- I2C data line		SDAout : out std_logic	);end entity bit_ctrl;architecture structural of bit_ctrl is	constant CMD_NOP	: std_logic_vector(2 downto 0) := "000";	constant CMD_START	: std_logic_vector(2 downto 0) := "010";	constant CMD_STOP	: std_logic_vector(2 downto 0) := "011";	constant CMD_READ	: std_logic_vector(2 downto 0) := "100";	constant CMD_WRITE	: std_logic_vector(2 downto 0) := "101";	type cmds is (idle, start_a, start_b, start_c, start_d, stop_a, stop_b, stop_c, rd_a, rd_b, rd_c, rd_d, wr_a, wr_b, wr_c, wr_d);	signal state : cmds;	signal SCLo, SDAo : std_logic;		-- internal I2C lines	signal sSCL, sSDA : std_logic;			-- synchronized SCL and SDA inputs	signal txd : std_logic;			-- transmit bit	signal clk_en, slave_wait :std_logic;		-- clock generation signals--	signal cnt : unsigned(15 downto 0) := clk_cnt;	-- clock divider counter (simulation)	signal cnt : unsigned(15 downto 0);             -- clock divider counter (synthesis)begin	-- synchronize SCL and SDA inputs	synch_SCL_SDA: process(clk)	begin		if (clk'event and clk = '1') then			sSCL <= SCLin;			sSDA <= SDAin;		end if;	end process synch_SCL_SDA;		-- whenever the slave is not ready it can delay the cycle by pulling SCL low	slave_wait <= '1' when ( (SCLo = '1') and (sSCL = '0') ) else '0';	-- generate clk enable signal	gen_clken: process(clk, nReset)	begin		if (nReset = '0') then			cnt <= (others => '0');			clk_en <= '1';		elsif (clk'event and clk = '1') then			if (rst = '1') then				cnt <= (others => '0');				clk_en <= '1';			else				if ( (cnt = 0) or (ena = '0') ) 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 if;	end process gen_clken;	-- generate bus status controller	bus_status_ctrl: block		signal dSDA : std_logic;		signal sta_condition : std_logic;		signal sto_condition : std_logic;		signal ibusy : std_logic;	begin		-- detect start condition => detect falling edge on SDA while SCL is high		-- detect stop condition => detect rising edge on SDA while SCL is high		det_sta_sto: process(clk)		begin			if (clk'event and clk = '1') then				dSDA <= sSDA;	-- generate a delayed version of sSDA				sta_condition <= (not sSDA and dSDA) and sSCL;				sto_condition <= (sSDA and not dSDA) and sSCL;			end if;		end process det_sta_sto;		-- generate bus busy signal		gen_busy: process(clk, nReset)		begin			if (nReset = '0') then				ibusy <= '0';			elsif (clk'event and clk = '1') then				if (rst = '1') then					ibusy <= '0';				else					ibusy <= (sta_condition or ibusy) and not sto_condition;				end if;			end if;		end process gen_busy;		-- assign output		busy <= ibusy;	end block bus_status_ctrl;	-- generate statemachine	nxt_state_decoder : process (clk, nReset, state, cmd)		variable nxt_state : cmds;		variable icmd_ack, store_sda : std_logic;		variable itxd : std_logic;	begin		nxt_state := state;		icmd_ack := '0'; -- default no acknowledge		store_sda := '0';		itxd := txd;		case (state) is			-- idle			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'; -- command completed					when CMD_WRITE =>						nxt_state := wr_a;						icmd_ack := '1'; -- command completed						itxd := Din;					when CMD_READ =>						nxt_state := rd_a;						icmd_ack := '1'; -- command completed					when others =>						nxt_state := idle;-- don't acknowledge NOP command						icmd_ack := '1'; -- command completed				end case;			-- start			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 := idle;			-- stop			when stop_a =>				nxt_state := stop_b;			when stop_b =>				nxt_state := stop_c;			when stop_c =>				nxt_state := idle;			-- read			when rd_a =>				nxt_state := rd_b;			when rd_b =>				nxt_state := rd_c;			when rd_c =>				nxt_state := rd_d;				store_sda := '1';			when rd_d =>				nxt_state := idle;			-- write			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 := idle;		end case;		-- generate regs		if (nReset = '0') then			state <= idle;			cmd_ack <= '0';			txd <= '0';			Dout <= '0';		elsif (clk'event and clk = '1') then			if (rst = '1') then				state <= idle;				cmd_ack <= '0';				txd <= '0';				Dout <= '0';			else				if (clk_en = '1') then					state <= nxt_state;					txd <= itxd;					if (store_sda = '1') then						Dout <= sSDA;					end if;				end if;				cmd_ack <= icmd_ack and clk_en;			end if;		end if;	end process nxt_state_decoder;	--	-- convert states to SCL and SDA signals	--	output_decoder: process (clk, nReset, state)		variable iscl, isda : std_logic;	begin		case (state) is			when idle =>				iscl := SCLo; -- keep SCL in same state				isda := sSDA; -- keep SDA in same state			-- start			when start_a =>				iscl := SCLo; -- keep SCL in same state (for repeated start)				isda := '1'; -- set SDA high			when start_b =>				iscl := '1';	-- set SCL high				isda := '1'; -- keep SDA high			when start_c =>				iscl := '1';	-- keep SCL high				isda := '0'; -- sel SDA low			when start_d =>				iscl := '0'; -- set SCL low				isda := '0'; -- keep SDA low			-- stop			when stop_a =>				iscl := '0'; -- keep SCL disabled				isda := '0'; -- set SDA low			when stop_b =>				iscl := '1'; -- set SCL high				isda := '0'; -- keep SDA low			when stop_c =>				iscl := '1'; -- keep SCL high				isda := '1'; -- set SDA high			-- write			when wr_a =>				iscl := '0';	-- keep SCL low				isda := Din;			when wr_b =>				iscl := '1';	-- set SCL high				isda := Din;			when wr_c =>				iscl := '1';	-- keep SCL high				isda := Din;			when wr_d =>				iscl := '0'; -- set SCL low				isda := Din;			-- read			when rd_a =>				iscl := '0'; -- keep SCL low				isda := '1'; -- tri-state SDA			when rd_b =>				iscl := '1'; -- set SCL high				isda := '1'; -- tri-state SDA			when rd_c =>				iscl := '1'; -- keep SCL high				isda := '1'; -- tri-state SDA			when rd_d =>				iscl := '0'; -- set SCL low				isda := '1'; -- tri-state SDA		end case;		-- generate registers		if (nReset = '0') then			SCLo <= '1';			SDAo <= '1';		elsif (clk'event and clk = '1') then			if (rst = '1') then				SCLo <= '1';				SDAo <= '1';			else				if (clk_en = '1') then					SCLo <= iscl;					SDAo <= isda;				end if;			end if;		end if;	end process output_decoder;	-- assign outputs	SCLout <= SCLo;	SDAout <= SDAo;end architecture structural;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -