altera/MainController/RAM9X8_SerialBusMaster.vhd

333 lines
10 KiB
VHDL

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity RAM9X8_SerialBusMaster is
generic(
REG_ADDR_DATA_UPPER_BYTE : integer := 0;
REG_ADDR_DATA_LOWER_BYTE : integer := 1;
REG_ADDR_CMD_UPPER_BYTE : integer := 2;
REG_ADDR_CMD_LOWER_BYTE : integer := 3;
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(DATA_BUS_WIDTH*2 - 1 downto 0);
signal dataBufOut : std_logic_vector(DATA_BUS_WIDTH*2 - 1 downto 0);
signal cmdBuf : std_logic_vector(DATA_BUS_WIDTH*2 - 1 downto 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);
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 511 := 0;
begin
if (ce = '0') then -- Если микросхема выбрана
addr := conv_integer(address);
if (addr = REG_ADDR_DATA_UPPER_BYTE or addr = REG_ADDR_DATA_LOWER_BYTE or addr = REG_ADDR_CMD_UPPER_BYTE or addr = REG_ADDR_CMD_LOWER_BYTE) then
if (oe = '0') then -- Если сигнал чтения активен
case addr is
when REG_ADDR_DATA_UPPER_BYTE =>
data <= dataBufOut(15 downto 8);
when REG_ADDR_DATA_LOWER_BYTE =>
data <= dataBufOut(7 downto 0);
when REG_ADDR_CMD_UPPER_BYTE =>
data <= cmdBuf(15 downto 8);
when REG_ADDR_CMD_LOWER_BYTE =>
data <= cmdBuf(7 downto 0);
when others =>
data <= (others => 'Z'); -- Запретить запись на шину
end case;
elsif (we = '0') then -- Если сигнал записи активен
case addr is
when REG_ADDR_DATA_UPPER_BYTE =>
dataBufIn(15 downto 8) <= data;
when REG_ADDR_DATA_LOWER_BYTE =>
dataBufIn(7 downto 0) <= data;
when REG_ADDR_CMD_UPPER_BYTE =>
cmdBuf(15 downto 8) <= data;
when REG_ADDR_CMD_LOWER_BYTE =>
cmdBuf(7 downto 0) <= data;
start <= '1';
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 countValue : integer range 0 to 255 := 63;
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';
sbdataout <= '0';
lineBusy <= '0';
count := 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;
CommunicationState <= TransmitAddress;
lineBusy <= '1';
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 < countValue and state = 1 then
if latch = 0 then
sbdataout <= direction;
else
sbdataout <= addressToTransmit(bitCnt);
end if;
sbclk <= '0';
count := count + 1;
elsif count = countValue and state = 1 then
latch := 1;
count := 0;
state := 0;
elsif count < countValue and state = 0 then
sbclk <= '1';
count := count + 1;
elsif count = countValue 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 < countValue and state = 1 then
sbdataout <= data(bitCnt);
sbclk <= '0';
count := count + 1;
elsif count = countValue and state = 1 then
count := 0;
state := 0;
elsif count < countValue and state = 0 then
sbclk <= '1';
count := count + 1;
elsif count = countValue 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;
--errors(1) <= '0';
else
if count < count and state = 1 then
sbdataout <= CRC(bitCnt);
sbclk <= '0';
count := count + 1;
elsif count = countValue and state = 1 then
count := 0;
state := 0;
elsif count < countValue and state = 0 then
sbclk <= '1';
count := count + 1;
elsif count = countValue and state = 0 then
count := 0;
state := 1;
bitCnt := bitCnt - 1;
end if;
end if;
else
CommunicationState <= Waiting;
--errors(1) <= '1';
--countError1 <= countError1 + 1;
end if;
when TransmitCheck =>
if count < countValue and state = 1 then
sbclk <= '0';
count := count + 1;
else
count := 0;
state := 0;
if sbdatain = '0' then
--countSuccessfulTransmite <= countSuccessfulTransmite + 1;
--errors(0) <= '0';
else
--errors(0) <= '1';
--countError0 <= countError0 + 1;
end if;
CommunicationState <= Waiting;
end if;
when ReceiveData =>
if bitCnt = -1 then
CommunicationState <= ReceiveCRC;
bitCnt := 3;
else
if count < countValue and state = 1 then
sbclk <= '0';
count := count + 1;
elsif count = countValue and state = 1 then
dataFromDevices(bitCnt) <= sbdatain;
count := 0;
state := 0;
elsif count < countValue and state = 0 then
sbclk <= '1';
count := count + 1;
elsif count = countValue 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 < countValue and state = 1 then
sbclk <= '0';
count := count + 1;
elsif count = countValue 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 < countValue and state = 0 then
sbclk <= '1';
count := count + 1;
elsif count = countValue 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
--countSuccessfulReceive <= countSuccessfulReceive + 1;
dataBufOut <= dataFromDevices;
--errors(3) <= '0';
else
--errors(3) <= '1';
--countError3 <= countError3 + 1;
end if;
--errors(2) <= '0';
else
--errors(2) <= '1';
--countError2 <= countError2 + 1;
end if;
CommunicationState <= Waiting;
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;