reading a nibble from file in verilog - file-io

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);

Related

Reading a file into Verilog

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

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."

Trying to test if a bit is set in a char value

If have an array of char's pulled out of an NSData object with getBytes:range:
I want to test if a particular bit is set. I would assume I would do it with a bitwise AND but it doesn't seem to be working for me.
I have the following:
unsigned char firstBytes[3];
[data getBytes:&firstBytes range:range];
int bitIsSet = firstBytes[0] & 00100000;
if (bitIsSet) {
// Do Something
}
The value of firstBytes[0] is 48 (or '0' as an ASCII character). However bitIsSet always seems to be 0. I would imagine I am just doing something silly here, I am new to working on a bit level so maybe my logic is wrong.
If you put a 0 before a number you are saying it's expressed in octal representation.
00100000 actually means 32768 in decimal representation, 10000000 00000000 in binary representation.
Try
int bitIsSet = firstBytes[0] & 32;
or
int bitIsSet = firstBytes[0] & 0x20;

Reading Binary File

so I am trying to read a filesystem disk, which has been provided.
So, what I want to do is read the 1044 byte from the filesystem. What I am currently doing is the following:
if (fp = fopen("filesysFile-full", "r")) {
fseek(fp, 1044, SEEK_SET); //Goes to 1024th byte
int check[sizeof(char)*4]; //creates a buffer array 4 bytes long
fread(check, 1, 4, fp); //reads 4 bytes from the file
printf("%d",check); //prints
int close = fclose(fp);
if (close == 0) {
printf("Closed");
}
}
The value that check should be printing is 1. However I am getting negative values which keep changing everytime I run the file. I don't understand what I am doing wrong. Am I taking the right approach to reading bytes of the disk, and printing them.
What I basically want to do is read bytes of the disk, and read the values at certain bytes. Those bytes are fields which will help me understand the structure/format of the disk.
Any help would be appreciated.
Thank you.
This line:
int check[sizeof(char)*4];
allocates an array of 4 ints.
The type of check is therefore int*, so this line:
printf("%d",check);
prints the address of the array.
What you should do it allocate it as an int:
int check;
and then fread into it:
fread(&check, 1, sizeof(int), fp);
(This code, incidentally, assumes that int is 4 bytes.)
int check[sizeof(char)*4]; //creates a buffer array 4 bytes long
This is incorrect. You are creating an array of four integers, which are typically 32 bits each, and then when you printf("%d",check) you are printing the address of that array, which will probably change every time you run the program. I think what you want is this:
if (fp = fopen("filesysFile-full", "r")) {
fseek(fp, 1044, SEEK_SET); //Goes to 1024th byte
int check; //creates a buffer array the size of one integer
fread(&check, 1, sizeof(int), fp); //reads an integer (presumably 1) from the file
printf("%d",check); //prints
int close = fclose(fp);
if (close == 0) {
printf("Closed");
}
}
Note that instead of declaring an array of integers, you are declaring just one. Also note the change from fread(check, ...) to fread(&check, ...). The first parameter to fread is the address of the buffer (in this case, a single integer) into which you want to read the data.
Keep in mind that while integers are probably 32 bits long, this isn't guaranteed. Also, in most operating systems, integers are stored with the least significant byte first on the disk, so you will only read 1 if the data on the disk looks like this at byte 1044:
0x01 0x00 0x00 0x00
If it is the other way around, 0x00 00 00 01, that will be read as 16777216 (0x01000000).
If you want to read more than one integer, you can use an array as follows:
if (fp = fopen("filesysFile-full", "r")) {
fseek(fp, 1044, SEEK_SET); //Goes to 1024th byte
int check[10]; //creates a buffer of ten integers
fread(check, 10, sizeof(int), fp); //reads 10 integers into the array
for (int i = 0; i < 10; i++)
printf("%d ", check[i]); //prints
int close = fclose(fp);
if (close == 0) {
printf("Closed");
}
}
In this case, check (without brackets) is a pointer to the array, which is why I've changed the fread back to fread(check, ...).
Hope this helps!