Vengo de un origen muy predominante en VHDL y recientemente he estado haciendo mucha más codificación en SystemVerilog. He notado un par de comportamientos extraños que no entiendo completamente.
Resumen
En el siguiente ejemplo, estoy realizando una adición de varias señales. Sé que esto es particularmente ineficiente (y probablemente de mal estilo), pero lo estoy usando para demostrar el tipo de problema que he encontrado recientemente.
// Main add (inside synchronous process)
// all signals are 32b logic or reg (except for 64, which is a 'define)
dma_ins.dest <= sdram_addr + slice_address + slice_offset - 64;
0x3800 0000 0x0001 0000 0x0000 0050
Cuando ejecuto este complemento en la simulación, obtengo el resultado correcto. En síntesis, es incorrecto.
Simulación: 0x38010010
Síntesis: 0x38008008
El valor de síntesis es un cambio a la derecha (0x8008 en lugar de 0x10010).
Para determinar el valor de síntesis, estoy escribiendo las cuatro señales para depurar los registros. El DMA también termina en la dirección incorrecta en el SDRAM en hardware.
Para solucionar este problema, hice lo siguiente:
dma_ins.dest <= sdram_addr;
dma_ins.dest[26:15] <= queue_prop_new[0].contig_head; // non-shifted versions of slice address
dma_ins.dest[14:4] <= queue_prop_new[0].contig_hoffset - 4; // and slice offset
Probablemente me esté perdiendo algo con respecto a las definiciones de tipo SystemVerilog, pero no estoy seguro de qué. He añadido algunos detalles a continuación.
Detalle
Las señales que se suman se definen de la siguiente manera:
// SDRAM ADDR (synchronus process, 32b reg)
sdram_addr <= 32'h38000000
// SLICE ADDRESS (asynchronus combinitorial assign)
// slice address: 32b logic
// queue_prop_new[0].contig_head: 12b logic: value of 0x02
// 32768 is a 'define that has been substituted.
assign slice_address = (queue_prop_new[0].contig_head <<($clog2(32768)-1));
// (slice_address = 0x02 << 15 = 0x10000)
// SLICE OFFSET
// slice_offset: 32b logic
// queue_prop_new[0].contig_hoffset: 11b logic: value of 0x05
// 16 is a substituted 'define
assign slice_offset = (queue_prop_new[0].contig_hoffset<<($clog2(16)-1));
// (slice_offset = 0x05 << 4 = 0x50)