360 lines
11 KiB
VHDL
360 lines
11 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
|
||
|
|
||
|
type mem is array (511 downto 0) of std_logic_vector(DATA_BUS_WIDTH - 1 downto 0);
|
||
|
signal memory : mem;
|
||
|
|
||
|
signal wePrev : std_logic := '0';
|
||
|
signal oePrev : std_logic := '0';
|
||
|
signal cePrev : std_logic := '0';
|
||
|
|
||
|
type MemoryMachine is (Waiting, Writing, Reading);
|
||
|
signal stateMM : MemoryMachine := Waiting;
|
||
|
|
||
|
signal dataBufIn : std_logic_vector(DATA_BUS_WIDTH*2 - 1 downro 0);
|
||
|
signal dataBufOut : std_logic_vector(DATA_BUS_WIDTH*2 - 1 downro 0);
|
||
|
signal cmdBuf : std_logic_vector(DATA_BUS_WIDTH*2 - 1 downro 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, TransmiteAddress, TransmiteData, TransmiteCRC, TransmiteCheck, 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';
|
||
|
|
||
|
begin
|
||
|
|
||
|
process(clk)
|
||
|
variable addr : integer range 0 to 2^ADDRESS_BUS_WIDTH := 0;
|
||
|
begin
|
||
|
if rising_edge(clk) then
|
||
|
case stateMM is
|
||
|
when Waiting =>
|
||
|
if ce = '0' and cePrev = '1' 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
|
||
|
stateMM <= Reading;
|
||
|
else
|
||
|
stateMM <= Writing;
|
||
|
end if;
|
||
|
end if;
|
||
|
else
|
||
|
start <= '0';
|
||
|
data <= (others => 'Z');
|
||
|
end if;
|
||
|
when Reading =>
|
||
|
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 =>
|
||
|
end case;
|
||
|
if oe = '1' and oePrev = '0' then
|
||
|
stateMM <= Waiting;
|
||
|
elsif ce = '1' then
|
||
|
stateMM <= Waiting;
|
||
|
end if;
|
||
|
when Writing =>
|
||
|
if we = '0' and wePrev = '1' 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 =>
|
||
|
end case;
|
||
|
stateMM <= Waiting;
|
||
|
elsif ce = '1' then
|
||
|
stateMM <= Waiting;
|
||
|
end if;
|
||
|
when others =>
|
||
|
end case;
|
||
|
|
||
|
oePrev <= oe;
|
||
|
cePrev <= ce;
|
||
|
wePrev <= we;
|
||
|
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;
|