Truncar y otras operaciones sobre la constante en Verilog

Ejemplo muy simple con el que estoy atrapado. Quiero que el diseño escrito en Verilog devuelva un año definido en la fuente como formato de 16 bits al mundo exterior usando dos bytes.

`define MY_YEAR 16'd2017

entonces necesito de alguna manera dividir esta constante en dos bytes para realizar algo como esto

wire [7:0] w_year_byte = w_current_byte ? (`MY_YEAR >> 8) : (`MY_YEAR & 8'hff);

Para mí, las expresiones anteriores con MY_YEAR no son correctas ya que su resultado sigue siendo de 16 bits. Y esta declaración no se compila en absoluto ...

Sé cómo hacerlo con vectores, pero nunca antes lo había hecho con constantes; vi varias respuestas para preguntas similares en Internet, pero aún no tengo claro cómo hacer las cosas correctamente . Puede parecer que mi enfoque es totalmente incorrecto, estará muy contento de educarme.

Actualización: mi fuente de Verilog es relativamente grande, y la idea principal era tener la definición de este año al principio del archivo fuente, en la primera línea, porque se cambiará con frecuencia y no necesitaría bajar para encontrar el valor a cambiar.

Al revisar la respuesta de Tom Carpenter, me di cuenta de que estaba cometiendo un error estúpido al intentar declarar un parámetro, un parámetro local o un cable fuera del módulo (en la parte superior de la fuente, antes de la declaración del módulo), así que sigo su sugerencia de tener

`define MY_YEAR 16'd2017

en la primera línea de la fuente, y luego en algún lugar después de la declaración del módulo que tiene

wire [15:0] c_MY_YEAR = `MY_YEAR;

y luego usando c_MY_YEAR[7:0]y c_MY_YEAR[15:8]como de costumbre. ¡Gracias Tom!

Respuestas (1)

Es mejor usar localparamen lugar de 'define.

Por ejemplo:

module blah (

);

localparam MY_YEAR = 16'd2017; //This is a local parameter which cannot be seen or changed outside the module

wire [7:0] w_year_byte = w_current_byte ? MY_YEAR[15:8] : MY_YEAR[7:0];

...

endmodule

Recuerde que con Verilog no está trabajando con programas de computadora, no está haciendo las cosas de manera procedimental, sino describiendo hardware. Si desea acceder a los MSB o LSB, simplemente puede describirlo: acceda a ellos directamente con el operador de selección de rango ( [MSB:LSB]) o el operador de selección de partes ( [LSB+:WIDTH]).

Los parámetros locales tienen la ventaja sobre los `defines en que se pueden tratar como cables constantes: puede acceder a su valor de la misma manera que accedería al valor de un cable.

Además, podría cambiar fácilmente su localparama a parameterque luego le permitiría cambiar el valor del parámetro cuando crea una instancia del módulo: este es uno de los componentes básicos de los módulos parametrizados reutilizables. Si su objetivo es tener los parámetros en la parte superior del archivo, esto puede lograrse con declaraciones de módulo de estilo ANSI de Verilog 2001:

module blah #(
    parameter MY_YEAR = 16'd2017
)(
    input whatever,
    output bob,
    input cheese
);
...

Si tiene su corazón puesto en un `define, puede acceder a él convirtiéndolo en un cable. Por ejemplo:

wire [15:0] my_year_wire = `MY_YEAR;

Una vez asignado a un cable, puede acceder a él de la misma manera que la versión del parámetro anterior:

wire [7:0] w_year_byte = w_current_byte ? my_year_wire[15:8] : my_year_wire[7:0];
Da un error al desear que el proyecto sea SystemVerilog. Tuve lo mismo para wire [15:0] MY_YEAR = 16'd2017.
@Anónimo eerm, esta es una sintaxis de Verilog perfectamente válida: ¿qué compilador está usando?
Oh, acabo de darme cuenta de mi error. ¡Estaba tratando de declarar localparamy wirefuera del módulo!
@Anónimo todo debe estar dentro de un archivo module. modulees el bloque de construcción de todo en Verilog.
Bueno, la idea principal de usar defineera tener las constantes al principio del texto, en la primera línea, incluso antes de la declaración del módulo.
Si usa parámetros, también puede lograrlo usando la declaración de puerto de estilo ANSI. Solo actualizo mi respuesta.