Tentei fazer o relógio que conta o tempo dado que o ciclo de clk é de um minuto. Mas tive dificuldade em descobrir quais duas tarefas estão em conflito. (Estou procurando há dois dias, mas não consegui encontrar)
Primeiro tentei esses códigos no playground da EDA.
//code for "design.sv"
module clock(
input clk, rstn,
output reg[6:0] minute, //line 1
output reg[5:0] hour //line 2
);
always @ (posedge clk, negedge rstn) begin
if(!rstn) begin
minute <= 0; hour = 0;
end
else begin
minute = minute + 1;
end
end
always @ (posedge clk) begin
if((minute%60==0)&&(minute != 0)) begin
minute <= 0;
hour = hour + 1;
end
if((hour%24==0)&&(hour !=0)) hour <= 0;
end
endmodule
//code for "testbench.sv"
module test;
reg clk, rstn;
reg [6:0] minute;
reg [5:0] hour;
initial begin
clk = 0;
forever #5 clk = ~clk;
end
initial begin
rstn = 1; minute = 0; hour = 0; //line 3
#30 rstn = 0;
#1 rstn = 1;
#600 $finish;
end
clock clock_inst(clk, rstn, minute, hour);
initial begin
$dumpfiles("wave.vcd");
$dumpvars(0, test);
end
endmodule
Simulei esses primeiros códigos e recebi o erro abaixo.
A "variável ""minuto"" não pode ser controlada pelas instruções de atribuição processual e contínua. A "variável ""hora"" não pode ser controlada pelas instruções de atribuição processual e contínua.
Minha primeira conclusão: concluí que as atribuições de line 1
e line 2
estão em conflito com as de line 3
. Eu pensei output reg minute
e output reg hour
em clock_inst
são tarefas contínuas implícitas. Conseqüentemente line 1
, line 2
entra em conflito com atribuições em minute
e hour
(colocadas em line 3
) levando ao problema de multidriver em uma variável.
Porém, para verificar minha conclusão, revisei o código conforme abaixo.
//revised code for "design.sv"
module clock(
input clk, rstn,
output reg[6:0] minute,
output reg[5:0] hour
);
initial begin // newly added block
minute = 0; hour = 0;
end
always @ (posedge clk, negedge rstn) begin
if(!rstn) begin
minute <= 0; hour = 0;
end
else begin
minute = minute + 1;
end
end
always @ (posedge clk) begin
if((minute%60==0)&&(minute != 0)) begin
minute <= 0;
hour = hour + 1;
end
if((hour%24==0)&&(hour !=0)) hour <= 0;
end
endmodule
//revised code for "testbench.sv"
module test;
reg clk, rstn;
reg [6:0] minute;
reg [5:0] hour;
initial begin
clk = 0;
forever #5 clk = ~clk;
end
initial begin
rstn = 1; //revised line
#30 rstn = 0;
#1 rstn = 1;
#600 $finish;
end
clock clock_inst(clk, rstn, minute, hour);
initial begin
$dumpfiles("wave.vcd");
$dumpvars(0, test);
end
endmodule
O que pensei é que esses códigos me dariam erros porque a atribuição newly added block
entraria em conflito com output reg[6:0] minute
as output reg[5:0] hour
atribuições.
Mas funcionou muito bem
VSIM: A simulação foi concluída. Não há mais vetores de teste para simular.
VSIM: A simulação foi concluída.
Agora, não consigo encontrar quais linhas constigiam erros de multi-condução em meu primeiro código.
No código original, a variável
minute
é controlada por mais de umalways
bloco.Essa é a definição de vários drivers e não será sintetizada.
A solução é colocar todos os drivers para as variáveis em um bloco sempre.
Assim:
O operador de módulo não será bem sintetizado, exceto nos casos em que você estiver usando um módulo que é uma potência de 2 ^ N, exemplo: 2,4,8,16,32...
Além disso, tome cuidado para sempre usar atribuições sem bloqueio
<=
em um bloco sempre síncrono, em vez de bloquear atribuições=
. Usar atribuições de bloqueio em um bloco sempre síncrono pode causar comportamento incompatível de simulação/síntese.O que você está vendo no código revisado é um exemplo do simulador que não detecta corretamente os vários drivers associados ao
always
bloco verilog na simulação. A instrução SystemVerilogalways_ff
corrige isso e detectará consistentemente um erro de múltiplos drivers na simulação e síntese.Para demonstrar, mudei os
always
blocos paraalways_ff
e corri novamente no playground eda.Assim:
Produz:
Usando Cadence e similares usando Modelsim/Questa.
always_ff
peguei os vários drivers ealways
perdi na simulação.