Forum: FPGA, VHDL & Co. Ansteuerung eines SRAM mit einem FPGA


von Tobias Danz (Gast)


Lesenswert?

Hallo zusammen,

ich habe ein Spartan 3 Starter Kit und dort befindet sich eine SRAM
drauf, ich will nun diesen SRAM ansteuern, um Daten abzuspeichern.
Meine Frage: wo kann ich eine Schnittstelle/Lösung zu meinem Problem
finden, bzw. was ist besonders zu beachten bei der Ansteuerung.
Ich habe schon ein Programm in VHDL, aber er liest die falsche Daten
aus, obwohl die Timing Simualtion korrekt aussieht.
Ich hoffe mir kann jemand helfen.

Danke, Gruß
Tobias

von Jörn (Gast)


Lesenswert?

Hallo Tobias,

Hast du dir die Place & Route Simulation schon angeschaut?
Kannst du deinen Code mal posten?

Gruss Jörn

von Tobias (Gast)


Lesenswert?

Ich habe mehrere Module,

entity mc_connect_uart is
    Port ( clk     : in std_logic;
           reset     : in std_logic;
     ub1      : out std_logic;
     lb1      : out std_logic;
     ce1      : out std_logic;
     ce2      : out std_logic;
     we       : out std_logic;
     oe       : out std_logic;
     addr_count   : out std_logic_vector(17 downto 0);
                 serial_out   : out std_logic;
     in_out    : inout std_logic_vector(7 downto 0)
          );
end mc_connect_uart;

architecture Behavioral of mc_connect_uart is

  signal connect    : std_logic;
  signal baud_rate  : std_logic;
  signal ground    : std_logic;
  signal stop_read  : std_logic;
  signal sram_uart   : std_logic_vector(7 downto 0);
  signal en_s_u     : std_logic;
  signal data_sig   : std_logic_vector(7 downto 0);
  signal data_help   : std_logic_vector(7 downto 0);
  signal enable    : std_logic;
  signal addr_sig   : std_logic_vector(17 downto 0);
  signal cv      : std_logic;
  signal wen    : std_logic;
  signal oen    : std_logic;
  signal cen    : std_logic;

------------------------------------------------------------------------ 
-------------------
-- DCM zum herunter teilen der 50 MHz auf 25 MHz
  COMPONENT clock_div
    PORT(
    RST_IN       : IN std_logic;
    CLKIN_IN       : IN std_logic;
    LOCKED_OUT     : OUT std_logic;
    CLKDV_OUT     : OUT std_logic;
    CLKIN_IBUFG_OUT   : OUT std_logic;
    CLK0_OUT       : OUT std_logic
    );
  END COMPONENT;
-- Komponente UART_Transmitter
  COMPONENT uart_tx
    PORT(
    data_in   : IN std_logic_vector(7 downto 0);
    write_buffer   : IN std_logic;
    reset_buffer   : IN std_logic;
    en_16_x_baud   : IN std_logic;
    clk       : IN std_logic;
    serial_out     : OUT std_logic;
    buffer_full     : OUT std_logic;
    buffer_half_full   : OUT std_logic
    );
  END COMPONENT;
------------------------------------------------------------------------ 
----------------------------
--Komponente Schreiben - Lesen
  COMPONENT write_read
  PORT(
    clock     : IN std_logic;
    reset     : IN std_logic;
    buffer_full   : IN std_logic;
    ADDRESS   : OUT std_logic_vector(17 downto 0);
    WE     : OUT std_logic;
    OE     : OUT std_logic;
    UB     : OUT std_logic;
    LB     : OUT std_logic;
    CE     : OUT std_logic;
    enab_io   : OUT std_logic
    );
  END COMPONENT;
-----Component data
counter----------------------------------------------------------------- 
----------------------------------
  COMPONENT data_count
  PORT(
    clock : IN std_logic;
    reset : IN std_logic;
    enable : IN std_logic;
    data : OUT std_logic_vector(7 downto 0)
    );
  END COMPONENT;
