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

📄 wishbone_i2c_master.html

📁 wishbone i2c master vhdl code
💻 HTML
📖 第 1 页 / 共 2 页
字号:
						icore_txd := sr(7);
						if (dcnt = 0) then
							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;

</PRE></BODY></HTML>

⌨️ 快捷键说明

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