我是否正确使用 $fscanf?想要使用值作为测试平台的输入

Am i using $fscanf correctly? Want to use values as an input to testbench

我正在尝试从 .txt 文件中读取 16384 个值,并将它们用作我的测试台中的值。我正在使用 $fopen 并尝试使用 $fscanf。我得到的错误是 'A' 是一个未打包的数组,即使没有这个错误,我也不确定我的方法是否正确。感谢您的帮助!

module tb2_fir;
// Inputs
reg Clk,rst_n;
reg signed [7:0] Xin;

// Outputs
wire signed [15:0] Yout;
reg signed [15:0]A[0:16383];
integer file,fd,i,file1,file2;


// Instantiate the Unit Under Test (UUT)
fir uut (
    .Clk(Clk), 
    .Xin(Xin), 
    .Yout(Yout),
    .rst_n(rst_n)
);

//Generate a clock with 10 ns clock period.
initial Clk = 0;
always #5 Clk =~Clk;
always @(negedge Clk)
begin
if(rst_n)
Xin<='0;
end

//Initialize and apply the inputs.
initial begin 
file=$fopen("data_1.txt","r");
file2=$fscanf(file,"%d",A);

for(i=0;i<16383;i=i+1)
@(negedge Clk) Xin=A[i];
$finish;
end   
endmodule

不,您不能通过一次调用 $fscanf 来读取数据来填充数组。为了从文件中读取所有数据(在注释中指定为 CSV),您需要一次循环一个元素:

reg signed [15:0] A[0:16383];
integer fd, i, scanRet;
...
initial begin
  fd = $fopen("data_1.txt", "r");
  
  i = 0;
  do begin
    // Note that if you have data like '0, 0, -10, 23, 1000, ...' in your file, you need the comma in the format string
    scanRet = $fscanf(fd, "%d,", A[i]);
    i = i + 1;
  end while (i < $size(A) && scanRet > 0);
  
  for (i = 0; i < $size(A); i = i + 1) begin
    @(negedge Clk) Xin = A[i]; // Note that you declare Xin as reg signed [7:0], while A[i] is reg signed [15:0]; are you sure you only want to truncate A[i] to a byte?
  end
  $finish;
end

请务必在格式字符串中说明文件中数据的实际格式。

要在一行代码中将文件读入内存样式变量,请使用 SystemVerilog 中的 $readmemh。

请参阅 SystemVerilog 规范 1800-2017 第 21.4 节从文件加载内存阵列数据。

// First example from the spec
// Define the memory style var
logic [7:0] mem[1:256];
// Read the file in   
initial $readmemh("mem.data", mem);

另请参阅: What is the function of $readmemh and $writememh in Verilog?.

或google搜索“SystemVerilog $readmemh”以获得更多解释和示例。

文本文件需要是十六进制的,因此请使用脚本 (Python?) 转换为二进制补码十六进制。也许可以修改文本文件的源代码(Matlab?)以写出二进制补码十六进制。 如果数据最初是在 Matlab 中生成的,则将带符号的数字写成二进制而不是二进制补码十六进制可能更容易。 SystemVerilog 将使用 $readmemb 以相同的方式提取它。例子见1800-2017同款。

不需要 $fopen 和循环。

$readmemh 适用于测试平台和 RTL。

reg signed [15:0]A[0:16383];

您将 A 实例化为一个包含 16384 个元素的未压缩数组,每个元素都是一个 16 位数组。 这里一切都很好。要使用$fscanf函数,你必须循环16384次来填充每个元素。

reg [16384:0] cnt = 16384;
//Initialize and apply the inputs.
initial begin 
file=$fopen("data_1.txt","r");
while (cnt>0) begin
    file2=$fscanf(file,"%d",A[cnt]);
    cnt = cnt - 1;
end

最后,您需要关闭文件以释放缓冲区。

$fclose(file);