Elektroda.pl
Elektroda.pl
X
PCBway
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

vhdl->symulacja a rzeczywistośc uk. fpga (xc3s200)

02 Gru 2007 22:07 2520 7
  • Poziom 15  
    Witam
    To już, następny wątek podczas pracy nad moim pierwszym układem z wykorzystaniem logiki programowalnej i vhdl'a; pokonałem konfigurowanie ale teraz układ nie zachowuje się tak jak podczas symulacji behawioralnej.
    Poniżej zamieszczę kod vhdl, aby ktoś mógł odnieść się krytycznie do sposobu w jaki to zapisałem, ale biorąc pod uwagę to, że symulację przechodzą poproszę raczej Was o wskazówki w jaki sposób zmusić mój układ do pracy.
    Pierwszy proces ma za zadanie obserwować stan wejścia uCDA - gdy te się podniesie sprawdza co jest na uCData(7:0) (rozkaz) i w zależności od tego może przypisac do zmiennej uCCommand RAMSTART, RAMWRITE, RAMSTOP, ustawia też isqe=1, która kontroluje, że przy następnym uruchomieniu procesu wykonywać sę już będzie cześć zależna od stanu uCCommand. Jeżeli rozkaz sie zgadza podnoszona jest noga uCDR potwierdzając tym samym poprawne odebranie rozkazu (czy później danych).
    RAMSTART i RAMSTOP stawia tylko 19bitowe rejestry, RAMWRITE pobiera dane z uCData i wpisuje do zewnętrznej pamięci (adres na MADDR(18:0), dane na MDATA(7:0), sygnały sterujące M_CS_1, M_OE_1, M_WE_1, sygnały te przechodzą przez multiplekser bo będą używane w innym procesie). Wpisywanie kończy się kiedy adres na MADDR zrówna się z RAMStopReg. Układ docelowo ma byc taktowany 60MHz, ale nie funkcjonuje prawidłowo nawet przy 2MHz. Te nieprawidłowości to:
    - czasami (losowo) nie ma potwierdzenia na uCDR, jeżeli steruje ręcznie (każdym sygnałem mogę ruszać przez terminal->ATMega) to wszystko jest okey, przy większych prędkościach (czyli jak wyśle do terminalu odpowiednio spreparowany plik) uCDA nie zawsze jest podnoszone.
    Podczas zapisu do pamięci jest też czytana (po zapisie) zawartość i sprawdzane czy zapisało się poprawnie - tu też są zgłaszane błędy (widze to na diodzie sygnał:ON_LED) i tylko wtedy kiedy wysyłam plik do terminalu (czyli przy większych prędkościach)... czasami zapisze 256 bajtów bez sygnalizacji błędu, innym razem w tej samym miejscu w pamięci wyskakują błędy... a czasami układ nie przestaje oczekiwać na kolejne dane mimo, ze wysłano ich tyle by adres na MADDR zrownal sie a RAMStopReg. Sprawdziłem, że wszystkie sygnały do pamięci i pomiędzy mikro kontrolerem a spartanem dochodzą.


    Code:
    library IEEE;
    
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.STD_LOGIC_ARITH.ALL;
    use IEEE.STD_LOGIC_UNSIGNED.ALL;

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

    entity dm is
        Port ( MADDR : out  STD_LOGIC_VECTOR (18 downto 0);
               MDATA : inout  STD_LOGIC_VECTOR (7 downto 0);
               M_CS : out  STD_LOGIC;
               M_WE : out  STD_LOGIC;
               M_OE : out  STD_LOGIC;
               DATA : out  STD_LOGIC_VECTOR (11 downto 0);
               DA_NOT_CS : out  STD_LOGIC;
               DA_NOT_WR : out  STD_LOGIC;
               DDS_WCLK : out  STD_LOGIC;
               DDS_FUP : out  STD_LOGIC;
               DDS_RESET : out  STD_LOGIC;
               uCData : inout  STD_LOGIC_VECTOR (7 downto 0);
               uCIRQ : out  STD_LOGIC;
               uCDR : out  STD_LOGIC;
               uCDA : in  STD_LOGIC;
               uCStRead : in  STD_LOGIC;
               GCLK : in  STD_LOGIC;
               GRESET : in  STD_LOGIC;
               DC_ON : out  STD_LOGIC;
               ON_LED : out  STD_LOGIC;          
               TrI_1 : in  STD_LOGIC;
               TrI_2 : in  STD_LOGIC;
               TrI_3 : in  STD_LOGIC;
               TrO_1 : out  STD_LOGIC;
               TrO_2 : out  STD_LOGIC;
               TrO_3 : out  STD_LOGIC);
    end dm;

    architecture Behavioral of dm is
    component ip_dcm
          port ( CLKIN_IN        : in    std_logic;
                 LOCKED_OUT      : out   std_logic;
                 CLKDV_OUT       : out   std_logic;
                 CLK2X_OUT       : out   std_logic;
                 CLKIN_IBUFG_OUT : out   std_logic;
                 CLK0_OUT        : out   std_logic);
       end component;
    type tCOMMAND is (DUMMY,RAMSTART,RAMSTOP,RAMWRITE);
    type tGenerateOPT is (GCC,GCS);
    type tModulateOPT is (AMFM,FM,AM,OFF);
    type tGState is (GON, GOFF);
    type tMemAcc is (WR,RE);
    signal CLK_LOCKED:STD_LOGIC;
    signal CLK_2MHz:STD_LOGIC;
    signal CLOCK:STD_LOGIC;
    signal MemAcc:tMemAcc:=RE;
    signal uCDataAcc:tMemAcc:=RE;
    signal MDATA_OUT:STD_LOGIC_VECTOR (7 downto 0):=(others=>'0');
    signal uCData_OUT:STD_LOGIC_VECTOR (7 downto 0):=(others=>'0');
    signal CLR:STD_LOGIC;
    signal MACountEn,MACountLoad:STD_LOGIC:='0';
    signal ADDR_EQ_STOP:STD_LOGIC:='0';
    signal RAMStartReg,RAMStopReg:STD_LOGIC_VECTOR (18 downto 0):=(others=>'0');
    signal uCCommand:tCOMMAND:=DUMMY;
    signal MDATA_OUT_2:STD_LOGIC_VECTOR (7 downto 0);
    signal MDATA_OUT_1:STD_LOGIC_VECTOR (7 downto 0);
    signal MDATA_DIR_1, M_CS_1, M_WE_1, M_OE_1, MACountEn_1,MACountLoad_1:STD_LOGIC;
    signal MDATA_DIR_2, M_CS_2, M_WE_2, M_OE_2, MACountEn_2,MACountLoad_2:STD_LOGIC;
    signal MemReadErr:STD_LOGIC:='0';
    signal GState:tGState:=GOFF;
    signal b_uCDR,b_ON_LED:STD_LOGIC:='0';

    --------------------
    signal LED_P_NR:integer range 0 to 30:=2;
    --------------------
    begin
    C_DCM:ip_dcm
       port map (CLKIN_IN=>GCLK,LOCKED_OUT=>CLK_LOCKED,CLKDV_OUT=>CLK_2MHz,CLK2X_OUT=>CLOCK);
    MDATA<=MDATA_OUT when MemAcc=WR else (others=>'Z');
    uCData<=uCData_OUT when uCDataAcc=WR else (others=>'Z');
    CLR<=(not CLK_LOCKED);
    uCDR<=b_uCDR;
    ON_LED<=b_ON_LED;
    --proces obslugujacy dekodowanie rozkazow z uC
    process (CLOCK)
    type tRAM_STATE is (s1,s2,s3);
    type tRAM_WRITE_STATE is (s1,s2,s3,s4,s5,s6,s7,s8,s9);
    variable reg_tmp:STD_LOGIC_VECTOR (18 downto 8):=(others=>'0');
    variable RAM_STATE:tRAM_STATE:=s1;
    variable RAM_WRITE_STATE:tRAM_WRITE_STATE:=s1;
    begin
       if rising_edge(CLOCK) then
          if CLR='1' then
             uCCommand<=DUMMY;
             RAMStartReg<=(others=>'0');
             RAMStopReg<=(others=>'0');         
             reg_tmp:=(others=>'0');
             MACountLoad_1<='0';
             MACountEn_1<='0';
             M_CS_1<='1';
             M_WE_1<='1';
             M_OE_1<='1';
             MemAcc<=RE;
             MemReadErr<='0';
             GState<=GOFF;
             b_uCDR<='0';
             RAM_STATE:=s1;
             RAM_WRITE_STATE:=s1;
          else
             MemReadErr<='0';
             MACountLoad_1<='0';
             MACountEn_1<='0';
             if GRESET='1' then
                uCCommand<=DUMMY;            
             end if;
             if (uCDA='0' and b_uCDR='1') then
                   b_uCDR<='0';
             end if;
             if (uCDA='1' and b_uCDR='0') then
                if uCCommand=DUMMY then
                   case uCData is
                      when "00000001"=>
                         uCCommand<=RAMSTART;                     
                         RAM_STATE:=s1;
                         b_uCDR<='1';
                      when "00000010"=>
                         uCCommand<=RAMSTOP;                     
                         RAM_STATE:=s1;
                         b_uCDR<='1';
                      when "00000011"=>
                         uCCommand<=RAMWRITE;                     
                         RAM_WRITE_STATE:=s1;
                         b_uCDR<='1';
                         MACountLoad_1<='1';
                      when others=>
                         uCCommand<=DUMMY;                     
                   end case;
                else
                ----
                   case uCCommand is
                      when RAMSTART | RAMSTOP =>
                         if RAM_STATE=s1 then
                            reg_tmp(18 downto 16):=uCData(2 downto 0);
                            b_uCDR<='1';
                            RAM_STATE:=s2;
                         elsif RAM_STATE=s2 then
                            reg_tmp(15 downto 8):=uCData;
                            b_uCDR<='1';   
                            RAM_STATE:=s3;
                         elsif RAM_STATE=s3 then
                            if uCCommand=RAMSTART then
                               RAMStartReg(18 downto 8)<=reg_tmp;
                               RAMStartReg(7 downto 0)<=uCData;
                            else
                               RAMStopReg(18 downto 8)<=reg_tmp;
                               RAMStopReg(7 downto 0)<=uCData;                           
                            end if;   
                            b_uCDR<='1';                        
                            uCCommand<=DUMMY;
                         end if;                  
                      when RAMWRITE=>                              
                         if RAM_WRITE_STATE=s1 then
                            MemAcc<=WR;
                            M_OE_1<='1';
                            MDATA_OUT_1(7 downto 0)<=uCData;
                            RAM_WRITE_STATE:=s2;
                         elsif RAM_WRITE_STATE=s2 then
                            RAM_WRITE_STATE:=s3;
                         elsif RAM_WRITE_STATE=s3 then
                            M_CS_1<='0';
                            M_WE_1<='0';
                            RAM_WRITE_STATE:=s4;
                         elsif RAM_WRITE_STATE=s4 then
                            M_CS_1<='1';
                            M_WE_1<='1';
                            RAM_WRITE_STATE:=s5;
                         elsif RAM_WRITE_STATE=s5 then
                            MemAcc<=RE;
                            RAM_WRITE_STATE:=s6;
                         elsif RAM_WRITE_STATE=s6 then
                            M_CS_1<='0';                                             
                            M_OE_1<='0';
                            RAM_WRITE_STATE:=s7;
                         elsif RAM_WRITE_STATE=s7 then
                            if MDATA/=uCData then
                               MemReadErr<='1';
                            end if;                        
                            RAM_WRITE_STATE:=s8;
                         elsif RAM_WRITE_STATE=s8 then   
                            M_CS_1<='1';
                            M_OE_1<='1';
                            MACountEn_1<='1';
                            RAM_WRITE_STATE:=s9;
                         elsif RAM_WRITE_STATE=s9 then      
                            if ADDR_EQ_STOP='1' then
                               uCCommand<=DUMMY;                                                      
                            else
                               RAM_WRITE_STATE:=s1;
                            end if;
                            b_uCDR<='1';
                         end if;                     
                      when others=>
                         uCCommand<=DUMMY;                     
                   end case;               
                ----
                end if;
             end if;         
          end if;
       end if;
    end process;--proces obslugujacy dekodowanie rozkazow z uC
    --multiplekser sygnalow dostepu do pamieci
    process (GState,MDATA_DIR_1, M_CS_1, M_WE_1, M_OE_1, MACountEn_1,MACountLoad_1,MDATA_OUT_1,MDATA_DIR_2, M_CS_2, M_WE_2, M_OE_2, MACountEn_2,MACountLoad_2,MDATA_OUT_2)
    begin
       if GState=GOFF then      
          MDATA_OUT<=MDATA_OUT_1;
          M_CS<=M_CS_1;
          M_WE<=M_WE_1;
          M_OE<=M_OE_1;
          MACountEn<=MACountEn_1;
          MACountLoad<=MACountLoad_1;
       end if;
       if GState=GON then      
          MDATA_OUT<=MDATA_OUT_2;
          M_CS<=M_CS_2;
          M_WE<=M_WE_2;
          M_OE<=M_OE_2;
          MACountEn<=MACountEn_2;
          MACountLoad<=MACountLoad_2;      
       end if;
    end process; --multiplekser sygnalow dostepu do pamieci

    --proces obslugujacy adres do pamieci
    process (CLOCK)
    variable MADDR_REG:STD_LOGIC_VECTOR (18 downto 0):=(others=>'0');
    begin
       if rising_edge(CLOCK) then
          if CLR='1' then
             ADDR_EQ_STOP<='0';
             MADDR<=(others=>'0');
             MADDR_REG:=(others=>'0');
          else
             if MADDR_REG=RAMStopReg then
                ADDR_EQ_STOP<='1';
             else
                ADDR_EQ_STOP<='0';
             end if;
             if MACountLoad='1' then
                MADDR_REG:=RAMStartReg;
             end if;
             if MACountEn='1' then
                MADDR_REG:=MADDR_REG+1;
             end if;         
          MADDR<=MADDR_REG;
          end if;
       end if;   
    end process;--proces obslugujacy adres do pamieci



    DATA<=(others=>'0');
    DA_NOT_CS<='0';
    DA_NOT_WR<='0';
    DDS_WCLK<='0';
    DDS_FUP<='0';
    DDS_RESET<='0';
    uCIRQ<='0';
    DC_ON<='0';
    TrO_1<='0';
    TrO_2<='0';
    TrO_3<='0';

    process(CLOCK)
    variable count:integer range 0 to 10000000:=0;
    variable count_en:STD_LOGIC:='0';
    variable nr:integer range 0 to 30:=0;
    begin
       if rising_edge(CLOCK) then
          if CLR='1' then
             b_ON_LED<='0';
             count:=0;
             count_en:='0';
          else
             if MemReadErr='1' then
                count_en:='1';
                b_ON_LED<='1';
                nr:=LED_P_NR;
             end if;
             if count_en='1' then
                count:=count+1;
             end if;
             if count=10000000 then            
                nr:=nr-1;
                if nr=0 then
                   b_ON_LED<='0';
                   count:=0;
                   count_en:='0';
                else
                   count:=0;
                   b_ON_LED<= not b_ON_LED;
                end if;
             end if;
          end if;   
       end if;
    end process;
    end Behavioral;
  • PCBway
  • Poziom 15  
    Postanowiłem jeszcze bardziej uprościć sprawę i napisałem coś takiego:

    Code:

    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.STD_LOGIC_ARITH.ALL;
    use IEEE.STD_LOGIC_UNSIGNED.ALL;


    library UNISIM;
    use UNISIM.VComponents.all;

    entity dm is
        Port ( uCData : in  STD_LOGIC_VECTOR (7 downto 0);
               uCDR : out  STD_LOGIC;
               uCDA : in  STD_LOGIC;
               TrO_1 : out  STD_LOGIC;
               TrO_2 : out  STD_LOGIC;
               GCLK : in  STD_LOGIC);
    end dm;

    architecture Behavioral of dm is
    component ip_dcm
          port ( CLKIN_IN        : in    std_logic;
                 CLKFX_OUT       : out   std_logic;
                 CLKIN_IBUFG_OUT : out   std_logic;
                 CLK0_OUT        : out   std_logic;
                 LOCKED_OUT      : out   std_logic);
                
       end component;
    signal CLK_LOCKED:STD_LOGIC;
    signal CLOCK:STD_LOGIC;
    signal CLR:STD_LOGIC;
    signal b_uCDR:STD_LOGIC:='0';

    begin
    C_DCM:ip_dcm
       port map (CLKIN_IN=>GCLK,LOCKED_OUT=>CLK_LOCKED,CLKFX_OUT=>CLOCK,CLK0_OUT=>TrO_1);

    CLR<=(not CLK_LOCKED);
    uCDR<=b_uCDR;
    TrO_2<=CLOCK;

    process (CLOCK)
    variable uCDataNew,uCDA_last:STD_LOGIC:='0';
    variable uCDataReg:STD_LOGIC_VECTOR (7 downto 0):=(others=>'0');
    variable iones:STD_LOGIC_VECTOR (8 downto 0):=(others=>'0');
    begin
       if rising_edge(CLOCK) then
          if CLR='1' then
             b_uCDR<='0';
             uCDA_last:='0';   
             uCDataNew:='0';
             uCDataReg:=(others=>'0');
          else
             if (uCDA='0' and uCDA_last='1') then
                uCDA_last:='0';
             end if;
             if (b_uCDR='1' and uCDA_last='0') then
                b_uCDR<='0';
             end if;
             if (uCDA='1' and uCDA_last='0') then
                uCDA_last:='1';
                uCDataNew:='1';
                uCDataReg:=uCData;
             end if;
             if uCDataNew='1' then
                iones:=(others=>'0');
                for I in 0 to 7 loop
                   if uCDataReg(I)='1' then
                      iones:=iones+'1';
                   end if;
                end loop;
                if iones(0)='0' then
                   b_uCDR<='1';
                else
                   b_uCDR<='0';
                end if;
                uCDataNew:='0';
             end if;
          end if;
       end if;
    end process;
    end Behavioral;


    Czyli po podniesieniu uCDA sprawdzane jest czy na uCData jest parzysta liczba jedynek i jeżeli tak to wystawiane jest uCDR.
    Poganiałem to z zewnątrz i sprawdzałem, czy mam dobre odpowiedzi (próbki są w plikach nazwanych odpowiednio do częstotliwości, na której było to badane, 'O' - dobra, 'B' - zla, '-' - początek (liczba zero... uCDATA ma 8 bitów więc w pliku jest to w sekwencjach po 256 odpowiedzi). Poniżej jest wykres, którego wartością jest stosunek złych do dobrych odpowiedzi w funkcji badanych częstotliwości. Oczywiście nie ma widocznej zależności, jak następują po sobie dobre i złe odpowiedzi, czyli raczej są losowe.
    Sprawdziłem podczas każdej z prób stan zasilania, tuż przy odnóżach układu i wahania nie przekraczają 50mV. Każdorazowo, też wyciągnąłem zegar na zewnątrz by sprawdzić czy jest okey... i był okey.
    Załączam też, raporty z przebiegu implementacji.
    Czy ten układ ma prawo nie wyrabiać się na takim prostym zadaniu? Czy poprawnie jest zapisany opis vhdl? Czy parametry implementacji są okey? Nie są domyślne bo na domyślnych jest raczej jeszcze gorzej.
    Co mogę jeszcze zrobić by zdiagnozować problem? Piszczie wszystko co Wam przyjdzie do głowy. Pozdrawiam.
  • Poziom 15  
    Zainteresowało mnie to, że w poprzedniej próbie błędów było mniej dla wyższych częstotliwości i postanowiłem zrobić próbę dla: 5,10,15,18,20,25,30,35,40,45,50,55,60,70,80,90,100,120,140,160,180,200,220 MHz. Dla każdej z nich zebrałem 300 prób dla każdej liczb z zakresu 0-255. Zadziwiające jest, że tylko dla 140 i 200 MHz otrzymałem zero błędów. Jak widać na err2.jpg błędy rozkładają się raczej równomiernie w zależności od liczby, której parzystość była sprawdzana poza przypadkiem 60MHz gdzie liczba 255 ma największy udział w błędzie.
    Uszczegóławiając generator 30MHz napędzał DCM, z którego pozyskiwałem różne częstotliwości, parametry syntezy jak w poprzedniej wiadomości... i tam i tu było podane wmuszenie w pliku *.ucf, postaci:
    TIMESPEC "TS_GCLK" = PERIOD "GCLK" 30 MHz HIGH 50 % INPUT_JITTER 2 ns;

    (poza zwykłym przypisaniem sygnałów do padów)

    W odróżnieniu do poprzedniej wiadomości, wykrywanie parzystości zrobiłem wprost xor-ując , czyli:

    Code:

    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.STD_LOGIC_ARITH.ALL;
    use IEEE.STD_LOGIC_UNSIGNED.ALL;

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

    entity dm is
        Port ( uCData : in  STD_LOGIC_VECTOR (7 downto 0);
               uCDR : out  STD_LOGIC;
               uCDA : in  STD_LOGIC;
               TrO_1 : out  STD_LOGIC;
               TrO_2 : out  STD_LOGIC;
               GCLK : in  STD_LOGIC);
    end dm;

    architecture Behavioral of dm is
    component ip_dcm
          port ( CLKIN_IN        : in    std_logic;
                 CLKDV_OUT       : out   std_logic;
                 CLKIN_IBUFG_OUT : out   std_logic;
                 CLK0_OUT        : out   std_logic;
                 LOCKED_OUT      : out   std_logic);
                
       end component;
    signal CLK_LOCKED:STD_LOGIC;
    signal CLOCK:STD_LOGIC;
    signal CLR:STD_LOGIC;
    signal b_uCDR:STD_LOGIC:='0';

    begin
    C_DCM:ip_dcm
       port map (CLKIN_IN=>GCLK,LOCKED_OUT=>CLK_LOCKED,CLKDV_OUT=>CLOCK,CLK0_OUT=>TrO_1);

    CLR<=(not CLK_LOCKED);
    uCDR<=b_uCDR;
    TrO_2<=CLOCK;
    --proces obslugujacy dekodowanie rozkazow z uC
    process (CLOCK)
    variable uCDataNew,uCDA_last:STD_LOGIC:='0';
    variable uCDataReg:STD_LOGIC_VECTOR (7 downto 0):=(others=>'0');
    begin
       if rising_edge(CLOCK) then
          if CLR='1' then
             b_uCDR<='0';
             uCDA_last:='0';   
             uCDataNew:='0';
             uCDataReg:=(others=>'0');
          else
             if (uCDA='0' and uCDA_last='1') then
                uCDA_last:='0';
             end if;
             if (b_uCDR='1' and uCDA_last='0') then
                b_uCDR<='0';
             end if;
             if (uCDA='1' and uCDA_last='0') then
                uCDA_last:='1';
                uCDataNew:='1';
                uCDataReg:=uCData;
             end if;
             if uCDataNew='1' then
                b_uCDR<=(uCDataReg(0) xor (uCDataReg(1) xor (uCDataReg(2) xor (uCDataReg(3) xor (uCDataReg(4) xor (uCDataReg(5) xor (uCDataReg(6) xor uCDataReg(7))))))));
                uCDataNew:='0';
             end if;
          end if;
       end if;
    end process;--proces obslugujacy dekodowanie rozkazow z uC
    end Behavioral;


    Wg mnie... i jutro postaram się to sprawdzić .. coś się dzieje z zasilaniem, tylko nie widzę tego na oscylu (pasmo 100MHz). Sprawdzę to na lepszym i/lub obleje wszystkie ścieżki zasilania dodatkowymi kondensatorami i je pogrubię.
    Chyba, że Wy - bardziej zaawansowani w logice programowalnej - spotkaliście się z podobnymi problemami, albo wynikają one z kodu, czy sposobu syntezy, hmm/
  • PCBway
  • Poziom 18  
    Generalnie wszystko ladnie, tylko w twoim kodzie nie podoba mi sie jedna rzecz. Mianowicie sposób w jaki używasz variable, w jednej linii robisz przypisanie:

    Cytat:
    uCDataNew:='1';
    uCDataReg:=uCData;


    a w następnej od wartości pierwszego variable uzależniasz przypisanie drugiego variable do kolejnego rejestru:

    Cytat:
    if uCDataNew='1' then
    b_uCDR<=(uCDataReg(0) xor (uCDataReg(1) xor (uCDataReg(2) xor (uCDataReg(3) xor (uCDataReg(4) xor (uCDataReg(5) xor (uCDataReg(6) xor uCDataReg(7))))))));


    W symulacji wszystko jest "ładnie" bo obydwie wartości zmieniają sie w tej samej "delcie symulacyjnej". "W sprzęcie" natomiast powstaje latch sterowany wartością obliczoną na podstawie wartości którą sa zatrzaskuje i co będzie szybsze to już zależy od paru innych rzeczy.

    Generalnie jak program generujący listę połączeń wstawia latch-e, a Ty o tym nie wiesz to nie jest dobrze.

    Ale na bok to, bo może się przypadkiem złożyć że zawsze wyniki będą o.k. Z tego co piszesz to problemem sa "timmingi", ale pomiedzy kolejnymi zboczami sygnału zegarowego. Twój projekt nie precyzuje wymagań na maksymalna długość(w sensie czasu) scieżki "uCDataReg" ani "uCA". Jeśli to nie problem w twoim projekcie to sugerowałbym wstawienia na wejściach dodatkowych przerzutników i postaranie się żeby trafily do I/O bloków, jeśli to problem to opcją jest wstawienie dodatkowych constraintów "BEFORE" i "AFTER" na tych ścieżkach.
  • Poziom 15  
    Hej [g.d.]!
    Dzięki za odpowiedź.
    Po tym jak sprawdziłem, że zasilanie jest cacy, wymyśliłem sobie jak to by wyglądało, jak bym nie używał syntezera i rozrysowałem to na bramkach i przerzutnikach - wszystko śmiga.
    Code:

    signal uCDataReg: STD_LOGIC_VECTOR (7 downto 0):=(others => '0');
    signal uCDA_out:STD_LOGIC:='0';

    uCDR<=uCDA_out and((uCDataReg(0) xor (uCDataReg(1) xor (uCDataReg(2) xor (uCDataReg(3) xor (uCDataReg(4) xor (uCDataReg(5) xor (uCDataReg(6) xor uCDataReg(7)))))))));


    process (CLOCK)
    begin
    if rising_edge(CLOCK) then
             uCDA_out<=uCDA;
        end if;
    end process;

    process (CLOCK)
    begin
     if rising_edge(CLOCK) then
       if uCDA='1' then
          uCDataReg<=uCData;
       end if;
     end if;
    end process;


    Potem wyrzuciłem zmienne zamieniając je na sygnały poza procesem (czyli, wymusiłem w ten sposób synchronizm, hmm?)...
    Code:

    signal uCDataNew,uCDA_last:STD_LOGIC:='0';
    signal uCDataReg:STD_LOGIC_VECTOR (7 downto 0):=(others=>'0');
    process (CLOCK)
    begin
       if rising_edge(CLOCK) then
          if CLR='1' then
             b_uCDR<='0';
             uCDA_last<='0';   
             uCDataNew<='0';
             uCDataReg<=(others=>'0');         
          else
             if (uCDA='0' and uCDA_last='1') then
                uCDA_last<='0';
             end if;
             if (b_uCDR='1' and uCDA_last='0') then
                b_uCDR<='0';
             end if;
             if (uCDA='1' and uCDA_last='0') then
                uCDA_last<='1';
                uCDataNew<='1';            
                uCDataReg<=uCData;
             end if;
             if uCDataNew='1' then
                b_uCDR<=(uCDataReg(0) xor (uCDataReg(1) xor (uCDataReg(2) xor (uCDataReg(3) xor (uCDataReg(4) xor (uCDataReg(5) xor (uCDataReg(6) xor uCDataReg(7))))))));
                uCDataNew<='0';
             end if;
          end if;
       end if;
    end process;--proces obslugujacy dekodowanie rozkazow z uC



    No, ale nie udało mi się powtórzyć sukcesu. Zaczyna mnie to trochę martwić...Czy wszystko będę musiał robić na piechotę?
  • Pomocny post
    Poziom 18  
    lordac napisał:

    Potem wyrzuciłem zmienne zamieniając je na sygnały poza procesem (czyli, wymusiłem w ten sposób synchronizm, hmm?)...

    Wymusiłeś wstawienie kilku przerzutników które miejmy nadzieje przetną ścieżki sygnałów tak aby nie było wyścigów.

    Sprawdź dokładnie w symulatorze czy o takie działanie układu Ci chodziło, variable a signal to dwie różne rzeczy.

    Jak już robisz kod na cacy to rozpisz wszyskie równania w jeden wielki if...elsif...elsif... albo coś na kształt tego. Troszkę więcej logiki pójdzie, ale będzie miął pewność że żaden if nie zaczął obowiązywać zanim przestał jakiś inny if. Jeśli uzywasz bufora zegarowego to właściwie jest to tylko kosmetyka, ale trudniej będzie o jakiś błąd w takim kodzie w przyszłości.

    Została jeszcze kwestia constaint'ów na wejscia, zależność od częstotliwości sugeruje że znaczące są opóźnienia logiki, a nie samo to czy są w niej wyścigi czy nie.
  • Poziom 15  
    Ponieważ jestem już z projektem 2 tygodni do tyłu pójdę trochę na łatwiznę-
    jak rozumiem użycie variable, w procesach syntezuje mi logikę asynchroniczną (czy ogólnie proces w środku jest asynchroniczny a zmienne variable nie są zatrzaskiwane z zegarem i może prowadzić do problemów) , dlatego postaram się jej unikać skoro na razie nie mam czasu na głębsza analizę.. zresztą chyba nie ma takiej potrzeby, bo to co ma robić układ raczej nie wymaga od niego zbyt wiele (jeżeli chodzi o szybkość i powierzchnię).
    Po wprowadzeniu dodatkowego zatrzaskiwania sygnałów wejściowych (uCDA, uCData) w przerzutnikach wszystko śmiga. Biorę się teraz do przepisywania tego wszystkiego co do tej pory nie działało a temat zamykam. Dzięki za pomoc.
  • Poziom 18  
    lordac napisał:
    Ponieważ jestem już z projektem 2 tygodni do tyłu pójdę trochę na łatwiznę-
    jak rozumiem użycie variable, w procesach syntezuje mi logikę asynchroniczną (czy ogólnie proces w środku jest asynchroniczny a zmienne variable nie są zatrzaskiwane z zegarem i może prowadzić do problemów)


    Zgadza się, variable (występuje tylko w procesach) i syntezuje Ci logikę asynchroniczną. Jeśli gdzieś "dalej" w procesie(niżej w kodzie) jest przypisanie variable do czegoś to nie będzie tam wstawiany przerzutnik(jeśli wcześniej w kodzie to już będzie - zakładam że proces z zegarem). To podstawowe zastosowanie variable do projektowania elektroniki, bo można wymyślić wiele konstrukcji z variable które cieżko zsyntezować, albo w ogóle sie nie da.