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


von Rene (Gast)


Angehängte Dateien:

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:
1
--------------------------------------------------------------------------------
2
--     This file is owned and controlled by Xilinx and must be used           --
3
--     solely for design, simulation, implementation and creation of          --
4
--     design files limited to Xilinx devices or technologies. Use            --
5
--     with non-Xilinx devices or technologies is expressly prohibited        --
6
--     and immediately terminates your license.                               --
7
--                                                                            --
8
--     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"          --
9
--     SOLELY FOR USE IN DEVELOPING PROGRAMS AND SOLUTIONS FOR                --
10
--     XILINX DEVICES.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION        --
11
--     AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION            --
12
--     OR STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS              --
13
--     IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,                --
14
--     AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE       --
15
--     FOR YOUR IMPLEMENTATION.  XILINX EXPRESSLY DISCLAIMS ANY               --
16
--     WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE                --
17
--     IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR         --
18
--     REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF        --
19
--     INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS        --
20
--     FOR A PARTICULAR PURPOSE.                                              --
21
--                                                                            --
22
--     Xilinx products are not intended for use in life support               --
23
--     appliances, devices, or systems. Use in such applications are          --
24
--     expressly prohibited.                                                  --
25
--                                                                            --
26
--     (c) Copyright 1995-2009 Xilinx, Inc.                                   --
27
--     All rights reserved.                                                   --
28
--------------------------------------------------------------------------------
29
-- You must compile the wrapper file newBlockRam.vhd when simulating
30
-- the core, newBlockRam. When compiling the wrapper file, be sure to
31
-- reference the XilinxCoreLib VHDL simulation library. For detailed
32
-- instructions, please refer to the "CORE Generator Help".
33
34
-- The synthesis directives "translate_off/translate_on" specified
35
-- below are supported by Xilinx, Mentor Graphics and Synplicity
36
-- synthesis tools. Ensure they are correct for your synthesis tool(s).
37
38
LIBRARY ieee;
39
USE ieee.std_logic_1164.ALL;
40
-- synthesis translate_off
41
Library XilinxCoreLib;
42
-- synthesis translate_on
43
ENTITY newBlockRam IS
44
  port (
45
  clka: IN std_logic;
46
  wea: IN std_logic_VECTOR(0 downto 0);
47
  addra: IN std_logic_VECTOR(12 downto 0);
48
  dina: IN std_logic_VECTOR(15 downto 0);
49
  douta: OUT std_logic_VECTOR(15 downto 0));
50
END newBlockRam;
51
52
ARCHITECTURE newBlockRam_a OF newBlockRam IS
53
-- synthesis translate_off
54
component wrapped_newBlockRam
55
  port (
56
  clka: IN std_logic;
57
  wea: IN std_logic_VECTOR(0 downto 0);
58
  addra: IN std_logic_VECTOR(12 downto 0);
59
  dina: IN std_logic_VECTOR(15 downto 0);
60
  douta: OUT std_logic_VECTOR(15 downto 0));
61
end component;
62
63
-- Configuration specification 
64
  for all : wrapped_newBlockRam use entity XilinxCoreLib.blk_mem_gen_v4_2(behavioral)
65
    generic map(
66
      c_has_regceb => 0,
67
      c_has_regcea => 0,
68
      c_mem_type => 0,
69
      c_rstram_b => 0,
70
      c_rstram_a => 0,
71
      c_has_injecterr => 0,
72
      c_rst_type => "SYNC",
73
      c_prim_type => 1,
74
      c_read_width_b => 16,
75
      c_initb_val => "0",
76
      c_family => "spartan3",
77
      c_read_width_a => 16,
78
      c_disable_warn_bhv_coll => 0,
79
      c_use_softecc => 0,
80
      c_write_mode_b => "WRITE_FIRST",
81
      c_init_file_name => "no_coe_file_loaded",
82
      c_write_mode_a => "WRITE_FIRST",
83
      c_mux_pipeline_stages => 0,
84
      c_has_softecc_output_regs_b => 0,
85
      c_has_mem_output_regs_b => 0,
86
      c_has_mem_output_regs_a => 0,
87
      c_load_init_file => 0,
88
      c_xdevicefamily => "spartan3e",
89
      c_write_depth_b => 8192,
90
      c_write_depth_a => 8192,
91
      c_has_rstb => 0,
92
      c_has_rsta => 0,
93
      c_has_mux_output_regs_b => 0,
94
      c_inita_val => "0",
95
      c_has_mux_output_regs_a => 0,
96
      c_addra_width => 13,
97
      c_has_softecc_input_regs_a => 0,
98
      c_addrb_width => 13,
99
      c_default_data => "0",
100
      c_use_ecc => 0,
101
      c_algorithm => 1,
102
      c_disable_warn_bhv_range => 0,
103
      c_write_width_b => 16,
104
      c_write_width_a => 16,
105
      c_read_depth_b => 8192,
106
      c_read_depth_a => 8192,
107
      c_byte_size => 9,
108
      c_sim_collision_check => "ALL",
109
      c_common_clk => 0,
110
      c_wea_width => 1,
111
      c_has_enb => 0,
112
      c_web_width => 1,
113
      c_has_ena => 0,
114
      c_use_byte_web => 0,
115
      c_use_byte_wea => 0,
116
      c_rst_priority_b => "CE",
117
      c_rst_priority_a => "CE",
118
      c_use_default_data => 0);
