Verilog 时序和时钟 - 输入和输出问题

Verilog timing and clocking - input and output issues

我用verilog写了这段代码,但我的代码有问题! 我想要做的是将数字 0 - 127 作为输入,这样它们就可以写在 mem 中,然后读取它们并查看输出。根据结果​​,我已将时钟设置为每 5 次从 0 变为 1,这正在发生。但是这些数字在记忆中不止一次出现。 我该如何解决这个问题,以便数字只写一次?这可能是计时问题吗?

一开始输出的数据是0,因为我要先写数据再读。

另外,我想知道我需要更改什么,以便当内存的最后一个位置填满数字 127 时,我的程序将理解内存的其他位置没有空着!! 我是运行 EDA Playground 的代码

module process_data(
  input wire [63:0] DATA_IN ,  //input data 
  input QUE_Mode,              //fifo or filo 
  //input wire [6:0] AdrR ,    //pointers for read, write
  //input wire [6:0] AdrW,  
  input R_W ,
  input Cen,  
  input clk,
  input reset, 
  output reg [63:0]Reg_Data_Out,  //output data
  output reg Que_Full,            //state of the queue
  output reg Que_Last, 
  output reg Que_Empty);

  integer i;
  reg [63:0] Memory [0:127];      //array 
  reg [6:0] AdrW;
  reg [6:0] AdrR;

  initial begin        //initialization 
   Que_Full= 1'b0;     //when  Que_Full = 1'b0, the queue is not full 
   Que_Last = 1'b0;    //when  Que_Last = 1'b0, this is not the last item of the list that can be added to 
   Que_Empty = 1'b0;   //when Que_Empty = 1'b0, the queue is empty.
   AdrR=7'b0000_000;
   AdrW=7'b0000_000;

   i=0;   
    repeat (128)        //initialization of memory 
    begin
        Memory[i]=64'd1;    //64 bits/ position , 127 positions 
        i=i+1;
    end
   end 

  always @* begin
    $display("AdrR=%d",AdrR);
    $display("AdrW=%d",AdrW);

  end 

  always @(negedge(clk))
  begin
    if(Cen == 1'b1) begin                        // cen = chip enabled , when 1=> chip is enabled => circuit works
    case (R_W)   
      1'b1:
         begin
           if(Que_Empty == 1'b1 )begin           //check if queue not empty
                                                 // Return the value from the FIFO  foun at the read address
              Reg_Data_Out <= Memory[AdrR];      // (read)  out put memory context          
              AdrR<=AdrR+7'b0000_001;            //assign  AdrR [6:0] <= AdrR [6:0] +7'b0000_001;   
           end 
         end 

      1'b0:
        begin 
          if( Que_Full == 1'b0  )begin               //check if queue not full 
            if(AdrW >= 7'b0000_000) begin
              Memory[AdrW] <= DATA_IN ;              // write input to memory , On any write -> update the memory
              AdrW <= AdrW+7'b0000_001;              //non blocking statements to avoid race conditions 
              Que_Empty = 1'b1;                      //when Que_Empty = 1'b1, the queue is NOT empty

              if(AdrW==7'b1111_111)begin  
                                                     //AdrW <= 7'b0000_000;
                 Que_Full= 1'b1;                     //when  Que_Full = 1'b1, the queue IS full 
                 Que_Last = 1'b1;                    //when  Que_Last = 1'b0, this IS the last item of the list that can be added to 
              end 
            end
          end 
        end 

      default:
        Reg_Data_Out = 64'bxxxxxxxx;  
    endcase

    end
  end 
endmodule 


module clock(output reg clk);
  initial
  clk=1'b0;
  always
  #5 clk=~clk;
endmodule


module TOP();
  parameter ENDTIME=40000;  

  reg [63:0] inputdata1;  // is an 63-bit "register", or variable  
  wire [6:0] AddressR,AddressW;

  reg cen, R_W, reset;  //clk=1'b0  , 
  reg QUE_Mode;

  wire [63:0] Data_Out;

  integer count;
  integer i;

  wire Que_Full, Que_Last, Que_Empty;

  wire clk;

  //call module for data I/O 
  process_data process_data(
    inputdata1,
    QUE_Mode,
    //AddressR,
    //AddressW, 
    R_W ,
    cen, 
    clk, 
    reset,
    Data_Out, 
    Que_Full,
    Que_Last,
    Que_Empty);  //reset, Que_Full, Que_Last, Que_Empty do not do anything yet

  clock MyClock(clk);
  initial
  begin
    $dumpfile("ALU.vcd");
    $dumpvars(0);

    $display("\t\t\t\t\t\t\t\t\tSIMULATION RESULT ");  
    $display("\t\ttime\tclk\t\t\tinputdata1\t\tData_Out\tQUE_Mode\t\tAddressR\t\tAddressW\t\tQue_Full\t\Que_Last\t\Que_Empty");
    $monitor($time, "\t%d\t%d\t%d\t%d",clk,inputdata1,Data_Out,QUE_Mode,AddressR,AddressW,Que_Full,Que_Last,Que_Empty);


    cen=1'b1;   //chip enabled 
    count = 0;
    R_W = 1'b0;   //write
    QUE_Mode = 1'b0; // QUE_Mode = 1'b0 => FIFO MODE 
    i=0;

    //input    
    for (i = 0; i < 128; i = i + 1) begin   //input   
                R_W=1'b0;   //write
                inputdata1 = i;
                #20;
           end  

    #10 
    for (i = 0; i < 128; i = i + 1) begin //output   
                #20; 
                R_W=1'b1;   //read  => output
                #20;
           end  
    $display("-------------- THE SIMULATION FINISHED ------------");  
    $finish; 
   end

endmodule


结果:

                            SIMULATION RESULT 
        time    clk         inputdata1      Data_Out    QUE_Mode        AddressR        AddressW         Que_Full   Que_Last    Que_Empty
AdrR=  0
AdrW=  0
AdrR=  0
AdrW=  1
                   0    0                      0                       x    0  z  z001
                   5    1                      0                       x    0  z  z001
AdrR=  0
AdrW=  2
                  10    0                      0                       x    0  z  z001
                  15    1                      0                       x    0  z  z001
AdrR=  0
AdrW=  3
                  20    0                      1                       x    0  z  z001
                  25    1                      1                       x    0  z  z001
AdrR=  0
AdrW=  4
                  30    0                      1                       x    0  z  z001
                  35    1                      1                       x    0  z  z001
AdrR=  0
AdrW=  5
                  40    0                      2                       x    0  z  z001
                  45    1                      2                       x    0  z  z001
AdrR=  0
AdrW=  6
                  50    0                      2                       x    0  z  z001
                  55    1                      2                       x    0  z  z001
AdrR=  0
AdrW=  7
                  60    0                      3                       x    0  z  z001
                  65    1                      3                       x    0  z  z001
AdrR=  0
AdrW=  8
                  70    0                      3                       x    0  z  z001
                  75    1                      3                       x    0  z  z001
AdrR=  0
AdrW=  9
                  80    0                      4                       x    0  z  z001
                  85    1                      4                       x    0  z  z001
AdrR=  0
AdrW= 10
                  90    0                      4                       x    0  z  z001
                  95    1                      4                       x    0  z  z001
AdrR=  0
AdrW= 11
                 100    0                      5                       x    0  z  z001
                 105    1                      5                       x    0  z  z001
AdrR=  0
AdrW= 12
                 110    0                      5                       x    0  z  z001
                 115    1                      5                       x    0  z  z001
AdrR=  0
AdrW= 13
                 120    0                      6                       x    0  z  z001
                 125    1                      6                       x    0  z  z001
AdrR=  0
AdrW= 14
                 130    0                      6                       x    0  z  z001
                 135    1                      6                       x    0  z  z001
......................


AdrR=121
AdrW=  0
                7630    0                    127                      60    0  z  z111
                7635    1                    127                      60    0  z  z111
AdrR=122
AdrW=  0
                7640    0                    127                      60    0  z  z111
                7645    1                    127                      60    0  z  z111
AdrR=123
AdrW=  0
                7650    0                    127                      61    0  z  z111
                7655    1                    127                      61    0  z  z111
AdrR=124
AdrW=  0
                7660    0                    127                      61    0  z  z111
                7665    1                    127                      61    0  z  z111
AdrR=125
AdrW=  0
                7670    0                    127                      62    0  z  z111
                7675    1                    127                      62    0  z  z111
AdrR=126
AdrW=  0
                7680    0                    127                      62    0  z  z111
                7685    1                    127                      62    0  z  z111
-------------- THE SIMULATION FINISHED ------------
AdrR=127
                7690    0                    127                      63    0  z  z111
Done


您需要以两倍的速度更改输入数据。将 #20 更改为 #10:

    //input    
    for (i = 0; i < 128; i = i + 1) begin   //input   
                R_W=1'b0;   //write
                inputdata1 = i;
//                #20;
                #10;
           end  

这会将 0 写入地址 0,将 1 写入地址 1,... 127 写入地址 127。


第一次写入是在时间=0 时写入地址0。但是,initialalways 块之间存在竞争条件,这可能导致在不同的模拟器上出现不同的行为。


日志文件显示 clk 的每个边上的输出,包括 posedge 和 negedge,因为您在 $monitor 语句中有 clk。但是,数据每个时钟周期仅更改一次(根据需要)。