altera/MainController/RAM9X8_PWM.vhd

368 lines
12 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_PWM is
generic(
PWM_BASE_ADDRESS : integer := 16;
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 PWM_MODE_CONTROL_LOWER : integer := PWM_BASE_ADDRESS;
signal PWM_MODE_CONTROL_UPPER : integer := PWM_BASE_ADDRESS + 1;
signal PWM_MASK_2_LOWER : integer := PWM_BASE_ADDRESS + 2;
signal PWM_MASK_2_UPPER : integer := PWM_BASE_ADDRESS + 3;
signal PWM_MASK_1_LOWER : integer := PWM_BASE_ADDRESS + 4;
signal PWM_MASK_1_UPPER : integer := PWM_BASE_ADDRESS + 5;
signal PWM_DIRECT_CONTROL_2_LOWER : integer := PWM_BASE_ADDRESS + 6;
signal PWM_DIRECT_CONTROL_2_UPPER : integer := PWM_BASE_ADDRESS + 7;
signal PWM_DIRECT_CONTROL_1_LOWER : integer := PWM_BASE_ADDRESS + 8;
signal PWM_DIRECT_CONTROL_1_UPPER : integer := PWM_BASE_ADDRESS + 9;
signal PWM_PERIOD_LOWER : integer := PWM_BASE_ADDRESS + 10;
signal PWM_PERIOD_UPPER : integer := PWM_BASE_ADDRESS + 11;
signal PWM_DIRECTION_2_LOWER : integer := PWM_BASE_ADDRESS + 12;
signal PWM_DIRECTION_2_UPPER : integer := PWM_BASE_ADDRESS + 13;
signal PWM_DIRECTION_1_LOWER : integer := PWM_BASE_ADDRESS + 14;
signal PWM_DIRECTION_1_UPPER : integer := PWM_BASE_ADDRESS + 15;
signal PWM_CHANNEL_LOWER : integer := PWM_BASE_ADDRESS + 16;
signal PWM_CHANNEL_UPPER : integer := PWM_BASE_ADDRESS + 17;
signal PWM_TIMING_LOWER : integer := PWM_BASE_ADDRESS + 18;
signal PWM_TIMING_UPPER : integer := PWM_BASE_ADDRESS + 19;
signal PWM_CMD_LOWER : integer := PWM_BASE_ADDRESS + 20;
signal PWM_CMD_UPPER : integer := PWM_BASE_ADDRESS + 21;
signal PWM_CONTROL_LOWER : integer := PWM_BASE_ADDRESS + 22;
signal PWM_CONTROL_UPPER : integer := PWM_BASE_ADDRESS + 23;
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 = PWM_MODE_CONTROL_UPPER or addr = PWM_MODE_CONTROL_LOWER
or addr = PWM_MASK_2_UPPER or addr = PWM_MASK_2_LOWER or addr = PWM_MASK_1_UPPER or addr = PWM_MASK_1_LOWER
or addr = PWM_DIRECT_CONTROL_2_UPPER or addr = PWM_DIRECT_CONTROL_2_LOWER or addr = PWM_DIRECT_CONTROL_1_UPPER or addr = PWM_DIRECT_CONTROL_1_LOWER
or addr = PWM_PERIOD_UPPER or addr = PWM_PERIOD_LOWER
or addr = PWM_DIRECTION_2_UPPER or addr = PWM_DIRECTION_2_LOWER or addr = PWM_DIRECTION_1_UPPER or addr = PWM_DIRECTION_1_LOWER
or addr = PWM_CHANNEL_UPPER or addr = PWM_CHANNEL_LOWER or addr = PWM_TIMING_UPPER or addr = PWM_TIMING_LOWER
or addr = PWM_CMD_UPPER or addr = PWM_CMD_LOWER or addr = PWM_CONTROL_UPPER or addr = PWM_CONTROL_LOWER) then
if (oe = '0' and we = '1') then -- Если сигнал чтения активен, а записи нет
case addr is
when PWM_MODE_CONTROL_UPPER =>
data <= modeBuf(15 downto 8);
when PWM_MODE_CONTROL_LOWER =>
data <= modeBuf(7 downto 0);
when PWM_MASK_2_UPPER =>
data <= maskBuf(31 downto 24);
when PWM_MASK_2_LOWER =>
data <= maskBuf(23 downto 16);
when PWM_MASK_1_UPPER =>
data <= maskBuf(15 downto 8);
when PWM_MASK_1_LOWER =>
data <= maskBuf(7 downto 0);
when PWM_DIRECT_CONTROL_2_UPPER =>
data <= directControlBuf(31 downto 24);
when PWM_DIRECT_CONTROL_2_LOWER =>
data <= directControlBuf(23 downto 16);
when PWM_DIRECT_CONTROL_1_UPPER =>
data <= directControlBuf(15 downto 8);
when PWM_DIRECT_CONTROL_1_LOWER =>
data <= directControlBuf(7 downto 0);
when PWM_PERIOD_UPPER =>
data <= periodBuf(15 downto 8);
when PWM_PERIOD_LOWER =>
data <= periodBuf(7 downto 0);
when PWM_DIRECTION_2_UPPER =>
data <= directionBuf(31 downto 24);
when PWM_DIRECTION_2_LOWER =>
data <= directionBuf(23 downto 16);
when PWM_DIRECTION_1_UPPER =>
data <= directionBuf(15 downto 8);
when PWM_DIRECTION_1_LOWER =>
data <= directionBuf(7 downto 0);
when PWM_CHANNEL_UPPER =>
data <= channelBuf(15 downto 8);
when PWM_CHANNEL_LOWER =>
data <= channelBuf(7 downto 0);
when PWM_TIMING_UPPER =>
data <= memory(conv_integer(channelBuf))(15 downto 8);
when PWM_TIMING_LOWER =>
data <= memory(conv_integer(channelBuf))(7 downto 0);
when PWM_CMD_UPPER =>
data <= cmdBuf(15 downto 8);
when PWM_CMD_LOWER =>
data <= cmdBuf(7 downto 0);
when PWM_CONTROL_UPPER =>
data <= controlBuf(15 downto 8);
when PWM_CONTROL_LOWER =>
data <= controlBuf(7 downto 0);
when others =>
data <= (others => 'Z'); -- Запретить запись на шину
end case;
if addr /= PWM_CONTROL_LOWER then
enableWriteControlBuf <= '1';
else
enableWriteControlBuf <= '0';
end if;
elsif (oe = '1' and we = '0') then -- Если сигнал записи активен, а чтения нет
case addr is
when PWM_MODE_CONTROL_UPPER =>
modeBuf(15 downto 8) <= data;
when PWM_MODE_CONTROL_LOWER =>
modeBuf(7 downto 0) <= data;
when PWM_MASK_2_UPPER =>
maskBuf(31 downto 24) <= data;
when PWM_MASK_2_LOWER =>
maskBuf(23 downto 16) <= data;
when PWM_MASK_1_UPPER =>
maskBuf(15 downto 8) <= data;
when PWM_MASK_1_LOWER =>
maskBuf(7 downto 0) <= data;
when PWM_DIRECT_CONTROL_2_UPPER =>
directControlBuf(31 downto 24) <= data;
when PWM_DIRECT_CONTROL_2_LOWER =>
directControlBuf(23 downto 16) <= data;
when PWM_DIRECT_CONTROL_1_UPPER =>
directControlBuf(15 downto 8) <= data;
when PWM_DIRECT_CONTROL_1_LOWER =>
directControlBuf(7 downto 0) <= data;
when PWM_PERIOD_UPPER =>
periodBuf(15 downto 8) <= data;
when PWM_PERIOD_LOWER =>
periodBuf(7 downto 0) <= data;
when PWM_DIRECTION_2_UPPER =>
directionBuf(31 downto 24) <= data;
when PWM_DIRECTION_2_LOWER =>
directionBuf(23 downto 16) <= data;
when PWM_DIRECTION_1_UPPER =>
directionBuf(15 downto 8) <= data;
when PWM_DIRECTION_1_LOWER =>
directionBuf(7 downto 0) <= data;
when PWM_CHANNEL_UPPER =>
channelBuf(15 downto 8) <= data;
when PWM_CHANNEL_LOWER =>
channelBuf(7 downto 0) <= data;
when PWM_TIMING_UPPER =>
memory(conv_integer(channelBuf))(15 downto 8) <= data;
when PWM_TIMING_LOWER =>
memory(conv_integer(channelBuf))(7 downto 0) <= data;
when PWM_CMD_UPPER =>
cmdBuf(15 downto 8) <= data;
when PWM_CMD_LOWER =>
cmdBuf(7 downto 0) <= data;
-- when PWM_CONTROL_UPPER =>
-- controlBuf(15 downto 8) <= data;
-- when PWM_CONTROL_LOWER =>
-- 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;