-- ############################################################################ -- # Project : VHDL-Modellbibliothek # -- # # -- # Filename : async_fifo.vhd # -- # # -- # Schaltung : "First In First Out" - Speicher mit asynchronem # -- # Datenausgang # -- # # -- # Modell : async_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; -- ############################################################################ -- ############################################################################ -- # Bibliotheks - SPEZIFISCHE PACKAGES # -- ############################################################################ use WORK.local.all; -- ############################################################################ ENTITY async_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 async_fifo; ARCHITECTURE verhalten OF async_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 : Variable fuer CASE-Anweisung -- : -- 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 < Y) THEN input_ready_var := '1'; ELSE input_ready_var := '0'; END IF; IF (content_counter_var /= 0) THEN output_ready_var := '1'; ELSE output_ready_var := '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_sig <= input_ready_var; output_ready_sig <= output_ready_var; write_pointer_naechst <= write_pointer_var_naechst; read_pointer_naechst <= read_pointer_var_naechst; data_out <= data_out_var; ram_naechst <= ram_var; END PROCESS; cont_FF: PROCESS(takt, content_counter_naechst, write_pointer_naechst, read_pointer_naechst) BEGIN IF (takt = '1') AND (takt'EVENT) THEN content_counter <= content_counter_naechst; write_pointer <= write_pointer_naechst; read_pointer <= read_pointer_naechst; ram <= ram_naechst; END IF; END PROCESS; END verhalten; CONFIGURATION CFG_async_fifo OF async_fifo IS FOR verhalten END FOR; END CFG_async_fifo;