Reading a file into Verilog - file-io

I am trying to read a text file which contains integer numbers. I have this txt file in project folder. I am trying to use this code but it is getting char due to $fgetc. Now what I want do is that how can I get integers from text?
Here is code:
integer file;
reg [31:0] char;
begin
file=$fopen ("Links.txt","rb");
char=$fgetc(file);
$display("char=%d", char);
end
PS: This is my first time, I am reading any file.

This solution was posted previously using SystemVerilog, edited verion here for Verilog compatible syntax.
integer data_file ; // file handler
integer scan_file ; // file handler
reg [21:0] captured_data;
`define NULL 0
initial begin
data_file = $fopen("data_file.dat", "r");
if (data_file == `NULL) begin
$display("data_file handle was NULL");
$finish;
end
end
always #(posedge clk) begin
scan_file = $fscanf(data_file, "%d\n", captured_data);
if (!$feof(data_file)) begin
//use captured_data as you would any other wire or reg value;
end
end

Related

reading a nibble from file in verilog

I need to read data from a file nibble by nibble (half byte) in verilog. I know I can read 8 bits using character but is there anyway of reading nibble?
The code I use for character reading is
reg [7:0] char1;
integer read_file;
initial begin
read_file = $fopen("D:\\signal.txt","rb");
char1 = $fgetc(read_file); // read a byte
end
is there anything else for reading nibble?
consider $fread.
reg [3:0] data;
integer rtn_val;
...
rtn_val = $fread(data, read_file);

Error (10170): expecting "<=", or "=", or "+=", or "-=", or "*=", or "/=", or "%=", or "&=", or "|=", or "^=", etc

module accumulator (
input [7:0] A ,
input reset,
input clk,
output reg carryout,
output reg overflow,
output reg [8:0] S,
output reg HEX0,
output reg HEX1,
output reg HEX2,
output reg HEX3
);
reg signA;
reg signS;
reg [7:0] magA;
reg [7:0] magS;
reg Alarger;
initial begin
S = 9'b000000000;
end
always_ff # (posedge clk, posedge reset) begin
if (reset) begin
S = 9'b000000000;
end
else begin
begin
signA <= A[7]; //Is A negative or positive
signS <= S[7];
S <= A + S;
end
if (signA == 1) begin //A is negative so magnitude is of 2s compliment
magA <= (~A[7:0] + 1'b1);
end
else begin
magA <= A;
end
if (signS == 1) begin //sum is negative so magnitude is of 2s compliment
magS <= (~S[7:0] + 1'b1);
end
else begin
magS <= S;
end
if (magA > magS) begin
Alarger <= 1'b1; //Magnitude of A is larger than magnitude of sum
end
else begin
Alarger <= 1'b0;
end
if ((signA == 1) & (Alarger == 1) & (S[7] == 0)) begin
overflow <= 1'b1;
end
else begin
overflow <= 1'b0;
end
if ((signS == 1) & (Alarger == 0) & (S[7] == 0)) begin
overflow <= 1'b1;
end
else begin
overflow <= 1'b0;
end
if ((signS == 1) & (signA == 1) & (S[7] == 0)) begin
overflow <= 1'b1;
end
else begin
overflow <= 1'b0;
end
if ((signS == 0) & (signA == 0) & (S[7] == 1)) begin
overflow <= 1'b1;
end
else begin
overflow <= 1'b0;
end
if (S[8] == 1) begin //carryout occurred
carryout <= 1'b1;
overflow <= 1'b0;
S <= 9'b000000000; //sum no longer valid
end
else begin
carryout <= 1'b0;
end
display_hex h1 //display of A
(
.bin (magA),
.hexl (HEX2),
.hexh (HEX3)
);
display_hex h2 //display of sum
(
.bin (S[7:0]),
.hexl (HEX0),
.hexh (HEX1)
);
end
end
endmodule
I am trying to make an accumulator that adds A (8 digit binary value that can be signed or unsigned) repeatedly to the sum. Once the sum is computed, then sum and A should display the value on 4 hex display LEDs (2 LEDs for A and 2 LEDs for sum). However, I am having a hard time getting it to compile. I have searched the error code and it seems like a general error for a syntax error and can have several meanings.
The error is the result of these two lines:
display_hex h1 //display of A
(
.bin (magA),
.hexl (HEX2),
.hexh (HEX3)
);
display_hex h2 //display of sum
(
.bin (S[7:0]),
.hexl (HEX0),
.hexh (HEX1)
);
Here, it appears you have a module named display_hex which converts an 8-bit value into the needed digits for a seven segment display. You are trying to use the module as if it were a function and modules are very much NOT functions. Modules in Verilog (or SystemVerilog as you are using, but the difference is really token at this point) can be though of as a group of hardware that takes in some inputs and spits out some outputs; and its important to note that they are static things. They either exist in the design or they do not; just like using ICs on a breadboard. The top module is the breadboard and the modules you declare under that module are components you are plugging into the board. The inputs and outputs are the various connections (pins) you must wire up to make everything work.
That said, always blocks (like the always_ff you are using) form a way of describing the logic and registers inside modules. Thus, you do thinks like assign logic/reg variables inside them to describe how the hardware behaves. If you look at your logic, you'll notice that the module declarations are dependent on reset; ie if reset is asserted, these modules wont exist, which doesnt make any sense. Electrical signals don't make entire ICs in a circuit disappear! Thus, you need to pull your module declaration out of your logical description of your acculumator, like so:
module accumulator (
...
);
...
display_hex h1 //display of A
(
.bin (magA),
.hexl (HEX2),
.hexh (HEX3)
);
display_hex h2 //display of sum
(
.bin (S[7:0]),
.hexl (HEX0),
.hexh (HEX1)
);
...
always_ff #(posedge clk, posedge reset) begin
// Your accumulator logic here
...
end
endmodule
Notice that the module declarations for the display_hex modules are stand alone, as I am declaring these modules exist, not dependence on anything!
However, there are a number of issues with your design besides that:
As you are using SystemVerilog constructs (always_ff), you should declare all of your variables type logic, not reg or left blank (ie, input clk should be input logic clk, reg signA should be logic signA). The logic type just makes everything easier, so use it :)
In your always_ff block, you do reset correctly except that the assignment should really be NBA (use S <= 9'b0;, not S = 9'b0; in the if (reset))
You use NBA inside your always_ff, which is correct, however, it appears you need to use these values right away in the following logic. This will not work as you expect, or at least it will not act within the same clock cycle. To fix this, youll need to decide what should be a register and what should just be values resulting from intermediate logic, then create a separate always_comb for the intermediate values.
I am making the assumption that the HEX variables are meant for seven segment displays, so they should probably declared at least [6:0] HEXn
I was not able to reproduce the exact error, but moving the instantiations of display_hex outside always_ff resolves the main issue:
module accumulator
(
/* ... */
);
// ...
always_ff # (posedge clk, posedge reset) begin
/* ... */
end
display_hex h1 (
/* ... */
);
display_hex h2 (
/* ... */
);
endmodule
Another thing: The code drives variable S from initial as well as always. This creates multiple drivers and the code will not compile. To fix this, remove the initial completely, you don't need it since S will be set to 0 when reset is asserted.
OR
You can move all the logic into the initial block; it'd look something like this (but this, most probably, won't synthesize):
initial begin
S = 0;
forever begin
wait #(posedge clock);
// Do stuff here ..
end
end

