Volver al inicio

Tarjeta SD como ROM para RISC-V YRV FPGA

El artículo describe el uso de una tarjeta SD como almacenamiento para código ejecutable del núcleo RISC-V YRV en la placa Tang Nano 9K. FSM implementado para leer sectores de 512 bytes con caché en RAM. Pruebas con salida HELO confirman la funcionalidad.

SD en lugar de RAM: RISC-V YRV en FPGA con tarjeta de memoria
Advertisement 728x90

Usar una tarjeta SD como almacenamiento de código para RISC-V YRV en FPGA Tang Nano 9K

En placas FPGA económicas como la Tang Nano 9K, los recursos limitados de síntesis restringen la RAM integrada, lo que hace inviable almacenar todo el código del programa en memoria de bloques. Solo se dispone de 16–20 KB para pila y datos: suficiente para pruebas básicas, pero no para firmware completo. Este artículo propone usar una tarjeta SD como memoria de solo lectura (ROM) externa, con lecturas sectoriales de 512 bytes —funcionalmente similar a la ejecución directa desde flash QSPI (XIP), pero adaptada a las limitaciones del protocolo SPI.

El núcleo YRV se conecta a la memoria mediante un bus de 16 bits. La lógica de lectura/escritura se implementa en Verilog:

always @ (posedge clk) begin
  if (mem_trans[0]) begin
    mem_rdata[31:24] <= mcu_mem_bank3 [mem_addr[13:2]];
    mem_rdata[23:16] <= mcu_mem_bank2 [mem_addr[13:2]];
    mem_rdata[15:8]  <= mcu_mem_bank1 [mem_addr[13:2]];
    mem_rdata[7:0]   <= mcu_mem_bank0 [mem_addr[13:2]];
  end
  if (mem_wr_byte[3]) mcu_mem_bank3 [mem_addr_reg[13:2]] <= mem_wdata[31:24];
  if (mem_wr_byte[2]) mcu_mem_bank2 [mem_addr_reg[13:2]] <= mem_wdata[23:16];
  if (mem_wr_byte[1]) mcu_mem_bank1 [mem_addr_reg[13:2]] <= mem_wdata[15:8];
  if (mem_wr_byte[0]) mcu_mem_bank0 [mem_addr_reg[13:2]] <= mem_wdata[7:0];
end

Máquina de estados para caché de sectores SD

La RAM se reduce a solo 512 bytes —un único sector—. Cuando la CPU accede a una dirección dentro del sector actualmente en caché, la ejecución continúa inmediatamente con mem_ready activado (análogo a HREADY en AHB-Lite). En caso de fallo de caché —es decir, al acceder fuera del sector actual—, la máquina de estados finita (FSM) desencadena una nueva lectura de sector desde la tarjeta SD. Un contador byte_cnt rastrea el progreso de la lectura.

Google AdInline article slot

La FSM incluye tres estados:

  • IDLE: Espera una solicitud de acceso a memoria.
  • READ: Lee el sector solicitado de 512 bytes desde la tarjeta SD.
  • START: Inicia el comando de lectura (envía rd).

El controlador SD se deriva de proyectos de código abierto como FPGA-SDcard-Reader y MIT 6.111, y luego se adapta a la interfaz SPI de la Tang Nano 9K (las líneas DAT1/DAT2 se dejan sin conectar). La inicialización se ejecuta a 400 kHz para garantizar robustez —no se requiere reinicio por ciclo de alimentación.

Integración en el proyecto YRV Plus

Implementado en labs/99_experimental/99_03_yrv_sd, construido sobre la base basics-graphics-music. La configuración tang_nano_9k_tm1638_sd asigna los pines SD a 3,3 V. La salida usa el controlador TM1638: port0 maneja los segmentos BCD; port1 selecciona la posición del dígito.

Google AdInline article slot

Ejemplo de código ensamblador para mostrar «HELO» (cada carácter almacenado en su propio sector):

li s0, 0xFFFF0000    # port0 — datos de segmentos
li s1, 0xFFFF0002    # port1 — posición del dígito

main_loop:
  # 'H' (dígito 3)
  li t1, 0x8
  sh t1, 0(s1)
  .rept 100
  nop
  .endr
  li t2, 0b00110111
  sh t2, 0(s0)
  .rept 1000
  nop
  .endr
  # Repetir de forma análoga para E, L, O

El firmware se escribe sector a sector usando HxD.

Resultados de las pruebas:

Google AdInline article slot
  • Se ejecutan ~1.000 instrucciones NOP entre caracteres (representando carga real).
  • «HELO» se muestra con claridad en cuatro dígitos de siete segmentos.
  • Reinicio e inicialización fiables —sin necesidad de reiniciar la alimentación.
  • Al retirar la tarjeta SD, la ejecución se detiene de forma limpia.

Conclusiones clave

  • Las tarjetas SD en modo SPI permiten una ejecución tipo XIP cuando se combinan con una caché de 512 bytes por sector.
  • La FSM minimiza la latencia; mem_ready mantiene sincronizada la CPU durante las lecturas.
  • Ideal para aplicaciones de bajo ancho de banda donde el tiempo de señal está en el rango de milisegundos.
  • Para un rendimiento más fluido, considere aumentar la caché a 1–2 KB.
  • Totalmente compatible con núcleos YRV en FPGAs Gowin —incluso sin SRAM externa.

Oportunidades de optimización

La implementación actual requiere 6+ ciclos de reloj por lectura de sector (frente a 6 en QSPI). Ampliar la caché a 2–4 sectores reduciría drásticamente los fallos de caché. También es factible implementar búferes multi-banco, replicando la lógica original de memoria de YRV. Para desarrolladores avanzados: integre esta solución con adaptadores Wishbone o AXI para escalarla en diseños SoC más grandes.

— Editorial Team

Advertisement 728x90

Leer después