Controlador LPDDR2

Temas de diseño con HDL que no dependen de un lenguaje en particular, o que pueden aplicarse a cualquier lenguaje (diseño óptimo de FSM, optimizaciones para facilitar el timing closure, etc). Si hay que poner algún ejemplo podrá usarse VHDL o Verilog (o idealmente, el mismo ejemplo en ambos lenguajes)
Responder
fpganoob
Veroboard
Mensajes: 17
Registrado: 11 Oct 2018, 15:31

Controlador LPDDR2

Mensaje por fpganoob » 17 Oct 2018, 16:15

Buenas a todos!!!

Como mi propio nombre indica soy un noob en este mundillo, pero espero poder cambiar eso, aunque me quedare con el nick en el foro :)

Tengo una placa con Cyclone V sin el ARM, SD, salida de Audio, hdmi, sRAM (4Mb) y LPDDR2 (4Gb).
Mi intencion es intentar portar/usar cores de unamiga(Gracias @jepalza!!) o cualquier otro del que disponga el "fuente".

Tengo claro, por el momento y espero no quedarme muy corto, que debere cambiar :
- Clocks : empezare con cores de C IV por lo que creo que bastaria con reasignar los pines de Clock, aunque no aprovecharia las mejoras de V, pero deberia funcionar...
- Audio : por lo que veo se utiliza un Pin de gpio "Digital" para generar el audio analogico directamente, mi placa tiene un chip de audio y salidas propias, pero podria comenzar por usar un pin de gpio tal y como estan los cores. Ya mas adelante veremos si puedo aprovechar el audio de la placa.
- Video : Pasa como con el audio... tiene una salida hdmi, pero por el momento cambiare los pines para sacar un analogico de VGA tal y como hacen los cores. Mas adelante veremos si podemos aprovechar ese hdmi.
- SD : lleva uno integrado, deberia bastar con reasignar los pines.
- RAM : aqui la liamos... Lleva SRAM, pero muy poca por lo que no creo que la pueda usar, salvo para cores con muy poca exigencia de ram, así que la idea seria usar la LPDDR2, pero no encuentro un controlador que pueda utilizar. El Quartus te crea uno con el Wizard, pero se escapa de mis conocimientos, ademas de fallar la generacion, seguramente por mi desconocimiento.

Asi que lo que necesitaria es un controlador de LPDDR2 (o SRAM) y si pudiera recibir las señales de SDRAM y de salida gestionar la LPDDR2 ya la leche !! :)
De esa manera podria substituir directamente los pines de SDRAM de los cores y conectarlos al controlador LPDRR2.

Bueno ya os he dado la chapa....

A ver si alguien me puede iluminar por donde tirar...

Gracias por Adelantado!!

Un Abrazo a todos!!

Avatar de Usuario
jepalza
Spartan 3
Mensajes: 226
Registrado: 14 Ago 2018, 18:51

Re: Controlador LPDDR2

Mensaje por jepalza » 20 Oct 2018, 07:09

Te he respondido aqui --> viewtopic.php?f=20&p=648#p648

A lo que comento ahí, añado, que un módulo de SDRAM es "1" fichero, punto pelota, pero uno de DDR son como unos 12 enlazados, aunque con paciencia, los puedes dejar en unos 5 nada mas.
Acabo de mirar los proyectos que hice para intentar usar LPDDR2 , y en el mas sencillo que tengo, salen unas ¡¡¡ 15mil líneas de código !!!
En una DDR se necesita un calibrado previo antes de usarla, y luego, trabaja de una forma bastante rara, que es en forma de bancos individuales, es como si tuvieras 20 cajones de datos, y tuvieses que acceder a cada cajón secuencialmente para coger de cada uno un bit suelto. En una SDRAM es sería el selector de bancos, que son dos nada mas, el alto y el bajo, pero en una DDR hay docenas de bancos para seleccionar.

Sé que no ayuda mucho explicar cosas sin profundizar, pero no soy capaz de dar una respuesta completa. Estuve varios meses tratando de usar la DDR a modo SDRAM, y no fui capaz. Tenía varios ejemplos en la mano, pero adaptarlos a mis necesidades no fui capaz.

