6 / 20 · Práctica
Práctica: elemento de procesamiento MAC con signo
Usa un modelo independiente para comprobar operandos válidos, detenciones y borrado.
Las lecciones se pueden leer gratis. Inscríbete para guardar el progreso.
Ejecuta el contrato de un PE
Guarda esto como pe-lab.mjs y ejecuta node pe-lab.mjs con Node.js. No usa paquetes externos e imprime PE lab passed. Comprueba un modelo aritmético y de control; no compila SystemVerilog ni demuestra su ejecución en DDS. Considera el trabajo ordinario de dos términos como W=8, K=2, AW=17, mientras que el modelo usa enteros anchos para su referencia.
El PE recibe indicadores de validez separados para A y B. Acumula solo cuando ambos son verdaderos. El reenvío sigue el indicador de validez propio de cada operando. Una lección posterior añade etiquetas para garantizar que dos operandos válidos pertenecen al mismo término de reducción.
import assert from 'node:assert/strict';
const pe = {acc:0,a:0,b:0,av:false,bv:false};
function edge({a=0,b=0,av=false,bv=false,
advance=true,clear=false,reset=false}={}) {
if (reset || clear) {
Object.assign(pe,{acc:0,a:0,b:0,av:false,bv:false});
} else if (advance) {
if (av && bv) pe.acc += a*b;
Object.assign(pe,{a,b,av,bv});
}
return {...pe};
}
edge({clear:true});
assert.equal(edge({a:-2,b:3,av:true,bv:true}).acc,-6);
const held={...pe};
assert.deepEqual(edge({a:99,b:99,av:true,bv:true,advance:false}),held);
assert.equal(edge({a:4,b:-5,av:true,bv:true}).acc,-26);
assert.equal(edge({a:8,b:8,av:true,bv:false}).acc,-26);
assert.equal(pe.av,true); assert.equal(pe.bv,false);
edge({clear:true,a:100,b:100,av:true,bv:true});
assert.equal(pe.acc,0); assert.equal(pe.av,false);
assert.equal(edge({a:-128,b:-128,av:true,bv:true}).acc,16384);
edge({reset:true,advance:false});
assert.deepEqual(pe,{acc:0,a:0,b:0,av:false,bv:false});
console.log('PE lab passed');Predice y pon a prueba el resultado
El primer par produce −6. Una pausa ignora los valores 99 ofrecidos y conserva todo el estado. El siguiente par válido aporta −20 y alcanza −26. El token A sin pareja se reenvía, pero no aporta ninguna MAC. El borrado tiene prioridad sobre el par válido simultáneo; mínimo×mínimo da después 16384. El reinicio borra el estado de validez incluso cuando advance es falso.
Traduce la misma prioridad a always_ff usando señales de producto y sumando explícitamente con signo. Al modelar una matriz, lee el estado anterior y escribe un estado siguiente separado. Actualizar los objetos PE en el mismo lugar puede permitir por accidente que un token atraviese varios PE durante un solo flanco.
Cambia la condición de acumulación de AND a OR. La aserción del token sin pareja debe fallar. Prueba también a aplicar advance solo al acumulador y dejar que el reenvío se mueva. Explica qué contrato protege cada aserción; un mensaje de éxito por sí solo no constituye todo el resultado de aprendizaje.
Registra los operandos ofrecidos por separado de los consumidos: los valores noventa y nueve de la pausa son visibles en la interfaz, pero nunca se consumen. El módulo envolvente debe conservar el siguiente término planificado hasta que se reanude advance. Las copias de estado devueltas conservan observaciones anteriores. Examina los indicadores de validez del reenvío además del acumulador al traducir estas comprobaciones a un banco de pruebas basado en formas de onda.
RTL real: el PE MAC con signo
Guarda juntos los adjuntos signed_mac_pe.sv, systolic_2x2.sv y tb_systolic_2x2.sv. Los dos primeros son RTL sintetizable; el banco de pruebas es solo para simulación. El PE extiende el signo de su producto completo de 2W bits a AW antes de acumular. Las comprobaciones W=8,K=4 usan AW=18 para 65536, −65024 y 64516. Las etiquetas k ordenadas rechazan términos discordantes mediante protocol_error.
La prioridad es reset, clear y después advance. Clear termina antes del primer flanco de datos. Observa el acumulador actualizado después de cada flanco ascendente; los vecinos consumen el reenvío registrado en el siguiente flanco con avance. Una pausa conserva todos los valores, indicadores de validez, etiquetas y contadores. Se ejecuta un trabajo entre borrados, sin cuantización de salida ni integración DDS.
Con Icarus Verilog instalado, ejecuta:
iverilog -g2012 -s tb_systolic_2x2 -o systolic.vvp signed_mac_pe.sv systolic_2x2.sv tb_systolic_2x2.sv
vvp systolic.vvpEspera RTL PASS:; los fallos terminan con $fatal. Modifica addend para usar extensión con ceros y reproduce el fallo de la matriz negativa. Explica el primer acumulador de PE discordante, restaura la extensión de signo y vuelve a ejecutar. Conserva registros Node y HDL separados.
Inténtalo tú
Inserta un par válido (0,7) entre (−2,3) y (4,−5). ¿Cuál es la suma y en qué se diferencia un cero válido de un token no válido?
Leer la explicación
La suma es −26. Un cero válido sigue consumiendo un término k real y hace avanzar el recuento de términos y las etiquetas. Un token no válido no consume ningún término. Para un trabajo de tres términos, actualiza K, el análisis de anchura y el control de finalización en consecuencia.