372 lines
12 KiB
VHDL
372 lines
12 KiB
VHDL
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 countPause : integer range 0 to 255 := 0;
|
||
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');
|
||
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; |