mikrocontroller.net

Forum: FPGA, VHDL & Co. VHDL, Nexys 2 Board, OnBoardRam-Zugriff


Autor: Rene (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Forum,
ich habe momentan ein "kleines" Problem damit, Zugriff auf den 
OnBoardspeicher des Nexys 2 Boards zu bekommen.

Ich will den RAM als einfachen RAM nutzen und habe mir zu erst mit dem 
Core Generator ein BlockRAM erstellt. (siehe Bild CoreGen.PNG)


Als nächstes habe ich mir den View HDL Functional Model-Code aus dem 
CoreGen kopiert und unter dem passenden Entitynamen "newBlockRam.vhd" 
abgespeichert.
Dessen Code sieht folgendermaßen aus:
--------------------------------------------------------------------------------
--     This file is owned and controlled by Xilinx and must be used           --
--     solely for design, simulation, implementation and creation of          --
--     design files limited to Xilinx devices or technologies. Use            --
--     with non-Xilinx devices or technologies is expressly prohibited        --
--     and immediately terminates your license.                               --
--                                                                            --
--     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"          --
--     SOLELY FOR USE IN DEVELOPING PROGRAMS AND SOLUTIONS FOR                --
--     XILINX DEVICES.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION        --
--     AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION            --
--     OR STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS              --
--     IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,                --
--     AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE       --
--     FOR YOUR IMPLEMENTATION.  XILINX EXPRESSLY DISCLAIMS ANY               --
--     WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE                --
--     IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR         --
--     REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF        --
--     INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS        --
--     FOR A PARTICULAR PURPOSE.                                              --
--                                                                            --
--     Xilinx products are not intended for use in life support               --
--     appliances, devices, or systems. Use in such applications are          --
--     expressly prohibited.                                                  --
--                                                                            --
--     (c) Copyright 1995-2009 Xilinx, Inc.                                   --
--     All rights reserved.                                                   --
--------------------------------------------------------------------------------
-- You must compile the wrapper file newBlockRam.vhd when simulating
-- the core, newBlockRam. When compiling the wrapper file, be sure to
-- reference the XilinxCoreLib VHDL simulation library. For detailed
-- instructions, please refer to the "CORE Generator Help".

-- The synthesis directives "translate_off/translate_on" specified
-- below are supported by Xilinx, Mentor Graphics and Synplicity
-- synthesis tools. Ensure they are correct for your synthesis tool(s).

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
-- synthesis translate_off
Library XilinxCoreLib;
-- synthesis translate_on
ENTITY newBlockRam IS
  port (
  clka: IN std_logic;
  wea: IN std_logic_VECTOR(0 downto 0);
  addra: IN std_logic_VECTOR(12 downto 0);
  dina: IN std_logic_VECTOR(15 downto 0);
  douta: OUT std_logic_VECTOR(15 downto 0));
END newBlockRam;

ARCHITECTURE newBlockRam_a OF newBlockRam IS
-- synthesis translate_off
component wrapped_newBlockRam
  port (
  clka: IN std_logic;
  wea: IN std_logic_VECTOR(0 downto 0);
  addra: IN std_logic_VECTOR(12 downto 0);
  dina: IN std_logic_VECTOR(15 downto 0);
  douta: OUT std_logic_VECTOR(15 downto 0));
end component;

-- Configuration specification 
  for all : wrapped_newBlockRam use entity XilinxCoreLib.blk_mem_gen_v4_2(behavioral)
    generic map(
      c_has_regceb => 0,
      c_has_regcea => 0,
      c_mem_type => 0,
      c_rstram_b => 0,
      c_rstram_a => 0,
      c_has_injecterr => 0,
      c_rst_type => "SYNC",
      c_prim_type => 1,
      c_read_width_b => 16,
      c_initb_val => "0",
      c_family => "spartan3",
      c_read_width_a => 16,
      c_disable_warn_bhv_coll => 0,
      c_use_softecc => 0,
      c_write_mode_b => "WRITE_FIRST",
      c_init_file_name => "no_coe_file_loaded",
      c_write_mode_a => "WRITE_FIRST",
      c_mux_pipeline_stages => 0,
      c_has_softecc_output_regs_b => 0,
      c_has_mem_output_regs_b => 0,
      c_has_mem_output_regs_a => 0,
      c_load_init_file => 0,
      c_xdevicefamily => "spartan3e",
      c_write_depth_b => 8192,
      c_write_depth_a => 8192,
      c_has_rstb => 0,
      c_has_rsta => 0,
      c_has_mux_output_regs_b => 0,
      c_inita_val => "0",
      c_has_mux_output_regs_a => 0,
      c_addra_width => 13,
      c_has_softecc_input_regs_a => 0,
      c_addrb_width => 13,
      c_default_data => "0",
      c_use_ecc => 0,
      c_algorithm => 1,
      c_disable_warn_bhv_range => 0,
      c_write_width_b => 16,
      c_write_width_a => 16,
      c_read_depth_b => 8192,
      c_read_depth_a => 8192,
      c_byte_size => 9,
      c_sim_collision_check => "ALL",
      c_common_clk => 0,
      c_wea_width => 1,
      c_has_enb => 0,
      c_web_width => 1,
      c_has_ena => 0,
      c_use_byte_web => 0,
      c_use_byte_wea => 0,
      c_rst_priority_b => "CE",
      c_rst_priority_a => "CE",
      c_use_default_data => 0);
-- synthesis translate_on
BEGIN
-- synthesis translate_off
U0 : wrapped_newBlockRam
    port map (
      clka => clka,
      wea => wea,
      addra => addra,
      dina => dina,
      douta => douta);
-- synthesis translate_on

END newBlockRam_a;



Dazu kommt dann noch eine  Art Kontrollinstanz, welche mir eine Instanz 
der VHDL-Datei bilden soll und das Lesen/Schreiben regelt.
Der Code:
----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    13:27:00 01/06/2011 
-- Design Name: 
-- Module Name:    ramComp - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity ramComp is
    Port ( DataIN : in  STD_LOGIC_VECTOR (15 downto 0);
           DataOUT : out  STD_LOGIC_VECTOR (15 downto 0);
           AddrLowByte : in  STD_LOGIC_VECTOR (7 downto 0);
           AddrMidByte : in  STD_LOGIC_VECTOR (7 downto 0);
           AddrHighByte : in  STD_LOGIC_VECTOR (7 downto 0);
           wea : in  STD_LOGIC_VECTOR(0 downto 0);
           dataValid : out  STD_LOGIC;
           clk : in  STD_LOGIC;
        active : in STD_LOGIC;
        reset : in  STD_LOGIC);
end ramComp;



architecture Behavioral of ramComp is
------------- Begin Cut here for COMPONENT Declaration ------ COMP_TAG
component newBlockRam
  port (
  clka: IN std_logic;
  wea: IN std_logic_VECTOR(0 downto 0);
  addra: IN std_logic_VECTOR(12 downto 0);
  dina: IN std_logic_VECTOR(15 downto 0);
  douta: OUT std_logic_VECTOR(15 downto 0));
end component;

-- Synplicity black box declaration
attribute syn_black_box : boolean;
attribute syn_black_box of newBlockRam: component is true;

-- COMP_TAG_END ------ End COMPONENT Declaration ------------
type state_type is (
  do,
  commit
);
signal mystate: state_type;
signal addra : std_logic_vector(12 downto 0);
signal dina : std_logic_vector(15 downto 0);
signal douta : std_logic_vector(15 downto 0);


begin

------------- Begin Cut here for INSTANTIATION Template ----- INST_TAG
myRam : newBlockRam
    port map (
      clka => clk,
      wea => wea,
      addra => addra,
      dina => dina,
      douta => douta);
-- INST_TAG_END ------ End INSTANTIATION Template ------------

myRamProcess: process
begin
wait until clk'event and clk='1';
if reset = '1' then
  mystate <= do;
  dataValid <= '0';
else
  --Wenn der nicht Ram angesprochen werden soll
  if active  = '0' then
    mystate <= do;
    dataValid <= '0';
  -- Wenn der RAM angesprochen werden soll
  else
    case myState is
    --do soll dem Ram die Befehle schicken
    when do =>
      dataValid <= '0';
      --Adresse setzen, hier nur 13 Bit!
      addra <= AddrMidByte(4 downto 0)&AddrLowByte;
      -- Zu schreibende Daten an den Ram-Eingang legen
      if wea = "1" then
        dina <= DataIN;
      end if;
      myState <= commit;
    --commit soll dem Aufrufenden ein Valid-Signal geben
    when commit =>
      if wea = "0" then
      --Vom RAM gelesene Daten an den Ausgang dieser Comp legen
        DataOUT <= douta;
      end if;
      --Der übergeordneten Stelle die Bereitschaft der Daten ausgeben
      dataValid <= '1';
    end case;
  end if;
  
end if;
end process;
end Behavioral;


Wie man sieht habe ich zur Instanziierung des newBlockRam das Template 
des CoreGens verwendet.

Diese Entity wird wieder in einem Controller instanziiert:
....
signal ramWEA : std_logic_VECTOR(0 downto 0);
signal ramActivate : std_logic;
signal ramAddress : std_logic_vector(12 downto 0) := "0000000000000";
signal ramAddrHigh : std_logic_vector(7 downto 0);
signal ramAddrMid : std_logic_vector(7 downto 0);
signal ramAddrLow : std_logic_vector(7 downto 0);
signal ramInGesamt : std_logic_vector(15 downto 0);
signal ramOutGesamt : std_logic_vector(15 downto 0);
signal ramValid : std_logic;
....
component ramComp is
    Port ( DataIN : in  STD_LOGIC_VECTOR (15 downto 0);
           DataOUT : out  STD_LOGIC_VECTOR (15 downto 0);
           AddrLowByte : in  STD_LOGIC_VECTOR (7 downto 0);
           AddrMidByte : in  STD_LOGIC_VECTOR (7 downto 0);
           AddrHighByte : in  STD_LOGIC_VECTOR (7 downto 0);
           wea : in  std_logic_VECTOR(0 downto 0);
           dataValid : out  STD_LOGIC;
           clk : in  STD_LOGIC;
        active : in STD_LOGIC;
        reset : in  STD_LOGIC);
end component;
....
myRamManager: ramComp port map (
        DataIN => ramInGesamt,
        DataOUT => ramOutGesamt,
        AddrLowByte => ramAddrLow,
        AddrMidByte => ramAddrMid,
        AddrHighByte => ramAddrHigh,
        wea => ramWEA,
        dataValid => ramValid,
        clk => clk,
        active => ramActivate,
        reset => reset
        );
....
--Der Prozessor will lesen, der Controller schaut auf welchem Port
elsif cpu_read_strobe = '1' then -- Falls die CPU lesen will
  BCD_links(3 downto 0) <= "0001";
  case port_id is
  when "00000100" =>
        rs232_readstrobe <= '1';
        cpu_in_port_valid <= '0';
  when "00010000" =>
    ramAddrLow <= cpu_port_out;
    cpu_in_port_valid <= '1';
  when "00010001" =>
    ramAddrMid <= cpu_port_out;
    cpu_in_port_valid <= '1';
  when "00010011" =>
--Hier wird der eigentlich Lesevorgang ausgeführt
    if ramValid = '1' then
    --fertig gelesen
    cpu_port_in <= ramOutGesamt(7 downto 0);
    cpu_in_port_valid <= '1';
    else
    --muss noch lesen
    ramActivate <= '1';
    ramWEA <= "0";
    cpu_in_port_valid <= '0';
    end if;
....
--Falls die CPU schreiben will, wird hier geschaut auf welchen Port
elsif cpu_write_strobe = '1' then --Falls die CPU schreiben will
  BCD_links(7 downto 4) <= "0001";
  case port_id is
  when "00000100" =>
    rs232_data_in <= cpu_port_out;
    rs232_writestrobe <= '1';
    cpu_out_port_ready <= '0';
  when "00010000" =>
    ramAddrLow <= cpu_port_out;
    cpu_out_port_ready <= '1';
  when "00010001" =>
    ramAddrMid <= cpu_port_out;
    cpu_out_port_ready <= '1';
--Hier soll nun auf den RAM geschrieben werden
  when "00010011" =>
    if ramValid = '1' then
    --fertig geschrieben
    BCD_links <= cpu_port_out;
    
    --cpu_out_port_ready <= '1';
    else
    --muss noch schreiben
    ramActivate <= '1';
    ramWEA <= "1";
    cpu_out_port_ready <= '0';
    
    ramInGesamt <= "00000000"&cpu_port_out;
    end if;
....


RS232 etc funktionieren, also sollte es nicht am Controller direkt 
liegen (außer in den geposteten Abschnitten versteht sich).

Dazu stellen sich mir mehrere Fragen:
Muss ich die Pins noch manuell zuweisen? Falls ja:
Wie mache ich das ohne die Ports bis in den Controller durchzuschleifen? 
Kann ich also irgendwie ein ucf-File für eine untergeordnete Instanz 
erstellen?

Falls Nein:
Was mache ich falsch mit meinem Code? Ich sehe es wirklich nicht. Das 
ganze kompiliert durch, das Board läuft auch, nur leider bekomme ich nur 
0 aus dem RAM rausgelesen, nachdem ich ihn beschreiben wollte.

Zur Übersicht befindet sich im Anhang noch die Projektstruktur unter 
strukt.PNG.

Autor: Rene (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
hat keiner eine Idee? Oder zumindest ein Tutorial, wo ich mir den 
Ramzugriff zu Gemüte führen kann?
Danke!

Autor: Anguel S. (anguel)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kann es sein, dass Du den BlockRAM im FPGA mit dem RAM auf dem Board 
verwechselst?

Autor: TokyoDrift (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der RAM auf deinem Board ist ein SDRAM. Das heißt er ist relativ 
kompliziert anzusteuern, weil man ihn refreshen muss und so. Schau dir 
mal den englischen Wikipedia-Artikel zu SDRAM an, da steht bisschen was 
über die Ansteuerung. Ich glaube du hast einen SDR SDRAM, oder? Ich habe 
auf meinem Spartan3E Board einen DDR SDRAM und plane in naher zukunft 
mal einen Memory Controller dafür zu schreiben. Ich glaube der Core 
generator bietet keine Option dafür. Um auf den externen SDRAM 
zuzugreifen hast du also nur die IOs am FPGA, die mit dem RAM verbunden 
sind, den rest musst du selber nehmen.

Im FPGA ist auch ein s.g. Blockram verbaut, den kannst du mit dem Core 
Generator nutzen (aber auch noch viel einfacher mit Arrays). Der 
Blockram ist sehr schnell, statisch und kann dual port ansteuerung, 
dafür ists eben nicht so viel RAM wie der externe. Schau ins Datenblatt 
deines FPGAs um zu sehen wie viel drinn ist.

Autor: Johny (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

Der Ram auf dem Board ist ein PSRam, entweder du sprichst in an die ein 
70ns schnellen SRAM oder wie ein 80 Mhz SRAM mit Takt und Bursts usw.
Aber das Datenblatt ist echt gut, vllt. sollte man das mal Lesen . . .

Gruß Johny

Autor: TokyoDrift (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Johny schrieb:
> Der Ram auf dem Board ist ein PSRam, entweder du sprichst in an die ein
> 70ns schnellen SRAM oder wie ein 80 Mhz SRAM mit Takt und Bursts usw.
> Aber das Datenblatt ist echt gut, vllt. sollte man das mal Lesen . . .

Ja, richtig, sorry, habe nur kurz die Beschreibung überflogen, da stand 
SDRAM, im handbuch steht PSRAM. Der ist natürlich genauso einfach 
anzusteuern wie SRAM, kein Problem.

Autor: Anguel S. (anguel)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
TokyoDrift schrieb:
> Ja, richtig, sorry, habe nur kurz die Beschreibung überflogen, da stand
> SDRAM, im handbuch steht PSRAM. Der ist natürlich genauso einfach
> anzusteuern wie SRAM, kein Problem.

Aber nicht mit dem Core Generator, der ausschließlich für den 
FPGA-internen BlockRAM gedacht ist. Das war der Fehler im ursprünglichen 
Post.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.