Код:
--------
-- EPCS Memory Package
--------
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY epcs_mem IS
PORT(
RST : IN std_logic;
CLK : IN std_logic;
-- ASMI interface
--exemplar translate_off
ASMI_CLK : OUT std_logic;
ASMI_CS : OUT std_logic;
ASMI_MOSI : OUT std_logic;
ASMI_MISO : IN std_logic;
--exemplar translate_on
-- Local Interface
EPCS_CS : IN std_logic;
EPCS_RD : IN std_logic;
EPCS_WR : IN std_logic;
EPCS_ERASE : IN std_logic;
EPCS_ADDR : IN std_logic_vector(23 DOWNTO 0);
EPCS_DATA_IN : IN std_logic_vector(7 DOWNTO 0);
EPCS_DATA_OUT : OUT std_logic_vector(7 DOWNTO 0);
EPCS_WAITREQ : OUT std_logic
);
END ENTITY epcs_mem;
-----
-- Architecture
-----
ARCHITECTURE behaviour OF epcs_mem IS
CONSTANT flash_sector_code_offset : INTEGER := 2;
CONSTANT flash_sector_code_size : INTEGER := 1;
CONSTANT flash_sector_data_offset : INTEGER := 3;
CONSTANT flash_sector_data_size : INTEGER := 2;
CONSTANT dp_avalon_addr_width : INTEGER := 17;
CONSTANT cp_avalon_addr_width : INTEGER := 16;
CONSTANT delay_counter_data : INTEGER := 2;
CONSTANT avalon_clk_is_too_fast : std_logic := '0';
-----
-- Components
-----
--synthesis read_comments_as_HDL on
--COMPONENT cycloneii_asmiblock is
--PORT (
-- signal data0out : OUT STD_LOGIC;
-- signal oe : IN STD_LOGIC;
-- signal scein : IN STD_LOGIC;
-- signal dclkin : IN STD_LOGIC;
-- signal sdoin : IN STD_LOGIC
-- );
--END COMPONENT cycloneii_asmiblock;
--synthesis read_comments_as_HDL off
-----
-- State Machine
-----
TYPE state_type IS
(
idle,
read, read_loop,
write, write_enable_loop, write_cmd, write_cmd_loop, write_data, write_data_loop, write_status, write_status_loop, write_check_status,
release
);
SIGNAL current_state, next_state : state_type;
-----
-- Signals
-----
-- Misc
CONSTANT zeros_3bytes : std_logic_vector(23 DOWNTO 0) := x"000000";
-- ASMI
CONSTANT read_bytes_cmd : std_logic_vector(7 DOWNTO 0) := "00000011";
CONSTANT read_status_cmd : std_logic_vector(7 DOWNTO 0) := "00000101";
CONSTANT write_bytes_cmd : std_logic_vector(7 DOWNTO 0) := "00000010";
CONSTANT write_enable_cmd : std_logic_vector(7 DOWNTO 0) := "00000110";
CONSTANT erase_sector_cmd : std_logic_vector(7 DOWNTO 0) := "11011000";
--synthesis read_comments_as_HDL on
--SIGNAL asmi_clk, asmi_cs, asmi_mosi, asmi_miso : std_logic;
--synthesis read_comments_as_HDL off
SIGNAL asmi_clk_int : std_logic;
SIGNAL asmi_cs_int : std_logic;
-- Counter
SIGNAL counter, counter_data : INTEGER RANGE 0 TO 64;
SIGNAL counter_load, counter_zero : std_logic;
-- Shift Register
SIGNAL shift_register, shift_register_data : std_logic_vector(31 DOWNTO 0);
SIGNAL shift_register_load, shift_register_run : std_logic;
-- Delay Counter
SIGNAL delay_counter : INTEGER RANGE 0 TO 15;
SIGNAL avalon_clk_divided : std_logic;
SIGNAL asmi_clk_enable : std_logic;
BEGIN
EPCS_DATA_OUT <= shift_register(7 DOWNTO 0);
-- Clock divider
PROCESS(CLK, RST, delay_counter)
BEGIN
IF RST = '1' THEN
avalon_clk_divided <= '0';
delay_counter <= 0;
ELSIF (CLK'event AND CLK = '1') THEN
IF delay_counter = 0 THEN
delay_counter <= delay_counter_data;
avalon_clk_divided <= '1';
ELSE
delay_counter <= delay_counter - 1;
avalon_clk_divided <= '0';
END IF;
END IF;
END PROCESS;
-- Select ASMI CLK
asmi_clk_int <= avalon_clk_divided WHEN avalon_clk_is_too_fast = '1' ELSE CLK;
asmi_clk_enable <= avalon_clk_divided WHEN avalon_clk_is_too_fast = '1' ELSE '1';
asmi_clk <= asmi_clk_int;
-- State Machine
PROCESS(RST, CLK)
BEGIN
IF RST = '1' THEN
current_state <= idle;
ELSIF (CLK'event AND CLK = '1') THEN
current_state <= next_state AFTER 2 ns;
END IF;
END PROCESS;
PROCESS(current_state, EPCS_CS, EPCS_WR, EPCS_RD, EPCS_ERASE, EPCS_ADDR, EPCS_DATA_IN, counter_zero, shift_register)
BEGIN
EPCS_WAITREQ <= '0';
shift_register_data <= (others => '0');
shift_register_load <= '0';
shift_register_run <= '0';
counter_data <= 0;
counter_load <= '0';
CASE current_state IS
WHEN idle =>
IF EPCS_CS = '1' THEN
IF EPCS_RD = '1' THEN
EPCS_WAITREQ <= '1';
next_state <= read;
ELSIF (EPCS_WR = '1' OR EPCS_ERASE = '1') THEN
EPCS_WAITREQ <= '1';
next_state <= write;
ELSE
next_state <= idle;
END IF;
ELSE
next_state <= idle;
END IF;
-- Read one byte from flash
WHEN read =>
EPCS_WAITREQ <= '1';
shift_register_data <= read_bytes_cmd & EPCS_ADDR;
shift_register_load <= '1';
counter_data <= 38; -- was 62 for one word
counter_load <= '1';
next_state <= read_loop;
-- Wait for data to shift in
WHEN read_loop =>
EPCS_WAITREQ <= '1';
shift_register_run <= '1';
IF counter_zero = '1' THEN
next_state <= release;
ELSE
next_state <= read_loop;
END IF;
-- Write one byte to flash
-- First set the Write Enable bit
WHEN write =>
EPCS_WAITREQ <= '1';
shift_register_data <= write_enable_cmd & zeros_3bytes;
shift_register_load <= '1';
counter_data <= 6;
counter_load <= '1';
next_state <= write_enable_loop;
-- Wait for the command be shifted out
WHEN write_enable_loop =>
EPCS_WAITREQ <= '1';
shift_register_run <= '1';
IF counter_zero = '1' THEN
next_state <= write_cmd;
ELSE
next_state <= write_enable_loop;
END IF;
WHEN write_cmd =>
EPCS_WAITREQ <= '1';
IF EPCS_ERASE = '1' THEN
shift_register_data <= erase_sector_cmd & EPCS_ADDR;
counter_data <= 30;
ELSE
shift_register_data <= write_bytes_cmd & EPCS_ADDR;
counter_data <= 29;
END IF;
shift_register_load <= '1';
counter_load <= '1';
next_state <= write_cmd_loop;
-- Wait for data to shift out
WHEN write_cmd_loop =>
EPCS_WAITREQ <= '1';
shift_register_run <= '1';
IF counter_zero = '1' THEN
IF EPCS_ERASE = '1' THEN
next_state <= write_status;
ELSE
next_state <= write_data;
END IF;
ELSE
next_state <= write_cmd_loop;
END IF;
-- Write data
WHEN write_data =>
EPCS_WAITREQ <= '1';
shift_register_data <= EPCS_DATA_IN & zeros_3bytes;
shift_register_load <= '1';
counter_data <= 6; -- was 30 for one word
counter_load <= '1';
shift_register_run <= '1';
next_state <= write_data_loop;
-- Wait for data to shift out
WHEN write_data_loop =>
EPCS_WAITREQ <= '1';
shift_register_run <= '1';
IF counter_zero = '1' THEN
next_state <= write_status;
ELSE
next_state <= write_data_loop;
END IF;
-- Check the WIP (Write In Progress) bit
WHEN write_status =>
EPCS_WAITREQ <= '1';
shift_register_data <= read_status_cmd & zeros_3bytes;
shift_register_load <= '1';
counter_data <= 14;
counter_load <= '1';
next_state <= write_status_loop;
-- Wait for status to shift in
WHEN write_status_loop =>
EPCS_WAITREQ <= '1';
shift_register_run <= '1';
IF counter_zero = '1' THEN
next_state <= write_check_status;
ELSE
next_state <= write_status_loop;
END IF;
-- Is the flash ready?
WHEN write_check_status =>
EPCS_WAITREQ <= '1';
IF shift_register(0) = '0' THEN
next_state <= release;
ELSE
next_state <= write_status;
END IF;
-- Release the waitrequest signal
WHEN release =>
EPCS_WAITREQ <= '0';
next_state <= idle;
WHEN others =>
next_state <= idle;
END CASE;
END PROCESS;
-- Shift Register
PROCESS(RST, CLK, shift_register_load, shift_register_run, asmi_clk_enable, asmi_cs_int)
BEGIN
IF RST = '1' THEN
shift_register <= (others => '0');
ELSIF (CLK'event AND CLK = '1') THEN
IF shift_register_load = '1' THEN
shift_register <= shift_register_data;
ELSIF shift_register_run = '1' THEN
IF asmi_clk_enable = '1' THEN
IF asmi_cs_int = '0' THEN
shift_register <= shift_register((shift_register'high - 1) DOWNTO 0) & asmi_miso;
END IF;
END IF;
END IF;
END IF;
END PROCESS;
-- The data is clocked out on the falling edge.
PROCESS(RST, asmi_clk_int, shift_register_run)
BEGIN
IF RST = '1' THEN
asmi_mosi <= '0';
asmi_cs_int <= '1';
--ELSIF (CLK'event AND CLK = '0') THEN
ELSIF (asmi_clk_int'event AND asmi_clk_int = '0') THEN
--IF asmi_clk_enable = '1' THEN
asmi_mosi <= shift_register(shift_register'high);
IF shift_register_run = '1' THEN
asmi_cs_int <= '0';
ELSE
asmi_cs_int <= '1';
END IF;
--END IF;
END IF;
END PROCESS;
asmi_cs <= asmi_cs_int;
-- Counter
PROCESS(RST, CLK, counter_load, asmi_clk_enable, asmi_cs_int)
BEGIN
IF RST = '1' THEN
counter <= 0;
counter_zero <= '0';
ELSIF (CLK'event AND CLK = '1') THEN
IF counter_load = '1' THEN
counter <= counter_data;
counter_zero <= '0';
ELSE
IF asmi_clk_enable = '1' THEN
IF asmi_cs_int = '0' THEN
IF counter = 0 THEN
counter_zero <= '1';
ELSE
counter <= counter - 1;
counter_zero <= '0';
END IF;
END IF;
END IF;
END IF;
END IF;
END PROCESS;
--synthesis read_comments_as_HDL on
--asmi_block : cycloneii_asmiblock
-- port map(
-- data0out => ASMI_MISO,
-- oe => '0',
-- scein => asmi_cs,
-- dclkin => asmi_clk,
-- sdoin => ASMI_MOSI
-- );
--synthesis read_comments_as_HDL off
END ARCHITECTURE behaviour;
Пока плохо разумею в этих языках, но вроде компилится в символ, уже хорошо.