altera/MainController/RAM9X8_OpticalBusMaster.vhd

298 lines
10 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_OpticalBusMaster is
generic(
REG_ADDR_CMD_LOWER_BYTE : integer := 54;
REG_ADDR_CMD_UPPER_BYTE : integer := 55;
REG_ADDR_WORD_8_LOWER_BYTE : integer := 56;
REG_ADDR_WORD_8_UPPER_BYTE : integer := 57;
REG_ADDR_WORD_7_LOWER_BYTE : integer := 58;
REG_ADDR_WORD_7_UPPER_BYTE : integer := 59;
REG_ADDR_WORD_6_LOWER_BYTE : integer := 60;
REG_ADDR_WORD_6_UPPER_BYTE : integer := 61;
REG_ADDR_WORD_5_LOWER_BYTE : integer := 62;
REG_ADDR_WORD_5_UPPER_BYTE : integer := 63;
REG_ADDR_WORD_4_LOWER_BYTE : integer := 64;
REG_ADDR_WORD_4_UPPER_BYTE : integer := 65;
REG_ADDR_WORD_3_LOWER_BYTE : integer := 66;
REG_ADDR_WORD_3_UPPER_BYTE : integer := 67;
REG_ADDR_WORD_2_LOWER_BYTE : integer := 68;
REG_ADDR_WORD_2_UPPER_BYTE : integer := 69;
REG_ADDR_WORD_1_LOWER_BYTE : integer := 70;
REG_ADDR_WORD_1_UPPER_BYTE : integer := 71;
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) := x"0004";
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_UPPER_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;
if conv_integer(cmdBuf(3 downto 0)) < 9 and conv_integer(cmdBuf(3 downto 0)) > 0 then
bitCnt := (conv_integer(cmdBuf(3 downto 0)) * 16) - 1;
else
bitCnt := 63;
end if;
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
if conv_integer(cmdBuf(3 downto 0)) < 9 and conv_integer(cmdBuf(3 downto 0)) > 0 then
bitCnt := (conv_integer(cmdBuf(3 downto 0)) * 16) - 1;
else
bitCnt := 63;
end if;
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;