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.