Files
PWrProjUCiSW2/ucisw2_magnetometr/Magneto_Drv.vhd
T
2018-06-02 16:31:19 +02:00

311 lines
9.2 KiB
VHDL

----------------------------------------------------------------------------------
-- Company:
-- Engineer:
--
-- Create Date: 17:16:45 02/27/2018
-- Design Name:
-- Module Name: Magneto_Drv - Behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity Magneto_Drv is
Port ( I2C_FIFO_Empty : in STD_LOGIC;
I2C_FIFO_Full : in STD_LOGIC;
I2C_FIFO_DO : in STD_LOGIC_VECTOR (7 downto 0);
I2C_Busy : in STD_LOGIC;
DRDY : in STD_LOGIC;
OutputRate : in STD_LOGIC_VECTOR (2 downto 0);
Reset : in STD_LOGIC;
Clk : in STD_LOGIC;
I2C_Go : out STD_LOGIC;
I2C_FIFO_Push : out STD_LOGIC;
I2C_FIFO_Pop : out STD_LOGIC;
I2C_FIFO_DI : out STD_LOGIC_VECTOR (7 downto 0);
I2C_Addr : out STD_LOGIC_VECTOR (7 downto 0);
I2C_ReadCnt : out STD_LOGIC_VECTOR (3 downto 0);
ID : out STD_LOGIC_VECTOR (23 downto 0);
DRX : out STD_LOGIC_VECTOR (15 downto 0);
DRY : out STD_LOGIC_VECTOR (15 downto 0);
DRZ : out STD_LOGIC_VECTOR (15 downto 0);
DR_New : out STD_LOGIC);
end Magneto_Drv;
architecture Behavioral of Magneto_Drv is
-- Main state machine
type state_type is ( Init, PushAddrID, SendAddrID, BusyAddrID, ReceiveID, BusyID, ReadID, PopID, CheckID,
PushAddrConfigA, PushDataConfigA, SendConfigA, BusyConfigA, PushAddrMode, PushDataMode,
SendMode, BusyMode, MeasureWait, MeasureReceive, MeasureBusy, MeasureRead, MeasurePop,
MeasureCheck, MeasureLoad, MeasureOutput, MeasurePushAddr, MeasureSendAddr, MeasureBusyAddr );
signal state, next_state : state_type;
-- DRDY synchronized input
signal DRDY_in : STD_LOGIC;
-- Input registers
signal ID_reg : STD_LOGIC_VECTOR (23 downto 0);
signal Input : STD_LOGIC_VECTOR (47 downto 0);
-- Input byte counter
signal bytes : integer range 0 to 5 := 0;
-- Measure output registers
signal DRX_reg : STD_LOGIC_VECTOR (15 downto 0);
signal DRY_reg : STD_LOGIC_VECTOR (15 downto 0);
signal DRZ_reg : STD_LOGIC_VECTOR (15 downto 0);
begin
-- DRDY input synchronization to internal clock
sync_process : process(Clk, Reset)
begin
if Reset = '1' then
DRDY_in <= '0';
elsif rising_edge(Clk) then
DRDY_in <= DRDY;
end if;
end process sync_process;
-- Main HMC5883L FSM
-- (continuos measurement)
process1 : process(Clk)
begin
if rising_edge(Clk) then
if Reset = '1' then
state <= Init;
else
state <= next_state;
end if;
end if;
end process process1;
process2 : process(state, I2C_FIFO_Empty, I2C_Busy, DRDY_in)
begin
next_state <= state; -- by default
case state is
-- Initialization
-- Reading identification register
when Init =>
next_state <= PushAddrID;
when PushAddrID =>
next_state <= SendAddrID;
when SendAddrID =>
next_state <= BusyAddrID;
when BusyAddrID =>
if I2C_Busy = '0' then
next_state <= ReceiveID;
end if;
when ReceiveID =>
next_state <= BusyID;
when BusyID =>
if I2C_Busy = '0' then
next_state <= ReadID;
end if;
when ReadID =>
next_state <= PopID;
when PopID =>
next_state <= CheckID;
when CheckID =>
if I2C_FIFO_Empty = '1' then
next_state <= PushAddrConfigA;
else
next_state <= ReadID;
end if;
-- Setting data rate and mode
when PushAddrConfigA =>
next_state <= PushDataConfigA;
when PushDataConfigA =>
next_state <= SendConfigA;
when SendConfigA =>
next_state <= BusyConfigA;
when BusyConfigA =>
if I2C_Busy = '0' then
next_state <= PushAddrMode;
end if;
when PushAddrMode =>
next_state <= PushDataMode;
when PushDataMode =>
next_state <= SendMode;
when SendMode =>
next_state <= BusyMode;
when BusyMode =>
if I2C_Busy = '0' then
next_state <= MeasureWait;
end if;
-- Measuring...
when MeasureWait =>
if DRDY_in = '0' then
next_state <= MeasureReceive;
end if;
when MeasureReceive =>
next_state <= MeasureBusy;
when MeasureBusy =>
if I2C_Busy = '0' then
next_state <= MeasureRead;
end if;
-- Reading results...
when MeasureRead =>
next_state <= MeasurePop;
when MeasurePop =>
next_state <= MeasureCheck; --
when MeasureCheck =>
if I2C_FIFO_Empty = '1' then
next_state <= MeasureLoad;
else
next_state <= MeasureRead;
end if;
when MeasureLoad =>
next_state <= MeasureOutput;
when MeasureOutput =>
next_state <= MeasurePushAddr;
when MeasurePushAddr =>
next_state <= MeasureSendAddr;
when MeasureSendAddr =>
next_state <= MeasureBusyAddr;
when MeasureBusyAddr =>
if I2C_Busy = '0' then
next_state <= MeasureWait;
end if;
end case;
end process process2;
id_register : process(Clk, state, next_state)
begin
if rising_edge(Clk) then
if state = ReadID then
case bytes is
when 0 =>
ID_reg(23 downto 16) <= I2C_FIFO_DO;
when 1 =>
ID_reg(15 downto 8) <= I2C_FIFO_DO;
when 2 =>
ID_reg(7 downto 0) <= I2C_FIFO_DO;
when others =>
ID_reg <= X"000000";
end case;
end if;
end if;
end process id_register;
-- Storing measurements in register
input_register : process(Clk, state, next_state)
begin
if rising_edge(Clk) then
if state = MeasureRead then
case bytes is
when 0 =>
Input(47 downto 40) <= I2C_FIFO_DO;
when 1 =>
Input(39 downto 32) <= I2C_FIFO_DO;
when 2 =>
Input(31 downto 24) <= I2C_FIFO_DO;
when 3 =>
Input(23 downto 16) <= I2C_FIFO_DO;
when 4 =>
Input(15 downto 8) <= I2C_FIFO_DO;
when 5 =>
Input(7 downto 0) <= I2C_FIFO_DO;
end case;
end if;
end if;
end process input_register;
-- Stored bytes counter
byte_counter : process(Clk)
begin
if rising_edge(Clk) then
if Reset = '1' then
bytes <= 0;
end if;
if state = MeasurePop then
if bytes = 5 then
bytes <= 0;
else
bytes <= bytes + 1;
end if;
end if;
if state = PopID then
if bytes = 2 then
bytes <= 0;
else
bytes <= bytes + 1;
end if;
end if;
end if;
end process byte_counter;
-- Buffering output in registers
output_sync : process(Clk, state, next_state)
begin
if rising_edge(Clk) then
if state = MeasureLoad then
DRX_reg <= Input(47 downto 32);
DRZ_reg <= Input(31 downto 16);
DRY_reg <= Input(15 downto 0);
end if;
end if;
end process output_sync;
-- Output signals for FSM
I2C_FIFO_DI <= X"0A" when next_state = PushAddrID or state = PushAddrID else
X"00" when next_state = PushAddrConfigA or state = PushAddrConfigA else
"000" & OutputRate & "00" when next_state = PushDataConfigA or state = PushDataConfigA else
X"02" when next_state = PushAddrMode or state = PushAddrMode else
X"00" when next_state = PushDataMode or state = PushDataMode else
X"03" when next_state = MeasurePushAddr or state = MeasurePushAddr else
X"00";
I2C_FIFO_Push <= '1' when state = PushAddrID or state = PushAddrConfigA or state = PushDataConfigA
or state = PushAddrMode or state = PushDataMode or state = MeasurePushAddr else
'0';
I2C_Addr <= X"3C" when next_state = SendAddrID or state = SendAddrID or next_state = SendConfigA
or state = SendConfigA or next_state = SendMode or state = SendMode
or next_state = MeasureSendAddr or state = MeasureSendAddr else
X"3D" when next_state = ReceiveID or state = ReceiveID or next_state = MeasureReceive
or state = MeasureReceive else
X"00";
I2C_Go <= '1' when state = SendAddrID or state = ReceiveID or state = SendConfigA or state = SendMode
or state = MeasureReceive or state = MeasureSendAddr else
'0';
I2C_ReadCnt <= X"3" when next_state = ReceiveID or state = ReceiveID else
X"6" when next_state = MeasureReceive or state = MeasureReceive else
X"0";
I2C_FIFO_Pop <= '1' when state = PopID or state = MeasurePop else
'0';
DR_New <= '1' when state = MeasureOutput else
'0';
-- Output registers
ID <= ID_reg;
DRX <= DRX_reg;
DRY <= DRY_reg;
DRZ <= DRZ_reg;
end Behavioral;