fpganoob escribió:
17 Oct 2018, 16:15
De esa manera podria substituir directamente los pines de SDRAM de los cores y conectarlos al controlador LPDRR2.
Si lo consigues, pasas de nivel novato a nivel dios en un plis plas. Yo, como ya digo, MESES estuve tratando de hacerlo. Estuve incluso en foros de gente que tenía la misma inquietud, y nadie daba con una respuesta clara. Encontré un foro donde un señor lograba usar la DDR a modo SDRAM, pero no decía como, no daba la solución, y me quedé con las ganas.


ejemplo de cabecera de parámetros LPDDR y de líneas de entrada salida:

Código: Seleccionar todo

   parameter         C_MEMCLK_PERIOD           = 2500,
   parameter         C_P0_MASK_SIZE            = 4,
   parameter         C_P0_DATA_PORT_SIZE       = 32,
   parameter         C_P1_MASK_SIZE            = 4,
   parameter         C_P1_DATA_PORT_SIZE       = 32,

   parameter         C_PORT_ENABLE             = 6'b111111,
   parameter         C_PORT_CONFIG             = "B128",
   parameter         C_MEM_ADDR_ORDER          = "BANK_ROW_COLUMN",
   // The following parameter reflects the GUI selection of the Arbitration algorithm.
   // Zero value corresponds to round robin algorithm and one to custom selection.
   // The parameter is used to calculate the arbitration time slot parameters.                           
   parameter         C_ARB_ALGORITHM           = 0,    								   					   
   parameter         C_ARB_NUM_TIME_SLOTS      = 12,
   parameter         C_ARB_TIME_SLOT_0         = 18'o012345,
   parameter         C_ARB_TIME_SLOT_1         = 18'o123450,
   parameter         C_ARB_TIME_SLOT_2         = 18'o234501,
   parameter         C_ARB_TIME_SLOT_3         = 18'o345012,
   parameter         C_ARB_TIME_SLOT_4         = 18'o450123,
   parameter         C_ARB_TIME_SLOT_5         = 18'o501234,
   parameter         C_ARB_TIME_SLOT_6         = 18'o012345,
   parameter         C_ARB_TIME_SLOT_7         = 18'o123450,
   parameter         C_ARB_TIME_SLOT_8         = 18'o234501,
   parameter         C_ARB_TIME_SLOT_9         = 18'o345012,
   parameter         C_ARB_TIME_SLOT_10        = 18'o450123,
   parameter         C_ARB_TIME_SLOT_11        = 18'o501234,
   parameter         C_MEM_TRAS                = 45000,
   parameter         C_MEM_TRCD                = 12500,
   parameter         C_MEM_TREFI               = 7800,
   parameter         C_MEM_TRFC                = 127500,
   parameter         C_MEM_TRP                 = 12500,
   parameter         C_MEM_TWR                 = 15000,
   parameter         C_MEM_TRTP                = 7500,
   parameter         C_MEM_TWTR                = 7500,
   parameter         C_NUM_DQ_PINS             = 8,
   parameter         C_MEM_TYPE                = "DDR3",
   parameter         C_MEM_DENSITY             = "512M",
   parameter         C_MEM_BURST_LEN           = 8,
   parameter         C_MEM_CAS_LATENCY         = 4,
   parameter         C_MEM_ADDR_WIDTH          = 13,
   parameter         C_MEM_BANKADDR_WIDTH      = 3,
   parameter         C_MEM_NUM_COL_BITS        = 11,
   parameter         C_MEM_DDR3_CAS_LATENCY    = 7,
   parameter         C_MEM_MOBILE_PA_SR        = "FULL",
   parameter         C_MEM_DDR1_2_ODS          = "FULL",
   parameter         C_MEM_DDR3_ODS            = "DIV6",
   parameter         C_MEM_DDR2_RTT            = "50OHMS",
   parameter         C_MEM_DDR3_RTT            = "DIV2",
   parameter         C_MEM_MDDR_ODS            = "FULL",
   parameter         C_MEM_DDR2_DIFF_DQS_EN    = "YES",
   parameter         C_MEM_DDR2_3_PA_SR        = "OFF",
   parameter         C_MEM_DDR3_CAS_WR_LATENCY = 5,
   parameter         C_MEM_DDR3_AUTO_SR        = "ENABLED",
   parameter         C_MEM_DDR2_3_HIGH_TEMP_SR = "NORMAL",
   parameter         C_MEM_DDR3_DYN_WRT_ODT    = "OFF",
   parameter         C_MC_CALIB_BYPASS         = "NO",

   parameter         LDQSP_TAP_DELAY_VAL       = 0,
   parameter         UDQSP_TAP_DELAY_VAL       = 0,
   parameter         LDQSN_TAP_DELAY_VAL       = 0,
   parameter         UDQSN_TAP_DELAY_VAL       = 0,
   parameter         DQ0_TAP_DELAY_VAL         = 0,
   parameter         DQ1_TAP_DELAY_VAL         = 0,
   parameter         DQ2_TAP_DELAY_VAL         = 0,
   parameter         DQ3_TAP_DELAY_VAL         = 0,
   parameter         DQ4_TAP_DELAY_VAL         = 0,
   parameter         DQ5_TAP_DELAY_VAL         = 0,
   parameter         DQ6_TAP_DELAY_VAL         = 0,
   parameter         DQ7_TAP_DELAY_VAL         = 0,
   parameter         DQ8_TAP_DELAY_VAL         = 0,
   parameter         DQ9_TAP_DELAY_VAL         = 0,
   parameter         DQ10_TAP_DELAY_VAL        = 0,
   parameter         DQ11_TAP_DELAY_VAL        = 0,
   parameter         DQ12_TAP_DELAY_VAL        = 0,
   parameter         DQ13_TAP_DELAY_VAL        = 0,
   parameter         DQ14_TAP_DELAY_VAL        = 0,
   parameter         DQ15_TAP_DELAY_VAL        = 0,

   parameter         C_CALIB_SOFT_IP           = "TRUE",
   parameter         C_SIMULATION              = "FALSE",
   parameter         C_SKIP_IN_TERM_CAL        = 1'b0,
   parameter         C_SKIP_DYNAMIC_CAL        = 1'b0,
   parameter         C_MC_CALIBRATION_MODE     = "CALIBRATION",
   parameter         C_MC_CALIBRATION_DELAY    = "HALF"

  )

  (

   // Raw Wrapper Signals
   input                                     sysclk_2x,          
   input                                     sysclk_2x_180, 
   input                                     pll_ce_0,
   input                                     pll_ce_90, 
   input                                     pll_lock,
   input                                     async_rst,
   input                                     mcb_drp_clk,       
   output      [C_MEM_ADDR_WIDTH-1:0]        mcbx_dram_addr,  
   output      [C_MEM_BANKADDR_WIDTH-1:0]    mcbx_dram_ba,
   output                                    mcbx_dram_ras_n,       
   output                                    mcbx_dram_cas_n,       
   output                                    mcbx_dram_we_n,  
   output                                    mcbx_dram_cke, 
   output                                    mcbx_dram_clk, 
   output                                    mcbx_dram_clk_n,       
   inout       [C_NUM_DQ_PINS-1:0]           mcbx_dram_dq,
   inout                                     mcbx_dram_dqs, 
   inout                                     mcbx_dram_dqs_n,       
   inout                                     mcbx_dram_udqs,  
   inout                                     mcbx_dram_udqs_n,       
   output                                    mcbx_dram_udm, 
   output                                    mcbx_dram_ldm, 
   output                                    mcbx_dram_odt, 
   output                                    mcbx_dram_ddr3_rst,      
   inout                                     mcbx_rzq,
   inout                                     mcbx_zio,
   output                                    calib_done,
   input                                     selfrefresh_enter,       
   output                                    selfrefresh_mode,

y aquí un módulo de llamada a LPDDR, como ves, tiene un montón de valores de entrada (una SDRAM tiene solo 10 valores de entrada, pero la DDR ya lo ves, como unos 50, eso, en este ejemplo reducido)

Código: Seleccionar todo

module lpddr #
(
  parameter C3_P0_MASK_SIZE         = 8,
  parameter C3_P0_DATA_PORT_SIZE    = 64,
  parameter C3_P1_MASK_SIZE         = 8,
  parameter C3_P1_DATA_PORT_SIZE    = 64,
  parameter DEBUG_EN                = 0,       
  parameter C3_MEMCLK_PERIOD        = 5000,       
  parameter C3_CALIB_SOFT_IP        = "TRUE",       
  parameter C3_SIMULATION           = "FALSE",       
  parameter C3_RST_ACT_LOW          = 0,       
  parameter C3_INPUT_CLK_TYPE       = "SINGLE_ENDED",       
  parameter C3_MEM_ADDR_ORDER       = "ROW_BANK_COLUMN",       
  parameter C3_NUM_DQ_PINS          = 16,       
  parameter C3_MEM_ADDR_WIDTH       = 13,       
  parameter C3_MEM_BANKADDR_WIDTH   = 2        
)  

(
  input                                sys_clk,
  input                                sys_rst,
  output                               c3_calib_done,
  output                               clock,
  output                               reset,
  inout  [C3_NUM_DQ_PINS-1:0]          mcb3_dram_dq,
  output [C3_MEM_ADDR_WIDTH-1:0]       mcb3_dram_a,
  output [C3_MEM_BANKADDR_WIDTH-1:0]   mcb3_dram_ba,
  output                               mcb3_dram_cke,
  output                               mcb3_dram_ras_n,
  output                               mcb3_dram_cas_n,
  output                               mcb3_dram_we_n,
  output                               mcb3_dram_dm,
  inout                                mcb3_dram_udqs,
  inout                                mcb3_rzq,
  output                               mcb3_dram_udm,
  inout                                mcb3_dram_dqs,
  output                               mcb3_dram_ck,
  output                               mcb3_dram_ck_n,
  input                                c3_p0_cmd_clk,
  input                                c3_p0_cmd_en,
  input [2:0]                          c3_p0_cmd_instr,
  input [5:0]                          c3_p0_cmd_bl,
  input [29:0]                         c3_p0_cmd_byte_addr,
  output                               c3_p0_cmd_empty,
  output                               c3_p0_cmd_full,
  input                                c3_p0_wr_clk,
  input                                c3_p0_wr_en,
  input [C3_P0_MASK_SIZE - 1:0]        c3_p0_wr_mask,
  input [C3_P0_DATA_PORT_SIZE - 1:0]   c3_p0_wr_data,
  output                               c3_p0_wr_full,
  output                               c3_p0_wr_empty,
  output [6:0]                         c3_p0_wr_count,
  output                               c3_p0_wr_underrun,
  output                               c3_p0_wr_error,
  input                                c3_p0_rd_clk,
  input                                c3_p0_rd_en,
  output [C3_P0_DATA_PORT_SIZE - 1:0]  c3_p0_rd_data,
  output                               c3_p0_rd_full,
  output                               c3_p0_rd_empty,
  output [6:0]                         c3_p0_rd_count,
  output                               c3_p0_rd_overflow,
  output                               c3_p0_rd_error
);

Dejo adjunto uno de los ejemplos. Es el que genera el Xilinx al crear un módulo de control MIG para DDR, y lo único que hace es montón de líneas, es encender la DDR, calibrarla y si todo es correcto, encender un LED.
ejemplo_usando_LPDDR.rar
(515.91 KiB) Descargado 421 veces
Si quieres ejemplos funcionando con DDR, mira la placa Pipistrello, que ademas de DDR usa HDMI:
http://saanlima.com/forum/viewtopic.php?f=12&t=1234

fpganoob
Veroboard
Mensajes: 17
Registrado: 11 Oct 2018, 15:31

Re: Controlador LPDDR2

Mensaje por fpganoob » 20 Oct 2018, 09:49

Gracias!!!

Ya veo que me he metido en un jardín sin saber si tamaño

Cómo tiene 4Mb de sram, seguramente comience por intentar cores que necesiten menos de 512KB, por poder avanzar y ver algún resultado. Más adelante veremos si le meto SDRAM por gpios o me sigo pegando con el lpddr2.

Alguna recomendación de por qué Core , con pocos requisitos de RAM, comenzar?





Enviado desde mi iPhone utilizando Tapatalk

Avatar de Usuario
jepalza
Spartan 3
Mensajes: 226
Registrado: 14 Ago 2018, 18:51

Re: Controlador LPDDR2

Mensaje por jepalza » 20 Oct 2018, 10:11

¿llevas 4mb de SRAM? buen bicho, pero pocos (o ningún) core usan tanta. Lo mas va a ser, como veo que ya sabes, 512k.
Mas de eso, cores como el Spectrum con el modulo de sonido que llega a 2mb, y el del CPC 6128 de Renaud Hélias que usa 2mb, pero que yo logré reducir a solo 512k para que entrara en el ZXUNO.

El mas sencillo, te diría que el júpiter ace de mcleod_ideafix o un zx81, pero son tan simples, que no necesitan ni SRAM, pueden con solo BRAM. Con SRAM probaría con cualquiera de las docenas de cores de Spectrum que hay, ya que, al haber tantas versiones, está muy bien documentado para usar SRAM hasta 128k.

fpganoob
Veroboard
Mensajes: 17
Registrado: 11 Oct 2018, 15:31

Re: Controlador LPDDR2

Mensaje por fpganoob » 20 Oct 2018, 11:31

jepalza escribió:
20 Oct 2018, 10:11
¿llevas 4mb de SRAM? buen bicho, pero pocos (o ningún) core usan tanta. Lo mas va a ser, como veo que ya sabes, 512k.
Mas de eso, cores como el Spectrum con el modulo de sonido que llega a 2mb, y el del CPC 6128 de Renaud Hélias que usa 2mb, pero que yo logré reducir a solo 512k para que entrara en el ZXUNO.
:shock: Pensaba que con la SRAM no me bastaria para casi nada... algun arcade, y algun 8bits basico...
El de amiga 500 necesitaria por lo menos 512 para Rom y 512 para ram, pero el de 1200(aga) necesita 2MB de ram al menos, no?

Avatar de Usuario
jepalza
Spartan 3
Mensajes: 226
Registrado: 14 Ago 2018, 18:51

Re: Controlador LPDDR2

Mensaje por jepalza » 20 Oct 2018, 11:52

Es que yo hablo de cores sencillos, los de 8bits.

Si lo que quieres es de 16bits, por poder puedes, pero vas a tener problemas con el ancho de bits, por que cualquier core de 16bits, emplea eso mismo, 16bits de ancho de datos, menos el QL que hace una mezcla 8-16 debido a la naturaleza del 68008, que es un 68000 capado para funcionar en modo 8bits.

El minimig entra de sobra en 4mb, solo que no tendrías ampliaciones extras como las ZORRO de 4 y 8 mb, pero vamos, que un A500 normal solo tiene 512k, junto a los 512k de ROM, te sobra para una ampliacion de 2mb.

Tienes que resolver el ancho de 8bits de salida la SRAM (a no ser que sea de doble puerto, que las hay).
Los accesos a SRAM y SDRAM son muy diferentes, sobre todo a nivel velocidad, por eso el 90% de los cores de 16bits usan SDRAM.
En el ZXUNO, el core del XT que hizo distwave emplea SRAM como si fuera SDRAM (ademas, con un modo 16bits), pero el core va algo mas lento que si usara SDRAM.

fpganoob
Veroboard
Mensajes: 17
Registrado: 11 Oct 2018, 15:31

Re: Controlador LPDDR2

Mensaje por fpganoob » 20 Oct 2018, 12:01

jepalza escribió:
20 Oct 2018, 11:52
Es que yo hablo de cores sencillos, los de 8bits.
Jeje, eso me parecia :)
jepalza escribió:
20 Oct 2018, 11:52
Si lo que quieres es de 16bits, por poder puedes, pero vas a tener problemas con el ancho de bits, por que cualquier core de 16bits, emplea eso mismo, 16bits de ancho de datos, menos el QL que hace una mezcla 8-16 debido a la naturaleza del 68008, que es un 68000 capado para funcionar en modo 8bits.

El minimig entra de sobra en 4mb, solo que no tendrías ampliaciones extras como las ZORRO de 4 y 8 mb, pero vamos, que un A500 normal solo tiene 512k, junto a los 512k de ROM, te sobra para una ampliacion de 2mb.
Bueno paso a paso... primero tengo que conseguir algun resultado en 8Bits o algun arcade, ya correre cuando sea capaz de andar...
jepalza escribió:
20 Oct 2018, 11:52
Tienes que resolver el ancho de 8bits de salida la SRAM (a no ser que sea de doble puerto, que las hay).
Los accesos a SRAM y SDRAM son muy diferentes, sobre todo a nivel velocidad, por eso el 90% de los cores de 16bits usan SDRAM.
En el ZXUNO, el core del XT que hizo distwave emplea SRAM como si fuera SDRAM (ademas, con un modo 16bits), pero el core va algo mas lento que si usara SDRAM.
Interesante eso de usar la SRAM como SDRAM, voy a ver si encuentro el fuente de eso, a ver si aprendo algo.

Gracias!!

Responder

Volver a “General”