119
-- synthesis translate_on
120
BEGIN
121
-- synthesis translate_off
122
U0 : wrapped_newBlockRam
123
    port map (
124
      clka => clka,
125
      wea => wea,
126
      addra => addra,
127
      dina => dina,
128
      douta => douta);
129
-- synthesis translate_on
130
131
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:
1
----------------------------------------------------------------------------------
2
-- Company: 
3
-- Engineer: 
4
-- 
5
-- Create Date:    13:27:00 01/06/2011 
6
-- Design Name: 
7
-- Module Name:    ramComp - Behavioral 
8
-- Project Name: 
9
-- Target Devices: 
10
-- Tool versions: 
11
-- Description: 
12
--
13
-- Dependencies: 
14
--
15
-- Revision: 
16
-- Revision 0.01 - File Created
17
-- Additional Comments: 
18
--
19
----------------------------------------------------------------------------------
20
library IEEE;
21
use IEEE.STD_LOGIC_1164.ALL;
22
23
-- Uncomment the following library declaration if using
24
-- arithmetic functions with Signed or Unsigned values
25
--use IEEE.NUMERIC_STD.ALL;
26
27
-- Uncomment the following library declaration if instantiating
28
-- any Xilinx primitives in this code.
29
--library UNISIM;
30
--use UNISIM.VComponents.all;
31
32
entity ramComp is
33
    Port ( DataIN : in  STD_LOGIC_VECTOR (15 downto 0);
34
           DataOUT : out  STD_LOGIC_VECTOR (15 downto 0);
35
           AddrLowByte : in  STD_LOGIC_VECTOR (7 downto 0);
36
           AddrMidByte : in  STD_LOGIC_VECTOR (7 downto 0);
37
           AddrHighByte : in  STD_LOGIC_VECTOR (7 downto 0);
38
           wea : in  STD_LOGIC_VECTOR(0 downto 0);
39
           dataValid : out  STD_LOGIC;
40
           clk : in  STD_LOGIC;
41
        active : in STD_LOGIC;
42
        reset : in  STD_LOGIC);
43
end ramComp;
44
45
46
47
architecture Behavioral of ramComp is
48
------------- Begin Cut here for COMPONENT Declaration ------ COMP_TAG
49
component newBlockRam
50
  port (
51
  clka: IN std_logic;
52
  wea: IN std_logic_VECTOR(0 downto 0);
53
  addra: IN std_logic_VECTOR(12 downto 0);
54
  dina: IN std_logic_VECTOR(15 downto 0);
55
  douta: OUT std_logic_VECTOR(15 downto 0));
56
end component;
57
58
-- Synplicity black box declaration
59
attribute syn_black_box : boolean;
60
attribute syn_black_box of newBlockRam: component is true;
61
62
-- COMP_TAG_END ------ End COMPONENT Declaration ------------
63
type state_type is (
64
  do,
65
  commit
66
);
67
signal mystate: state_type;
68
signal addra : std_logic_vector(12 downto 0);
69
signal dina : std_logic_vector(15 downto 0);
70
signal douta : std_logic_vector(15 downto 0);
71
72
73
begin
74
75
------------- Begin Cut here for INSTANTIATION Template ----- INST_TAG
76
myRam : newBlockRam
77
    port map (
78
      clka => clk,
79
      wea => wea,
80
      addra => addra,
81
      dina => dina,
82
      douta => douta);
83
-- INST_TAG_END ------ End INSTANTIATION Template ------------
84
85
myRamProcess: process
86
begin
87
wait until clk'event and clk='1';
88
if reset = '1' then
89
  mystate <= do;
90
  dataValid <= '0';
91
else
92
  --Wenn der nicht Ram angesprochen werden soll
93
  if active  = '0' then
94
    mystate <= do;
95
    dataValid <= '0';
96
  -- Wenn der RAM angesprochen werden soll
97
  else
98
    case myState is
99
    --do soll dem Ram die Befehle schicken
100
    when do =>
101
      dataValid <= '0';
102
      --Adresse setzen, hier nur 13 Bit!
103
      addra <= AddrMidByte(4 downto 0)&AddrLowByte;
104
      -- Zu schreibende Daten an den Ram-Eingang legen
105
      if wea = "1" then
106
        dina <= DataIN;
107
      end if;
108
      myState <= commit;
109
    --commit soll dem Aufrufenden ein Valid-Signal geben
110
    when commit =>
111
      if wea = "0" then
