FlyingDutch Kwiecień 16, 2019 Autor tematu Udostępnij Kwiecień 16, 2019 (edytowany) Cześć, podczas tworzenia pliku "user constraint file" dla płytki Mimas V.2. napotkałem problem z Briey SoC . Otóż ten soft-procesor ma osobno magistralę do odczytu i zapisu pamięci DDR - patrz te sygnały procesora: input [15:0] io_sdram_DQ_read, output [15:0] io_sdram_DQ_write, A pamięć LPDDR na płytce Mimas V.2 ma 16 bitową dwukierunkową magistralę danych. Zastanawiam się jak to zamapować w pliku ucf (czy być może do Briey trzeba dodać jakiś dodatkowy bufor z wyborem kierunku transmisji) ? Może ktoś może coś doradzić? Na razie zamapowałem te piny dwa razy (raz jako wejściowe i raz jako wyjściowe) - nie ma żadnych błędów podczas wszystkich faz implementacji projektu, ale czy będzie działać to nie jestem pewien. Tak to wygląda w pliku ucf projektu: NET "Clk100Mhz1" LOC = V10 | IOSTANDARD = LVCMOS33 | PERIOD = 100MHz ; NET "Clk100Mhz2" LOC = V10 | IOSTANDARD = LVCMOS33 | PERIOD = 100MHz ; NET "io_asyncReset" LOC = M18 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST | PULLUP; #SW1 NET "io_jtag_tms" LOC = U7 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ; #Pin 1 NET "IO_P6[6]" LOC = V7 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ; #Pin 2 NET "IO_P6[5]" LOC = T4 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ; #Pin 3 NET "IO_P6[4]" LOC = V4 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ; #Pin 4 NET "io_sdram_ADDR[0]" LOC = J7 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_ADDR[10]" LOC = F4 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_ADDR[11]" LOC = D3 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_ADDR[12]" LOC = G6 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_ADDR[1]" LOC = J6 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_ADDR[2]" LOC = H5 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_ADDR[3]" LOC = L7 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_ADDR[4]" LOC = F3 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_ADDR[5]" LOC = H4 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_ADDR[6]" LOC = H3 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_ADDR[7]" LOC = H6 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_ADDR[8]" LOC = D2 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_ADDR[9]" LOC = D1 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_BA[0]" LOC = F2 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_BA[1]" LOC = F1 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DQ_read[0]" LOC = L2 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DQ_read[10]" LOC = N2 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DQ_read[11]" LOC = N1 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DQ_read[12]" LOC = T2 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DQ_read[13]" LOC = T1 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DQ_read[14]" LOC = U2 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DQ_read[15]" LOC = U1 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DQ_read[1]" LOC = L1 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DQ_read[2]" LOC = K2 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DQ_read[3]" LOC = K1 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DQ_read[4]" LOC = H2 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DQ_read[5]" LOC = H1 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DQ_read[6]" LOC = J3 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DQ_read[7]" LOC = J1 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DQ_read[8]" LOC = M3 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DQ_read[9]" LOC = M1 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DQ_write[0]" LOC = L2 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DQ_write[10]" LOC = N2 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DQ_write[11]" LOC = N1 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DQ_write[12]" LOC = T2 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DQ_write[13]" LOC = T1 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DQ_write[14]" LOC = U2 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DQ_write[15]" LOC = U1 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DQ_write[1]" LOC = L1 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DQ_write[2]" LOC = K2 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DQ_write[3]" LOC = K1 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DQ_write[4]" LOC = H2 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DQ_write[5]" LOC = H1 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DQ_write[6]" LOC = J3 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DQ_write[7]" LOC = J1 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DQ_write[8]" LOC = M3 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DQ_write[9]" LOC = M1 | IOSTANDARD = MOBILE_DDR; Pozdrawiam Edytowano Kwiecień 16, 2019 przez FlyingDutch 1
FlyingDutch Kwiecień 20, 2019 Autor tematu Udostępnij Kwiecień 20, 2019 (edytowany) Cześć, miałem trochę czasu, aby dalej popracować nad projektem BrieySoC na układzie FPGA (Mimas V.2 - Spartan6). Jak się zapewne domyślacie te same piny nie mogą być podane dwa razy w pliku ucf (patrz post wyżej). Dokonałem trochę zmian: Zmieniłem generator (PLL) dla zegarów magistrali AXI i wyjścia VGA - teraz jest to jeden komponent o nazwie CLKGEN, który generuje obydwa zegary Dodałem komponent o nazwie BiDirBuffer, który jest dwukierunkowym buforem magistrali równoległej o szerokości 16 bitów - jest to IP Core Xilinxa o nazwie "SelectIO Wizard" Top entity projektu (cały projekt w Verilogu) nazywa się BrieySOC. Wygląda teraz tak: `timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: // // Create Date: 15:41:45 04/15/2019 // Design Name: // Module Name: BrieySOC // Project Name: // Target Devices: // Tool versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// /* Top module: Briey SOC */ module BrieySOC( input io_asyncReset, input Clk100Mhz1, input io_jtag_tms, input io_jtag_tdi, output io_jtag_tdo, input io_jtag_tck, output [12:0] io_sdram_ADDR, output [1:0] io_sdram_BA, input [15:0] io_sdram_DQ_read, output [15:0] io_sdram_DQ_write, output io_sdram_DQ_writeEnable, output [1:0] io_sdram_DQM, output io_sdram_CASn, output io_sdram_CKE, output io_sdram_CSn, output io_sdram_RASn, output io_sdram_WEn, input [3:0] io_gpioA_read, output [3:0] io_gpioA_write, output [3:0] io_gpioA_writeEnable, output io_uart_txd, input io_uart_rxd, output io_vga_vSync, output io_vga_hSync, output io_vga_colorEn, output [4:0] io_vga_color_r, output [5:0] io_vga_color_g, output [4:0] io_vga_color_b, input io_timerExternal_clear, input io_timerExternal_tick, input io_coreInterrupt ); //---------------------------------------------------- //-- Connecting wires wire clkAXIOut; wire clkLOCKED; wire clkVGAOut; wire clkBuf100MHz; CLKWizard CLKGEN (// Clock in ports .CLK_IN1(Clk100Mhz1), // Clock out ports .CLK_OUT1(clkAXIOut), .CLK_OUT2(clkVGAOut), .CLK_OUT3(clkBuf100MHz), // Status and control signals .RESET(io_asyncReset), .LOCKED(clkLOCKED)); //---- CPU instance --------- Briey SoC( .io_asyncReset(io_asyncReset), .io_axiClk(clkAXIOut), .io_vgaClk(clkVGAOut), .io_jtag_tms(io_jtag_tms), .io_jtag_tdi(io_jtag_tdi), .io_jtag_tdo(io_jtag_tdo), .io_jtag_tck(io_jtag_tck), .io_sdram_ADDR(io_sdram_ADDR), .io_sdram_BA(io_sdram_BA), .io_sdram_DQ_read(io_sdram_DQ_read), .io_sdram_DQ_write(io_sdram_DQ_write), .io_sdram_DQ_writeEnable(io_sdram_DQ_writeEnable), .io_sdram_DQM(io_sdram_DQM), .io_sdram_CASn(io_sdram_CASn), .io_sdram_CKE(io_sdram_CKE), .io_sdram_CSn(io_sdram_CSn), .io_sdram_RASn(io_sdram_RASn), .io_sdram_WEn(io_sdram_WEn), .io_gpioA_read(io_gpioA_read), .io_gpioA_write(io_gpioA_write), .io_gpioA_writeEnable(io_gpioA_writeEnable), .io_uart_txd(io_uart_txd), .io_uart_rxd(io_uart_rxd), .io_vga_vSync(io_vga_vSync), .io_vga_hSync(io_vga_hSync), .io_vga_colorEn(io_vga_colorEn), .io_vga_color_r(io_vga_color_r), .io_vga_color_g(io_vga_color_g), .io_vga_color_b(io_vga_color_b), .io_timerExternal_clear(io_timerExternal_clear), .io_timerExternal_tick(io_timerExternal_tick), .io_coreInterrupt(io_coreInterrupt) ); endmodule A tak wygląda IP core z buforem magistrali danych do pamięci LPDDR: Komponent dwu-kierunkowego (trzy stanowego) bufora BiDirBuffer nie został jeszcze włączony (jako komponent) do top-entity. Tak wygląda kod dla stworzenia instancji tego komponentu: //----------- Begin Cut here for INSTANTIATION Template ---// INST_TAG // User Notes: // None BiDirBuffer instance_name ( .DATA_TO_AND_FROM_PINS(DATA_TO_AND_FROM_PINS), //Bi-Directional pins .DATA_IN_TO_DEVICE(DATA_IN_TO_DEVICE), //Output pins // From the device out to the system .DATA_OUT_FROM_DEVICE(DATA_OUT_FROM_DEVICE), //Input pins .CLK_TO_PINS(CLK_TO_PINS), //Output pins .TRISTATE_OUTPUT(TRISTATE_OUTPUT), //Input pin .CLK_IN(CLK_IN), // Single ended clock from IOB .CLK_OUT(CLK_OUT), //Fast clock ouput .CLK_RESET(CLK_RESET), //clocking logic reset .IO_RESET(IO_RESET) //system reset ); // INST_TAG_END ------ End INSTANTIATION Template --------- Z jednej strony ma dwie jednokierunkowe magistrale danych (16-bit każda) komponentu Briey (CPU) , a z drugiej dwukierunkową magistralę do układu pamięci DDR. Jak już pisałem docelowo chę uruchomić ten projekt na płytce FPGA firmy Numato o nazwie Mimas V.2 ze Spartanem6.Tutaj link do tej płytki: https://numato.com/product/mimas-v2-spartan-6-fpga-development-board-with-ddr-sdram Jak jest napisane w opisie ta płytka ma układ scalony: DDR Memory: 166MHz 512Mb LPDDR (MT46H32M16LF/W949D6CBHX6E) i właśnie tą pamięć chcę wykorzystać dla Briey SOC. Tutaj schemat płytki Mimas V.2, oraz datasheet dla kostki pamięci DDR: MimasV2Sch.pdf t67m_512mb_embedded_lpddr.pdf Właśnie teraz analizuję tego datasheet'a dla pamięci DDR bo implementacja Briey oraz użyta pamięć mają część sygnałów sterujących odmienną (pomijając samą magistralę danych 16 bit, która zostanie obsłużona po podłączeniu bufora opisanego powyżej). Tutaj spakowany projekt dla ISE 14.7: BrieySoCNext.zip Może może ktoś coś doradzić z mapowaniem sygnałów do obsługi pamięci DDR, bo nie wszystko jest dla mnie jasne Np. zegar dla kostki pamięci jest różnicowy (dwie linie) a dla Briey jest normalny i mam problem z kilkoma innymi sygnałami sterującymi (dla pamięci DDR i bufora dwu-kierunkowego). Znalazłem serię tutoriali, która trochę rozjaśnia wewnętrzną budowę RISC-V implementowanego w układzie FPGA: http://labs.domipheus.com/blog/tpu-series-quick-links/ Pozdrawiam Edytowano Kwiecień 22, 2019 przez FlyingDutch 1
FlyingDutch Kwiecień 22, 2019 Autor tematu Udostępnij Kwiecień 22, 2019 Cześć, poprawiłem projekt tak, że nie ma żadnych błędów podczas implementacji. Zmodyfikowałem " clocking wizard" (module CLKGEN), tak, że generuje teraz 3 sygnały zegarowe. Podłączony został dwukierunkowy bufor magistrali danych (16 bit) pamięci DDR (kostka MT46H32M16LF pamięci LPDDR ma dwukierunkową magistralę danych a RISC-V dwie jednokierunkowe). Mam problem z faktem iż kostka pamięci na płytce Mimas V.2 potrzebuje różnicowego zegara (dwie linie przesunięte w fazie o 180 stopni) a ja mam 'zwykły' zegar o częstotliwości 100 MHz. Tak teraz wygląda główny moduł: /* Top module: Briey SOC */ module BrieySOC( input io_asyncReset, input Clk100Mhz, input io_jtag_tms, input io_jtag_tdi, output io_jtag_tdo, input io_jtag_tck, output [12:0] io_sdram_ADDR, output [1:0] io_sdram_BA, //input [15:0] io_sdram_DQ_read, //output [15:0] io_sdram_DQ_write, inout [15:0] io_sdram_DATA, output io_sdram_DQ_writeEnable, output [1:0] io_sdram_DQM, output io_sdram_CASn, output io_sdram_CKE, output io_sdram_CSn, output io_sdram_RASn, output io_sdram_WEn, input [3:0] io_gpioA_read, output [3:0] io_gpioA_write, output [3:0] io_gpioA_writeEnable, output io_uart_txd, input io_uart_rxd, output io_vga_vSync, output io_vga_hSync, output io_vga_colorEn, output [4:0] io_vga_color_r, output [5:0] io_vga_color_g, output [4:0] io_vga_color_b, input io_timerExternal_clear, input io_timerExternal_tick, input io_coreInterrupt ); //---------------------------------------------------- //-- Connecting wires wire clkAXIOut; wire clkLOCKED; wire clkVGAOut; wire clkBuf100MHz; wire clkDDR100MHz; wire clkForward100MHz; wire CLK_TO_PINS; wire TRISTATE_OUTPUT; wire CLK_RESET; wire [15:0] io_sdram_DQ_read; wire [15:0] io_sdram_DQ_write; CLKWizard CLKGEN (// Clock in ports .CLK_IN1(Clk100Mhz), // Clock out ports .CLK_OUT1(clkAXIOut), //50 MHz AXI clock .CLK_OUT2(clkVGAOut), //25.175 MHz VGA clock .CLK_OUT3(clkBuf100MHz), //100 MHz DDR memory clock // Status and control signals .RESET(io_asyncReset), .LOCKED(clkLOCKED)); //---- DDR memory bufer bi-directional --------- BiDirBuffer DDRDataBuffer ( .DATA_TO_AND_FROM_PINS(io_sdram_DATA), //Bi-Directional pins .DATA_IN_TO_DEVICE(io_sdram_DQ_read), //Output pins // From the device out to the system .DATA_OUT_FROM_DEVICE(io_sdram_DQ_write), //Input pins .CLK_TO_PINS(CLK_TO_PINS), //Output pins .TRISTATE_OUTPUT(TRISTATE_OUTPUT), //Input pin .CLK_IN(clkBuf100MHz), // Fast clock input from PLL/MMCM .LOCKED_IN(clkLOCKED), //Input pin .LOCKED_OUT(LOCKED_OUT), //Output pin .CLK_RESET(CLK_RESET), //clocking logic reset .IO_RESET(io_asyncReset) //system reset ); //---- CPU instance --------- Briey SoC( .io_asyncReset(io_asyncReset), .io_axiClk(clkAXIOut), .io_vgaClk(clkVGAOut), .io_jtag_tms(io_jtag_tms), .io_jtag_tdi(io_jtag_tdi), .io_jtag_tdo(io_jtag_tdo), .io_jtag_tck(io_jtag_tck), .io_sdram_ADDR(io_sdram_ADDR), .io_sdram_BA(io_sdram_BA), .io_sdram_DQ_read(io_sdram_DQ_read), .io_sdram_DQ_write(io_sdram_DQ_write), .io_sdram_DQ_writeEnable(io_sdram_DQ_writeEnable), .io_sdram_DQM(io_sdram_DQM), .io_sdram_CASn(io_sdram_CASn), .io_sdram_CKE(io_sdram_CKE), .io_sdram_CSn(io_sdram_CSn), .io_sdram_RASn(io_sdram_RASn), .io_sdram_WEn(io_sdram_WEn), .io_gpioA_read(io_gpioA_read), .io_gpioA_write(io_gpioA_write), .io_gpioA_writeEnable(io_gpioA_writeEnable), .io_uart_txd(io_uart_txd), .io_uart_rxd(io_uart_rxd), .io_vga_vSync(io_vga_vSync), .io_vga_hSync(io_vga_hSync), .io_vga_colorEn(io_vga_colorEn), .io_vga_color_r(io_vga_color_r), .io_vga_color_g(io_vga_color_g), .io_vga_color_b(io_vga_color_b), .io_timerExternal_clear(io_timerExternal_clear), .io_timerExternal_tick(io_timerExternal_tick), .io_coreInterrupt(io_coreInterrupt) ); endmodule Nie wiem też jakim sygnałem sterować kierunkiem przepływu danych przez komponent dwu-kierunkowego bufora danych. Może ktoś ma jakiś pomysł? W załączniku spakowany projekt (bez błędów implementacji). BrieySoCNex02t.zip Pozdrawiam 1
FlyingDutch Kwiecień 27, 2019 Autor tematu Udostępnij Kwiecień 27, 2019 Dnia 10.04.2019 o 17:42, Elvis napisał: Ja próbowałem uruchomić gotowego Briey-a zsyntetyzowanego na płytki Terasic-a, ale nic mi z tego nie wyszło. Stad była moja propozycja zaczęcia od czegoś łatwiejszego Cześć Elvis, mam do Ciebie pytanie: mógłbyś zamieścić ten projekt dla płytki Terasic i podać jaki dokładnie model płytki Terasic był używany przez Ciebie do prób z Briey? Posunąłem się dużo dalej z moim projektem Briey dla Spartan6, ale nie zdążyłem tego opisać bo zmian było dużo. Mam zamiar niedługo zaktualizować wątek dot. BrieySoC. Największy problem jaki posiadam to fakt, że implementacja RISC-V (BrieySoC) ma kontroler pamięci DDR dla typu DDR3, a na płytce Mimas V.2 jest kostka pamięci DDR zgodna ze standardem DDR1. Drugi problem to dwie jednokierunkowe magistrale danych do pamięci RAM wychodzace z Briey, a po stronie kostki pamięci DDR jedna dwukierunkowa magistrala danych. Podejrzewam, że płytka Terasic, której używałeś do prób z BrieySoC miała właśnie na pokładzie pamięć DDR3, czy się mylę. Jakie dokładnie problemy napotkałeś z uruchomieniem tego projektu na FPGA? Pozdrawiam
Elvis Kwiecień 27, 2019 Udostępnij Kwiecień 27, 2019 Na stronie Briey-a (https://github.com/SpinalHDL/VexRiscv#briey-soc) jest link do gotowych projektów dla Terasic DE0-Nano i DE1-SoC: https://drive.google.com/drive/folders/0B-CqLXDTaMbKZGdJZlZ5THAxRTQ Testowałem na obu, chociaż więcej na DE0-Nano: https://www.terasic.com.tw/cgi-bin/page/archive.pl?No=593 DE1-SoC: https://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English&CategoryNo=165&No=836 Udało mi się uruchomić projekt i połączyć używając JTAG-a. Było to trochę czasu temu, więc nie pamiętam szczegółów, chyba był problem z wgraniem programu, albo jego uruchomieniem. W każdym razie na tym skończyłem i uznałem, że do RISC-V lepiej użyć gotowego układu, np. K210. 2
FlyingDutch Kwiecień 27, 2019 Autor tematu Udostępnij Kwiecień 27, 2019 (edytowany) 11 minut temu, Elvis napisał: Testowałem na obu, chociaż więcej na DE0-Nano: https://www.terasic.com.tw/cgi-bin/page/archive.pl?No=593 DE1-SoC: https://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English&CategoryNo=165&No=836 Udało mi się uruchomić projekt i połączyć używając JTAG-a. Było to trochę czasu temu, więc nie pamiętam szczegółów, chyba był problem z wgraniem programu, albo jego uruchomieniem. Cześć, dzięki za odpowiedź. Pobrałem te dwa projekty - chcę przeanalizować kilka szczegółów dot. obsługi pamięci DDR. A miałeś może jakąś sygnalizację poprawności pracy pamięci DDR np. na LEDach (często są wyprowadzane 2 sygnały: Calib_done i Error). Czy pamiętasz, czy obsługa pamięci DDR działała poprawnie? Widzę, że ta druga płytka ma właśnie pamięć DDR3. Pozdrawiam Edytowano Kwiecień 27, 2019 przez FlyingDutch
Elvis Kwiecień 27, 2019 Udostępnij Kwiecień 27, 2019 Z tego co pamiętam założyłem że skoro projekt jest sprawdzony to wszystko powinno działać Na płytce DE1-SoC pamięć DDR działa na pewno, używałem jej jako pamięci dla wbudowanego Cortex-A9 do uruchamiania linuksa i problemów nie było. Miałem za to mnóstwo problemów z jtag-iem i kiedy się w końcu połączyłem właściwie odechciało mi się tym bawić. 2
FlyingDutch Kwiecień 28, 2019 Autor tematu Udostępnij Kwiecień 28, 2019 (edytowany) Cześć, dokonałem kilka istotnych zmian w projekcie BrieySOC. Najważniejsze z nich: 1) Zmiany w buforowaniu sygnałów w CLKWizard (PLL) 2) Dodany bufor wejściowy (prymityw) IBUFG dla wejściowego zegara JTAG (sygnał: io_jtag_tck) 3) Generacja zegara różnicowego (dwie linie) dla pamięci DDR z pojedyńczego zegara 100 Mhz z PL. Dodany prymityw: OBUFDS (bufor wyjściowy różnicowy) 4) Podłączony bufor dwukierunkowy DDRDataBuffer (Select i/O wizard) do magistral Briey i kostki pamięci DDR. 5) W pliku "user constraints" (ucf) zamapowana poprawnie większość wejść/Wyjść z BrieySOC (brakuje kliku sygnałów - opisane później). 6) Usunięte błędy podczas syntezy/implementqacji Aktualnie schemat głównego modułu (mój obudowany Briey.v) o nazwie BrieySOC.v wygląda następująco: Kod głównego modułu (obudowuje on oryginalny CPU Briey.v o elementy niezbędne do uruchomienia na płytce Mimas v.2): /* Top module: Briey SOC */ module BrieySOC( input io_asyncReset, input Clk100Mhz, input io_jtag_tms, input io_jtag_tdi, output io_jtag_tdo, input io_jtag_tck, output [12:0] io_sdram_ADDR, output [1:0] io_sdram_BA, //input [15:0] io_sdram_DQ_read, //output [15:0] io_sdram_DQ_write, inout [15:0] io_sdram_DATA, output io_sdram_DQ_writeEnable, output [1:0] io_sdram_DQM, output io_sdram_CASn, output io_sdram_CKE, output io_sdram_CSn, output io_sdram_RASn, output io_sdram_WEn, output io_sdram_clk, output io_sdram_clk_n, input [3:0] io_gpioA_read, output [3:0] io_gpioA_write, output [3:0] io_gpioA_writeEnable, output io_uart_txd, input io_uart_rxd, output io_vga_vSync, output io_vga_hSync, output io_vga_colorEn, output [4:0] io_vga_color_r, output [5:0] io_vga_color_g, output [4:0] io_vga_color_b, input io_timerExternal_clear, input io_timerExternal_tick, input io_coreInterrupt ); //---------------------------------------------------- //-- Connecting wires wire clkAXIOut; wire clkLOCKED; wire clkVGAOut; wire clkBuf100MHz; wire clkDDR100MHz; wire clkJTAGBuf; wire CLK_TO_PINS; wire TRISTATE_OUTPUT; wire CLK_RESET; wire [15:0] io_sdram_DQ_read; wire [15:0] io_sdram_DQ_write; CLKWizard CLKGEN (// Clock in ports .CLK_IN1(Clk100Mhz), // Clock out ports .CLK_OUT1(clkAXIOut), //50 MHz AXI clock .CLK_OUT2(clkVGAOut), //25.175 MHz VGA clock .CLK_OUT3(clkBuf100MHz), //100 MHz DDR memory clock // Status and control signals .RESET(io_asyncReset), .LOCKED(clkLOCKED)); //Input buffer for JTAG in clock IBUFG IBUFG_01 ( .O(clkJTAGBuf), .I(io_jtag_tck) ); //Output buffer for DDR diff clock (out) OBUFDS #( .IOSTANDARD("DIFF_MOBILE_DDR") ) OBUFDS_01 ( .O(io_sdram_clk), .OB(io_sdram_clk_n), .I(clkBuf100MHz) ); //---- DDR memory bufer bi-directional --------- BiDirBuffer DDRDataBuffer ( .DATA_TO_AND_FROM_PINS(io_sdram_DATA), //Bi-Directional pins .DATA_IN_TO_DEVICE(io_sdram_DQ_read), //Output pins // From the device out to the system .DATA_OUT_FROM_DEVICE(io_sdram_DQ_write), //Input pins .CLK_TO_PINS(CLK_TO_PINS), //Output pins .TRISTATE_OUTPUT(TRISTATE_OUTPUT), //Input pin .CLK_IN(clkBuf100MHz), // Fast clock input from PLL/MMCM .LOCKED_IN(clkLOCKED), //Input pin .LOCKED_OUT(LOCKED_OUT), //Output pin .CLK_RESET(CLK_RESET), //clocking logic reset .IO_RESET(io_asyncReset) //system reset ); //---- CPU instance --------- Briey SoC( .io_asyncReset(io_asyncReset), .io_axiClk(clkAXIOut), .io_vgaClk(clkVGAOut), .io_jtag_tms(io_jtag_tms), .io_jtag_tdi(io_jtag_tdi), .io_jtag_tdo(io_jtag_tdo), .io_jtag_tck(clkJTAGBuf), .io_sdram_ADDR(io_sdram_ADDR), .io_sdram_BA(io_sdram_BA), .io_sdram_DQ_read(io_sdram_DQ_read), .io_sdram_DQ_write(io_sdram_DQ_write), .io_sdram_DQ_writeEnable(io_sdram_DQ_writeEnable), .io_sdram_DQM(io_sdram_DQM), .io_sdram_CASn(io_sdram_CASn), .io_sdram_CKE(io_sdram_CKE), .io_sdram_CSn(io_sdram_CSn), .io_sdram_RASn(io_sdram_RASn), .io_sdram_WEn(io_sdram_WEn), .io_gpioA_read(io_gpioA_read), .io_gpioA_write(io_gpioA_write), .io_gpioA_writeEnable(io_gpioA_writeEnable), .io_uart_txd(io_uart_txd), .io_uart_rxd(io_uart_rxd), .io_vga_vSync(io_vga_vSync), .io_vga_hSync(io_vga_hSync), .io_vga_colorEn(io_vga_colorEn), .io_vga_color_r(io_vga_color_r), .io_vga_color_g(io_vga_color_g), .io_vga_color_b(io_vga_color_b), .io_timerExternal_clear(io_timerExternal_clear), .io_timerExternal_tick(io_timerExternal_tick), .io_coreInterrupt(io_coreInterrupt) ); endmodule A tak wygląda plik user constraints (BrieySoC.ucf): #--------------------------------------------------- NET "Clk100Mhz" LOC = V10 | IOSTANDARD = LVCMOS33 | PERIOD = 100MHz ; NET "io_asyncReset" LOC = M18 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST | PULLUP; #SW1 ################################################################################################################################################### # HEADER P6 # ################################################################################################################################################### NET "io_jtag_tms" LOC = U7 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ; #Pin 1 Header P6 NET "io_jtag_tdi" LOC = V7 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ; #Pin 2 NET "io_jtag_tdo" LOC = T4 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ; #Pin 3 #NET "io_jtag_tck" LOC = V4 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ; #Pin 4 - issue #-------------------------- LPDDR RAM START-------------------------------------------------------------------- #NET "calib_done" LOC = P15 | IOSTANDARD = LVCMOS33; #NET "error" LOC = P16 | IOSTANDARD = LVCMOS33; #NET "c3_sys_rst_n" LOC = L15 | IOSTANDARD = LVCMOS33 | PULLDOWN; # Pin 7 of Header P9 NET "io_sdram_ADDR[0]" LOC = J7 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_ADDR[10]" LOC = F4 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_ADDR[11]" LOC = D3 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_ADDR[12]" LOC = G6 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_ADDR[1]" LOC = J6 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_ADDR[2]" LOC = H5 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_ADDR[3]" LOC = L7 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_ADDR[4]" LOC = F3 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_ADDR[5]" LOC = H4 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_ADDR[6]" LOC = H3 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_ADDR[7]" LOC = H6 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_ADDR[8]" LOC = D2 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_ADDR[9]" LOC = D1 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_BA[0]" LOC = F2 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_BA[1]" LOC = F1 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_clk" LOC = G3 | IOSTANDARD = DIFF_MOBILE_DDR; NET "io_sdram_clk_n" LOC = G1 | IOSTANDARD = DIFF_MOBILE_DDR; NET "io_sdram_DATA[0]" LOC = L2 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DATA[10]" LOC = N2 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DATA[11]" LOC = N1 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DATA[12]" LOC = T2 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DATA[13]" LOC = T1 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DATA[14]" LOC = U2 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DATA[15]" LOC = U1 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DATA[1]" LOC = L1 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DATA[2]" LOC = K2 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DATA[3]" LOC = K1 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DATA[4]" LOC = H2 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DATA[5]" LOC = H1 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DATA[6]" LOC = J3 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DATA[7]" LOC = J1 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DATA[8]" LOC = M3 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_DATA[9]" LOC = M1 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_CASn" LOC = K5 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_CKE" LOC = H7 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_RASn" LOC = L5 | IOSTANDARD = MOBILE_DDR; NET "io_sdram_WEn" LOC = E3 | IOSTANDARD = MOBILE_DDR; #-------------------------- LPDDR RAM END -------------------------------------------------------------------- ################################################################################################################################################## # HEADER P7 # ################################################################################################################################################### NET "io_gpioA_read[0]" LOC = U8 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ; #Pin 1 NET "io_gpioA_read[1]" LOC = V8 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ; #Pin 2 NET "io_gpioA_read[2]" LOC = R8 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ; #Pin 3 NET "io_gpioA_read[3]" LOC = T8 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ; #Pin 4 NET "io_gpioA_write[0]" LOC = R5 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ; #Pin 5 NET "io_gpioA_write[1]" LOC = T5 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ; #Pin 6 NET "io_gpioA_write[2]" LOC = T9 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ; #Pin 7 NET "io_gpioA_write[3]" LOC = V9 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ; #Pin 8 ################################################################################################################################################### # HEADER P8 # ################################################################################################################################################### NET "io_gpioA_writeEnable[0]" LOC = R11 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ; #Pin 1 NET "io_gpioA_writeEnable[1]" LOC = T11 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ; #Pin 2 NET "io_gpioA_writeEnable[2]" LOC = R10 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ; #Pin 3 NET "io_gpioA_writeEnable[3]" LOC = T10 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ; #Pin 4 NET "io_vga_colorEn" LOC = U13 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ; #Pin 5 : VGA output NET "io_timerExternal_clear" LOC = V13 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ; #Pin 6 : Ext. timer NET "io_timerExternal_tick" LOC = U11 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ; #Pin 7 : Ext. timer NET "io_coreInterrupt" LOC = V11 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ; #Pin 8 : Ext. interrupt ################################################################################################################################################### # UART Interface # ################################################################################################################################################### NET "io_uart_txd" LOC = A8 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ; NET "io_uart_rxd" LOC = B8 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ; ################################################################################################################################################### # VGA - less color resolution than in Briey # ################################################################################################################################################### NET "io_vga_hSync" LOC = B12 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ; NET "io_vga_vSync" LOC = A12 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ; NET "io_vga_color_r[4]" LOC = C9 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ; NET "io_vga_color_r[3]" LOC = B9 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ; NET "io_vga_color_r[2]" LOC = A9 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ; NET "io_vga_color_g[5]" LOC = C11 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ; NET "io_vga_color_g[4]" LOC = A10 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ; NET "io_vga_color_g[3]" LOC = C10 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ; NET "io_vga_color_b[4]" LOC = A11 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ; NET "io_vga_color_b[3]" LOC = B11 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ; Fazy syntezy i implementacji kończą się w ISE 14.7 bez błędów (jest trochę warning'ów). Tutaj spakowany zipem pełen projekt (ISE 14.7) - implementuje się bez błędów: BrieySoCNext06.zip Potem opiszę ,jakie problemy jeszcze nie zostały rozwiązane (mapowanie kilku sygnałów pamięci DDR, wejściowy zegar JTAG, oraz sterowanie kierunkiem przepływu danych w dwukierunkowym buforze magistarali danych pamięci DDR). BTW: trochę nie rozumiem dlaczego oryginalny projekt Briey.v wygenerowany narzędziem SpinalHDL został sporządzony tak, że bez przeróbek bardzo trudno go uruchomić na dowolnym zestawie uruchomieniowym FPGA (abstrahując od płytki Mimas V.2, gdzie sytuacja jest jeszcze trudniejsza z powodu pami ęci typu SDRAM). Ogólnie liczba potrzebnych pinów I/O FPGA oraz brak odpowiednich buforów chociażby dla zegara zewnętrzego programatora JTAG jest dla mnie trochę niezrozumiałe (trzeba włożyć sporo pracy w przeróbki układu, tak, aby dało się uruchomić projekt, co przy braku dokumentacji jest trudne). Pozdrawiam Edytowano Kwiecień 28, 2019 przez FlyingDutch 1
FlyingDutch Maj 3, 2019 Autor tematu Udostępnij Maj 3, 2019 Cześć, właśnie niedawno otrzymałem odpowiedż z forum Sipeed.io (na komunikatorze Telegram) na moje pytanie dotyczące implementacji kontrolera pamięci SDRAM w BrieySOC. Oto odpowiedź: Cytat Briey uses IS42x320D SDRAM as an external memory. That controller has been developed in Spinal HDL and attached to the SoC. RISCV is an instruction set SPEC, isn't a SoC implementation. You have to do one of two things, either you develop the memory controller of your board and attach it to the Briey SoC, or simply use the on-chip ram. Szczerze mówiąc podejrzewałem to od jakiegoś czasu i sam myślałem aby podmienić oryginalny kontroler pamięci DDR w Briey.v działającym poprawnie dla zestawu FPGA Mimas V.2. Działający kontroler pamięci DDR (oparty na MIG Xilinxa) opisałem w tym poście: https://forbot.pl/forum/topic/16152-xilinx-spartan-6-i-obsluga-pamieci-ddr-mimas-v2/ i właśnie tak zrobię - podmienię oryginalną implementację kontrolera pamięci SDRAM na tą działającą implementację. Właściwie był to ostatni nierozwiązany problem z Briey SoC. Będzie to kosztowało sporo pracy ale jest wykonalne i mam zamiar wprowadzić ten plan w życie w najbliższej przyszłości. Pozdrawiam 1
Pomocna odpowiedź
Bądź aktywny - zaloguj się lub utwórz konto!
Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony
Utwórz konto w ~20 sekund!
Zarejestruj nowe konto, to proste!
Zarejestruj się »Zaloguj się
Posiadasz własne konto? Użyj go!
Zaloguj się »