...
Ishaan
Posted on 07 Jan 2024

Read and Write Files in Verilog

We can perform file system operation in Verilog HDL. We can write a file or read data from the file using Verilog HDL. We can use this to extract Verilog module output, get input test cases from the file or we can extract some more information which may be useful later for analysing the hardware better. We can do lots of things in Verilog HDL itself why we need this? Let's try to understand some of the usecase of Verilog filesystem.

A Verilog Module

A Verilog module is a piece a code which will be converted into hardware later. Before hardware implementation, the Verilog module needs to be tested Well. The failure of the hardware in later stage can be very problematic because we can not update the hardware like we can in the case of software updates. Let's create a simple adder module in Verilog and test it.

module adder(
    input [3:0]a,b,
    output [4:0]sum,
    output cout
    );

assign sum = a + b;

endmodule

The above Verilog code generates a 4-bit adder. It is very simple code, output is addition of the inputs a and b. Do we really needs to test this module? You might say we should test this or should not. But let's test this Verilog module.

Testbench - Write File

We needs two 4-bit inputs, A and B and let's say we needs to check all the inputs and respective output. We can write verilog testbench as follows:

module adder_tb();
    reg [3:0]A,B;
    wire [4:0]sum;

adder uut(A,B,sum,cout);

integer i , j;

initial begin
A = 0;
B = 0;
for (i = 0; i < 16; i = i+1)
    for(j = 0; j < 16; j = j + 1) begin
        #10
        A = i;
        B = j;
    end
end

endmodule

The above testbench has lots of testcases and we can't verify this manually checking each input and output. Let's the programming language get this job done.

Now we will extract the inputs and the respective outputs to a text file, and we'll analyze the output dump with some programming langulage say Python. But why? Can't we do same thing with Verilog? The answer is yes but, just for the sake of the learning, let's forget about this.

Like C/C++ filesystem, we can use Verilog function to read and write the file. Below are some Verilog functions we can use to access the filesystem.

  • $fopen() -- A file is created using this function
  • $fclose() -- The file can be closed using this function
  • $fdisplay() -- It writes the respective file with the data we provide

module adder_tb();
    reg [3:0]A,B;
    wire [4:0]sum;

adder uut(A,B,sum,cout);

integer i , j;
integer file_A, file_B, file_sum;

initial begin
file_A = $fopen("output_A.txt", "w");
file_B = $fopen("output_B.txt", "w");
file_sum = $fopen("output_sum.txt", "w");
A = 0;
B = 0;
for (i = 0; i < 16; i = i+1)
    for(j = 0; j < 16; j = j + 1) begin
        #10
        A = i;
        B = j;
        $fwrite(file_A,"%d\n", A);
        $fwrite(file_B,"%d\n", B);
        $fwrite(file_sum,"%d\n", sum);
    end
$fclose(file_A);
$fclose(file_B);
$fclose(file_sum);
end

endmodule

The above Verilog testbench generates three files which contains inputs A, B and output sum. Ndw we can read these files and test if the module has generated expected output or not. The Verilog module is simple enough and we don't have to perform these complicated things but note that the Verilog module can be so much complicated and we can use this technique to test the module.

Testbench - Read File

In above testbench, we extracted the inputs and outputs, do we really needs to check all the inputs and output? No right? we can give some random inputs and check if it generating the expected output out not. Instead of giving 256 testcases (in our case), we can give let's say 10 testcases and check the expected output. This will significantly save the testing time. Let's generate two files which consists of inputs A and B. The inputs are genreated randomly but you may have some program which may generate the right minimum testcases to give it to the Verilog module which test the module efficiently.

Let's say we have two files which the following contentes which are the ten random testcases.

file_A.txt | file_b.txt
_______________________
0          |          0 
2          |          5 
5          |          6
9          |          1
F          |          1
F          |          F 
4          |          7 
8          |          9 
1          |          1
5          |          0
_______________________

Let's write Verilog testbench which reads this testcases, pass the test cases to the Verilog Module and check the output if is expected output or not.

module adder_tb();
    reg [3:0]A,B;
    wire [4:0]sum;

adder uut(A,B,sum,cout);

reg [3:0]temp_A[0:9];
reg [3:0]temp_B[0:9];

integer i;

initial begin
$readmemh("file_A.txt", temp_A);
$readmemh("file_B.txt", temp_B);

for (i = 0; i < 16; i = i+1)
    #10
    A = temp_A[i];
    B = temp_B[i];
end

endmodule

The above Verilog code reads the 10 testcases and store that testcases in the two temporary memory temp_A and temp_B. Now we can access the memory using the address of the memory. The above testcase has very few testcases and we can analyse this using the waveform. If the testcase is large, we can use the first method the test the Verilog module.

Learn Verilog HDL

Click like if you found this useful

Add Comment

* Required information
1000

Comments

No comments yet. Be the first!