Hy, ich habe ein Projekt wo ich Daten zuerst ins RAM schreibe und wenn
dieses voll sollen sie ins EEPROM geleert werden..
Bisher funktioniert es, dass die Daten richtig ins RAM kommen jedoch vom
RAM kommen zu gänze die falschen Daten (ich vermute stark,dass nur die
letzte Adresse ausgegeben wird....ich würde mich sehr freuen wenn mir da
jemand helfen könnte denn selbst finde ich den Fehler einfach nicht
Hier der Code vom RAM:(welcher so funktioniert wie er sollte):
process(Clk_i,Reset_n_i)
begin
if(Reset_n_i = '0')then
Data_o <= (others => '0'); -- Reset Data output
ram <= (others => (others =>'0')); -- Reset RAM
elsif(rising_edge(Clk_i)) then
if(WriteEnable_i = '1') then
ram(to_integer(unsigned(Address_i))) <= Data_i; -- Write Data_i
to RAM
else
Data_o <= ram(to_integer(unsigned(Address_i))); -- Read RAM
end if;
end if;
end process;
end rtl;
und hier mein Code welcher dafür zuständig ist die Daten vom RAM zum
SPI(EEPROM) zu leiten:
when stRAM2EEPROM =>
CommandE_o <= write_c; -- SPI -Command -->Write
CommandR_o <= "0000";
ControlR_o <= "00000000";
Writeenable_o <= '0';
state <= stRAM2EEPROM_Addr;
CountAddress <= (others =>'0');
count <= (others =>'0');
when stRAM2EEPROM_Addr =>
if(AddrWrDone_i = '1') then
state <= stRAM2EEPROM_Data;
else
DataEEPROM_o <= std_logic_vector(CountAddress);
end if;
when stRAM2EEPROM_Data =>
if(DataWrDone_i= '1') then
if(CountAddress ="11111111") then
state <= stCAN2RAM;
else
CountAddress <= CountAddress+1;
state <= stRAM2EEPROM_Addr;
end if;
else
DataEEPROM_o <= DataRAM_i;
end if;
nochmals im Voraus ein Dankeschön für diejenigen die sich die mühe
machen zu helfen :-)
Welches EEPROM? (Atmel,Ti,ST,...) Welches FPGA/CPLD? Was sagt die Simulation? Wo ist der Rest vom Code?
Hier der gesamte Code des Schreib/Lese Moduls ....Vom CAN-Controller
wird gelesen und ins RAM geschrieben und vom RAM kommen die Daten ins
EEPROM
....das ganze soll erstmal in der Smulation funktionen und erst dann
wird es auf auf realer Hardware realisiert...
Die Sumulation des RAM Moduls und des Writestorage Moduls alleine
funktioniert ....jedoch im Gesamtpaket dann nicht mehr
Die Daten kommen zwar erfolgreich vom Can über SPI zum RAM aber vom RAM
nicht mehr raus bzw. nur die Daten aus der letzten Addresse werden
gelesen und damit stehen dann im EEPROM auf jeder Adresse die selben
Daten.
entity WriteStorage is
Generic ( AddrWidth : integer := 8;
Byte : integer := 8;
EEPROMSize : integer := 8192);
Port ( Reset_n_i : IN STD_LOGIC;
Clk_i : IN STD_LOGIC;
DataRAM_i : IN STD_LOGIC_VECTOR(Byte-1 downto 0);
DataSPI_i : IN STD_LOGIC_VECTOR(Byte-1 downto 0);
ControlR_o : out Std_logic_Vector(Byte-1 downto 0);
CommandE_o : OUT STD_LOGIC_VECTOR(3 downto 0);
CommandR_o : OUT STD_LOGIC_VECTOR(3 downto 0);
AddressRAM_o : OUT STD_LOGIC_VECTOR(AddrWidth-1 downto 0);
DataEEPROM_o : OUT STD_LOGIC_VECTOR(Byte-1 downto 0);
DataRAM_o : OUT STD_LOGIC_VECTOR(Byte-1 downto 0);
WriteEnable_o : OUT STD_LOGIC;
--SPI- Done-Signals:
AddrWrDone_i : in std_logic;
AddrRdDone_i : in std_logic;
DataWrDone_i : in std_logic;
DataRdDone_i : in std_logic);
end WriteStorage;
architecture rtl of WriteStorage is
type states is
(stCAN2RAM,stCAN2RAM_Addr,stCAN2RAM_Data,stRAM2EEPROM,stRAM2EEPROM_Addr,
stRAM2EEPROM_Data); -- stRead = Read from the CAN controller | stWrite
= Write from RAM to EEPROM
signal state : states;
signal CountAddress : unsigned(Byte-1 downto 0); --Count
Addresss
signal count : unsigned(3 downto 0);
begin
SeqProc: process(Reset_n_i, Clk_i)
begin
if(Reset_n_i = '0') then
AddressRAM_o <= (others => '0');
DataRAM_o <= (others => '0');
DataEEPROM_o <= (others => '0');
WriteEnable_o <= '0';
CountAddress <= (others => '0');
count <= (others => '0');
ControlR_o <= (others => '0');
CommandE_o <= "0000";
CommandR_o <= "0000";
state <= stCAN2RAM;
elsif rising_edge(Clk_i) then
case state is
---------------------------READ from
CAN---------------------------------------------------------------------
-------------------
when stCAN2RAM =>
CommandR_o <= read_c; -- SPI-Command --> read
CommandE_o <="0000";
WriteEnable_o <= '1';
ControlR_o <= "11110000";
state <= stCAN2RAM_Addr;
CountAddress <= (others =>'0');
count <= (others =>'0');
when stCAN2RAM_Addr =>
if(AddrRdDone_i = '1') then
state <= stCAN2RAM_Data;
else
AddressRAM_o <= std_logic_vector(CountAddress);
end if;
when stCAN2RAM_Data =>
if (DataRdDone_i = '1') then
if(CountAddress ="11111111") then
state <= stRAM2EEPROM;
else
CountAddress <= CountAddress +1;
state <=stCAN2RAM_Addr;
end if;
else
DataRAM_o <= DataSPI_i;
end if;
-------------------------------WRITE from RAM to
EEPROM------------------------------------------------------------------
-----------
when stRAM2EEPROM =>
CommandE_o <= write_c; -- SPI -Command -->Write
CommandR_o <= "0000";
ControlR_o <= "00000000";
Writeenable_o <= '0';
state <= stRAM2EEPROM_Addr;
CountAddress <= (others =>'0');
count <= (others =>'0');
when stRAM2EEPROM_Addr =>
if(AddrWrDone_i = '1') then
state <= stRAM2EEPROM_Data;
else
DataEEPROM_o <= std_logic_vector(CountAddress);
end if;
when stRAM2EEPROM_Data =>
if(DataWrDone_i= '1') then
if(CountAddress ="11111111") then
state <= stCAN2RAM;
else
CountAddress <= CountAddress+1;
state <= stRAM2EEPROM_Addr;
end if;
else
DataEEPROM_o <= DataRAM_i;
end if;
when others =>
AddressRAM_o <= (others => '0');
DataRAM_o <= (others => '0');
DataEEPROM_o <= (others => '0');
WriteEnable_o <= '0';
CountAddress <= (others => '0');
ControlR_o <= (others => '0');
CommandE_o <= "0000";
CommandR_o <= "0000";
State <= stCAN2RAM;
end case;
end if;
end process;
end rtl;
Richard schrieb: > if(Reset_n_i = '0')then > Data_o <= (others => '0'); -- Reset Data output > ram <= (others => (others =>'0')); -- Reset RAM ich bezweifle, das das synthetisierbar ist. MfG,
Geanu das Gegenteil ist der Fall ...so ist es synthetisierbar. LG,
Soso, naja, dann kann aber kein BRAM verwendet werden, sondern der komplette RAM wird aus einzelnen FlipFlops bzw. LUTs zusammen gebaut.
>Soso, naja, dann kann aber kein BRAM verwendet werden, sondern der >komplette RAM wird aus einzelnen FlipFlops bzw. LUTs zusammen gebaut. Ja, es gibt meines Wissens keinen RAM der sich auf ein einzelnes Signal hin komplett auf "0" setzen lässt. RAM muss wordweise addressiert werden. mit einzelnen FF geht das, schon bei LUT#s habe ich meine Zweifel, blockweises Löschen von Flash wäre auch noch ne Idee, aber das würde auch nur einen Block ( i.e. 512 byte) betreffen und nicht den gesamten memory. Schon bei distributed RAM aus LUTs hätte ich meine Zweifel (check mal mit datenblatt). Schau doch mal in den synthesereport, vielleicht hat ja die Synthese oder der mapper das array komplett ignoriert? Auf jeden fall sollte man die zeile mit "others ... others ..." im reset weglassen. Initialisiere es doch bei der Deklaration. MfG
Du zählst zwar die addressen hoch, aus deinem Code ist aber nicht erkenntlich ob die writeleitung zum RAM (WriteEnable_i) auch auf '0' gezogen wird. MfG,
Hallo Richard,
habe mir den Code mal angeschaut, den Fehler aber ohne mir das Design
mal zu skizzieren nicht auf gefunden, was daran liegt das der Code -
sorry - nicht sehr hardwarenah geschrieben ist. Hier meine 2 Cent.
- Datenpfade & Controlpfade strikt getrennt halten!
Eine Zuweisung wie "DataRAM_o <= DataSPI_i" hat in einer FSM nichts zu
suchen. Wenn man Datenpfade schalten will (multiplexen), dann einen
Multiplexer verwenden und das Kontrolsignal von der FSM generieren
lassen. Soweit ich das in deinem Code sehe wird DataRam_o immer von
DataSPI_i getrieben, also raus damit aus der FSM. Inbesondere nicht in
einer If-Else Anweisung innerhalb eines geclockten Prozesses, das kann
dir "versteckte" Register generieren.
- Gleiches gilt fur AddressRam_o. Soweit ich das sehe wird der Adressbus
nur von einem Counter getrieben. Also:
prcoess(clk)
begin
if rising_edge(clk) then
if Counter_Reset = '1' then
Counter <= (others=>'0');
elsif Counter_Increment = 1' then
Counter <= Counter + '1';
end if;
end process;
AddressRam_o <= Counter;
Die Signale Counter_Reset und Counter_Increment werden über die
Kontroll-FSM gesteuert.
- Vorsicht mit 1-Process FSMs. Die kann man zwar verwenden, sollte sich
aber bewusst sein, dass die generierten Kontrolsignale einen Takt nach
dem State erst gültig sind. Ist nicht falsch, aber macht es
komplizierter das Verhalten im Kopf nachzuvollziehen. Sauberer - und
meiner Erfahrung nach - einfacher zu lesen sind 2-Prozess FSMs. Ein
synchroner Prozess für die State-Register, in denen der aktuelle State
gespeichert wird. Und ein asynchroner der den nächsten State berechnet
und die Outputs entsprechend treibt.
FSM-States : process(clk)
begin
if rising_edge(clk) then
if Reset = '1' then
State <= Initial_State;
else
State <= Next_State;
end if;
end process;
FSM-Logic : process(State, Start_FSM, Input_A, Input_B)
begin
-- default assignments --
Next-State <= State;
Output_A <= '0';
Output_B <= '0';
-- state transitions --
case State is
when S_IDLE =>
if Start_FSM = '1' then
Next_State <= S_Drive_A;
end if;
when S_Drive_A =>
Next_State <= S_Drive_B;
Output_A <= '1';
when S_Drive_B =>
Next_State <= S_IDLE;
Output_B <= '1';
when others =>
null;
end case;
end process;
Diese Schreibweise hat mehrere Vorteile:
1) Der Output entspricht immer genau dem State in dem man gerade ist und
kommt genau in diesem Taktzyklus. Bei einer 1-Prozess FSM muss das nicht
der Fall sein (wie in deinem, in dem sich die Signalzuweisung innerhalb
des If rising_edge(clk) Statements befindet).
2) Durch die Default Assignments sind alle Signale zu jedem Zeitpunkt
sauber definiert und es entsehen keine "versteckten" Register.
Abschließend noch 3 Anmerkungen:
- Vergiss asynchrone Reset, die hat man Anfang 2000 bei FPGAs beerdigt.
Mit steigender Logikdichte und Geschwindigkeit machen die mehr Probleme
als dass sie Nutzen bringen. Detailiert kann man das im Xilinx
WhitePaper WP272 nachlesen.
- Dein Code zur Synthese des RAM ist korrekt, jeder Syntheizer sollte
das erkennen, manche könnten sich aber an dem Reset verschlucken. Reset
an einem RAM existiert so auch nicht, im schlimsten Fall, wie schon
andere zuvor angemerkt haben, wird das RAM in FFs implementiert. Reset
an einem RAM braucht man aber auch nicht, es ist völlig egal was da drin
steht, da man in ein RAM überlicherweise erstmal reinschreibt, bevor man
rausliest. Falls man vorinitialisierte RAMS braucht, dann macht man das
über spezielle Init Direktiven.
- Digital Design ist kein Software Design. VHDL und Verilog sind
Beschreibungssprachen, die beschreiben Systeme, die im Falle von FPGAs
aus bestimmten diskreten Elementen bestehen (LUTs, FF, RAMs, Hardcores,
DSPs). Und Synthesizer sind dumm! Alles was die versuchen ist zu
erkennen, wie man die Beschreibung auf diese diskreten Elemente abbilden
kann. Je klarer man seinen Code schreibt (und sich an gewisse Regeln
hält) desto eher tut der Synthesizer das was er tun soll. Am besten geht
das mit einem Blatt Papier und einem Stift. Man skizziert erstmal das
Design oder einen Teil davon, hält Daten- und Kontrolpfade strikt
getrennt und schreibt es dann genau so in VHDL/Verilog runter.
Viel Erfolg,
JD
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.