filtersystem-verilog

Error Illegal combination of driver and procedural assignment to variable inStream detected


I'm trying to implement a FIR filter using SystemVerilog, but I came up with this error when I try to simulate it:

Illegal combination of driver and procedural assignment to variable inStream detected (procedural assignment found in initial block at line 22 in file ./testbench.sv).

Can someone help me fix this? I'm quite new to SystemVerilog.

The filter module is this:

module lpf900 (input real inStream, output real outStream);
  
  localparam int nCampioni = 101;
  
  real campioni[0:nCampioni-1] = '{0.0018, 0.0011, 0.0002, -0.0006, -0.0015, -0.0025, -0.0034, -0.0043, -0.0051, -0.0060, -0.0067, -0.0074, -0.0080, -0.0084, -0.0088, -0.0090, -0.0090, -0.0089, -0.0087, -0.0082, -0.0076, -0.0068, -0.0059, -0.0047, -0.0034, -0.0019, -0.0002, 0.0016, 0.0035, 0.0056, 0.0077, 0.0100, 0.0123, 0.0147, 0.0171, 0.0195, 0.0219, 0.0242, 0.0265, 0.0287, 0.0308, 0.0327, 0.0346, 0.0362, 0.0377, 0.0389, 0.0400, 0.0408, 0.0414, 0.0418, 0.0419, 0.0418, 0.0414, 0.0408, 0.0400, 0.0389, 0.0377, 0.0362, 0.0346, 0.0327, 0.0308, 0.0287, 0.0265, 0.0242, 0.0219, 0.0195, 0.0171, 0.0147, 0.0123, 0.0100, 0.0077, 0.0056, 0.0035, 0.0016, -0.0002, -0.0019, -0.0034, -0.0047, -0.0059, -0.0068, -0.0076, -0.0082, -0.0087, -0.0089, -0.0090, -0.0090, -0.0088, -0.0084, -0.0080, -0.0074, -0.0067, -0.0060, -0.0051, -0.0043, -0.0034, -0.0025, -0.0015, -0.0006, 0.0002, 0.0011, 0.0018};
  real firMemory [0:nCampioni-1];
  
  function void initFirMemory();
    /* the finite memory is initialized at all-zeros */
    for(int j = 0; j < nCampioni; j++) begin
      firMemory[j] = 0.0;
    end
  endfunction
  
  function void shiftFirMemory(input real newSample);
    for(int j = nCampioni-1; j > 0; j--) begin
      firMemory[j] = firMemory[j-1];
    end
    firMemory[0] = newSample;
  endfunction
  
  function real computeSingleOut();
    real res;
    res = 0;
    for(int j = 0; j < nCampioni; j++) begin
      res += firMemory[j] * campioni[j];
    end
    return res;
  endfunction
  
  initial begin //initialize the result to all-zeros at time zero
    initFirMemory();
  end
  
  always @(inStream) begin
    shiftFirMemory(inStream);
    outStream = computeSingleOut();
  end
  
endmodule

The code also include this program to elaborate both left and right channels:

program stimulus #(localparam qBits = 8)
  (input logic clk, output real inStream, input real outStream);
  
  localparam int nChannels = 2;
  
  import soundPackage::*;
  
  typedef logic signed [qBits-1:0] qType;
  typedef qType queValueType_q[0:nChannels-1];
  typedef real queValueType_r[0:nChannels-1];
  queValueType_q myQueue_q[$];
  queValueType_r myQueue_r[$];
  real myChannel[$];

  soundErrorType myError;
  
  soundSequence #(.nChannels(nChannels), .qBits(8), .qLSB(-15)) inSequence;
  soundSequence #(.nChannels(1), .qBits(8), .qLSB(-15)) outSequence;
  
  clocking myCk @ (posedge clk);
    default input #1step output #1ps;
    input outStream;
    output inStream;
  endclocking
  
  task acquireoutStream();
    real myVal[0:0];
    myVal[0] = myCk.outStream; // pre-clock
    outSequence.putSample_r(myVal);
  endtask
  
  initial begin
    inSequence = new;
    outSequence = new;
    
    //elaborate left channel
    $display("[%0d] elaborating channel 0 of read sequence",$time);
    inSequence.getChannel_r(myChannel, 0);
    $display("[%0d] the channel has %d values",$time,myChannel.size);
    void'(outSequence.cleanSequence());
    myCk.inStream <= myChannel.pop_front();
    @(myCk);
    while (myChannel.size>0) begin
      myCk.inStream <= myChannel.pop_front();
      acquireoutStream;
      @(myCk);
    end
    acquireoutStream;
    void'(outSequence.storeToFile(.fname("outStream_r_0.txt"), .RnQ(1)));
    void'(outSequence.storeToFile(.fname("outStream_q_0.txt"), .RnQ(0)));
    
    //elaborate right channel
    $display("[%0d] elaborating channel 1 of read sequence",$time);
    inSequence.getChannel_r(myChannel, 1);
    $display("[%0d] the channel has %d values",$time,myChannel.size);
    void'(outSequence.cleanSequence());
    myCk.inStream <= myChannel.pop_front();
    @(myCk);
    while (myChannel.size>0) begin
      myCk.inStream <= myChannel.pop_front();
      acquireoutStream;
      @(myCk);
    end
    acquireoutStream;
    void'(outSequence.storeToFile(.fname("outStream_r_1.txt"), .RnQ(1)));
    void'(outSequence.storeToFile(.fname("outStream_q_1.txt"), .RnQ(0)));
  end

endprogram

I tried to test this code with the following testbench:

`include "packages.sv"
/*the packages must be loaded before this point*/
`include "programs.sv"

module myTB();

  real inStream, outStream;
  
  logic clk = 1'b0;
  
  always #5 clk = ~clk;
  
  stimulus myStim (clk, inStream, outStream); 
  lpf900 mylpf900 (inStream, outStream);

  initial begin
    $dumpfile("dump.vcd"); $dumpvars;
  end
  
  initial begin
    // Inizializzazione
    clk = 0;
    inStream = 0.0;
  
  
     // Applicazione dei test
    $display("Inizio test");
    
    // Generazione di un segnale di ingresso
    // Simuliamo una sequenza di campioni per testare il filtro FIR
    
    #10 inStream = 0.2;
    #10 inStream = 0.4;
    #10 inStream = 0.6;
    #10 inStream = 0.8;
    #10 inStream = 1.0;
    #10 inStream = 0.8;
    #10 inStream = 0.6;
    #10 inStream = 0.4;
    #10 inStream = 0.2;
    #10 inStream = 0.0;
    
    // Continuazione dei test
    #10 inStream = -0.2;
    #10 inStream = -0.4;
    #10 inStream = -0.6;
    #10 inStream = -0.8;
    #10 inStream = -1.0;

    // Fine del test
    #10;
    $display("Fine test");
    $finish; // Terminare la simulazione
  end

  // Monitoraggio dei segnali
  initial begin
    $monitor("Time = %0t, inStream = %f, outStream = %f", $time, inStream, outStream);
  end
endmodule

Solution

  • The problem is that you are driving the same myTB testbench signal, inStream, from 2 sources:

    1. In the initial block with procedural assignments like: inStream = 0.0;
    2. From the program instance output port driver inStream

    You can not drive it from 2 sources. You must pick only one: either the testbench or the program instance.