Siempre basado en el reloj Y una de las entradas cambia

-2

Tengo un módulo m(in1,in2,in3,in4,out1,out2); Necesito implementarlo de tal manera que en cada positive clock edge : Si se cambian in1 or in2 , la salida out1 se asigna como in1+in2 Si se cambian in3 or in4 , la salida out2 se asigna como in3*in4 ¿Cómo implementar eso en verilog?

always @(posedge clk and(in1 or in2))
begin 
out1 = in1 + in2;
end

always @(posedge clk and (in3 or in4))
begin 
out2 = in3 * in4;
end

Gracias

    
pregunta Yakov

4 respuestas

2

Su declaración de problema es ambigua. En primer lugar, su módulo no muestra una entrada clk , así que, ¿de dónde viene eso? Además, ¿ in1 a in4 cumplen con los requisitos de configuración y retención con respecto a este reloj?

En cualquier caso, la forma obvia de codificar lo que describe sería así:

module (
  input clk,
  input in1,
  input in2,
  input in3,
  input in4,
  output out1,
  output out2
);

  reg in1_a, in2_a, in3_a, in4_a;

  always @(posedge clk) begin
    in1_a <= in1;
    in2_a <= in2;
    in3_a <= in3;
    in4_a <= in4;
  end

  assign out1 = in1_a + in2_a;
  assign out2 = in3_a * in4_a;

endmodule

Con esta configuración, los registros de entrada solo cambian si las entradas han cambiado desde el límite del reloj anterior, y las salidas (y la lógica que las controla) solo cambian si los registros de entrada correspondientes cambian.

    
respondido por el Dave Tweed
4

Greg ofrece la forma habitual de realizar la función que solicitas:

always @(posedge clk)
  begin 
    out1 <= in1 + in2;
    out2 <= in3 * in4;
end

La pregunta ahora es, ¿por qué la gente lo hace de esta manera y no de la forma en que se te ocurrió?

Primero, recuerda que Verilog está destinado a describir hardware. No da una secuencia de pasos para ejecutarse uno tras otro como lo hace un lenguaje de programación de computadora común. Lo que el código anterior describe es algo como esto:

Apesardenoincluirin1yin2enlalistadesensibilidad,dehecho,loquesucedeesquecadavezqueunadeesasseñalescambia,lapartesumadoradelcircuitocambiarásuvalor.Sinembargo,laseñaldesalidanombradaout1solocambiasuvalorcuandoocurreeleventoposedgeclk.

DebidoalaformaenqueloselementosfuncionanenlalógicaCMOS,seconsumemuypocaenergíaenestecircuitoamenosquecambieunadelasentradas.Porlotanto,nodebepreocuparseporminimizarlasoperacionesinnecesariasenesacuenta.

Ahoraveamossuversiónsugerida:

always@(posedgeclkand(in1orin2))beginout1=in1+in2;end

Lógicamente,estoespedirquenosecambienlassalidasamenosqueocurrauneventoposedgeclkexactamentealmismotiempoqueuneventoin1oin2.Loqueconstituye"exactamente el mismo tiempo" tendría que ser definido por una peculiaridad de su simulador (significaría que los eventos suceden exactamente en el mismo paso de tiempo de simulación), o su hardware (la capacidad de algún circuito para distinguir un pequeño incremento de hora). Como tal, sería muy difícil para el simulador predecir la salida de la lógica sintetizada, por lo que no sería un estilo de codificación que recomendaría.

Lo que probablemente querrás hacer es esperar un evento in1 o in2 , luego esperar el borde del reloj. Esto puede, de hecho, ser codificado:

always @(in1 or in2)
  begin
    @(posedge clk);
    out1 <= in1 + in2;
  end

Sin embargo, no es probable que se sintetice, ya que no es obvio qué tipo de circuito podría ignorar más cambios en in1 y in2 mientras espera el límite del reloj (¿algún tipo de bloqueo, tal vez?) Si asume in1 y in2 no cambian más de una vez por ciclo de reloj, entonces la salida será idéntica a la forma habitual (código de Greg).

    
respondido por el The Photon
2

Estás usando un evento de temporización, por lo tanto, no hay razón para tener las entradas en la lista de sensibilidad. No importa si las entradas cambian o no. En cada reloj de posición, asigne las salidas.

always @(posedge clk)
  begin 
    out1 <= in1 + in2;
    out2 <= in3 * in4;
  end
    
respondido por el Greg
0

Aquí hay un reloj que cumple con los requisitos. Dicho esto, un mejor enfoque puede ser guardar los valores anteriores de todas las entradas y compararlos con los nuevos valores, y luego Y el resultado con el clk.

  reg out1_sense;
  reg out2_sense;
  wire out1_clk;
  wire out2_clk;

  always @(in1 or in2) begin
    out1_sense <= 1'b1;
  end
  assign out1_clk = clk & out1_sense;

  always @(in3 or in4) begin
    out2_sense <= 1'b1;
  end
  assign out2_clk = clk & out2_sense;

  always @(posedge clk) begin
    out1_sense <= 1'b0;
    out2_sense <= 1'b0;
  end

  always @(posedge out1_clk) begin 
    out1 = in1 + in2;
  end

  always @(posedge out2_clk) begin 
    out2 = in3 * in4;
  end

Diseño y prueba compilados en EDA Playground: enlace

    
respondido por el Victor Lyuboslavsky

Lea otras preguntas en las etiquetas