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
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;
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;
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;
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;
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;
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.
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;
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
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
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.
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
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
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
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.
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.
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.
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.
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