Skocz do zawartości
FlyingDutch

LicheeTang Anlogic EG4S20 FPGA Board (RISC-V)

Pomocna odpowiedź

(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 przez FlyingDutch
  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites
(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:

  1. 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
  2. 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:

Briey01_.thumb.png.5caf04070ab55861c76711677d1e04ad.png

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 przez FlyingDutch
  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

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

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites
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

Udostępnij ten post


Link to post
Share on other sites

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.

  • Lubię! 2

Udostępnij ten post


Link to post
Share on other sites
(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 przez FlyingDutch

Udostępnij ten post


Link to post
Share on other sites

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

  • Lubię! 2

Udostępnij ten post


Link to post
Share on other sites
(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:

BrieySOC.thumb.png.6a76e4e05467b026443085efe96c962c.png

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 przez FlyingDutch
  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

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

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Gość
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.


×
×
  • Utwórz nowe...