altera/MainController/RAM9X8_OpticalBusMaster.vhd

290 lines
9.7 KiB
VHDL
Raw Normal View History

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity RAM9X8_OpticalBusMaster is
generic(
REG_ADDR_CMD_UPPER_BYTE : integer := 52;
REG_ADDR_CMD_LOWER_BYTE : integer := 53;
REG_ADDR_WORD_8_UPPER_BYTE : integer := 54;
REG_ADDR_WORD_8_LOWER_BYTE : integer := 55;
REG_ADDR_WORD_7_UPPER_BYTE : integer := 56;
REG_ADDR_WORD_7_LOWER_BYTE : integer := 57;
REG_ADDR_WORD_6_UPPER_BYTE : integer := 58;
REG_ADDR_WORD_6_LOWER_BYTE : integer := 59;
REG_ADDR_WORD_5_UPPER_BYTE : integer := 60;
REG_ADDR_WORD_5_LOWER_BYTE : integer := 61;
REG_ADDR_WORD_4_UPPER_BYTE : integer := 62;
REG_ADDR_WORD_4_LOWER_BYTE : integer := 63;
REG_ADDR_WORD_3_UPPER_BYTE : integer := 64;
REG_ADDR_WORD_3_LOWER_BYTE : integer := 65;
REG_ADDR_WORD_2_UPPER_BYTE : integer := 66;
REG_ADDR_WORD_2_LOWER_BYTE : integer := 67;
REG_ADDR_WORD_1_UPPER_BYTE : integer := 68;
REG_ADDR_WORD_1_LOWER_BYTE : integer := 69;
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;
obclk : out std_logic := '1';
obdata : out std_logic := '1'
);
end entity;
architecture behavorial of RAM9X8_OpticalBusMaster is
signal dataBuf : std_logic_vector(127 downto 0) := (others => '0');
signal dataToSend : std_logic_vector(127 downto 0) := (others => '0');
signal cmdBuf : std_logic_vector(15 downto 0) := (others => '0');
type CommunicationState_start is (Waiting, DataSending, CRCSending);
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(127 downto 0) := (others => '0'); -- переключает
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 = REG_ADDR_CMD_UPPER_BYTE or addr = REG_ADDR_CMD_LOWER_BYTE
or addr = REG_ADDR_WORD_8_UPPER_BYTE or addr = REG_ADDR_WORD_8_LOWER_BYTE
or addr = REG_ADDR_WORD_7_UPPER_BYTE or addr = REG_ADDR_WORD_7_LOWER_BYTE
or addr = REG_ADDR_WORD_6_UPPER_BYTE or addr = REG_ADDR_WORD_6_LOWER_BYTE
or addr = REG_ADDR_WORD_5_UPPER_BYTE or addr = REG_ADDR_WORD_5_LOWER_BYTE
or addr = REG_ADDR_WORD_4_UPPER_BYTE or addr = REG_ADDR_WORD_4_LOWER_BYTE
or addr = REG_ADDR_WORD_3_UPPER_BYTE or addr = REG_ADDR_WORD_3_LOWER_BYTE
or addr = REG_ADDR_WORD_2_UPPER_BYTE or addr = REG_ADDR_WORD_2_LOWER_BYTE
or addr = REG_ADDR_WORD_1_UPPER_BYTE or addr = REG_ADDR_WORD_1_LOWER_BYTE) then
if (oe = '0' and we = '1') then -- Если сигнал чтения активен, а записи нет
case addr is
when REG_ADDR_CMD_UPPER_BYTE =>
data <= cmdBuf(15 downto 8);
when REG_ADDR_CMD_LOWER_BYTE =>
data <= cmdBuf(7 downto 0);
when REG_ADDR_WORD_8_UPPER_BYTE =>
data <= dataBuf(127 downto 120);
when REG_ADDR_WORD_8_LOWER_BYTE =>
data <= dataBuf(119 downto 112);
when REG_ADDR_WORD_7_UPPER_BYTE =>
data <= dataBuf(111 downto 104);
when REG_ADDR_WORD_7_LOWER_BYTE =>
data <= dataBuf(103 downto 96);
when REG_ADDR_WORD_6_UPPER_BYTE =>
data <= dataBuf(95 downto 88);
when REG_ADDR_WORD_6_LOWER_BYTE =>
data <= dataBuf(87 downto 80);
when REG_ADDR_WORD_5_UPPER_BYTE =>
data <= dataBuf(79 downto 72);
when REG_ADDR_WORD_5_LOWER_BYTE =>
data <= dataBuf(71 downto 64);
when REG_ADDR_WORD_4_UPPER_BYTE =>
data <= dataBuf(63 downto 56);
when REG_ADDR_WORD_4_LOWER_BYTE =>
data <= dataBuf(55 downto 48);
when REG_ADDR_WORD_3_UPPER_BYTE =>
data <= dataBuf(47 downto 40);
when REG_ADDR_WORD_3_LOWER_BYTE =>
data <= dataBuf(39 downto 32);
when REG_ADDR_WORD_2_UPPER_BYTE =>
data <= dataBuf(31 downto 24);
when REG_ADDR_WORD_2_LOWER_BYTE =>
data <= dataBuf(23 downto 16);
when REG_ADDR_WORD_1_UPPER_BYTE =>
data <= dataBuf(15 downto 8);
when REG_ADDR_WORD_1_LOWER_BYTE =>
data <= dataBuf(7 downto 0);
when others =>
data <= (others => 'Z'); -- Запретить запись на шину
end case;
elsif (oe = '1' and we = '0') then -- Если сигнал записи активен, а чтения нет
case addr is
when REG_ADDR_CMD_UPPER_BYTE =>
cmdBuf(15 downto 8) <= data;
when REG_ADDR_CMD_LOWER_BYTE =>
cmdBuf(7 downto 0) <= data;
when REG_ADDR_WORD_8_UPPER_BYTE =>
dataBuf(127 downto 120) <= data;
when REG_ADDR_WORD_8_LOWER_BYTE =>
dataBuf(119 downto 112) <= data;
when REG_ADDR_WORD_7_UPPER_BYTE =>
dataBuf(111 downto 104) <= data;
when REG_ADDR_WORD_7_LOWER_BYTE =>
dataBuf(103 downto 96) <= data;
when REG_ADDR_WORD_6_UPPER_BYTE =>
dataBuf(95 downto 88) <= data;
when REG_ADDR_WORD_6_LOWER_BYTE =>
dataBuf(87 downto 80) <= data;
when REG_ADDR_WORD_5_UPPER_BYTE =>
dataBuf(79 downto 72) <= data;
when REG_ADDR_WORD_5_LOWER_BYTE =>
dataBuf(71 downto 64) <= data;
when REG_ADDR_WORD_4_UPPER_BYTE =>
dataBuf(63 downto 56) <= data;
when REG_ADDR_WORD_4_LOWER_BYTE =>
dataBuf(55 downto 48) <= data;
when REG_ADDR_WORD_3_UPPER_BYTE =>
dataBuf(47 downto 40) <= data;
when REG_ADDR_WORD_3_LOWER_BYTE =>
dataBuf(39 downto 32) <= data;
when REG_ADDR_WORD_2_UPPER_BYTE =>
dataBuf(31 downto 24) <= data;
when REG_ADDR_WORD_2_LOWER_BYTE =>
dataBuf(23 downto 16) <= data;
when REG_ADDR_WORD_1_UPPER_BYTE =>
dataBuf(15 downto 8) <= data;
when REG_ADDR_WORD_1_LOWER_BYTE =>
dataBuf(7 downto 0) <= data;
when others =>
data <= (others => 'Z'); -- Запретить запись на шину
end case;
if (addr = REG_ADDR_WORD_1_LOWER_BYTE) then
start <= '1';
else
start <= '0';
end if;
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 31 := 0;
variable countValue : integer range 0 to 31 := 25;
variable state : integer range 0 to 1 := 0;
variable bitCnt : integer range 0 to 127 := 0;
begin
if(rising_edge (clk)) then
case CommunicationState is
when Waiting =>
obclk <= '1';
obdata <= '1';
resetCRC <= '1';
count := 0;
state := 0;
if start = '1' and startPrev = '0' then
dataToSend <= dataBuf;
dataCRC <= dataBuf;
bitCnt := (conv_integer(cmdBuf(2 downto 0)) * 16) - 1;
CommunicationState <= DataSending;
resetCRC <= '0';
end if;
when DataSending =>
if count < countValue and state = 0 then
if count = 0 then
obdata <= dataToSend(bitCnt);
end if;
count := count + 1;
elsif count = countValue and state = 0 then
obclk <= '0';
count := 0;
state := 1;
elsif count < countValue and state = 1 then
count := count + 1;
elsif count = countValue and state = 1 then
obclk <= '1';
count := 0;
state := 0;
if bitCnt > 0 then
bitCnt := bitCnt - 1;
else
bitCnt := 3;
CommunicationState <= CRCSending;
end if;
end if;
when CRCSending =>
if count < countValue and state = 0 then
if count = 0 then
obdata <= CRC(bitCnt);
end if;
count := count + 1;
elsif count = countValue and state = 0 then
obclk <= '0';
count := 0;
state := 1;
elsif count < countValue and state = 1 then
count := count + 1;
elsif count = countValue and state = 1 then
obclk <= '1';
count := 0;
state := 0;
if bitCnt > 0 then
bitCnt := bitCnt - 1;
else
CommunicationState <= Waiting;
end if;
end if;
when others =>
CommunicationState <= Waiting;
end case;
startPrev <= start;
end if;
end process;
process(clk)
variable lacth : integer range 0 to 1 := 0;
variable bitCnt : integer range -1 to 127 := 0;
begin
if rising_edge(clk) then
if resetCRC = '1' then
bitCnt := (conv_integer(cmdBuf(2 downto 0)) * 16) - 1;
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';
end if;
end if;
end if;
end if;
end if;
end process;
end behavorial;