2026-02-28 21:59:55 +01:00
|
|
|
# Verilog Roadmap: De Turing Complete a FPGA
|
|
|
|
|
|
|
|
|
|
> Objetivo: traducir tu CPU custom de 16 bits (Turing Complete) a Verilog sintetizable
|
|
|
|
|
> y montarla en la Tang Primer 20K (Gowin GW2A).
|
|
|
|
|
>
|
|
|
|
|
> Prerequisitos que ya tienes:
|
|
|
|
|
> - Logica digital (puertas, muxes, flip-flops, FSMs) — via Turing Complete
|
|
|
|
|
> - Arquitectura de CPU de 16 bits — tu CPU custom
|
|
|
|
|
> - Lenguaje j-lang + compilador para tu CPU
|
|
|
|
|
> - Toolchain: iverilog + vvp + gtkwave funcionando
|
|
|
|
|
> - Primer ejercicio (half_adder) completado en 3 estilos
|
|
|
|
|
>
|
|
|
|
|
> Tu CPU (mycpu_v2):
|
|
|
|
|
> - 16 registros de 16 bits (REG0-REG11 generales, REG12=RAM_VAL, REG13=RAM_ADDR,
|
|
|
|
|
> REG14=PC, REG15=IN/OUT)
|
|
|
|
|
> - Instrucciones de 64 bits: [OPCODE:16][PARAM1:16][PARAM2:16][TARGET:16]
|
|
|
|
|
> - Modo de direccionamiento en bits 7-6 del opcode (reg/reg, imm/reg, reg/imm, imm/imm)
|
|
|
|
|
> - 12 ops ALU (ADD,SUB,MUL,DIV,AND,OR,NOT,NAND,NOR,XOR,XNOR,NEG)
|
|
|
|
|
> - 6 condicionales (EQ,NEQ,LS,LSE,GR,GRE) — branch si condicion true
|
|
|
|
|
> - Stack: PUSH, POP, RSTR
|
|
|
|
|
> - Funciones: CALL, RET, HALT
|
|
|
|
|
> - ISA completo en: D:\Proyectos\c-labs\j-lang\mycpu_v2.md
|
|
|
|
|
>
|
|
|
|
|
> FPGA target: Tang Primer 20K (Gowin GW2A-LV18PG256C8/I7)
|
|
|
|
|
> - 20736 LUT4 | 15552 FF | 828K BSRAM | 48 multiplicadores 18x18
|
|
|
|
|
> - 128MB DDR3 | 32Mbit Flash | JTAG+UART debug | 117 IO
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Fase 1: Bloques combinacionales fundamentales
|
|
|
|
|
|
|
|
|
|
Cosas que ya conoces del juego, ahora las escribes en Verilog.
|
|
|
|
|
Cada ejercicio: modulo + testbench + simulacion con gtkwave.
|
|
|
|
|
|
|
|
|
|
### 1.1 Full Adder
|
|
|
|
|
- **Carpeta:** `full_adder/`
|
|
|
|
|
- **Objetivo:** Combinar dos half adders para hacer un full adder (con carry-in)
|
|
|
|
|
- **Practica:** Hacerlo structural (instanciando tu half_adder) y dataflow
|
|
|
|
|
- **Concepto Verilog:** instanciacion de modulos, jerarquia
|
|
|
|
|
|
|
|
|
|
### 1.2 Adder de N bits (ripple carry)
|
|
|
|
|
- **Carpeta:** `adder_nbit/`
|
|
|
|
|
- **Objetivo:** Sumador parametrizable de N bits usando `generate` y `parameter`
|
|
|
|
|
- **Practica:** Parametrizarlo a 4, 8 y 16 bits desde el testbench
|
|
|
|
|
- **Concepto Verilog:** `parameter`, `generate for`, buses `[N-1:0]`
|
|
|
|
|
|
|
|
|
|
### 1.3 ALU basica
|
|
|
|
|
- **Carpeta:** `alu_basic/`
|
|
|
|
|
- **Objetivo:** ALU de 16 bits con las 12 operaciones de tu CPU:
|
|
|
|
|
ADD, SUB, MUL, DIV, AND, OR, NOT, NAND, NOR, XOR, XNOR, NEG
|
|
|
|
|
- **Practica:** Selector de operacion de 4 bits (opcode[3:0]), flags (zero, carry, negative)
|
|
|
|
|
- **Concepto Verilog:** `case`, operadores aritmeticos, concatenacion `{}`
|
|
|
|
|
- **Conexion directa:** Este modulo es tu `alu.v` final casi tal cual
|
|
|
|
|
|
|
|
|
|
### 1.4 Multiplexor y Demultiplexor
|
|
|
|
|
- **Carpeta:** `mux_demux/`
|
|
|
|
|
- **Objetivo:** Mux 2:1, 4:1 y 8:1 parametrizables. Demux 1:4
|
|
|
|
|
- **Practica:** Mux con `assign` ternario vs `case` vs `generate`
|
|
|
|
|
- **Concepto Verilog:** operador ternario `? :`, seleccion por bits
|
|
|
|
|
|
|
|
|
|
### 1.5 Decoder / Encoder
|
|
|
|
|
- **Carpeta:** `decoder_encoder/`
|
|
|
|
|
- **Objetivo:** Decoder 3:8, encoder con prioridad
|
|
|
|
|
- **Practica:** Usar `casez` para don't cares
|
|
|
|
|
- **Concepto Verilog:** `casez`, `casex`, wildcards
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Fase 2: Bloques secuenciales
|
|
|
|
|
|
|
|
|
|
Aqui entran los flip-flops y el clock. Es el salto mas importante desde la logica
|
|
|
|
|
combinacional.
|
|
|
|
|
|
|
|
|
|
### 2.1 Flip-Flop D y registro
|
|
|
|
|
- **Carpeta:** `flip_flop/`
|
|
|
|
|
- **Objetivo:** FF-D con reset sincrono y asincrono, enable
|
|
|
|
|
- **Practica:** Registro de N bits parametrizable
|
|
|
|
|
- **Concepto Verilog:** `always @(posedge clk)`, `posedge`/`negedge`, blocking vs
|
|
|
|
|
non-blocking (`=` vs `<=`)
|
|
|
|
|
|
|
|
|
|
> **CRITICO:** En logica secuencial SIEMPRE usa `<=` (non-blocking).
|
|
|
|
|
> En combinacional usa `=` (blocking). Mezclarlos es el error #1 de Verilog.
|
|
|
|
|
|
|
|
|
|
### 2.2 Contador
|
|
|
|
|
- **Carpeta:** `counter/`
|
|
|
|
|
- **Objetivo:** Contador up/down de N bits con enable, load y reset
|
|
|
|
|
- **Practica:** Hacerlo parametrizable, probarlo a distintas frecuencias
|
|
|
|
|
- **Concepto Verilog:** Aritmetica en always secuencial, overflow
|
|
|
|
|
|
|
|
|
|
### 2.3 Shift Register
|
|
|
|
|
- **Carpeta:** `shift_register/`
|
|
|
|
|
- **Objetivo:** Registro de desplazamiento con carga paralela, shift left/right
|
|
|
|
|
- **Practica:** SISO, SIPO, PISO, PIPO
|
|
|
|
|
- **Concepto Verilog:** Operadores de shift en contexto secuencial
|
|
|
|
|
|
|
|
|
|
### 2.4 Register File
|
|
|
|
|
- **Carpeta:** `register_file/`
|
|
|
|
|
- **Objetivo:** Banco de 16 registros de 16 bits (como tu CPU: REG0-REG15),
|
|
|
|
|
2 puertos de lectura simultanea, 1 de escritura
|
|
|
|
|
- **Practica:** Lectura combinacional, escritura sincrona. Registros especiales
|
|
|
|
|
(REG12=RAM_VAL, REG13=RAM_ADDR, REG14=PC, REG15=IO) pueden tener logica extra
|
|
|
|
|
- **Concepto Verilog:** Arreglos `reg [15:0] regs [0:15]`, indexado por variable de 4 bits
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Fase 3: Memorias
|
|
|
|
|
|
|
|
|
|
### 3.1 RAM sincrona
|
|
|
|
|
- **Carpeta:** `ram/`
|
|
|
|
|
- **Objetivo:** RAM de 256x16 (256 posiciones de 16 bits), lectura/escritura sincrona
|
|
|
|
|
- **Practica:** Single port y dual port
|
|
|
|
|
- **Concepto Verilog:** Inferencia de block RAM, `$readmemh` para cargar datos iniciales
|
|
|
|
|
|
|
|
|
|
### 3.2 ROM
|
|
|
|
|
- **Carpeta:** `rom/`
|
|
|
|
|
- **Objetivo:** ROM de 256x16 con contenido inicializado desde archivo .hex
|
|
|
|
|
- **Practica:** Cargar un programa simple en hex y leerlo secuencialmente
|
|
|
|
|
- **Concepto Verilog:** `$readmemh`, `initial begin`
|
|
|
|
|
- **Conexion con tu proyecto:** Aqui eventualmente cargaras el binario que genera
|
|
|
|
|
tu compilador j-lang
|
|
|
|
|
|
|
|
|
|
### 3.3 Stack (LIFO)
|
|
|
|
|
- **Carpeta:** `stack/`
|
|
|
|
|
- **Objetivo:** Stack de 256 posiciones de 16 bits con PUSH, POP y RSTR (reset)
|
|
|
|
|
- **Practica:** Puntero de stack, deteccion de overflow/underflow
|
|
|
|
|
- **Conexion directa:** Tu CPU usa PUSH (0x19/0x59), POP (0x1A), RSTR (0x18)
|
|
|
|
|
y CALL/RET que tambien usan el stack para guardar/restaurar el PC
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Fase 4: Maquinas de estados finitos (FSM)
|
|
|
|
|
|
|
|
|
|
Ya las conoces de Turing Complete. Ahora las codificas formalmente.
|
|
|
|
|
|
|
|
|
|
### 4.1 FSM basica — Semaforo
|
|
|
|
|
- **Carpeta:** `fsm_traffic/`
|
|
|
|
|
- **Objetivo:** Semaforo con estados RED, GREEN, YELLOW y temporizador
|
|
|
|
|
- **Practica:** FSM con patron de 2 always (estado_actual + logica_siguiente)
|
|
|
|
|
- **Concepto Verilog:** `localparam` para estados, el patron clasico de FSM
|
|
|
|
|
|
|
|
|
|
### 4.2 FSM — Controlador UART TX (simplificado)
|
|
|
|
|
- **Carpeta:** `uart_tx/`
|
|
|
|
|
- **Objetivo:** Transmitir un byte por UART (start bit, 8 data, stop bit)
|
|
|
|
|
- **Practica:** Baud rate configurable con counter, FSM de transmision
|
|
|
|
|
- **Concepto:** FSM real que usaras para debug en FPGA
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Fase 5: Pipeline y CPU simples
|
|
|
|
|
|
|
|
|
|
Aqui empiezas a armar las piezas en subsistemas tipo CPU.
|
|
|
|
|
|
|
|
|
|
### 5.1 Fetch unit
|
|
|
|
|
- **Carpeta:** `fetch_unit/`
|
|
|
|
|
- **Objetivo:** Program Counter + ROM = fetch de instrucciones
|
|
|
|
|
- **Practica:** PC con increment, load (para jumps), reset
|
|
|
|
|
- **Conexion:** Este es el primer pedazo real de tu CPU
|
|
|
|
|
|
|
|
|
|
### 5.2 Decoder de instrucciones
|
|
|
|
|
- **Carpeta:** `instruction_decoder/`
|
|
|
|
|
- **Objetivo:** Tomar una instruccion de 64 bits y extraer:
|
|
|
|
|
- `opcode[7:0]` — operacion + tipo de grupo
|
|
|
|
|
- `opcode[7:6]` — modo de direccionamiento (00=R/R, 01=I/R, 10=R/I, 11=I/I)
|
|
|
|
|
- `opcode[5:4]` — grupo (00=ALU, 01=COND, 01=CTRL, 10=FUNC)
|
|
|
|
|
- `opcode[3:0]` — operacion dentro del grupo
|
|
|
|
|
- `param1[15:0]` — registro o inmediato segun modo
|
|
|
|
|
- `param2[15:0]` — registro o inmediato segun modo
|
|
|
|
|
- `target[15:0]` — registro destino o direccion de salto
|
|
|
|
|
- **Practica:** Generar senales de control: alu_op, reg_write, mem_read, mem_write,
|
|
|
|
|
branch, stack_op, is_immediate1, is_immediate2
|
|
|
|
|
- **Conexion:** Mapeo directo del ISA de mycpu_v2
|
|
|
|
|
|
|
|
|
|
### 5.3 CPU single-cycle minima
|
|
|
|
|
- **Carpeta:** `cpu_minimal/`
|
|
|
|
|
- **Objetivo:** CPU simplificada que ejecuta un subconjunto de tu ISA:
|
|
|
|
|
ADD (reg,imm), SUB, AND, OR — EQ, NEQ — PUSH, POP — CALL, RET, HALT
|
|
|
|
|
- **Practica:** Conectar fetch + decode + ALU + register file + RAM + stack
|
|
|
|
|
- **Concepto:** Datapath + Control Unit, todo single-cycle
|
|
|
|
|
- **Nota:** Tu instruccion es de 64 bits (4 words), asi que el fetch necesita
|
|
|
|
|
4 ciclos de lectura de ROM o una ROM con palabra de 64 bits
|
|
|
|
|
|
|
|
|
|
### 5.4 Programa de prueba
|
|
|
|
|
- **Objetivo:** Escribir a mano un programa en hex que sume numeros del 1 al 10
|
|
|
|
|
- **Practica:** Cargarlo en la ROM con `$readmemh`, simular, verificar resultado
|
|
|
|
|
- **Conexion:** Eventualmente esto lo hara tu compilador j-lang automaticamente
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Fase 6: TU CPU de Turing Complete en Verilog
|
|
|
|
|
|
|
|
|
|
Aqui es donde todo converge.
|
|
|
|
|
|
|
|
|
|
### 6.1 Documentar tu ISA (ya tienes mycpu_v2.md — completar)
|
|
|
|
|
- **Carpeta:** `tc_cpu/docs/`
|
|
|
|
|
- **Base:** Ya tienes mycpu_v2.md con registros, opcodes y modos
|
|
|
|
|
- **Que falta agregar para Verilog:**
|
|
|
|
|
- Diagrama de bloques del datapath (que se conecta con que)
|
|
|
|
|
- Ciclo de ejecucion: fetch (4 words) -> decode -> execute -> writeback
|
|
|
|
|
- Como funciona el acceso a RAM (escribir REG13=addr, leer/escribir REG12=data)
|
|
|
|
|
- Comportamiento exacto de CALL (push PC al stack, jump) y RET (pop PC del stack)
|
|
|
|
|
- Comportamiento de RSTR (reset del stack pointer?)
|
|
|
|
|
- Que pasa con flags/condiciones: se compara en el mismo ciclo?
|
|
|
|
|
- Senales de I/O via REG15: protocolo?
|
|
|
|
|
|
|
|
|
|
### 6.2 Implementar modulos individuales
|
|
|
|
|
- **Carpeta:** `tc_cpu/rtl/`
|
|
|
|
|
- **Objetivo:** Cada bloque testeado independientemente
|
|
|
|
|
- **Modulos concretos de tu CPU:**
|
|
|
|
|
|
|
|
|
|
| Modulo | Archivo | Descripcion |
|
|
|
|
|
| -------------------- | -------------------- | --------------------------------------------------- |
|
|
|
|
|
| ALU | `alu.v` | 12 ops (ADD-NEG), entradas 16bit, flags Z/C/N |
|
|
|
|
|
| Register File | `register_file.v` | 16 regs x 16bit, 2 read + 1 write, regs especiales |
|
|
|
|
|
| Program Counter | `pc.v` | Increment por 4 words, load para branch/CALL |
|
|
|
|
|
| Instruction Memory | `imem.v` | ROM de 64 bits de ancho (o 4 lecturas de 16 bits) |
|
|
|
|
|
| Data Memory (RAM) | `dmem.v` | RAM 16 bit, interfaz via REG12/REG13 |
|
|
|
|
|
| Stack | `stack.v` | PUSH/POP/RSTR, para datos y CALL/RET |
|
|
|
|
|
| Control Unit | `control_unit.v` | Decode opcode[7:0] -> senales de control |
|
|
|
|
|
| Mux de operandos | `operand_mux.v` | Selecciona reg o inmediato segun opcode[7:6] |
|
|
|
|
|
| Comparador | `comparator.v` | EQ/NEQ/LS/LSE/GR/GRE para branches |
|
|
|
|
|
| I/O Controller | `io_controller.v` | Interfaz REG15 con el mundo exterior |
|
|
|
|
|
|
|
|
|
|
### 6.3 Integrar el top-level
|
|
|
|
|
- **Archivo:** `tc_cpu/rtl/cpu_top.v`
|
|
|
|
|
- **Objetivo:** Conectar todos los modulos
|
|
|
|
|
- **Ciclo de ejecucion probable (multi-ciclo o FSM):**
|
|
|
|
|
1. **FETCH:** Leer 4 words consecutivos de IMEM -> registro de instruccion de 64 bits
|
|
|
|
|
2. **DECODE:** Extraer opcode, modo, param1, param2, target. Generar senales de control
|
|
|
|
|
3. **EXECUTE:** ALU o comparacion. Resolver operandos (reg/imm mux)
|
|
|
|
|
4. **MEMORY:** Si opcode accede a RAM (via REG12/REG13), hacer read/write
|
|
|
|
|
5. **WRITEBACK:** Escribir resultado en registro target
|
|
|
|
|
- **Nota:** Como tus instrucciones son de 64 bits, probablemente sea multi-ciclo
|
|
|
|
|
(4 ciclos de fetch + 1-2 de execute). Alternativa: ROM de 64 bits de ancho
|
|
|
|
|
|
|
|
|
|
### 6.4 Compilar j-lang -> hex -> simular en tu CPU Verilog
|
|
|
|
|
- **Objetivo:** Cerrar el loop completo
|
|
|
|
|
- **Flujo:** `codigo.j` -> compilador j-lang -> `.hex` -> `$readmemh` -> simulacion iverilog
|
|
|
|
|
- **Test sugerido:** Un programa j-lang simple (fibonacci, factorial, algo con loops)
|
|
|
|
|
- **Verificacion:** Comparar traza de ejecucion en gtkwave vs ejecucion en Turing Complete
|
|
|
|
|
- **Esto es el momento "wow":** el mismo programa que corria en Turing Complete
|
|
|
|
|
ahora corre en tu CPU Verilog
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Fase 7: FPGA — Tang Primer 20K
|
|
|
|
|
|
|
|
|
|
Tu placa: **Tang Primer 20K** con Gowin GW2A-LV18PG256C8/I7.
|
|
|
|
|
|
|
|
|
|
### Recursos de tu FPGA vs lo que necesita tu CPU
|
|
|
|
|
```
|
|
|
|
|
Recurso | Disponible | Tu CPU necesita (estimado)
|
|
|
|
|
-----------------|---------------|---------------------------
|
|
|
|
|
LUT4 | 20,736 | ~2,000-4,000 (sobra mucho)
|
|
|
|
|
Flip-Flops | 15,552 | ~500-1,000
|
|
|
|
|
BSRAM (828Kb) | 46 bloques | ~2-4 bloques (IMEM + DMEM)
|
|
|
|
|
Multiplicador | 48 (18x18) | 1 (para MUL de 16 bits)
|
|
|
|
|
PLL | 4 | 1 (para generar tu clock)
|
|
|
|
|
IO | 117 | ~20-30 (UART, LEDs, botones)
|
|
|
|
|
```
|
|
|
|
|
Te sobra FPGA para tu CPU. Podrias meter varias instancias si quisieras.
|
|
|
|
|
|
|
|
|
|
### 7.1 Instalar Gowin EDA y primer proyecto
|
|
|
|
|
- **Toolchain:** Gowin EDA (Education Edition es gratuita)
|
|
|
|
|
- Descarga: https://www.gowinsemi.com (necesitas registro)
|
|
|
|
|
- Incluye: Gowin Synthesizer, Place & Route, Programmer
|
|
|
|
|
- **Primer proyecto:** Blink LED
|
|
|
|
|
- Aprender: crear proyecto, seleccionar chip GW2A-LV18PG256C8/I7
|
|
|
|
|
- Constraints (.cst): asignar pines fisicos a senales
|
|
|
|
|
- Clock: la placa tiene un oscilador de 27 MHz, usar PLL para tu frecuencia
|
|
|
|
|
- Flujo: Synthesis -> Place & Route -> Generate Bitstream -> Program
|
|
|
|
|
- **Dock vs Lite:** Dependiendo de que placa de expansion uses, los pines cambian.
|
|
|
|
|
El Dock trae mas LEDs, botones y conectores
|
|
|
|
|
|
|
|
|
|
### 7.2 Adaptar tu CPU para sintesis
|
|
|
|
|
- **Cambios necesarios:**
|
|
|
|
|
- Quitar todo `$display`, `$dumpfile`, `$dumpvars`, `#delays` (solo simulacion)
|
|
|
|
|
- IMEM: Usar inicializacion de BSRAM de Gowin (soporta `$readmemh` en sintesis
|
|
|
|
|
para block RAM, pero verificar con Gowin Synthesizer)
|
|
|
|
|
- DMEM: Inferir BSRAM (el synthesizer lo detecta si sigues el patron correcto)
|
|
|
|
|
- MUL: Gowin puede mapear `*` a los multiplicadores DSP hardware automaticamente
|
|
|
|
|
- Clock: Usar la PLL Gowin (PLLVR primitive) para generar un clock limpio
|
|
|
|
|
- Reset: Usar el boton de la placa como reset global (con debouncing)
|
|
|
|
|
|
|
|
|
|
### 7.3 Agregar I/O real
|
|
|
|
|
- **Basico (debug):**
|
|
|
|
|
- LEDs de la placa -> mostrar estado/registro/flags
|
|
|
|
|
- Botones -> reset, step (ejecutar instruccion a instruccion), run
|
|
|
|
|
- 7-segmentos (si hay en el dock) -> mostrar PC o valor de registro
|
|
|
|
|
- **UART (esencial para debug):**
|
|
|
|
|
- Ya la habras hecho en Fase 4.2, conectarla al REG15 (IN/OUT)
|
|
|
|
|
- Permite enviar/recibir datos entre PC y tu CPU via terminal serial
|
|
|
|
|
- Debug: imprimir valor de registros, estado del PC, etc.
|
|
|
|
|
- **Avanzado (futuro):**
|
|
|
|
|
- LCD via el conector de 8 pines
|
|
|
|
|
- Tarjeta SD para cargar programas sin resintesis
|
|
|
|
|
- DDR3 para expandir RAM (requiere controlador DDR3, mas complejo)
|
|
|
|
|
|
|
|
|
|
### 7.4 Meta final
|
|
|
|
|
- Tu CPU ejecutando un programa compilado con j-lang en hardware real
|
|
|
|
|
- Poder cargar programas y ver resultados via UART desde tu PC
|
|
|
|
|
- El loop completo: `codigo.j` -> compilador -> `.hex` -> FPGA -> resultados reales
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Consejos generales
|
|
|
|
|
|
|
|
|
|
### Estructura de cada ejercicio
|
|
|
|
|
```
|
|
|
|
|
nombre_ejercicio/
|
|
|
|
|
nombre.v # modulo principal
|
|
|
|
|
nombre_tb.v # testbench
|
|
|
|
|
readme.md # notas, comandos, que aprendiste
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Comandos (ya los conoces)
|
|
|
|
|
```bash
|
|
|
|
|
iverilog -o modulo_tb.vvp modulo_tb.v
|
|
|
|
|
vvp modulo_tb.vvp
|
|
|
|
|
gtkwave modulo.vcd
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Errores comunes a evitar
|
|
|
|
|
1. **Blocking vs non-blocking:** `=` en combinacional, `<=` en secuencial. Siempre.
|
|
|
|
|
2. **Latch inferido:** Si usas `always @(*)` con `if` sin `else`, Verilog infiere un
|
|
|
|
|
latch. Siempre pon `else` o valores por defecto.
|
|
|
|
|
3. **Sensitivity list incompleta:** Usa `always @(*)` para combinacional, nunca listes
|
|
|
|
|
senales manualmente (es error-prone).
|
|
|
|
|
4. **Senales no inicializadas en testbench:** Todo `reg` empieza en `x` si no lo
|
|
|
|
|
inicializas.
|
|
|
|
|
5. **Confusion wire vs reg:** `wire` para assign y conexiones, `reg` para always blocks.
|
|
|
|
|
|
|
|
|
|
### Recursos recomendados
|
|
|
|
|
- **HDLBits** (hdlbits.01xz.net) — Ejercicios interactivos de Verilog online.
|
|
|
|
|
Excelente complemento para practicar sintaxis.
|
|
|
|
|
- **"Digital Design and Computer Architecture"** (Harris & Harris) — El libro de
|
|
|
|
|
referencia para ir de compuertas a CPU. Tiene ejemplos en Verilog.
|
|
|
|
|
- **Nand2Tetris** — Ya hiciste algo similar con Turing Complete, pero el libro tiene
|
|
|
|
|
buena formalizacion del ISA y el compilador.
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Progreso
|
|
|
|
|
|
|
|
|
|
- [x] Fase 1.0 — Half Adder (3 estilos + testbench)
|
|
|
|
|
- [x] Fase 1.1 — Full Adder
|
|
|
|
|
- [x] Fase 1.2 — Adder N bits
|
|
|
|
|
- [x] Fase 1.3 — ALU basica
|
2026-03-01 01:02:57 +01:00
|
|
|
- [x] Fase 1.4 — Mux / Demux
|
|
|
|
|
- [x] Fase 1.5 — Decoder / Encoder
|
2026-03-01 01:21:07 +01:00
|
|
|
- [x] Fase 2.1 — Flip-Flop D y registro
|
2026-03-01 01:42:33 +01:00
|
|
|
- [x] Fase 2.2 — Contador
|
2026-02-28 21:59:55 +01:00
|
|
|
- [ ] Fase 2.3 — Shift Register
|
|
|
|
|
- [ ] Fase 2.4 — Register File
|
|
|
|
|
- [ ] Fase 3.1 — RAM sincrona
|
|
|
|
|
- [ ] Fase 3.2 — ROM
|
|
|
|
|
- [ ] Fase 3.3 — Stack
|
|
|
|
|
- [ ] Fase 4.1 — FSM Semaforo
|
|
|
|
|
- [ ] Fase 4.2 — UART TX
|
|
|
|
|
- [ ] Fase 5.1 — Fetch Unit
|
|
|
|
|
- [ ] Fase 5.2 — Decoder de instrucciones
|
|
|
|
|
- [ ] Fase 5.3 — CPU single-cycle minima
|
|
|
|
|
- [ ] Fase 5.4 — Programa de prueba
|
|
|
|
|
- [ ] Fase 6.1 — Documentar ISA de tu CPU
|
|
|
|
|
- [ ] Fase 6.2 — Modulos individuales de tu CPU
|
|
|
|
|
- [ ] Fase 6.3 — Top-level integrado
|
|
|
|
|
- [ ] Fase 6.4 — j-lang -> hex -> simulacion
|
|
|
|
|
- [ ] Fase 7.1 — Gowin EDA + blink LED en Tang Primer 20K
|
|
|
|
|
- [ ] Fase 7.2 — CPU sintetizable (quitar sim-only, inferir BSRAM, PLL)
|
|
|
|
|
- [ ] Fase 7.3 — I/O real (LEDs, botones, UART)
|
|
|
|
|
- [ ] Fase 7.4 — j-lang corriendo en hardware real
|