altera/MainController/RAM9X8_SerialBusMaster.vhd

372 lines
12 KiB
VHDL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity RAM9X8_SerialBusMaster is
generic(
SB_DATA_LOWER : integer := 0;
SB_DATA_UPPER : integer := 1;
SB_CMD_LOWER : integer := 2;
SB_CMD_UPPER : integer := 3;
SB_CONTROL_LOWER : integer := 4;
SB_CONTROL_UPPER : integer := 5;
DATA_BUS_WIDTH : integer := 8;
ADDRESS_BUS_WIDTH : integer := 9
);
port(
clk : in std_logic;
data : inout std_logic_vector(DATA_BUS_WIDTH - 1 downto 0);
address : in std_logic_vector(ADDRESS_BUS_WIDTH - 1 downto 0);
we : in std_logic;
oe : in std_logic;
ce : in std_logic;
sbclk : out std_logic := '0';
sbdataout : out std_logic := '0';
sbdatain : in std_logic
);
end entity;
architecture behavorial of RAM9X8_SerialBusMaster is
signal dataBufIn : std_logic_vector(15 downto 0) := (others => '0');
signal dataBufOut : std_logic_vector(15 downto 0) := (others => '0');
signal cmdBuf : std_logic_vector(15 downto 0) := (others => '0');
signal controlBuf : std_logic_vector(15 downto 0) := (others => '0');
signal direction : std_logic := '0';
signal addressToTransmit : std_logic_vector(7 downto 0) := x"00";
signal dataToTransmit : std_logic_vector(15 downto 0) := x"0000";
signal dataFromDevices : std_logic_vector(15 downto 0) := x"0000";
type CommunicationState_start is (Waiting, TransmitAddress, TransmitData, TransmitCRC, TransmitCheck, ReceiveData, ReceiveCRC, ReceiveCheck, Timeout);
signal CommunicationState : CommunicationState_start := Waiting;
signal resetCRC : std_logic := '1';
signal CRC : std_logic_vector(3 downto 0) := x"0";
signal bufCRC : std_logic_vector(3 downto 0) := x"0";
signal dataCRC : std_logic_vector(31 downto 0) := x"00000000"; -- переключает
signal readyCRC : std_logic := '0'; -- готовность контрольной суммы
signal lineBusy : std_logic := '1';
signal start : std_logic := '0';
signal startPrev : std_logic := '0';
begin
process (we, oe, ce)
variable addr : integer range 0 to 2**ADDRESS_BUS_WIDTH - 1 := 0;
begin
if (ce = '0') then -- Если микросхема выбрана
addr := conv_integer(address);
if (addr = SB_DATA_UPPER or addr = SB_DATA_LOWER or addr = SB_CMD_UPPER or addr = SB_CMD_LOWER
or addr = SB_CONTROL_UPPER or addr = SB_CONTROL_LOWER) then
if (oe = '0' and we = '1') then -- Если сигнал чтения активен, а записи нет
case addr is
when SB_DATA_UPPER =>
data <= dataBufOut(15 downto 8);
when SB_DATA_LOWER =>
data <= dataBufOut(7 downto 0);
when SB_CMD_UPPER =>
data <= cmdBuf(15 downto 8);
when SB_CMD_LOWER =>
data <= cmdBuf(7 downto 0);
when SB_CONTROL_UPPER =>
data <= controlBuf(15 downto 8);
start <= '0';
when SB_CONTROL_LOWER =>
data <= controlBuf(7 downto 0);
when others =>
data <= (others => 'Z'); -- Запретить запись на шину
end case;
elsif (oe = '1' and we = '0') then -- Если сигнал записи активен, а чтения нет
case addr is
when SB_DATA_UPPER =>
dataBufIn(15 downto 8) <= data;
when SB_DATA_LOWER =>
dataBufIn(7 downto 0) <= data;
when SB_CMD_UPPER =>
cmdBuf(15 downto 8) <= data;
start <= '1';
when SB_CMD_LOWER =>
cmdBuf(7 downto 0) <= data;
when others =>
data <= (others => 'Z'); -- Запретить запись на шину
end case;
else
data <= (others => 'Z'); -- Запретить запись на шину
end if;
else
data <= (others => 'Z'); -- Запретить запись на шину
end if;
else
data <= (others => 'Z'); -- Запретить запись на шину
end if;
end process;
process(clk) is
variable count : integer range 0 to 255 := 0;
variable halfPeriod : integer range 0 to 255 := 50;
variable pause : integer range 0 to 255 := 200;
variable state : integer range 0 to 1 := 1;
variable bitCnt : integer range -1 to 31 := 0;
variable latch : integer range 0 to 1 := 0;
begin
if(rising_edge (clk)) then
case CommunicationState is
when Waiting =>
sbclk <= '0';
bitCnt := 8;
latch := 0;
resetCRC <= '1';
count := 0;
sbdataout <= '0';
state := 1;
if start = '1' and startPrev = '0' then
direction <= cmdBuf(15);
dataCRC(24) <= cmdBuf(15);
addressToTransmit(7 downto 0) <= cmdBuf(7 downto 0);
dataCRC(23 downto 16) <= cmdBuf(7 downto 0);
dataToTransmit <= dataBufIn;
dataCRC(15 downto 0) <= dataBufIn;
controlBuf(15 downto 0) <= (others => '0');
halfPeriod := conv_integer(cmdBuf(14 downto 8));
CommunicationState <= TransmitAddress;
end if;
when Timeout =>
if count < pause then
sbclk <= '0';
count := count + 1;
else
controlBuf(1) <= '0';
CommunicationState <= Waiting;
end if;
when TransmitAddress =>
if bitCnt = -1 then
if direction = '1' then
CommunicationState <= TransmitData;
resetCRC <= '0';
else
CommunicationState <= ReceiveData;
end if;
bitCnt := 15;
else
if count < halfPeriod and state = 1 then
if count = 0 then
if latch = 0 then
sbdataout <= direction;
controlBuf(1) <= '1';
else
sbdataout <= addressToTransmit(bitCnt);
end if;
sbclk <= '0';
end if;
count := count + 1;
elsif count = halfPeriod and state = 1 then
latch := 1;
count := 0;
state := 0;
elsif count < halfPeriod and state = 0 then
if count = 0 then
sbclk <= '1';
end if;
count := count + 1;
elsif count = halfPeriod and state = 0 then
count := 0;
state := 1;
bitCnt := bitCnt - 1;
end if;
end if;
when TransmitData =>
if bitCnt = -1 then
CommunicationState <= TransmitCRC;
bitCnt := 3;
else
if count < halfPeriod and state = 1 then
if count = 0 then
sbdataout <= dataToTransmit(bitCnt);
sbclk <= '0';
end if;
count := count + 1;
elsif count = halfPeriod and state = 1 then
count := 0;
state := 0;
elsif count < halfPeriod and state = 0 then
if count = 0 then
sbclk <= '1';
end if;
count := count + 1;
elsif count = halfPeriod and state = 0 then
count := 0;
state := 1;
bitCnt := bitCnt - 1;
end if;
end if;
when TransmitCRC =>
if readyCRC = '1' then
if bitCnt = -1 then
CommunicationState <= TransmitCheck;
else
if count < halfPeriod and state = 1 then
if count = 0 then
sbdataout <= CRC(bitCnt);
sbclk <= '0';
end if;
count := count + 1;
elsif count = halfPeriod and state = 1 then
count := 0;
state := 0;
elsif count < halfPeriod and state = 0 then
if count = 0 then
sbclk <= '1';
end if;
count := count + 1;
elsif count = halfPeriod and state = 0 then
count := 0;
state := 1;
bitCnt := bitCnt - 1;
end if;
end if;
else
--CommunicationState <= Waiting;
count := 0;
CommunicationState <= Timeout;
controlBuf(15) <= '1';
end if;
when TransmitCheck =>
if count < halfPeriod and state = 1 then
if count = 0 then
sbclk <= '0';
end if;
count := count + 1;
else
count := 0;
if sbdatain = '0' then
controlBuf(0) <= '1';
else
controlBuf(14) <= '1';
end if;
--CommunicationState <= Waiting;
count := 0;
CommunicationState <= Timeout;
end if;
when ReceiveData =>
if bitCnt = -1 then
CommunicationState <= ReceiveCRC;
bitCnt := 3;
else
if count < halfPeriod and state = 1 then
if count = 0 then
sbclk <= '0';
end if;
count := count + 1;
elsif count = halfPeriod and state = 1 then
dataFromDevices(bitCnt) <= sbdatain;
count := 0;
state := 0;
elsif count < halfPeriod and state = 0 then
if count = 0 then
sbclk <= '1';
end if;
count := count + 1;
elsif count = halfPeriod and state = 0 then
count := 0;
state := 1;
bitCnt := bitCnt - 1;
end if;
end if;
when ReceiveCRC =>
if bitCnt = -1 then
CommunicationState <= ReceiveCheck;
else
if count < halfPeriod and state = 1 then
if count = 0 then
sbclk <= '0';
end if;
count := count + 1;
elsif count = halfPeriod and state = 1 then
bufCRC(BitCnt) <= sbdatain;
count := 0;
state := 0;
if bitCnt = 0 then
dataCRC(24) <= direction;
dataCRC(23 downto 16) <= addressToTransmit;
dataCRC(15 downto 0) <= dataFromDevices(15 downto 0);
resetCRC <= '0';
end if;
elsif count < halfPeriod and state = 0 then
if count = 0 then
sbclk <= '1';
end if;
count := count + 1;
elsif count = halfPeriod and state = 0 then
count := 0;
state := 1;
bitCnt := bitCnt - 1;
end if;
end if;
when ReceiveCheck =>
if readyCRC = '1' then
if bufCRC = CRC then
dataBufOut <= dataFromDevices;
controlBuf(0) <= '1';
else
controlBuf(13) <= '1';
end if;
else
controlBuf(12) <= '1';
end if;
--CommunicationState <= Waiting;
count := 0;
CommunicationState <= Timeout;
when others =>
end case;
startPrev <= start;
end if;
end process;
process(clk)
variable lacth : integer range 0 to 1 := 0;
variable bitCnt : integer range -1 to 24 := 0;
begin
if rising_edge(clk) then
if resetCRC = '1' then
bitCnt := 24;
CRC <= x"0";
lacth := 0;
readyCRC <= '0';
else
if readyCRC = '0' then
if lacth = 0 then
if bitCnt /= -1 then
CRC(3) <= CRC(2) xor CRC(3);
CRC(2) <= CRC(1) xor CRC(0);
CRC(1) <= CRC(0);
CRC(0) <= dataCRC(bitCnt) xor CRC(1);
bitCnt := bitCnt - 1;
else
bitCnt := 3;
lacth := 1;
end if;
else
if bitCnt /= -1 then
CRC(3) <= CRC(2) xor CRC(3);
CRC(2) <= CRC(1) xor CRC(0);
CRC(1) <= CRC(0);
CRC(0) <= '1' xor CRC(1);
bitCnt := bitCnt - 1;
else
readyCRC <= '1';
--countreadyCRC <= countreadyCRC + 1;
end if;
end if;
end if;
end if;
end if;
end process;
end behavorial;