Pascal File Handling

I'm using free Pascal 2.6.4 and I created this code. It's a program that asks for number which represents line in file. Everything works except one thing. When I want to display 1. line it stops with "exitcode 217". Why?
Program FileTruncate;
uses
SysUtils;
label znova;
const
filename = 'C:\Users\KVIKY\Desktop\Pascal\Projects\FileHandling\test.txt';
var
myfile: text;
line: string;
counter:integer;
position:double;
begin
znova:
Writeln('Zadaj cislo riadku: ');
Readln(position);
if position=0 then exit;
if position>26 then exit;
Assign(myfile, filename);
Reset(myfile);
counter:=0;
Repeat
inc(counter);
readln(myfile);
until counter = position-1;
readln(myfile, line);
Close(myfile);
writeln(line);
Writeln('Stlacte enter pre pokracovanie.');
Writeln('Zadajte 0 pre ukoncenie programu.');
readln;
goto znova;
end.
Because when position is 1, your repeat-until condition will never be met (because your counter=1 and position-1 is zero, so counter = position-1 will never happen).
counter represents the line before the target, so...
Instead, you could initialize differently:
counter := -1
or, better, change your loop to a while-do:
while counter < position-1 do
because you have a readln within the loop

How to read a text file line by line in verilog?

I have a SREC file which is a simple text file and I want to read it line by line in verilog. How can I do that?
The following reads through a file, 1 line per clock cycle: expected data format is one decimal number per line.
integer data_file ; // file handler
integer scan_file ; // file handler
logic signed [21:0] captured_data;
`define NULL 0
initial begin
data_file = $fopen("data_file.dat", "r");
if (data_file == `NULL) begin
$display("data_file handle was NULL");
$finish;
end
end
always #(posedge clk) begin
scan_file = $fscanf(data_file, "%d\n", captured_data);
if (!$feof(data_file)) begin
//use captured_data as you would any other wire or reg value;
end
end
Thank you for the solution.
I modified it just a little to use 2 .txt file containing 32 HEX numbers on each row and found some difficulties on the way since I didn't understand what each line of code did. My findings were the following.
Just vars and regs declaration
////////I'm using inputs.txt and outputs.txt to read both lines at the same time
module Decryption_Top_Testbench;
////////TEXT DOC variables
integer file_outputs ; // var to see if file exists
integer scan_outputs ; // captured text handler
integer file_inputs ; // var to see if file exists
integer scan_inputs ; // captured text handler
//TXT
reg [127:0] captured_outputs; ///Actual text obtained from outputs.txt lines
reg [127:0] captured_inputs; ///Actual text obtained from inputs.txt lines
Opening both files
initial
begin
// TEXT FILE outputs///////////////////////
file_outputs = $fopen("C:/outputs.txt", "r"); //Opening text file
//you should use the full path if you don't want to get in the trouble
//of using environment vars
if (file_outputs == 0) begin // If outputs file is not found
$display("data_file handle was NULL"); //simulation monitor command
$finish;
end
// TEXT FILE inputs///////////////////////
file_inputs = $fopen("C:/inputs.txt", "r"); //Opening text file (inputs)
if (file_inputs == 0) begin //If inputs file is not found
$display("data_file handle was NULL");
$finish;
end
end
At this part, I will read line by line in HEX format and store it in "captured_outputs" register and "captured_inputs" register.
///Since I'm using it just to simulate I'm not interested on a clock pulse,
/// I want it to happen all at the same time with whatever comes first
always #(* )
begin
if (!$feof(file_outputs))
begin
///!$feof means if not reaching the end of file
///file_outputs is always returning a different number other than "0" if the doc
///has not ended. When reaching "0" it means the doc is over.
///Since both of my docs are the same length I'm only validating one of them
///but if you have different lenghts you should verify each doc you're reading
///
scan_inputs = $fscanf(file_inputs, "%h\n", captured_inputs); //Inputs Line text
scan_outputs = $fscanf(file_outputs, "%h\n", captured_outputs); //Outputs line text
$display ("Line :[inputs: %h _ outputs: %h ]" captured_inputs, captured_outputs);
// Displaying each line at the simulation monitor
///$fscanf means formatted text, $scanf would read text ignoring the format
/// %h\n means it should expect HEX numbers and the end of line character, that means
/// the line is over, but if you want to use a diff criteria
/// you can replace \n to whatever you may need
end
else
begin
$finish;
$fclose(file_outputs); //Closing files just in case to prevent wasting memory
$fclose(file_inputs);
end
end
I just wanted to contribute with something anybody who's starting to code in Verilog could understand and attach this great feature to his/her project.
Enjoy!