112
      --Vom RAM gelesene Daten an den Ausgang dieser Comp legen
113
        DataOUT <= douta;
114
      end if;
115
      --Der übergeordneten Stelle die Bereitschaft der Daten ausgeben
116
      dataValid <= '1';
117
    end case;
118
  end if;
119
  
120
end if;
121
end process;
122
end Behavioral;
Wie man sieht habe ich zur Instanziierung des newBlockRam das Template 
des CoreGens verwendet.

Diese Entity wird wieder in einem Controller instanziiert:
1
....
2
signal ramWEA : std_logic_VECTOR(0 downto 0);
3
signal ramActivate : std_logic;
4
signal ramAddress : std_logic_vector(12 downto 0) := "0000000000000";
5
signal ramAddrHigh : std_logic_vector(7 downto 0);
6
signal ramAddrMid : std_logic_vector(7 downto 0);
7
signal ramAddrLow : std_logic_vector(7 downto 0);
8
signal ramInGesamt : std_logic_vector(15 downto 0);
9
signal ramOutGesamt : std_logic_vector(15 downto 0);
10
signal ramValid : std_logic;
11
....
12
component ramComp is
13
    Port ( DataIN : in  STD_LOGIC_VECTOR (15 downto 0);
14
           DataOUT : out  STD_LOGIC_VECTOR (15 downto 0);
15
           AddrLowByte : in  STD_LOGIC_VECTOR (7 downto 0);
16
           AddrMidByte : in  STD_LOGIC_VECTOR (7 downto 0);
17
           AddrHighByte : in  STD_LOGIC_VECTOR (7 downto 0);
18
           wea : in  std_logic_VECTOR(0 downto 0);
19
           dataValid : out  STD_LOGIC;
20
           clk : in  STD_LOGIC;
21
        active : in STD_LOGIC;
22
        reset : in  STD_LOGIC);
23
end component;
24
....
25
myRamManager: ramComp port map (
26
        DataIN => ramInGesamt,
27
        DataOUT => ramOutGesamt,
28
        AddrLowByte => ramAddrLow,
29
        AddrMidByte => ramAddrMid,
30
        AddrHighByte => ramAddrHigh,
31
        wea => ramWEA,
32
        dataValid => ramValid,
33
        clk => clk,
34
        active => ramActivate,
35
        reset => reset
36
        );
37
....
38
--Der Prozessor will lesen, der Controller schaut auf welchem Port
39
elsif cpu_read_strobe = '1' then -- Falls die CPU lesen will
40
  BCD_links(3 downto 0) <= "0001";
41
  case port_id is
42
  when "00000100" =>
43
        rs232_readstrobe <= '1';
44
        cpu_in_port_valid <= '0';
45
  when "00010000" =>
46
    ramAddrLow <= cpu_port_out;
47
    cpu_in_port_valid <= '1';
48
  when "00010001" =>
49
    ramAddrMid <= cpu_port_out;
50
    cpu_in_port_valid <= '1';
51
  when "00010011" =>
52
--Hier wird der eigentlich Lesevorgang ausgeführt
53
    if ramValid = '1' then
54
    --fertig gelesen
55
    cpu_port_in <= ramOutGesamt(7 downto 0);
56
    cpu_in_port_valid <= '1';
57
    else
58
    --muss noch lesen
59
    ramActivate <= '1';
60
    ramWEA <= "0";
61
    cpu_in_port_valid <= '0';
62
    end if;
63
....
64
--Falls die CPU schreiben will, wird hier geschaut auf welchen Port
65
elsif cpu_write_strobe = '1' then --Falls die CPU schreiben will
66
  BCD_links(7 downto 4) <= "0001";
67
  case port_id is
68
  when "00000100" =>
69
    rs232_data_in <= cpu_port_out;
70
    rs232_writestrobe <= '1';
71
    cpu_out_port_ready <= '0';
72
  when "00010000" =>
73
    ramAddrLow <= cpu_port_out;
74
    cpu_out_port_ready <= '1';
75
  when "00010001" =>
76
    ramAddrMid <= cpu_port_out;
77
    cpu_out_port_ready <= '1';
78
--Hier soll nun auf den RAM geschrieben werden
79
  when "00010011" =>
80
    if ramValid = '1' then
81
    --fertig geschrieben
82
    BCD_links <= cpu_port_out;
83
    
84
    --cpu_out_port_ready <= '1';
85
    else
86
    --muss noch schreiben
87
    ramActivate <= '1';
88
    ramWEA <= "1";
89
    cpu_out_port_ready <= '0';
90
    
91
    ramInGesamt <= "00000000"&cpu_port_out;
92
    end if;
93
....


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.

von Rene (Gast)


Lesenswert?

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

von Anguel S. (anguel)


Lesenswert?

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

von TokyoDrift (Gast)


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.

von Johny (Gast)


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

von TokyoDrift (Gast)


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.

von Anguel S. (anguel)


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.

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.