-----component
Input-output-buffer----------------------------------------------------- 
-------------------------------------------
  component IOBUF
     port (I: in std_logic;
     T: in std_logic;
           O: out std_logic;
           IO: inout std_logic);
  end component;

  attribute box_type  : string;
  attribute box_type of IOBUF : component is "black_box";

  constant DATA_WIDTH : integer := 8;
------------------------------------------------------------------------ 
--------------------------------

begin


-- Instanziate an input-output buffer
    U1 : for i in 0 to DATA_WIDTH - 1 generate
    U2: IOBUF port map (
          I => data_sig(i),
          T => enable,
                 O => sram_uart(i),
            IO => in_out(i)
    );
    end generate;

 --  help_data <= data_sig;
 --   help_2 <= sram_uart;

-----Instanziate the DCM (Digital Clock
Manager)---------------------------------------------------------
  ground <= '0';

  Inst_clock_div: clock_div PORT MAP(
    RST_IN => ground,
    CLKIN_IN => clk,
    CLKDV_OUT => connect

  );

-- mit diesem Prozess erzeuge ich den entsprechenden Takt um das Uart
mit der richtigen Frequenz arbeiten zu lassen
  baud_timer: process (connect)
    variable baud_count : integer range 0 to 2 := 0;
    begin
      if (connect = '1' and connect'event) then
        if (baud_count=1) then
          baud_count := 0;
          baud_rate <= '1';
        else
          baud_count := baud_count + 1;
          baud_rate <= '0';
        end if;
      end if;
  end process;
-----Instanziate the microcontroller
PicoBlaze-----------------------------------------------------------
--   Inst_embedded_kcpsm3: embedded_kcpsm3 PORT MAP(
--    out_port => out_sig,
--    port_id => id_sig,
--    in_port => bufferout_inport,
--    interrupt => int_en,
--    reset => reset,
--    clk => connect
--  );

-----Instanziate the modul uart which change 1 byte to 1
bit---------------------------------------------
  Inst_uart_tx: uart_tx PORT MAP(
    data_in => sram_uart,
    write_buffer => en_s_u,
    reset_buffer => reset,
    en_16_x_baud => baud_rate,
    serial_out => serial_out,
  --  buffer_full => stop_read,
    buffer_half_full => stop_read,
    clk => connect
  );
-----Instanziate the modul that set the control signals and the
address--------------------------------------------------
  Inst_write_read: write_read PORT MAP(
    clock => connect,
    reset => reset,
    buffer_full => stop_read,
    ADDRESS => addr_count,
    WE => we,
    OE => oe,
    UB => ub1,
    LB => lb1,
    CE => ce1,
    enab_io => enable
  );

  ce2 <= '1';
-----Instanziate the
data_counter------------------------------------------------------------ 
------------
  Inst_data_count: data_count PORT MAP(
    clock => connect,
    reset => reset,
    enable => enable,
    data => data_sig
  );
------change between writing data in sram and reading data from sram to
uart-----------------------------
  set_enab_uart: process (connect, reset, enable)
  begin
    if (reset = '1') then          en_s_u <= '0';
    elsif (connect = '1' and connect'event) then
      if (enable = '1') then          en_s_u <= '1';
      elsif (enable = '0') then      en_s_u <= '0';
      end if;
    end if;
  end process;

  div_clock: process(connect, reset)
  begin
    if (reset = '1') then          cv <= '0';
    elsif (connect = '1' and connect'event) then  cv <= not cv;
    end if;
  end process;

--  delay_addr: process (cv, reset, addr_sig)
--  begin
--    if (reset = '1') then
--    elsif (cv = '1' and cv'event) then  data_sig <="01000000";
--    end if;
--  end process;

--  addr_count <= addr_sig;
   --data_help;
--  delay_data: process (cv, reset, data_help, addr_sig, wen)
--  begin
--    if (reset = '1') then
--    elsif (cv = '0' and cv'event) then
      --if (wen = '1') then
--      if (wen = '0') then
--      end if;
--    end if;
--  end process;

--  we <= wen;
--  oe <= oen;
--  ce1 <= cen;
end Behavioral;

von Tobias (Gast)


Lesenswert?

entity data_count is
    Port ( clock  : in std_logic;
           reset  : in std_logic;
     enable   : in std_logic;
           data   : out std_logic_vector(7 downto 0));
end data_count;

architecture Behavioral of data_count is
    signal counter   : std_logic_vector(7 downto 0);
    signal cv     : std_logic;
    constant cons   : std_logic_vector(7 downto 0) := "10101010";
begin

  clock_div: process(clock, reset)
  begin
    if (reset = '1') then          cv <= '0';
    elsif (clock = '1' and clock'event) then  cv <= not cv;
    end if;
  end process;

  data_count_proc: process (cv, reset)
  begin
    if (reset = '1') then          counter <= (others => '0');
    elsif (cv = '0' and cv'event) then
                      counter <= counter + 1;
                      data <= cons;  --counter;
    end if;
  end process;

end Behavioral;

von Tobias (Gast)


Lesenswert?

entity write_read is
  Port (clock     : in std_logic;
           reset     : in std_logic;
     buffer_full   : in std_logic;
     --data_mikrocontroller: in std_logic_vector (7 downto 0);
           ADDRESS     : out std_logic_vector(17 downto 0);
     WE       : out std_logic;
     OE       : out std_logic;
     UB       : out std_logic;
     LB       : out std_logic;
     CE       : out std_logic;
     enab_io     : out std_logic);
end write_read;

architecture Behavioral of write_read is

  COMPONENT address_set
  PORT(
    clock     : IN std_logic;
    reset     : IN std_logic;
    buffer_full   : IN std_logic;
    enab      : OUT std_logic;
    addr_wr     : OUT std_logic_vector(17 downto 0);
    addr_re     : OUT std_logic_vector(17 downto 0)
    );
  END COMPONENT;
------------------------------------------------------------------------ 
---------------------------------
  COMPONENT control
  PORT(
    clock     : IN std_logic;
    reset     : IN std_logic;
    addr_wr     : IN std_logic_vector(17 downto 0);
    addr_re     : IN std_logic_vector(17 downto 0);
    enab     : IN std_logic;
    buffer_full   : IN std_logic;
    we       : OUT std_logic;
    oe       : OUT std_logic;
    ce       : OUT std_logic;
    ub       : OUT std_logic;
    lb       : OUT std_logic;
    addr     : OUT std_logic_vector(17 downto 0);
    enab_io     : OUT std_logic
    );
  END COMPONENT;
------------------------------------------------------------------------ 
---------------------------------
  signal address_write   : std_logic_vector(17 downto 0);
  signal address_read   : std_logic_vector(17 downto 0);
  signal enable_signal   : std_logic := '0';
------------------------------------------------------------------------ 
---------------------------------
begin
  Inst_address_set: address_set PORT MAP(
    clock => clock,
    reset => reset,
    buffer_full => buffer_full,
    enab => enable_signal,
    addr_wr => address_write,
    addr_re => address_read
  );
------------------------------------------------------------------------ 
---------------------------------
  Inst_control: control PORT MAP(
    clock => clock,
    reset => reset,
    addr_wr => address_write,
    addr_re => address_read,
    enab => enable_signal,
    buffer_full => buffer_full,
    we => WE,
    oe => OE,
    ce => CE,
    ub => UB,
    lb => LB,
    addr => ADDRESS,
    enab_io => enab_io
  );
end Behavioral;

von Tobias (Gast)


Lesenswert?

entity address_set is
    Port ( clock     : in std_logic;
           reset     : in std_logic;
           buffer_full   : in std_logic;
           enab     : out std_logic;
           addr_wr     : out std_logic_vector(17 downto 0);
           addr_re     : out std_logic_vector(17 downto 0));
end address_set;

architecture Behavioral of address_set is
  signal enab_sig  : std_logic;
  signal addr_wr_sig   : std_logic_vector (17 downto 0);
  signal addr_re_sig   : std_logic_vector (17 downto 0);
  signal cv      : std_logic;

begin

  clock_div: process(clock, reset)
  begin
    if (reset = '1') then          cv <= '0';
    elsif (clock = '1' and clock'event) then  cv <= not cv;
    end if;
  end process;

    enable_process: process(cv, reset, addr_wr_sig, addr_re_sig)
    begin
      if (reset = '1') then              enab_sig <= '0';
  elsif (cv = '1' and cv'event) then
    if (addr_wr_sig = "000000000011111111") then    enab_sig <= '1';
    elsif (addr_re_sig = "000000000011111111") then  enab_sig <= '0';
    end if;
                        enab <= enab_sig;
  end if;
    end process;

    addr_write: process(cv, reset, enab_sig)
    begin
      if (reset = '1') then              addr_wr_sig <= (others => '0');
  elsif (cv = '1' and cv'event) then
    if (enab_sig = '0') then            addr_wr_sig <= addr_wr_sig + 1;
      if (addr_wr_sig = "000000000011111111") then  addr_wr_sig <=
(others => '0');
      end if;
    end if;
                        addr_wr <= addr_wr_sig;
  end if;
    end process;

    addr_read: process(cv, reset, enab_sig, buffer_full)
    begin
      if (reset = '1') then                addr_re_sig <= (others => 
'0');
  elsif (cv = '1' and cv'event) then
    if (buffer_full = '0') then
      if (enab_sig = '1') then            addr_re_sig <= addr_re_sig + 
1;
        if (addr_re_sig = "000000000011111111") then  addr_re_sig <=
(others => '0');
        end if;
      end if;
    end if;
                          addr_re <= addr_re_sig;
  end if;
    end process;
end Behavioral;

von Tobias (Gast)


Lesenswert?

entity control is
    Port ( clock     : in std_logic;
           reset     : in std_logic;
           addr_wr     : in std_logic_vector(17 downto 0);
           addr_re     : in std_logic_vector(17 downto 0);
           enab     : in std_logic;
           buffer_full   : in std_logic;

           we       : out std_logic;
           oe       : out std_logic;
           ce       : out std_logic;
           ub       : out std_logic;
           lb       : out std_logic;
           addr     : out std_logic_vector(17 downto 0);
           enab_io     : out std_logic);
end control;

architecture Behavioral of control is
   signal we_sig   : std_logic;
   signal cv    : std_logic;

begin
  clock_div: process(clock, reset)
  begin
    if (reset = '1') then          cv <= '0';
    elsif (clock = '1' and clock'event) then  cv <= not cv;
    end if;
  end process;

  set_addr: process (cv, reset, enab, addr_wr, addr_re, buffer_full)
  begin
    if (reset = '1') then        addr <= (others => '0');
    elsif (cv = '1' and cv'event) then
      if (enab = '0') then       addr <= addr_wr;
                      enab_io <= '0';
      elsif (buffer_full = '0') then  addr <= addr_re;
                    enab_io <= '1';

      end if;
    end if;
  end process;

  set_control_signals: process (clock, reset, enab, buffer_full)
  begin
    if (reset = '1') then          ce <= '0';
                      ub <= '1';
                      lb <= '0';
                      oe <= '1';
                      we <= '0';
    elsif (clock = '1' and clock'event) then
      if (enab = '0') then        ce <= '0';
                      ub <= '1';
                      lb <= '0';
                      oe <= '1';
                      we_sig <= not we_sig;
      elsif (buffer_full = '0') then    ce <= '0';
                      ub <= '1';
                      lb <= '0';
                      oe <= '0';
                      we_sig <= '0';
      end if;
      we <= not we_sig;
    end if;
  end process;
end Behavioral;

von Jörn (Gast)


Lesenswert?

Kannst du das ganze Projekt packen und als Datei hochladen?

Gruss Jörn

von Tobias (Gast)


Angehängte Dateien:

Lesenswert?

Ja mache ich, das Prokjekt heißt beispiel.npl, ich habe jetzt nur die
relevantesten dateien hinzugefügt, clock_div ist en DCM im Spartan - 3.

von Jörn (Gast)


Lesenswert?

Der DCM wird bei mir nicht erkannt. Wird ein ? in der Projektverwaltung
angezeigt.

von Tobias Danz (Gast)


Lesenswert?

Ein DCM gibt es, glaub ich nur beim Spartan - 3 Starter Kit.
Bei z.B. Spartan II mußt du, glaub ich, DLL's nehmen, anstelle des
DCM.
Der DCM dient nur nur dazu den Systemtakt herunter zu teilen.

von Jörn (Gast)


Angehängte Dateien:

Lesenswert?

ich hab einen Spartan 3 Baustein eingestellt. Wird trotzdem nicht
erkannt, s. Bild.

Vielleicht stimmt mit der Instanzierung noch was nicht.

von Tobias (Gast)


Lesenswert?

Hast du folgende Bibliotheken mit eingebunden?



library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

von Jörn (Gast)


Angehängte Dateien:

Lesenswert?

Ja, sind eingebunden.

von Tobias (Gast)


Angehängte Dateien:

Lesenswert?

Ja, mir fiel grad auf ich habe vergessen die xaw Datei mit zu geben.

von Jörn (Gast)


Lesenswert?

Hallo Tobias,

dein Design ist etwas unübersichtlich. Wenn ich dir einen Rat geben
darf, nimmt das Top-Design (Oberste Hierarchieebene) nur um die
einzelnen Komponenten zu instanzieren und diese zu verbinden. Lass dort
die Prozesse weg.

z.B.

top
|
|-Uart
|   |-tx_makro
|   |      |-Fifo
|   |      |-tx
|   |-Baudraten_gen
|
|- Sram
|- FSM

Fördert die Übersichtlichkeit enorm und die einzelnen Komponenten
lassen sich besser simulieren.

Weiter ist mir aufgefallen, dass die funktionale Simulation scheitert
(UART TX Leitung wird zu 'X'). Vermutlich liegt das an der
Baudratengenerierung. Dein Zähler teilt deine 25 Mhz um Faktor 2
runter. Du musst aber einen Puls mit der 16fachen Frequenz deiner
Baudrate generieren, s. Uart_Manual.pdf von Xilinx.

Gruss Jörn

von Tobias (Gast)


Lesenswert?

Hallo Jörn

danke für dein Tip, ich werde es ausprobieren und es umbauen. Du meinst
das ganze Problem liegt darin begründet? Oder könnte noch irgendwas
fehlen in meiner Schaltung?
Wie soll ich runter gehen mit den Hierarchieebenen? Soll ich für die
Baudratengenerierung ein alleiniges Modul verwenden?

Gruß Tobias

von Tobias (Gast)


Lesenswert?

Hallo Jörn,

ich habe es geändert und die tx leitung wird nicht mehr auf 'X'
gesetzt.
Aber ich habe immer noch das Problem, dass auf dem PC nicht die Werte
angezeigt werden, die ich ürsprünglich in den SRAM abgespeichert habe.
oran könnte das liegen?

Gruß Tobias.

von Jörn (Gast)


Lesenswert?

Kannst du dein aktuelle Design posten oder mir als Email schicken.

von Marcus (Gast)


Lesenswert?

Hallo.
Ich habe zu der SRAM-Problematik zwei Zwischenfragen. SRAM mit einem
FPGA anzusteuern scheint ja zu funktionieren. Handelt es sich um
asynchronen oder synchronen SRAM? Wie sieht es mit der Ansteuerung aus
zwei verschiedenen Taktumgebungen aus, z.B. eine Taktumgebung zum
Beschreiben des RAMs und eine andere zum Auslesen? Ist das sehr
aufwändig in VHDL?

Gruß,   Marcus

von Jörn (Gast)


Lesenswert?

Hallo Marcus,

es ist ein asychrones RAM von ISSI.
Du musst sicher stellen, dass die zwei Teilnehmer nicht gleichzeit auf
das SRAM zugreifen. Für die deine Frage würde ich aber zu Dual Port
RAMs greifen. Dies sind für so ausgelegt.
Wieviel Speicher wird benötigt?

Gruss Jörn

von Marcus (Gast)


Lesenswert?

Moin Jörn,

ja, Dual Port RAM, das habe ich mir auch schon überlegt. Dummerweise
bin ich schon im Besitz von asynchronen SRAMs von Alliance Semi. (2x
1MBIT) inkl. Leiterplatine. Wir wollten ursprünglich die Sache in
HandelC machen. Das klappt aber nicht so richtig.
Meine 2. Frage in VHDL zu lösen sieht dann wohl eher schwierig aus?

Gruß,   Marcus

von Tobias Danz (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Jörn,

ich hab mal mein überarbeitetes Projekt drangehängt. auf
www.issi.com/pdf/61LV25616AL.pdf kannst du das Datenblatt finden zu
meinem SRAM. Ich bin soweit, dass bei der Simualtion die ersten Werten
nicht sauber zugewiesen werden.
Wenn ich den FPGA prgrammiert habe, habe ich mir das ganze im HYper
Terminal angeschaut und habe festgestellt, dass der SPeicher nur zwei
Werte ausgibt.

Ich hoffe du kannst mir helfen.
Gruß Tobias


P.S. die Baudratengenerierung funktioniert, d.h. dassist nicht das
Problem.

von Tobias Danz (Gast)


Lesenswert?

Hallo

noch eine Ergänzung.
Nachdem ich kleinere Veränderungen an den Steuersignalen vorgenommen
hatte, hatte ich einen festen Wert abspeichern und auslesen wollen,
dies Funktioniert auch,d.h. ich kann einen Wert abspeichern und
auslesen, aber wenn ein Zähler läuft funktioniert es nicht.

von Jörn (Gast)


Lesenswert?

Welche der vier Möglichkeiten auf das SRAM zu schreiben, hast du benutzt
?

von Tobias Danz (Gast)


Lesenswert?

Gleich die erste Möglichkeit habe ich verwendet.

von Jörn (Gast)


Lesenswert?

benutzt du auch die /WE /LB&/UB Signale? die bewegen sich in der
Simulation überhaupt nicht. Lt. Datenblatt müssen sie für einen
Schreibzugriff auch betätigt werden.

von Tobias Danz (Gast)


Lesenswert?

Naja LB und UB habe ich so verstanden, dass ise statisch sein können,
das WE benutze ich beim Schreibvorgang und beim Lesevorgang kann es
statischs sein.

Mein Problem besteht ja darin, wenn ich einen festen Wert anlege, dann
wird dieser abgespeichert und auch wieder ausgelesen. Wenn ich aber
eine Folge von Werten verwende, z.B. einen Zähler bekomme ich am PC
immer nur einen statischen Wert ausgelesen.

von Tobias Danz (Gast)


Lesenswert?

Hallo, ist denn keiner hier, der mein Programm mal auf eine Spartan-3
Board programmieren kann?

Ich möchte mal wissen, ob mein Fehler an meiner Schaltung oder an
meinem Board liegt. Ich habe versucht mir meinen Adresszähler auf einem
Logikanalysator anzuschauen und festgestellt, dass die Adressen gar
nicht gezählt werden, sondern beim Wert null bleiben.

Ich hoffe mir kann jemand helfen.

(P.S. meine VHDL Quellen befinden sich weiter oben)

Gruß Tobias

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.