код часового стробирования Verilog работает некорректно - PullRequest
0 голосов
/ 30 мая 2020

Я пытаюсь закодировать логику стробирования часов c, которая позволяет передавать данные только в posedge write_clk_en. код скомпилирован правильно в игровой площадке EDA, но результат не такой, как задумано. Итак, согласно коду,

@ (posedge write_clk_en)begin
 data_in[3] <= 1'b1;
end

в этом случае write_clk_en отключен, поэтому data_in [3] NBA должен быть остановлен и ждет для следующей допустимой позиции (которая здесь является следующей позицией write_clk_en) следует записать data_in [3]. Но этого не происходит, скорее также учитывается период стробирования, и назначение NBA происходит, даже когда write_clk_en стробируется для 4-го импульса. В чем может быть проблема? Здесь показана форма волны.

enter image description here

код sv:

module tb;

logic [4:0]  data_in;
logic  write_clk;
logic  write_clk_en;
logic write_clk_mod;  
logic [5:0] write_clk_init;

always//write_clk 500M
  begin
        write_clk  =0;
    #10 write_clk = 1;
    #10 write_clk = 0;
  end


initial begin
  $dumpfile("dump.vcd");
  $dumpvars;
  #10000 $finish;
end  

initial begin
data_in=5'b00000;
write_clk_init = 6'b000000;
write_clk_mod=0;
end

initial begin
write_clk_init =6'b110111;
end

initial begin
repeat (3) begin
@(posedge write_clk)begin
if(write_clk_init[0]==1 || write_clk_init[0]==0)
write_clk_mod<=write_clk_init[0];
end
@(posedge write_clk)begin
if(write_clk_init[1]==1 || write_clk_init[1]==0)
write_clk_mod<=write_clk_init[1];
end
@(posedge write_clk)begin
if(write_clk_init[2]==1 || write_clk_init[2]==0)
write_clk_mod<=write_clk_init[2];
end
@(posedge write_clk)begin
if(write_clk_init[3]==1 || write_clk_init[3]==0)
write_clk_mod<=write_clk_init[3];
end
@(posedge write_clk)begin
if(write_clk_init[4]==1 || write_clk_init[4]==0)
write_clk_mod<=write_clk_init[4];
end
@(posedge write_clk)begin
if(write_clk_init[5]==1 || write_clk_init[5]==0)
write_clk_mod<=write_clk_init[5];
end
end
end

  always @ (*) begin 
  write_clk_en  = write_clk & write_clk_mod;
end

initial begin 

@ (posedge write_clk_en)begin
data_in[0] <= 1'b1;
end
@ (posedge write_clk_en)begin
data_in[1] <= 1'b1;
end
@ (posedge write_clk_en)begin
 data_in[2] <= 1'b1;
 end
@ (posedge write_clk_en)begin
 data_in[3] <= 1'b1;
end
@ (posedge write_clk_en)begin
data_in[4] <= 1'b1;
end

end


endmodule

1 Ответ

2 голосов
/ 31 мая 2020

В начальных блоках измените свои NBA на BA. NBA следует использовать только в пределах always @(posedge clocksignal) block

. Также учтите, что в симуляциях блоки @(posedge clocksignal) (без зарезервированного слова always) обрабатываются как задержки (подождите, пока не произойдет событие clk нарастающего фронта. , затем продолжите моделирование). Кстати, вы записали эти блоки в своих начальных утверждениях, я не знал наверняка, знали ли вы об их истинном поведении. Я переписал эти @(posedge) блоки, чтобы сделать поток симуляции немного яснее.

Я также объединил некоторые из ваших начальных блоков в один. Каждый начальный блок у вас запускается одновременно (время моделирования 0). В частности, write_clk_init назначается в двух разных начальных блоках.

Этот отредактированный код работает должным образом. Он также доступен по адресу https://www.edaplayground.com/x/3VYk

OpenWavwe output

module tb;
  reg [4:0]  data_in;
  reg  write_clk;
  reg  write_clk_en;
  reg write_clk_mod;  
  reg [5:0] write_clk_init;

  initial begin
    $dumpfile("dump.vcd");
    $dumpvars;
    #10000 $finish;
  end  

  initial begin
    data_in = 5'b00000;
    write_clk_init = 6'b110111;
    write_clk_mod = 0;
    write_clk = 0;

    repeat (3) begin
      @(posedge write_clk);
      if(write_clk_init[0]==1 || write_clk_init[0]==0)
          write_clk_mod = write_clk_init[0];

      @(posedge write_clk);
      if(write_clk_init[1]==1 || write_clk_init[1]==0)
          write_clk_mod = write_clk_init[1];

      @(posedge write_clk);
      if(write_clk_init[2]==1 || write_clk_init[2]==0)
          write_clk_mod = write_clk_init[2];

      @(posedge write_clk);
      if(write_clk_init[3]==1 || write_clk_init[3]==0)
          write_clk_mod = write_clk_init[3];

      @(posedge write_clk);
      if(write_clk_init[4]==1 || write_clk_init[4]==0)
          write_clk_mod = write_clk_init[4];

      @(posedge write_clk);
      if(write_clk_init[5]==1 || write_clk_init[5]==0)
          write_clk_mod = write_clk_init[5];
    end
  end

  always @* begin 
    write_clk_en  = write_clk & write_clk_mod;
  end

  initial begin 
    @(posedge write_clk_en);
    data_in[0] = 1'b1;

    @(posedge write_clk_en);
    data_in[1] = 1'b1;

    @(posedge write_clk_en);
    data_in[2] = 1'b1;

    @(posedge write_clk_en);
    data_in[3] = 1'b1;

    @(posedge write_clk_en);
    data_in[4] = 1'b1;
  end

  always begin
    write_clk = #10 ~write_clk;
  end      
endmodule
...