Non riesco a mettere un immagine più esaustiva perché la versione di ModelSim che ho non me lo permette. Cercherò di fare uno spiegone aggiungendo porzioni di codice dell'ambiente di simulazione che ho creato. Il problema credo che sia nell'ambiente di simulazione perché usando un testbench più semplice il problema non esiste.
Dal principio: ho compilato su Quartus il progetto e generato i files .vho e .sdo necessari per la simulazione gate level.
Un altro dettaglio importate e che i valori vengono assegnati a DataTest in maniera concorrente. DataTest è definito come out nella top entity e nel file vho che uso per la simulazione.
Ho creato un ambiente di simulazione che utilizza alcune funzioni/process del framework UVVM. Ho strutturato il tutto come segue:
Per ogni componente ho creato tre pkg. Type, Sequencer e BFM. Questi tre pkg sono su 3 livelli di astrazione diversi e vanno rispettivamente dal livello più alto a quello più basso.
N.B: i tipi definit come t_uart_nome vengono definti nel pkg type in base al segnale (in genere std_logic o std_logic_vector)
Il
pkg type definisce le strutture dati necessarie per la rappresentazioni delle operazioni del componente:
- Codice: Seleziona tutto
type t_uart_transaction_kind is (
UART_RX,
UART_TX,
DATA_TEST_UART
);
In questo pkg viene definito un record che incapsula le informazioni relative a una singola transazione:
- Codice: Seleziona tutto
type t_uart_transaction is record
kind : t_uart_transaction_kind;
baud : t_uart_baud;
rxD_ser : t_uart_rxD_ser;
txD_ser : t_uart_txD_ser;
expected_txD_ser : t_uart_txD_ser;
clk_cycle : integer;
DataTest : t_uart_DataTest;
expected_DataTest : t_uart_DataTest;
msg_id : t_msg_id;
messaggio : string(1 to C_STANDARD_MSG_LENGTH);
end record;
il
pkg bfm definisce delle strutture dati necessarie per rappresentare le operazioni del componente:
- Codice: Seleziona tutto
procedure DataTest_uart(
signal DataTest : in t_uart_DataTest; --è definito in perché deve leggere i dati
expected_DataTest : in t_uart_DataTest
) is
begin
check_value( --procedura di UVVM: si occupa di confrontare DataTest letto con un valore atteso
DataTest,
expected_DataTest,
messaggio => pad_string("DataTest status: " & to_string(DataTest) & " (expected: " & to_string(expected_DataTest) & ")", C_STANDARD_MSG_LENGTH)
);
infine il
pkg sequencer orchestra le operazioni chiamando le appropriate procedure BFM in base al tipo di transazione richiesta.
- Codice: Seleziona tutto
procedure uart_do_transaction (
signal baud : out t_uart_baud;
signal rxD_ser : out t_uart_rxD_ser;
signal txD_ser : in t_uart_txD_ser;
signal DataTest : in t_uart_DataTest;
transaction_in : in t_uart_transaction
) is
begin
log(transaction_in.msg_id, "SEQUENCER: Executing transaction: " & transaction_in.messaggio, "uart_Sequencer");
case transaction_in.kind is
...
when DATA_TEST_UART =>
DataTest_uart(
DataTest => DataTest,
expected_DataTest => transaction_in.expected_DataTest
);
Il test vero e proprio è definito come segue:
- Codice: Seleziona tutto
...
variable v_transaction_req_uart : t_uart_transaction;
begin
...
v_transaction_req_uart := init_uart_transaction(
kind => DATA_TEST_UART,
baud => "000",
rxD_ser => '1',
clk_cycle => 1,
expected_DataTest => "0001",
messaggio => pad_string("\nChecking Data test value: ", C_STANDARD_MSG_LENGTH)
);
uart_do_transaction(
Baud_rate_dut, rxD_ser_dut, txD_ser_dut, DataTest_dut, v_transaction_req_uart
);
N.B: in questo caso baud, rxD_ser e clk_cycle non sono necessari per effettuare il check di DataTest. Devo inserirli perché se no avrei degli errori di compilazione. In futuro creerò una "transazione" dedicata
Con init_uart_transaction definita come segue:
- Codice: Seleziona tutto
--Funzione di utilità per creare un record t_uart_transaction
function init_uart_transaction(
kind : t_uart_transaction_kind;
baud : t_uart_baud := (others => '0');
rxD_ser : t_uart_rxD_ser := '0';
txD_ser : t_uart_txD_ser := '0';
expected_txD_ser : t_uart_txD_ser := '0';
clk_cycle : integer;
DataTest : t_uart_DataTest := (others => 'Z');
expected_DataTest : t_uart_DataTest := (others => 'Z');
msg_id : t_msg_id := ID_SEQUENCER;
messaggio : in string(1 to C_STANDARD_MSG_LENGTH) := (others => ' ')
) return t_uart_transaction;
Viene creata la transizione init_uart_transaction che va a popolare la variabile v_transaction_req_uart e viene eseguita la transazione (uart_do_transaction).
Questo è l'esempio di un testcase che viene definito come pkg che poi viene richiamato dal testbench.
Nel
testbench dichiaro come componente la top entity da testare, dichiaro i segnali del testbench (in questo caso i segnali_dut), mappo i segnali e dopo definisco il processo principale che esegue i testcase:
- Codice: Seleziona tutto
component wsp_aux is
port (
...
-- Other signals
DataTest : out std_logic_vector (3 downto 0);
end component wsp_aux;
....
signal Baud_rate_dut : std_logic_vector (2 downto 0);
begin
i_wsp_aux : wsp_aux
port map(
...
DataTest => DataTest_dut,
...
);
- Codice: Seleziona tutto
when C_IT_INT_022 =>
log(ID_LOG_HDR_XL, "Starting IT_INT_022", "C_HEADER");
IT_INT_022 (GClk_dut, GReset_dut, B_Life_dut, addr_slot_dut, addr10_dut, addr_low_dut, DataG2_dut, B_AS0n_dut, B_RWn_dut, B_Dack0n_dut, Bd_en_dut, RxD_Ser_dut, TxD_Ser_dut, DataTest_dut, Baud_rate_dut);
log(ID_LOG_HDR_XL, "Finished IT_INT_022", "C_HEADER");
Questo è come funziona il tutto.
Ho caricato anche un'immagine modificata di quella precedente. Il problema è che ww_DataTest che è un senale interno al DUT riceve informazioni, in simulazione vedo i valori ma non li passa a DataTest (pin del DUT). Internamente funziona tutto anche i registri da cui DataTest riceve i valori.