altera/MainController/RAM9X8_PWM.vhd

366 lines
12 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_PWM is
generic(
REG_ADDR_MODE_CONTROL_UPPER_BYTE : integer := 14;
REG_ADDR_MODE_CONTROL_LOWER_BYTE : integer := 15;
REG_ADDR_MASK_2_UPPER_BYTE : integer := 16;
REG_ADDR_MASK_2_LOWER_BYTE : integer := 17;
REG_ADDR_MASK_1_UPPER_BYTE : integer := 18;
REG_ADDR_MASK_1_LOWER_BYTE : integer := 19;
REG_ADDR_DIRECT_CONTROL_2_UPPER_BYTE : integer := 20;
REG_ADDR_DIRECT_CONTROL_2_LOWER_BYTE : integer := 21;
REG_ADDR_DIRECT_CONTROL_1_UPPER_BYTE : integer := 22;
REG_ADDR_DIRECT_CONTROL_1_LOWER_BYTE : integer := 23;
REG_ADDR_PERIOD_UPPER_BYTE : integer := 24;
REG_ADDR_PERIOD_LOWER_BYTE : integer := 25;
REG_ADDR_DIRECTION_2_UPPER_BYTE : integer := 26;
REG_ADDR_DIRECTION_2_LOWER_BYTE : integer := 27;
REG_ADDR_DIRECTION_1_UPPER_BYTE : integer := 28;
REG_ADDR_DIRECTION_1_LOWER_BYTE : integer := 29;
REG_ADDR_CHANNEL_UPPER_BYTE : integer := 30;
REG_ADDR_CHANNEL_LOWER_BYTE : integer := 31;
REG_ADDR_TIMING_UPPER_BYTE : integer := 32;
REG_ADDR_TIMING_LOWER_BYTE : integer := 33;
REG_ADDR_CMD_UPPER_BYTE : integer := 34;
REG_ADDR_CMD_LOWER_BYTE : integer := 35;
REG_ADDR_CONTROL_UPPER_BYTE : integer := 36;
REG_ADDR_CONTROL_LOWER_BYTE : integer := 37;
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;
tk : out std_logic_vector(31 downto 0) := (others => '1');
interrupt : out std_logic := '1';
pwm : in std_logic_vector(5 downto 0);
error : in std_logic
);
end entity;
architecture behavorial of RAM9X8_PWM is
signal modeBuf : std_logic_vector(15 downto 0) := (others => '0');
signal maskBuf : std_logic_vector(31 downto 0) := (others => '1');
signal directControlBuf : std_logic_vector(31 downto 0) := (others => '1');
signal periodBuf : std_logic_vector(15 downto 0) := (others => '0');
signal directionBuf : std_logic_vector(31 downto 0) := (others => '0');
signal channelBuf : 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 tkBuf : std_logic_vector(31 downto 0) := (others => '1');
type mem is array (31 downto 0) of std_logic_vector(15 downto 0);
signal memory : mem;
signal memoryBuf : mem;
signal pwm3level : std_logic_vector(31 downto 0) := (others => '1');
signal upDown : std_logic := '0';
signal upDownPrev : std_logic := '0';
signal interruptBuf : std_logic := '0';
signal period : std_logic_vector(15 downto 0) := (others => '0');
signal counter : std_logic_vector(15 downto 0) := (others => '0');
signal enableWriteControlBuf : std_logic := '1';
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_MODE_CONTROL_UPPER_BYTE or addr = REG_ADDR_MODE_CONTROL_LOWER_BYTE
or addr = REG_ADDR_MASK_2_UPPER_BYTE or addr = REG_ADDR_MASK_2_LOWER_BYTE or addr = REG_ADDR_MASK_1_UPPER_BYTE or addr = REG_ADDR_MASK_1_LOWER_BYTE
or addr = REG_ADDR_DIRECT_CONTROL_2_UPPER_BYTE or addr = REG_ADDR_DIRECT_CONTROL_2_LOWER_BYTE or addr = REG_ADDR_DIRECT_CONTROL_1_UPPER_BYTE or addr = REG_ADDR_DIRECT_CONTROL_1_LOWER_BYTE
or addr = REG_ADDR_PERIOD_UPPER_BYTE or addr = REG_ADDR_PERIOD_LOWER_BYTE
or addr = REG_ADDR_DIRECTION_2_UPPER_BYTE or addr = REG_ADDR_DIRECTION_2_LOWER_BYTE or addr = REG_ADDR_DIRECTION_1_UPPER_BYTE or addr = REG_ADDR_DIRECTION_1_LOWER_BYTE
or addr = REG_ADDR_CHANNEL_UPPER_BYTE or addr = REG_ADDR_CHANNEL_LOWER_BYTE or addr = REG_ADDR_TIMING_UPPER_BYTE or addr = REG_ADDR_TIMING_LOWER_BYTE
or addr = REG_ADDR_CMD_UPPER_BYTE or addr = REG_ADDR_CMD_LOWER_BYTE or addr = REG_ADDR_CONTROL_UPPER_BYTE or addr = REG_ADDR_CONTROL_LOWER_BYTE) then
if (oe = '0' and we = '1') then -- Если сигнал чтения активен, а записи нет
case addr is
when REG_ADDR_MODE_CONTROL_UPPER_BYTE =>
data <= modeBuf(15 downto 8);
when REG_ADDR_MODE_CONTROL_LOWER_BYTE =>
data <= modeBuf(7 downto 0);
when REG_ADDR_MASK_2_UPPER_BYTE =>
data <= maskBuf(31 downto 24);
when REG_ADDR_MASK_2_LOWER_BYTE =>
data <= maskBuf(23 downto 16);
when REG_ADDR_MASK_1_UPPER_BYTE =>
data <= maskBuf(15 downto 8);
when REG_ADDR_MASK_1_LOWER_BYTE =>
data <= maskBuf(7 downto 0);
when REG_ADDR_DIRECT_CONTROL_2_UPPER_BYTE =>
data <= directControlBuf(31 downto 24);
when REG_ADDR_DIRECT_CONTROL_2_LOWER_BYTE =>
data <= directControlBuf(23 downto 16);
when REG_ADDR_DIRECT_CONTROL_1_UPPER_BYTE =>
data <= directControlBuf(15 downto 8);
when REG_ADDR_DIRECT_CONTROL_1_LOWER_BYTE =>
data <= directControlBuf(7 downto 0);
when REG_ADDR_PERIOD_UPPER_BYTE =>
data <= periodBuf(15 downto 8);
when REG_ADDR_PERIOD_LOWER_BYTE =>
data <= periodBuf(7 downto 0);
when REG_ADDR_DIRECTION_2_UPPER_BYTE =>
data <= directionBuf(31 downto 24);
when REG_ADDR_DIRECTION_2_LOWER_BYTE =>
data <= directionBuf(23 downto 16);
when REG_ADDR_DIRECTION_1_UPPER_BYTE =>
data <= directionBuf(15 downto 8);
when REG_ADDR_DIRECTION_1_LOWER_BYTE =>
data <= directionBuf(7 downto 0);
when REG_ADDR_CHANNEL_UPPER_BYTE =>
data <= channelBuf(15 downto 8);
when REG_ADDR_CHANNEL_LOWER_BYTE =>
data <= channelBuf(7 downto 0);
when REG_ADDR_TIMING_UPPER_BYTE =>
data <= memory(conv_integer(channelBuf))(15 downto 8);
when REG_ADDR_TIMING_LOWER_BYTE =>
data <= memory(conv_integer(channelBuf))(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 REG_ADDR_CONTROL_UPPER_BYTE =>
data <= controlBuf(15 downto 8);
when REG_ADDR_CONTROL_LOWER_BYTE =>
data <= controlBuf(7 downto 0);
when others =>
data <= (others => 'Z'); -- Запретить запись на шину
end case;
if addr /= REG_ADDR_CONTROL_UPPER_BYTE then
enableWriteControlBuf <= '1';
else
enableWriteControlBuf <= '0';
end if;
elsif (oe = '1' and we = '0') then -- Если сигнал записи активен, а чтения нет
case addr is
when REG_ADDR_MODE_CONTROL_UPPER_BYTE =>
modeBuf(15 downto 8) <= data;
when REG_ADDR_MODE_CONTROL_LOWER_BYTE =>
modeBuf(7 downto 0) <= data;
when REG_ADDR_MASK_2_UPPER_BYTE =>
maskBuf(31 downto 24) <= data;
when REG_ADDR_MASK_2_LOWER_BYTE =>
maskBuf(23 downto 16) <= data;
when REG_ADDR_MASK_1_UPPER_BYTE =>
maskBuf(15 downto 8) <= data;
when REG_ADDR_MASK_1_LOWER_BYTE =>
maskBuf(7 downto 0) <= data;
when REG_ADDR_DIRECT_CONTROL_2_UPPER_BYTE =>
directControlBuf(31 downto 24) <= data;
when REG_ADDR_DIRECT_CONTROL_2_LOWER_BYTE =>
directControlBuf(23 downto 16) <= data;
when REG_ADDR_DIRECT_CONTROL_1_UPPER_BYTE =>
directControlBuf(15 downto 8) <= data;
when REG_ADDR_DIRECT_CONTROL_1_LOWER_BYTE =>
directControlBuf(7 downto 0) <= data;
when REG_ADDR_PERIOD_UPPER_BYTE =>
periodBuf(15 downto 8) <= data;
when REG_ADDR_PERIOD_LOWER_BYTE =>
periodBuf(7 downto 0) <= data;
when REG_ADDR_DIRECTION_2_UPPER_BYTE =>
directionBuf(31 downto 24) <= data;
when REG_ADDR_DIRECTION_2_LOWER_BYTE =>
directionBuf(23 downto 16) <= data;
when REG_ADDR_DIRECTION_1_UPPER_BYTE =>
directionBuf(15 downto 8) <= data;
when REG_ADDR_DIRECTION_1_LOWER_BYTE =>
directionBuf(7 downto 0) <= data;
when REG_ADDR_CHANNEL_UPPER_BYTE =>
channelBuf(15 downto 8) <= data;
when REG_ADDR_CHANNEL_LOWER_BYTE =>
channelBuf(7 downto 0) <= data;
when REG_ADDR_TIMING_UPPER_BYTE =>
memory(conv_integer(channelBuf))(15 downto 8) <= data;
when REG_ADDR_TIMING_LOWER_BYTE =>
memory(conv_integer(channelBuf))(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;
-- when REG_ADDR_CONTROL_UPPER_BYTE =>
-- controlBuf(15 downto 8) <= data;
-- when REG_ADDR_CONTROL_LOWER_BYTE =>
-- controlBuf(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
begin
if rising_edge(clk) then
if upDown = '0' then
if conv_integer(counter) < conv_integer(period) then
counter <= counter + 1;
else
counter <= period;
updown <= '1';
end if;
else
if conv_integer(counter) > 0 then
counter <= counter - 1;
else
counter <= (others => '0');
upDown <= '0';
end if;
end if;
upDownPrev <= upDown;
end if;
end process;
process(clk) is
variable count : integer range 0 to 7 := 0;
begin
if rising_edge(clk) then
if upDown /= upDownPrev then
count := 0;
if cmdBuf(14) = '0' then
interrupt <= '1';
else
if updown = '0' then
interrupt <= '1';
interruptBuf <= '1';
period <= periodBuf; -- новый период грузится сразу во время начала подъема пилы
end if;
end if;
else
if count < 7 then
count := count + 1;
else
interrupt <= '0';
interruptBuf <= '0';
end if;
end if;
end if;
end process;
process(interruptBuf) is
begin
if interruptBuf = '0' then
for i in 0 to 31 loop
memoryBuf(i) <= memory(i); -- а вот новые значения таймингов загрузяться только после счетчика. Но зато могут грузиться дважды за период, если выбран соответствующий тип формирования прерывания
end loop;
end if;
end process;
process(clk) is
begin
if rising_edge(clk) then
for i in 0 to 11 loop
if(conv_integer(memoryBuf(i)) > counter) then
if(directionBuf(i) = '0') then
pwm3level(i) <= '0';
else
pwm3level(i) <= '1';
end if;
else
if(directionBuf(i) = '0') then
pwm3level(i) <= '1';
else
pwm3level(i) <= '0';
end if;
end if;
end loop;
for i in 12 to 15 loop
if(conv_integer(memoryBuf(i)) > counter) then
pwm3level(i) <= '0';
else
pwm3level(i) <= '1';
end if;
end loop;
for i in 16 to 27 loop
if(conv_integer(memoryBuf(i)) > counter) then
if(directionBuf(i) = '0') then
pwm3level(i) <= '0';
else
pwm3level(i) <= '1';
end if;
else
if(directionBuf(i) = '0') then
pwm3level(i) <= '1';
else
pwm3level(i) <= '0';
end if;
end if;
end loop;
for i in 28 to 31 loop
if(conv_integer(memoryBuf(i)) > counter) then
pwm3level(i) <= '0';
else
pwm3level(i) <= '1';
end if;
end loop;
end if;
end process;
process(clk) is
begin
if rising_edge(clk) then
case modeBuf is
when x"0000" =>
tkBuf <= pwm3level;
when x"0001" =>
tkBuf <= (others => '1');
tkBuf(5 downto 0) <= pwm;
when x"0002" =>
tkBuf <= pwm3level;
when x"0003" =>
tkBuf <= directControlBuf;
when others =>
tkBuf <= (others => '1');
end case;
end if;
end process;
process(clk) is
begin
if rising_edge(clk) then
if cmdBuf(15) = '1' and error = '1' then
tk <= tkBuf or maskBuf;
else
tk <= (others => '1');
end if;
end if;
end process;
process(clk) is
begin
if rising_edge(clk) then
if enableWriteControlBuf = '1' then
controlBuf <= counter;
end if;
end if;
end process;
end behavorial;