Esto no daría lo que Alexis quiere.
module and_clk (
input wire clk,
input wire rst_n,
input wire enable,
output reg cond
);
always @(posedge clk or negedge rst_n)
begin
if(~rst_n) begin
cond <= 1'b0;
end else begin
cond <= enable & clk;
end
end
endmodule
A medida que el FF captura datos solo en la posición del reloj, cond <= enable & clk
siempre pondrá 1'b1
en cond
(cuando la habilitación es alta por cierto).
Puedo ver dos soluciones para hacer lo que quieres:
-
Agregue lógica en el reloj (lo que puede dar como resultado problemas graves en la síntesis)
module and_clk (
input wire clk,
input wire rst_n,
input wire enable,
output wire cond
);
reg enable_q;
always @(posedge clk or negedge rst_n)
begin
if(~rst_n) begin
enable_q <= 1'b0;
end else begin
enable_q <= enable;//stores enable value in a FF
end
end
assign cond = enable_q & clk; //it is not safe to add combinatorial cells on the clock path. It will complicate the generation of the clock tree
endmodule
-
Utilice un FF desencadenado por negedge, un poco más complicado pero mucho más seguro para la síntesis
module and_clk (
input wire clk,
input wire rst_n,
input wire enable,
output wire cond
);
reg enable_q;
always @(posedge clk or negedge rst_n)
begin
if(~rst_n) begin
enable_q <= 1'b0;
end else begin
enable_q <= enable & ~enable_qn;//stores enable value in a FF
//set to 0 when enable_qn is high to generate the cycles you want
end
end
always @(negedge clk or negedge rst_n)
begin
if(~rst_n) begin
enable_qn <= 1'b0;
end else begin
enable_qn <= enable_q;
//will take the value of enable_q half a cycle later
end
end
assign cond = enable_q ^ enable_qn;
//xoring the output will give you what you want
endmodule
Finalmente, no es una pregunta tan simple :)
EDIT:
Problemas sobre la adición de lógica en la ruta del reloj:
Agregar lógica en la ruta del reloj agrega dos cosas:
- Retraso a la salida de la lógica: lo que puede crear metastabilidad ya que la señal resultante cambiará en una ventana cercana de los bordes del reloj. ( Este sitio explica claramente el problema de la metastabilidad)
- Capacitancia a la entrada: Esto provoca un desequilibrio en el árbol del reloj, es decir, arruina el trabajo que realizó la herramienta de síntesis para garantizar que todos los FF, con el mismo reloj, se activen al mismo tiempo. ( explica cómo se genera un árbol de reloj)
Este interesante pdf agrupa un montón de cosas que deben evitarse para diseñar circuitos confiables.
Problemas al agregar enable
en la ruta de salida:
(Para entender lo que trataré de explicar en las siguientes líneas, debe leer y entender cuidadosamente, mi primera referencia )
No sé de dónde viene su señal enable
, pero como se dibuja, parece ser asíncrono. El problema con las señales asíncronas en los diseños síncronos es que pueden violar las restricciones de configuración / retención del FF y luego crear una metastabilidad que dará como resultado un valor impredecible del FF de salida que se violaron las restricciones.
Si entendió el artículo sobre metastabilidad, debería haber imaginado que incluso poner enable
en enable_q
puede crear metastabilidad. Para estar (más) cubierto sobre eso, una solución es agregar un FF activado por negedge "entre" enable
y enable_q
.
Como es una cuestión de probabilidad, la metastabilidad puede ocurrir en todas partes. Una versión más segura de tu diseño sería:
module and_clk (
input wire clk,
input wire rst_n,
input wire enable,
output wire cond
);
reg enable_q, enable_meta;
//This FF store on negedge the value of enable
always @(negedge clk or negedge rst_n)
begin
if(~rst_n) begin
enable_meta <= 1'b0;
end else begin
enable_meta <= enable;//stores enable value in a FF
end
end
//By doubling this FF the risk of metastability is greatly reduced
always @(posedge clk or negedge rst_n)
begin
if(~rst_n) begin
enable_q <= 1'b0;
end else begin
enable_q <= enable_meta & ~enable_qn;//stores enable value in a FF
//set to 0 when enable_qn is high to generate the cycles you want
end
end
always @(negedge clk or negedge rst_n)
begin
if(~rst_n) begin
enable_qn <= 1'b0;
end else begin
enable_qn <= enable_q;
//will take the value of enable_q half a cycle later
end
end
assign cond = (enable_q ^ enable_qn) & enable_meta;
//adding "& enable_meta" can replace "enable"
//This should be safe as the result of the xor will have a very low probability of metastability
endmodule
Esta solución será más segura, pero también más grande y bastante más complicada.
También habrá configuraciones de eventos que conducirán a un ciclo adicional en cond
o un retraso de 1 reloj dependiendo de la llegada de subida / caída de enable
.
Espero que esto ayude.