Synchronous FIFO
Parametereinstellung
Eine kurze Funktions- und Schnittstellenbeschreibung:
- Das Modell ist in der Speichertiefe (@SPTF) und der Speicherbreite (@BITBR) parametrisierbar.
- Ein- und Auslesen erfolgt erfolgt bei einer positiven Flanke des anliegenden Taktsignals
Schnittstellen
- takt : Taktsignal für die Zähler innerhalb des FIFOs
- shift_in : mit Aktivierung diese Signals zeigt ein angeschlossenes Modul an, daß es gültige Daten an den Eingang des FIFOs angelegt hat.
- input_ready : FIFO signalisiert damit, daß es bereit ist, Daten aufzunehmen.
- data_in : Vektor für die Eingabedaten
- master_reset : Rücksetzsignal für gesamtes FIFO
- output_enable : FIFO signalisiert damit, daß es bereit ist, Daten auszugeben
- data_out : Vektor für die Ausgabedaten
- shift_out : mit Aktivierung dieses Signals zeigt ein angeschlossenes Modul an, daß es Daten aus dem FIFO auslesen möchte
- output_ready : FIFO signalisiert damit, daß es bereit ist, Daten auszugeben
Model
- sync_fifo.vhd
-- ############################################################################ -- # Project : VHDL-Modellbibliothek # -- # # -- # Filename : sync_fifo.vhd # -- # # -- # Schaltung : "First In First Out" - Speicher # -- # # -- # # -- # Modell : sync_fifo.vhd # -- # # -- # Designer : Wolfgang Sehr; ueberarbeitet von Stefan Schmechtig # -- # Abteilung : Lehrstul fuer rechnergestuetzten Schaltungsentwurf # -- # Datum : 20.02.1995 # -- ############################################################################ -- ############################################################################ -- # IEEE PACKAGES # -- ############################################################################ Library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; -- ############################################################################ -- ############################################################################ -- # PROJEKT - SPEZIFISCHE PACKAGES # -- ############################################################################ use WORK.local.all; -- ############################################################################ ENTITY sync_fifo IS GENERIC(X : INTEGER := @BITBR; -- X: Bitbreite Y : INTEGER := @SPTF -- Y: Speichertiefe ); PORT(takt : IN STD_LOGIC; shift_in : IN STD_LOGIC; input_ready : OUT STD_LOGIC; data_in : IN UNSIGNED ((X-1) DOWNTO 0); master_reset : IN STD_LOGIC; output_enable : IN STD_LOGIC; data_out : OUT UNSIGNED ((X-1) DOWNTO 0); shift_out : IN STD_LOGIC; output_ready : OUT STD_LOGIC ); -- takt : Taktsignal fuer die Zaehler innerhalb des FIFOs -- : -- shift_in : mit Aktivierung diese Signals zeigt angeschlossenes -- : Modul an, dass es gueltige Daten an den Eingang des -- : FIFOs angelegt hat -- : -- input_ready : FIFO signalisiert damit, ob es bereit ist, -- : Daten aufzunehmen -- : -- data_in : Vektor fuer die Eingabedaten -- : -- master_reset : Ruecksetzsignal fuer gesamtes FIFO -- : -- output_enable: FIFO signalisiert damit, ob es bereit ist, -- : Daten auszugeben -- : -- data_out : Vektor fuer die Ausgabedaten -- : -- shift_out : mit Aktivierung diese Signals zeigt angeschlossenes -- : Modul an, dass es Daten aus dem FIFO auslesen moechte -- : -- output_ready : FIFO signalisiert damit, dass es bereit ist, -- : Daten auszugeben -- : END sync_fifo; ARCHITECTURE verhalten OF sync_fifo IS SIGNAL ram : UNSIGNED(((X*Y)-1) DOWNTO 0); SIGNAL ram_naechst : UNSIGNED(((X*Y)-1) DOWNTO 0); SIGNAL write_pointer : UNSIGNED(LOG_2(Y) DOWNTO 0); SIGNAL read_pointer : UNSIGNED(LOG_2(Y) DOWNTO 0); SIGNAL write_pointer_naechst : UNSIGNED(LOG_2(Y) DOWNTO 0); SIGNAL read_pointer_naechst : UNSIGNED(LOG_2(Y) DOWNTO 0); SIGNAL content_counter : UNSIGNED(LOG_2(Y) DOWNTO 0); SIGNAL content_counter_naechst : UNSIGNED(LOG_2(Y) DOWNTO 0); SIGNAL input_ready_naechst : STD_LOGIC; SIGNAL output_ready_naechst : STD_LOGIC; SIGNAL input_ready_sig : STD_LOGIC; SIGNAL output_ready_sig : STD_LOGIC; SIGNAL data_out_naechst : UNSIGNED ((X-1) DOWNTO 0); -- ram : eigentlicher Speicher -- : -- write_pointer : zeigt auf die Plazierung des zu -- : schreibenden Datums -- : -- write_pointer_naechst : zeigt auf die Plazierung des naechsten -- : zu schreibenden Datums -- : -- read_pointer : zeigt auf die Plazierung des zu -- : lesenden Datums -- : -- read_pointer_naechst : zeigt auf die Plazierung des naechsten -- : zu Lesenden Datums -- : -- content_counter : gibt die Anzahl der aktuell einge- -- : schriebenen Daten an -- : -- content_counter_naechst : gibt die Anzahl der beim naechsten -- : Taktzyklus eingeschriebenen Daten an -- : -- input_ready_sig : gleiche Bedeutung wie 'input_ready' -- : -Port -- : jedoch auch innerhalb der Architecture -- : lesbar -- : -- output_ready_sig : gleiche Bedeutung wie 'output_ready' -- : -Port, jedoch auch innerhalb der -- : Architecture lesbar -- : -- input_ready_naechst : input_ready Signal fuer den naechsten -- : Taktzyklus -- output_ready_naechst : output_ready Signal fuer den naechsten -- : Zustand -- : -- data_out_naechst : Wert von 'data_out', der bei der -- : naechsten positiven Taktflanke ueber- -- : nommen wird BEGIN input_ready <= input_ready_sig; output_ready <= output_ready_sig; cont_komb: PROCESS(master_reset, shift_in, shift_out, data_in, read_pointer, write_pointer, output_enable, input_ready_sig, output_ready_sig, content_counter, ram) VARIABLE content_counter_var : UNSIGNED((content_counter'LENGTH-1) DOWNTO 0); VARIABLE content_counter_var_naechst : UNSIGNED((content_counter'LENGTH-1) DOWNTO 0); VARIABLE input_ready_var : STD_LOGIC; VARIABLE output_ready_var : STD_LOGIC; VARIABLE input_ready_var_naechst : STD_LOGIC; VARIABLE output_ready_var_naechst : STD_LOGIC; VARIABLE ram_var : UNSIGNED((ram'LENGTH-1) DOWNTO 0); VARIABLE data_out_var : UNSIGNED ((data_out'LENGTH-1) DOWNTO 0); VARIABLE write_pointer_var : UNSIGNED((write_pointer'LENGTH-1) DOWNTO 0); VARIABLE write_pointer_var_naechst : UNSIGNED((write_pointer'LENGTH-1) DOWNTO 0); VARIABLE read_pointer_var : UNSIGNED((read_pointer'LENGTH-1) DOWNTO 0); VARIABLE read_pointer_var_naechst : UNSIGNED((read_pointer'LENGTH-1) DOWNTO 0); VARIABLE ents : UNSIGNED(6 DOWNTO 0); VARIABLE ents_log : STD_LOGIC_VECTOR(6 DOWNTO 0); VARIABLE cont_count_var_kl_Y : STD_LOGIC; VARIABLE rd_pt_var_gl_Y : STD_LOGIC; VARIABLE wr_pt_var_gl_Y : STD_LOGIC; VARIABLE write_var : STD_LOGIC; VARIABLE read_var : STD_LOGIC; -- content_counter_var : Variable fuer den Zaehlerinhalt von -- : 'content_counter' -- : -- content_counter_var_naechst : Variable fuer den im naechsten -- : Taktzyklus gueltigen Zaehlerinhalt von -- : 'content_counter' -- : -- input_ready_var : Variable fuer 'input_ready' Signal -- : -- output_ready_var : Variable fuer 'output_ready' Signal -- : -- input_ready_var_naechst : Variable fuer den im naechsten Takt- -- : zyklus gueltigen Wert des Signals -- : 'input_ready_var' -- : -- output_ready_var_naechst : Variable fuer den im naechsten Takt- -- : zyklus gueltigen Wert des Signals -- : 'output_ready_var' -- : -- ram_var : Variable fuer den Wert des Speichers -- : -- write_pointer_var : gibt aktuellen Wert des write-pointer -- : an -- : -- write_pointer_var_naechst : gibt den Wert des write-pointers im -- : naechsten Taktzyklus an -- : -- read_pointer_var : gibt aktuellen Wert des read-pointers -- : an -- : -- read_pointer_var_naechst : gibt den im naechsten Taktzyklus -- : gueltigen Wert von read_pointer an -- : -- ents : Entscheidungsvariable im UNSIGNED- -- : Format -- : -- ents_log : Entscheidungsvariable als STD_LOGIC_ -- : VECTOR -- : -- cont_count_var_kl_Y : o '1', wenn content_counter kleiner Y -- : o '0', sonst -- : -- rd_pt_var_gl_Y : o '1', wenn "write_pointer" = (Y-1) -- : o '0', sonst -- : -- wr_pt_var_gl_Y : o '1', wenn "read_pointer" = (Y-1) -- : o '0', sonst -- : -- write_var : o '1', wenn in das Ram geschrieben -- : werden soll -- : o '0', wenn nicht in das Ram ge- -- : schrieben werden soll -- read_var : o '1', wenn aus dem Ram gelesen werden -- : soll -- : o '0', wenn nicht aus dem Ram gelesen -- : werden soll BEGIN -- ###################################################################### -- ### Variablen-Zuweisungen ### -- ###################################################################### content_counter_var := content_counter; input_ready_var := input_ready_sig; output_ready_var := output_ready_sig; ram_var := ram; read_pointer_var := read_pointer; write_pointer_var := write_pointer; data_out_var := CONV_UNSIGNED(0, data_out_var'LENGTH); read_var := '0'; write_var := '0'; IF (content_counter_var < Y) THEN cont_count_var_kl_Y := '1'; ELSE cont_count_var_kl_Y := '0'; END IF; IF (read_pointer_var = (Y-1)) THEN rd_pt_var_gl_Y := '1'; ELSE rd_pt_var_gl_Y := '0'; END IF; IF (write_pointer_var = (Y-1)) THEN wr_pt_var_gl_Y := '1'; ELSE wr_pt_var_gl_Y := '0'; END IF; ents := shift_in & shift_out & input_ready_var & output_ready_var & cont_count_var_kl_Y & wr_pt_var_gl_Y & rd_pt_var_gl_Y; ents_log := CONV_STD_LOGIC_VECTOR(ents, ents_log'LENGTH); -- ###################################################################### -- ###################################################################### -- ### Bestimmung des naechsten Inhaltes der einzelnen Zaehler ### -- ###################################################################### IF (master_reset ='1') THEN content_counter_var_naechst := CONV_UNSIGNED(0,content_counter_var_naechst'LENGTH); write_pointer_var_naechst := CONV_UNSIGNED(0, write_pointer_var_naechst'LENGTH); read_pointer_var_naechst := CONV_UNSIGNED(0, read_pointer_var_naechst'LENGTH); ram_var := CONV_UNSIGNED(0, ram_var'LENGTH); ELSE IF (ents_log AND "1110110") = "1010100" THEN -- Fall_1: ents= "101-10-" content_counter_var_naechst := content_counter_var + 1; write_pointer_var_naechst := write_pointer_var + 1; read_pointer_var_naechst := read_pointer_var; write_var := '1'; read_var := '0'; ELSIF (ents_log AND "1110110") = "1010110" THEN -- Fall_2: ents= "101-11-" oder content_counter_var_naechst := content_counter_var + 1; write_pointer_var_naechst := CONV_UNSIGNED(0, write_pointer_var_naechst'LENGTH); read_pointer_var_naechst := read_pointer_var; write_var := '1'; read_var := '0'; ELSIF ((ents_log AND "1101001") = "0101000") OR ((ents_log AND "1111001") = "1101000") THEN -- Fall_3: ents= "01-1--0" oder -- ents= "1101--0" content_counter_var_naechst := content_counter_var - 1; write_pointer_var_naechst := write_pointer_var; read_pointer_var_naechst := read_pointer_var + 1; write_var := '0'; read_var := '1'; ELSIF ((ents_log AND "1101001") = "0101001") OR ((ents_log AND "1111001") = "1101001") THEN -- Fall_4: ents= "01-1--1" oder -- ents= "1101--1" content_counter_var_naechst := content_counter_var - 1; write_pointer_var_naechst := write_pointer_var; read_pointer_var_naechst := CONV_UNSIGNED(0, read_pointer_var_naechst'LENGTH); write_var := '0'; read_var := '1'; ELSIF ((ents_log AND "1110011") = "1110000") THEN -- Fall_5: ents= "111--00" content_counter_var_naechst := content_counter_var; write_pointer_var_naechst := write_pointer_var + 1; read_pointer_var_naechst := read_pointer_var + 1; write_var := '1'; read_var := '1'; ELSIF ((ents_log AND "1110011")= "1110001") THEN -- Fall_6: ents= "111--01" content_counter_var_naechst := content_counter_var; write_pointer_var_naechst := write_pointer_var + 1; read_pointer_var_naechst := CONV_UNSIGNED(0, read_pointer_var_naechst'LENGTH); write_var := '1'; read_var := '1'; ELSIF ((ents_log AND "1110011") = "1110010") THEN -- Fall_7: ents= "111--10" content_counter_var_naechst := content_counter_var; write_pointer_var_naechst := CONV_UNSIGNED(0, write_pointer_var_naechst'LENGTH); read_pointer_var_naechst := read_pointer_var + 1; write_var := '1'; read_var := '1'; ELSIF ((ents_log AND "1110011") = "1110011") THEN -- Fall_8: ents= "111--11" content_counter_var_naechst := content_counter_var; write_pointer_var_naechst := CONV_UNSIGNED(0, write_pointer_var_naechst'LENGTH); read_pointer_var_naechst := CONV_UNSIGNED(0, read_pointer_var_naechst'LENGTH); write_var := '1'; read_var := '1'; ELSE content_counter_var_naechst := content_counter_var; write_pointer_var_naechst := write_pointer_var; read_pointer_var_naechst := read_pointer_var; write_var := '0'; read_var := '0'; END IF; END IF; -- ###################################################################### -- ##################################################################### -- ### Bestimmung der Ausgangssignale / des RAM-Inhalts ### -- ##################################################################### FOR i IN 0 TO (Y-1) LOOP IF ((i = CONV_INTEGER(write_pointer_var)) AND (write_var='1')) THEN FOR j IN 0 TO (X-1) LOOP ram_var(X*i + j) := data_in(j); END LOOP; END IF; END LOOP; FOR i IN 0 TO (Y-1) LOOP IF ((i = CONV_INTEGER(read_pointer_var)) AND (read_var='1')) THEN FOR j IN 0 TO (X-1) LOOP data_out_var(j) := ram_var(X*i + j); END LOOP; END IF; END LOOP; IF (content_counter_var_naechst < Y) THEN input_ready_var_naechst := '1'; ELSE input_ready_var_naechst := '0'; END IF; IF (content_counter_var_naechst /= 0) THEN output_ready_var_naechst := '1'; ELSE output_ready_var_naechst := '0'; END IF; IF (output_enable /= '1') OR (read_var = '0')THEN data_out_var := CONV_UNSIGNED('Z', data_out_var'LENGTH); END IF; -- #################################################################### content_counter_naechst <= content_counter_var_naechst; input_ready_naechst <= input_ready_var_naechst; output_ready_naechst <= output_ready_var_naechst; write_pointer_naechst <= write_pointer_var_naechst; read_pointer_naechst <= read_pointer_var_naechst; data_out_naechst <= data_out_var; ram_naechst <= ram_var; END PROCESS; cont_FF: PROCESS(takt, content_counter_naechst, input_ready_naechst, output_ready_naechst, write_pointer_naechst, read_pointer_naechst) BEGIN IF (takt = '1') AND (takt'EVENT) THEN content_counter <= content_counter_naechst; input_ready_sig <= input_ready_naechst; output_ready_sig <= output_ready_naechst; write_pointer <= write_pointer_naechst; read_pointer <= read_pointer_naechst; data_out <= data_out_naechst; ram <= ram_naechst; END IF; END PROCESS; END verhalten; CONFIGURATION CFG_sync_fifo OF sync_fifo IS FOR verhalten END FOR; END CFG_sync_fifo;
Testbench
- tb_sync_fifo.vhd
-- ############################################################################ -- # Project : VHDL-Modellbibliothek # -- # # -- # Filename : tb_sync_fifo.vhd # -- # # -- # Schaltung : Testbench fuer parametrisierbaren FIFO-Speicher # -- # # -- # Modell : tb_sync_fifo # -- # # -- # Designer : Wolfgang Sehr; ueberarbeitet von Stefan Schmechtig # -- # Abteilung : Lehrstul fuer rechnergestuetzten Schaltungsentwurf # -- # Datum : 08.02.1995 # -- ############################################################################ -- ############################################################################ -- # SYNOPSYS PACKAGES # -- ############################################################################ Library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; USE IEEE.math_real.all; -- wird fuer die Erzeugung von Zufallszahlen -- benoetigt -- ############################################################################ ENTITY TB_sync_fifo IS GENERIC (X : INTEGER := @BITBR; -- X: Bitbreite Y : INTEGER := @SPTF); END TB_sync_fifo; ARCHITECTURE behaviour of TB_sync_fifo IS SIGNAL tb_takt : STD_LOGIC; SIGNAL tb_shift_in : STD_LOGIC; SIGNAL tb_input_ready : STD_LOGIC; SIGNAL tb_data_in : UNSIGNED ((X-1) DOWNTO 0); SIGNAL tb_master_reset : STD_LOGIC; SIGNAL tb_output_enable : STD_LOGIC; SIGNAL tb_data_out : UNSIGNED ((X-1) DOWNTO 0); SIGNAL tb_shift_out : STD_LOGIC; SIGNAL tb_output_ready : STD_LOGIC; -- tb_takt : Taktsignal der Testbench -- tb_shift_in : generiertes shift_in Signal -- tb_input_ready : empfangenes input_ready Signal -- tb_data_in : von der Testbench gelieferte Daten -- tb_master_reset : generiertes Resetsignal -- tb_output_enable : generiertes output_enable Signal -- tb_data_out : empfangene Ausgabedaten des UUT -- tb_shift_out : generiertes shift_out Signal -- tb_output_ready : empfangenes output_ready Signal COMPONENT sync_fifo PORT( takt : IN STD_LOGIC; shift_in : IN STD_LOGIC; input_ready : OUT STD_LOGIC; data_in : IN UNSIGNED ((X-1) DOWNTO 0); master_reset : IN STD_LOGIC; output_enable : IN STD_LOGIC; data_out : OUT UNSIGNED ((X-1) DOWNTO 0); shift_out : IN STD_LOGIC; output_ready : OUT STD_LOGIC ); END COMPONENT; BEGIN UUT: sync_fifo -- einzige Schaltung PORT MAP( takt => tb_takt, shift_in => tb_shift_in, input_ready => tb_input_ready, data_in => tb_data_in, master_reset => tb_master_reset, output_enable => tb_output_enable, data_out => tb_data_out, shift_out => tb_shift_out, output_ready => tb_output_ready ); tkt: PROCESS -- Generierung des Taktsignals BEGIN tb_takt <= '0'; WAIT FOR 2 ns; LOOP tb_takt <= NOT(tb_takt); WAIT FOR 5 ns; END LOOP; END PROCESS; res: PROCESS -- Generierung des Resetsignals BEGIN tb_master_reset <= '1'; WAIT FOR 5 ns; LOOP tb_master_reset <= not(tb_master_reset); WAIT FOR 300 ns; tb_master_reset <= not(tb_master_reset); WAIT FOR 10 ns; END LOOP; END PROCESS; write: PROCESS -- Generierung der Eingabedaten VARIABLE data_in_int : INTEGER; BEGIN tb_shift_in <= '0'; WAIT FOR 10 ns; LOOP data_in_int := RAND; tb_data_in <= CONV_UNSIGNED(data_in_int, tb_data_in'LENGTH); tb_shift_in <= NOT(tb_shift_in); WAIT FOR 10 ns; END LOOP; END PROCESS; read: PROCESS -- Generierung des shift_out Signals BEGIN tb_shift_out <= '0'; WAIT FOR 20 ns; LOOP tb_shift_out <= NOT(tb_shift_out); WAIT FOR 17 ns; END LOOP; END PROCESS; aus: PROCESS -- Generierung des output_enable Signals BEGIN tb_output_enable <= '1'; WAIT FOR 100 ns; LOOP tb_output_enable <= NOT(tb_output_enable); WAIT FOR 20 ns; tb_output_enable <= NOT(tb_output_enable); WAIT FOR 100 ns; END LOOP; END PROCESS; END behaviour; CONFIGURATION CFG_TB_sync_fifo OF TB_sync_fifo IS FOR behaviour FOR UUT: sync_fifo USE CONFIGURATION WORK.CFG_sync_fifo; END FOR; END FOR; END CFG_TB_sync_fifo;
Synopsys VSS Trace
- trace_sync_fifo.vhd
tr tb_master_reset tr tb_takt tr tb_shift_in tr tb_input_ready tr tb_shift_out tr tb_output_ready tr tb_output_enable tr tb_data_in tr tb_data_out cd UUT tr ram