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
The problem is that you are driving the same myTB
testbench signal, inStream
, from 2 sources:
initial
block with procedural assignments like: inStream = 0.0;
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.