lpp_lfr_ms_fsmdma.vhd
431 lines
| 16.3 KiB
| text/x-vhdl
|
VhdlLexer
pellion
|
r332 | |||
------------------------------------------------------------------------------ | ||||
-- This file is a part of the LPP VHDL IP LIBRARY | ||||
-- Copyright (C) 2009 - 2010, Laboratory of Plasmas Physic - CNRS | ||||
-- | ||||
-- This program is free software; you can redistribute it and/or modify | ||||
-- it under the terms of the GNU General Public License as published by | ||||
-- the Free Software Foundation; either version 3 of the License, or | ||||
-- (at your option) any later version. | ||||
-- | ||||
-- This program is distributed in the hope that it will be useful, | ||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
-- GNU General Public License for more details. | ||||
-- | ||||
-- You should have received a copy of the GNU General Public License | ||||
-- along with this program; if not, write to the Free Software | ||||
-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||||
------------------------------------------------------------------------------- | ||||
-- Author : Jean-christophe Pellion | ||||
-- Mail : jean-christophe.pellion@lpp.polytechnique.fr | ||||
-- jean-christophe.pellion@easii-ic.com | ||||
------------------------------------------------------------------------------- | ||||
-- 1.0 - initial version | ||||
------------------------------------------------------------------------------- | ||||
LIBRARY ieee; | ||||
USE ieee.std_logic_1164.ALL; | ||||
USE ieee.numeric_std.ALL; | ||||
LIBRARY grlib; | ||||
USE grlib.amba.ALL; | ||||
USE grlib.stdlib.ALL; | ||||
USE grlib.devices.ALL; | ||||
USE GRLIB.DMA2AHB_Package.ALL; | ||||
LIBRARY lpp; | ||||
USE lpp.lpp_amba.ALL; | ||||
USE lpp.apb_devices_list.ALL; | ||||
USE lpp.lpp_memory.ALL; | ||||
USE lpp.lpp_dma_pkg.ALL; | ||||
LIBRARY techmap; | ||||
USE techmap.gencomp.ALL; | ||||
ENTITY lpp_lfr_ms_fsmdma IS | ||||
PORT ( | ||||
-- AMBA AHB system signals | ||||
HCLK : IN STD_ULOGIC; | ||||
HRESETn : IN STD_ULOGIC; | ||||
--TIME | ||||
data_time : IN STD_LOGIC_VECTOR(47 DOWNTO 0); | ||||
-- fifo interface | ||||
fifo_data : IN STD_LOGIC_VECTOR(31 DOWNTO 0); | ||||
fifo_empty : IN STD_LOGIC; | ||||
fifo_ren : OUT STD_LOGIC; | ||||
-- header | ||||
header : IN STD_LOGIC_VECTOR(31 DOWNTO 0); | ||||
header_val : IN STD_LOGIC; | ||||
header_ack : OUT STD_LOGIC; | ||||
-- DMA | ||||
dma_addr : OUT STD_LOGIC_VECTOR(31 DOWNTO 0); | ||||
dma_data : OUT STD_LOGIC_VECTOR(31 DOWNTO 0); | ||||
dma_valid : OUT STD_LOGIC; | ||||
dma_valid_burst : OUT STD_LOGIC; | ||||
dma_ren : IN STD_LOGIC; | ||||
dma_done : IN STD_LOGIC; | ||||
-- Reg out | ||||
ready_matrix_f0_0 : OUT STD_LOGIC; | ||||
ready_matrix_f0_1 : OUT STD_LOGIC; | ||||
ready_matrix_f1 : OUT STD_LOGIC; | ||||
ready_matrix_f2 : OUT STD_LOGIC; | ||||
error_anticipating_empty_fifo : OUT STD_LOGIC; | ||||
error_bad_component_error : OUT STD_LOGIC; | ||||
debug_reg : OUT STD_LOGIC_VECTOR(31 DOWNTO 0); | ||||
-- Reg In | ||||
status_ready_matrix_f0_0 : IN STD_LOGIC; | ||||
status_ready_matrix_f0_1 : IN STD_LOGIC; | ||||
status_ready_matrix_f1 : IN STD_LOGIC; | ||||
status_ready_matrix_f2 : IN STD_LOGIC; | ||||
status_error_anticipating_empty_fifo : IN STD_LOGIC; | ||||
status_error_bad_component_error : IN STD_LOGIC; | ||||
config_active_interruption_onNewMatrix : IN STD_LOGIC; | ||||
config_active_interruption_onError : IN STD_LOGIC; | ||||
addr_matrix_f0_0 : IN STD_LOGIC_VECTOR(31 DOWNTO 0); | ||||
addr_matrix_f0_1 : IN STD_LOGIC_VECTOR(31 DOWNTO 0); | ||||
addr_matrix_f1 : IN STD_LOGIC_VECTOR(31 DOWNTO 0); | ||||
addr_matrix_f2 : IN STD_LOGIC_VECTOR(31 DOWNTO 0); | ||||
pellion
|
r345 | matrix_time_f0_0 : OUT STD_LOGIC_VECTOR(47 DOWNTO 0); | ||
matrix_time_f0_1 : OUT STD_LOGIC_VECTOR(47 DOWNTO 0); | ||||
matrix_time_f1 : OUT STD_LOGIC_VECTOR(47 DOWNTO 0); | ||||
matrix_time_f2 : OUT STD_LOGIC_VECTOR(47 DOWNTO 0) | ||||
pellion
|
r332 | |||
); | ||||
END; | ||||
ARCHITECTURE Behavioral OF lpp_lfr_ms_fsmdma IS | ||||
----------------------------------------------------------------------------- | ||||
-- SIGNAL DMAIn : DMA_In_Type; | ||||
-- SIGNAL header_dmai : DMA_In_Type; | ||||
-- SIGNAL component_dmai : DMA_In_Type; | ||||
-- SIGNAL DMAOut : DMA_OUt_Type; | ||||
----------------------------------------------------------------------------- | ||||
----------------------------------------------------------------------------- | ||||
----------------------------------------------------------------------------- | ||||
TYPE state_DMAWriteBurst IS (IDLE, | ||||
CHECK_COMPONENT_TYPE, | ||||
WRITE_COARSE_TIME, | ||||
WRITE_FINE_TIME, | ||||
TRASH_FIFO, | ||||
SEND_DATA, | ||||
WAIT_DATA_ACK | ||||
); | ||||
SIGNAL state : state_DMAWriteBurst; -- := IDLE; | ||||
-- SIGNAL nbSend : INTEGER; | ||||
SIGNAL matrix_type : STD_LOGIC_VECTOR(1 DOWNTO 0); | ||||
SIGNAL component_type : STD_LOGIC_VECTOR(3 DOWNTO 0); | ||||
SIGNAL component_type_pre : STD_LOGIC_VECTOR(3 DOWNTO 0); | ||||
SIGNAL header_check_ok : STD_LOGIC; | ||||
SIGNAL address_matrix : STD_LOGIC_VECTOR(31 DOWNTO 0); | ||||
SIGNAL send_matrix : STD_LOGIC; | ||||
-- SIGNAL request : STD_LOGIC; | ||||
-- SIGNAL remaining_data_request : INTEGER; | ||||
SIGNAL Address : STD_LOGIC_VECTOR(31 DOWNTO 0); | ||||
----------------------------------------------------------------------------- | ||||
----------------------------------------------------------------------------- | ||||
SIGNAL header_select : STD_LOGIC; | ||||
SIGNAL header_send : STD_LOGIC; | ||||
SIGNAL header_data : STD_LOGIC_VECTOR(31 DOWNTO 0); | ||||
SIGNAL header_send_ok : STD_LOGIC; | ||||
SIGNAL header_send_ko : STD_LOGIC; | ||||
SIGNAL component_send : STD_LOGIC; | ||||
SIGNAL component_send_ok : STD_LOGIC; | ||||
SIGNAL component_send_ko : STD_LOGIC; | ||||
----------------------------------------------------------------------------- | ||||
SIGNAL fifo_ren_trash : STD_LOGIC; | ||||
SIGNAL component_fifo_ren : STD_LOGIC; | ||||
----------------------------------------------------------------------------- | ||||
SIGNAL debug_reg_s : STD_LOGIC_VECTOR(31 DOWNTO 0); | ||||
SIGNAL fine_time_reg : STD_LOGIC_VECTOR(15 DOWNTO 0); | ||||
----------------------------------------------------------------------------- | ||||
SIGNAL log_empty_fifo : STD_LOGIC; | ||||
----------------------------------------------------------------------------- | ||||
SIGNAL header_reg : STD_LOGIC_VECTOR(31 DOWNTO 0); | ||||
SIGNAL header_reg_val : STD_LOGIC; | ||||
SIGNAL header_reg_ack : STD_LOGIC; | ||||
SIGNAL header_error : STD_LOGIC; | ||||
BEGIN | ||||
debug_reg <= debug_reg_s; | ||||
send_matrix <= '1' WHEN matrix_type = "00" AND status_ready_matrix_f0_0 = '0' ELSE | ||||
'1' WHEN matrix_type = "01" AND status_ready_matrix_f0_1 = '0' ELSE | ||||
'1' WHEN matrix_type = "10" AND status_ready_matrix_f1 = '0' ELSE | ||||
'1' WHEN matrix_type = "11" AND status_ready_matrix_f2 = '0' ELSE | ||||
'0'; | ||||
header_check_ok <= '0' WHEN component_type = "1111" ELSE -- ?? component_type_pre = "1111" | ||||
pellion
|
r345 | '1' WHEN component_type = "0000" ELSE --AND component_type_pre = "0000" ELSE | ||
pellion
|
r332 | '1' WHEN component_type = component_type_pre + "0001" ELSE | ||
'0'; | ||||
address_matrix <= addr_matrix_f0_0 WHEN matrix_type = "00" ELSE | ||||
addr_matrix_f0_1 WHEN matrix_type = "01" ELSE | ||||
addr_matrix_f1 WHEN matrix_type = "10" ELSE | ||||
addr_matrix_f2 WHEN matrix_type = "11" ELSE | ||||
(OTHERS => '0'); | ||||
----------------------------------------------------------------------------- | ||||
-- DMA control | ||||
----------------------------------------------------------------------------- | ||||
DMAWriteFSM_p : PROCESS (HCLK, HRESETn) | ||||
BEGIN -- PROCESS DMAWriteBurst_p | ||||
IF HRESETn = '0' THEN -- asynchronous reset (active low) | ||||
matrix_type <= (OTHERS => '0'); | ||||
component_type <= (OTHERS => '0'); | ||||
state <= IDLE; | ||||
-- header_ack <= '0'; | ||||
ready_matrix_f0_0 <= '0'; | ||||
ready_matrix_f0_1 <= '0'; | ||||
ready_matrix_f1 <= '0'; | ||||
ready_matrix_f2 <= '0'; | ||||
error_anticipating_empty_fifo <= '0'; | ||||
error_bad_component_error <= '0'; | ||||
component_type_pre <= "0000"; | ||||
fifo_ren_trash <= '1'; | ||||
component_send <= '0'; | ||||
address <= (OTHERS => '0'); | ||||
header_select <= '0'; | ||||
header_send <= '0'; | ||||
header_data <= (OTHERS => '0'); | ||||
fine_time_reg <= (OTHERS => '0'); | ||||
pellion
|
r345 | debug_reg_s(2 DOWNTO 0) <= (OTHERS => '0'); | ||
pellion
|
r332 | debug_reg_s(31 DOWNTO 4) <= (OTHERS => '0'); | ||
log_empty_fifo <= '0'; | ||||
ELSIF HCLK'EVENT AND HCLK = '1' THEN -- rising clock edge | ||||
debug_reg_s(31 DOWNTO 10) <= (OTHERS => '0'); | ||||
header_reg_ack <= '0'; | ||||
pellion
|
r345 | |||
pellion
|
r332 | CASE state IS | ||
WHEN IDLE => | ||||
debug_reg_s(2 DOWNTO 0) <= "000"; | ||||
pellion
|
r345 | |||
--matrix_type <= header(1 DOWNTO 0); | ||||
pellion
|
r332 | --component_type <= header(5 DOWNTO 2); | ||
ready_matrix_f0_0 <= '0'; | ||||
ready_matrix_f0_1 <= '0'; | ||||
ready_matrix_f1 <= '0'; | ||||
ready_matrix_f2 <= '0'; | ||||
error_bad_component_error <= '0'; | ||||
pellion
|
r345 | --header_select <= '1'; | ||
pellion
|
r332 | IF header_reg_val = '1' AND fifo_empty = '0' AND send_matrix = '1' THEN | ||
pellion
|
r345 | header_reg_ack <= '1'; | ||
pellion
|
r332 | debug_reg_s(5 DOWNTO 4) <= header_reg(1 DOWNTO 0); | ||
debug_reg_s(9 DOWNTO 6) <= header_reg(5 DOWNTO 2); | ||||
pellion
|
r345 | |||
pellion
|
r332 | matrix_type <= header_reg(1 DOWNTO 0); | ||
component_type <= header_reg(5 DOWNTO 2); | ||||
component_type_pre <= component_type; | ||||
state <= CHECK_COMPONENT_TYPE; | ||||
END IF; | ||||
log_empty_fifo <= '0'; | ||||
WHEN CHECK_COMPONENT_TYPE => | ||||
debug_reg_s(2 DOWNTO 0) <= "001"; | ||||
--header_ack <= '0'; | ||||
pellion
|
r345 | |||
pellion
|
r332 | IF header_check_ok = '1' THEN | ||
header_send <= '0'; | ||||
-- | ||||
IF component_type = "0000" THEN | ||||
pellion
|
r345 | address <= address_matrix; | ||
pellion
|
r332 | CASE matrix_type IS | ||
pellion
|
r345 | WHEN "00" => matrix_time_f0_0 <= data_time; | ||
WHEN "01" => matrix_time_f0_1 <= data_time; | ||||
WHEN "10" => matrix_time_f1 <= data_time; | ||||
WHEN "11" => matrix_time_f2 <= data_time; | ||||
pellion
|
r332 | WHEN OTHERS => NULL; | ||
END CASE; | ||||
pellion
|
r345 | |||
header_data <= data_time(31 DOWNTO 0); | ||||
fine_time_reg <= data_time(47 DOWNTO 32); | ||||
pellion
|
r332 | --state <= WRITE_COARSE_TIME; | ||
--header_send <= '1'; | ||||
state <= SEND_DATA; | ||||
header_send <= '0'; | ||||
component_send <= '1'; | ||||
header_select <= '0'; | ||||
ELSE | ||||
state <= SEND_DATA; | ||||
END IF; | ||||
-- | ||||
ELSE | ||||
error_bad_component_error <= '1'; | ||||
component_type_pre <= "0000"; | ||||
state <= TRASH_FIFO; | ||||
END IF; | ||||
pellion
|
r345 | --WHEN WRITE_COARSE_TIME => | ||
-- debug_reg_s(2 DOWNTO 0) <= "010"; | ||||
-- header_ack <= '0'; | ||||
pellion
|
r332 | |||
pellion
|
r345 | -- IF dma_ren = '0' THEN | ||
-- header_send <= '0'; | ||||
-- ELSE | ||||
-- header_send <= header_send; | ||||
-- END IF; | ||||
pellion
|
r332 | |||
pellion
|
r345 | -- IF header_send_ko = '1' THEN | ||
-- header_send <= '0'; | ||||
-- state <= TRASH_FIFO; | ||||
-- error_anticipating_empty_fifo <= '1'; | ||||
-- -- TODO : error sending header | ||||
-- ELSIF header_send_ok = '1' THEN | ||||
-- header_send <= '1'; | ||||
-- header_select <= '1'; | ||||
-- header_data(15 DOWNTO 0) <= fine_time_reg; | ||||
-- header_data(31 DOWNTO 16) <= (OTHERS => '0'); | ||||
-- state <= WRITE_FINE_TIME; | ||||
-- address <= address + 4; | ||||
-- END IF; | ||||
--WHEN WRITE_FINE_TIME => | ||||
-- debug_reg_s(2 DOWNTO 0) <= "011"; | ||||
pellion
|
r332 | |||
pellion
|
r345 | -- header_ack <= '0'; | ||
-- IF dma_ren = '0' THEN | ||||
-- header_send <= '0'; | ||||
-- ELSE | ||||
-- header_send <= header_send; | ||||
-- END IF; | ||||
pellion
|
r332 | |||
pellion
|
r345 | -- IF header_send_ko = '1' THEN | ||
-- header_send <= '0'; | ||||
-- state <= TRASH_FIFO; | ||||
-- error_anticipating_empty_fifo <= '1'; | ||||
-- -- TODO : error sending header | ||||
-- ELSIF header_send_ok = '1' THEN | ||||
-- header_send <= '0'; | ||||
-- header_select <= '0'; | ||||
-- state <= SEND_DATA; | ||||
-- address <= address + 4; | ||||
-- END IF; | ||||
pellion
|
r332 | |||
WHEN TRASH_FIFO => | ||||
debug_reg_s(2 DOWNTO 0) <= "100"; | ||||
pellion
|
r345 | |||
pellion
|
r332 | -- header_ack <= '0'; | ||
error_bad_component_error <= '0'; | ||||
error_anticipating_empty_fifo <= '0'; | ||||
IF fifo_empty = '1' THEN | ||||
state <= IDLE; | ||||
fifo_ren_trash <= '1'; | ||||
ELSE | ||||
fifo_ren_trash <= '0'; | ||||
END IF; | ||||
WHEN SEND_DATA => | ||||
-- header_ack <= '0'; | ||||
debug_reg_s(2 DOWNTO 0) <= "101"; | ||||
pellion
|
r345 | |||
pellion
|
r332 | IF fifo_empty = '1' OR log_empty_fifo = '1' THEN | ||
state <= IDLE; | ||||
IF component_type = "1110" THEN --"1110" -- JC | ||||
CASE matrix_type IS | ||||
WHEN "00" => ready_matrix_f0_0 <= '1'; | ||||
WHEN "01" => ready_matrix_f0_1 <= '1'; | ||||
WHEN "10" => ready_matrix_f1 <= '1'; | ||||
WHEN "11" => ready_matrix_f2 <= '1'; | ||||
WHEN OTHERS => NULL; | ||||
END CASE; | ||||
END IF; | ||||
ELSE | ||||
component_send <= '1'; | ||||
address <= address; | ||||
state <= WAIT_DATA_ACK; | ||||
END IF; | ||||
WHEN WAIT_DATA_ACK => | ||||
log_empty_fifo <= fifo_empty OR log_empty_fifo; | ||||
pellion
|
r345 | |||
pellion
|
r332 | debug_reg_s(2 DOWNTO 0) <= "110"; | ||
pellion
|
r345 | |||
pellion
|
r332 | component_send <= '0'; | ||
IF component_send_ok = '1' THEN | ||||
address <= address + 64; | ||||
state <= SEND_DATA; | ||||
ELSIF component_send_ko = '1' THEN | ||||
error_anticipating_empty_fifo <= '0'; | ||||
pellion
|
r345 | state <= TRASH_FIFO; | ||
pellion
|
r332 | END IF; | ||
pellion
|
r345 | |||
--WHEN CHECK_LENGTH => | ||||
-- component_send <= '0'; | ||||
-- debug_reg_s(2 DOWNTO 0) <= "111"; | ||||
-- state <= IDLE; | ||||
pellion
|
r332 | |||
WHEN OTHERS => NULL; | ||||
END CASE; | ||||
END IF; | ||||
END PROCESS DMAWriteFSM_p; | ||||
pellion
|
r345 | |||
pellion
|
r332 | dma_valid_burst <= '0' WHEN header_select = '1' ELSE component_send; | ||
dma_valid <= header_send WHEN header_select = '1' ELSE '0'; | ||||
dma_data <= header_data WHEN header_select = '1' ELSE fifo_data; | ||||
dma_addr <= address; | ||||
fifo_ren <= fifo_ren_trash WHEN header_select = '1' ELSE dma_ren; | ||||
component_send_ok <= '0' WHEN header_select = '1' ELSE dma_done; | ||||
component_send_ko <= '0'; | ||||
header_send_ok <= '0' WHEN header_select = '0' ELSE dma_done; | ||||
header_send_ko <= '0'; | ||||
----------------------------------------------------------------------------- | ||||
-- FSM HEADER ACK | ||||
----------------------------------------------------------------------------- | ||||
PROCESS (HCLK, HRESETn) | ||||
BEGIN -- PROCESS | ||||
pellion
|
r345 | IF HRESETn = '0' THEN -- asynchronous reset (active low) | ||
pellion
|
r332 | header_ack <= '0'; | ||
header_reg <= (OTHERS => '0'); | ||||
header_reg_val <= '0'; | ||||
pellion
|
r345 | ELSIF HCLK'EVENT AND HCLK = '1' THEN -- rising clock edge | ||
pellion
|
r332 | header_ack <= '0'; | ||
pellion
|
r345 | |||
pellion
|
r332 | IF header_val = '1' THEN | ||
header_ack <= '1'; | ||||
header_reg <= header; | ||||
END IF; | ||||
IF header_val = '1' THEN | ||||
header_reg_val <= '1'; | ||||
ELSIF header_reg_ack = '1' THEN | ||||
header_reg_val <= '0'; | ||||
END IF; | ||||
header_error <= header_val AND header_reg_val AND (NOT Header_reg_ack); | ||||
END IF; | ||||
END PROCESS; | ||||
debug_reg_s(3) <= header_error; | ||||
pellion
|
r345 | END Behavioral; | ||