Verilog I/O reading a character

I seem to have some issues anytime I try anything with I/O for verilog. Modelsim either throws function not supported for certain functions or does nothing at all. I simply need to read a file character by character and send each bit through the port. Can anyone assist
module readFile(clk,reset,dEnable,dataOut,done);
parameter size = 4;
//to Comply with S-block rules which is a 4x4 array will multiply by
// size so row is the number of size bits wide
parameter bits = 8*size;
input clk,reset,dEnable;
output dataOut,done;
wire [1:0] dEnable;
reg dataOut,done;
reg [7:0] addr;
integer file;
reg [31:0] c;
reg eof;
always#(posedge clk)
begin
if(file == 0 && dEnable == 2'b10)begin
file = $fopen("test.kyle");
end
end
always#(posedge clk) begin
if(addr>=32 || done==1'b1)begin
c <= $fgetc(file);
// c <= $getc();
eof <= $feof(file);
addr <= 0;
end
end
always#(posedge clk)
begin
if(dEnable == 2'b10)begin
if($feof(file))
done <= 1'b1;
else
addr <= addr+1;
end
end
//done this way because blocking statements should not really be used
always#(addr)
begin:Access_Data
if(reset == 1'b0) begin
dataOut <= 1'bx;
file <= 0;
end
else if(addr<32)
dataOut <= c[31-addr];
end
endmodule
I would suggest reading the entire file at one time into an array, and then iterate over the array to output the values.
Here is a snippet of how to read bytes from a file into a SystemVerilog queue. If you need to stick to plain old Verilog you can do the same thing with a regular array.
reg [8:0] c;
byte q[$];
int i;
// Read file a char at a time
file = $fopen("filename", "r");
c = $fgetc(file);
while (c != 'h1ff) begin
q.push_back(c);
$display("Got char [%0d] 0x%0h", i++, c);
c = $fgetc(file);
end
Note that c is defined as a 9-bit reg. The reason for is that $fgetc will return -1 when it reaches the end of the file. In order to differentiate between EOF and a valid 0xFF you need this extra bit.
I'm not familiar with $feof and don't see it in the Verilog 2001 spec, so that may be something specific to Modelsim. Or it could be the source of the "function not supported."