file read using fgetc adds FF at the end - system-verilog

I'm reading a file using fgetc. File reading starts at an offset.At the end I see 8'hFF getting appended at the end of file.I'm expecting 6 bytes in the file but see 7 in them.I'm not sure why this is happening. Any ideas?
Below is my code:
module file_read();
integer fd,fd1,file_char,status;
logic [7:0] captured_data;
initial begin
fd = $fopen("input_file", "rb");
fd1 =$fopen("write_file","w");
status=$fseek(fd,1872,0);
assert (status);
// while ($fgetc(fd) != `EOF) begin
while (!$feof(fd)) begin
file_char=$fgetc(fd);
$display("file char is %h",file_char);
end
end // initial begin
Below are the file contents(in hex):
last line of input_file(total file size =1878):
0000750: 0000 1567 d48d ...g..
write_file:
0000000: 0000 1567 d48d ff ...g...
Thanks!

The reason you are getting the extra 'hff at the end of the written file is due to how $feof (or generally the foef C function) works. Simply put, it doesn't check if the next read is off the end of the file but if the previous read read off the end of the file. So, if you are reading character by character (byte by byte) using $fgetc, $feof will only return true once $fgetc reads off the end of the file, and returns EOF itself (ie, -1 or 'hff if converted to logic [7:0]). You should be checking for this error condition each time you read a byte, something like this:
integer fd, ch;
...
fd = $fopen("file.bin", "rb");
...
while ((ch = $fgetc(fd)) != -1) begin
$display(ch);
end

Related

stm32f4 fatfs f_write whitemarks

Im struggling with fatfs on stm32f4. With no problem i can mount, create file and write on it by : char my_data[]="hello world" and in windows file shows normally but when i try use code as loger :
float bmp180Pressure=1000.1;
char presur_1[6];//bufor znakow do konwersji
sprintf(presur_1,"%0.1f",bmp180Pressure);
char new_line[]="\n\r";
if(f_mount(&myFat, SDPath, 1)== FR_OK)
{
f_open(&myFile, "dane.txt", FA_READ|FA_WRITE);
f_lseek(&myFile, f_size(&myFile));//sets end of data
f_write(&myFile, presur_1, 6, &byteCount);
f_write(&myFile, new_line,4, &byteCount);
f_close(&myFile);
HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_15);
}
When i was read from computer i have :top : notepad ++ buttom :windows notepad
There are at least two problems in your code:
The string for the number is too short. C strings are terminated with a null byte. So presur_1 needs to be at least 7 bytes long (6 for the number and 1 for the null byte). Since it's only 6 bytes long, sprintf will write beyond the allocated length and destroy some other data.
The string for the newline is initialized with a string of 2 characters (plus the null byte). However, you write 4 characters to the file. So in addition to the newline, a NUL character and a garbage byte will end up in the file.
The fixed code looks like this:
float bmp180Pressure = 1000.1;
char presur_1[20];//bufor znakow do konwersji
int presur_1_len = sprintf(presur_1,"%0.1f\n\r",bmp180Pressure);
if(f_mount(&myFat, SDPath, 1)== FR_OK)
{
f_open(&myFile, "dane.txt", FA_READ|FA_WRITE);
f_lseek(&myFile, f_size(&myFile));//sets end of data
f_write(&myFile, presur_1, presur_1_len, &byteCount);
f_close(&myFile);
HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_15);
}

Reading data only when present

I'm trying to read the data from the COM3 port.
I'm using this code:
in = fscanf(s);
if(in == 'A')
fclose(s);
break;
end
The problem is that when no data is sent to the com3 port, the fscanf() will wait for a certain time interval and then give a timeout.
Is there a way to read data only when it is present?
Read only when data present
You can read out the BytesAvailable-property of the serial object s to know how many bytes are in the buffer ready to be read:
bytes = get(s,'BytesAvailable'); % using getter-function
bytes = s.BytesAvailable; % using object-oriented-addressing
Then you can check the value of bytes to match your criteria. Assuming a char is 1 byte, then you can check for this easily before reading the buffer.
if (bytes >= 1)
in = fscanf(s);
% do the handling of 'in' here
end
Minimize the time to wait
You can manually set the Timeout-property of the serial object s to a lower value to continue execution earlier as the default timeout.
set(s,'Timeout',1); % sets timeout to 1 second (default is 10 seconds)
Most likely you will get the following warning:
Unsuccessful read: A timeout occurred before the Terminator was
reached..
It can be suppressed by executing the following command before fscanf.
warning('off','MATLAB:serial:fscanf:unsuccessfulRead');
Here is an example:
s = serial('COM3');
set(s,'Timeout',1); % sets timeout to 1 second (default is 10 seconds)
fopen(s);
warning('off','MATLAB:serial:fscanf:unsuccessfulRead');
in = fscanf(s);
warning('on','MATLAB:serial:fscanf:unsuccessfulRead');
if(in == 'A')
fclose(s);
break;
end

Not understanding types in Verilog

I am trying to make a block for an 8-bit multiplier, and the testbench is giving me a result that basically says that I don't know what I'm doing with my wires and regs. To make this easier to answer, I'm going to display my code, and then the parts that I think are important:
module multiplier_result(
input ADD_cmd,
input LOAD_cmd,
input SHIFT_cmd,
input reset,
input [7:0] B_in,
input [7:0] Add_out,
input cout,
output wire [7:0] RB,
output wire [15:0] RC,
output wire [8:0] temp_reg,
output wire LSB
);
wire [8:0] from_mux;
reg[16:0] balreg;
reg tempadd;
//assign the outputs. all combinational
assign RB = balreg[15:8];
assign RC = balreg[15:0];
assign LSB = balreg[0];
assign temp_reg = balreg[16:8];
mux_9 mux(
.sel(~ADD_cmd),
.Add_out(Add_out),
.cout(cout),
.mux_out(from_mux),
.temp_reg(temp_reg)
);
always # (*) begin
if(reset) begin
balreg[16:0] = 17'd0;
tempadd = 1'b0;
end
else
begin
if(LOAD_cmd)
begin
balreg[16:8] = 9'b000000000;
balreg[7:0] = B_in;
end
if(SHIFT_cmd)
begin
balreg[16:8] = from_mux;
balreg = balreg >> 1;
end
end
end
endmodule
Now, here is what's troubling me:
Here I'm assigning wires to different bits of the balreg register (in black). What is going on in my head (please excuse my paint skills):
But for some reason, LSB gets what it's supposed to, while RB and RC get high impedance. Here is the simulate result, followed by the code I used (just a simple test case)
module multiplier_result_tb(
);
reg ADD_cmd;
reg LOAD_cmd;
reg SHIFT_cmd;
reg reset;
reg [7:0] B_in;
reg [8:0] Add_out;
wire [7:0] RB;
wire [15:0] RC;
wire [8:0] temp_reg; //size 9
wire LSB;
multiplier_result dut(ADD_cmd,LOAD_cmd,SHIFT_cmd,reset,B_in,Add_out,RB,RC,temp_reg,LSB);
initial begin
LOAD_cmd = 0;
#10;
LOAD_cmd = 1;
reset = 0;
B_in = 8'b00001010;
Add_out = 9'd0;
ADD_cmd = 0;
SHIFT_cmd = 0;
end
endmodule
I'm not following these results at all. The balreg register is all set up, so the RB and RC wires MUST be defined, but according to the simulation, they are high impedance.
The only conclusion that I get at, is that I really don't know what's going on with the types (the model I had in my had worked for me so far).
Any help, ideas, tips are much appreciated.
You only connected 10 of the 11 ports of the dut. Didn't you get a warning? You are making connections by position, not by name. You connected RB to input cout. You need to drive cout in your testbench.
Another way to make connections is by name. This is more verbose, but it can make your code clearer:
multiplier_result dut (
// Inputs:
.ADD_cmd (ADD_cmd),
.Add_out (Add_out),
.B_in (B_in),
.LOAD_cmd (LOAD_cmd),
.SHIFT_cmd (SHIFT_cmd),
.cout (cout),
.reset (reset),
// Outputs:
.LSB (LSB),
.RB (RB),
.RC (RC),
.temp_reg (temp_reg)
);

How to make string input in Assembly language?

Please, does anybody know how to code string input in assembly language? I'm using int 21 to display and input characters.
You can use function 0Ah to read buffered input. Given a string buffer in ds:dx it reads a string of up to length 255. The buffer layout is:
Byte 0 String length (0-255)
Byte 1 Bytes read (0-255, filled by DOS on return)
Bytes 2-..Length+2 (The character string including newline as read by DOS).
An example of a small COM file that reads a string and then echos it back to the user:
org 0x100
start:
push cs
pop ds ; COM file, ds = cs
mov ah, 0x0A ; Function 0Ah Buffered input
mov dx, string_buf ; ds:dx points to string buffer
int 0x21
movzx si, byte [string_buf+1] ; get number of chars read
mov dx, string_buf + 2 ; start of actual string
add si, dx ; si points to string + number of chars read
mov byte [si], '$' ; Terminate string
mov ah, 0x09 ; Function 09h Print character string
int 0x21 ; ds:dx points to string
; Exit
mov ax, 0x4c00
int 0x21
string_buf:
db 255 ; size of buffer in characters
db 0 ; filled by DOS with actual size
times 255 db 0 ; actual string
Note that it will overwrite the input line (and it thus might not look the program is doing anything!)
Alternatively you can use function 01h and read the characters yourself in a loop. Something like this (note it will overflow later buffers if more than 255 characters are entered):
org 0x100
start:
push cs
pop ax
mov ds, ax
mov es, ax; make sure ds = es = cs
mov di, string ; es:di points to string
cld ; clear direction flag (so stosb incremements rather than decrements)
read_loop:
mov ah, 0x01 ; Function 01h Read character from stdin with echo
int 0x21
cmp al, 0x0D ; character is carriage return?
je read_done ; yes? exit the loop
stosb ; store the character at es:di and increment di
jmp read_loop ; loop again
read_done:
mov al, '$'
stosb ; 'Make sure the string is '$' terminated
mov dx, string ; ds:dx points to string
mov ah, 0x09 ; Function 09h Print character string
int 0x21
; Exit
mov ax, 0x4c00
int 0x21
string:
times 255 db 0 ; reserve room for 255 characters
A string is just a series of characters, so you can use your int 21 code inside of a loop to get a string, one character at a time. Create a label in the data segment to hold your string, and each time you read a character, copy it to that label (incrementing an offset each time so your characters get stored sequentially). Stop looping when a certain character is read (perhaps enter).
Doing all this manually is tedious (think about how backspace will work) but you can do it. Alternatively, you can link against stdio, stdlib, etc. and call library functions to do much of the work for you.

Need help identifying and computing a number representation

I need help identifying the following number format.
For example, the following number format in MIB:
0x94 0x78 = 2680
0x94 0x78 in binary: [1001 0100] [0111 1000]
It seems that if the MSB is 1, it means another character follows it. And if it is 0, it is the end of the number.
So the value 2680 is [001 0100] [111 1000], formatted properly is [0000 1010] [0111 1000]
What is this number format called and what's a good way for computing this besides bit manipulation and shifting to a larger unsigned integer?
I have seen this called either 7bhm (7-bit has-more) or VLQ (variable length quantity); see http://en.wikipedia.org/wiki/Variable-length_quantity
This is stored big-endian (most significant byte first), as opposed to the C# BinaryReader.Read7BitEncodedInt method described at Encoding an integer in 7-bit format of C# BinaryReader.ReadString
I am not aware of any method of decoding other than bit manipulation.
Sample PHP code can be found at
http://php.net/manual/en/function.intval.php#62613
or in Python I would do something like
def encode_7bhm(i):
o = [ chr(i & 0x7f) ]
i /= 128
while i > 0:
o.insert(0, chr(0x80 | (i & 0x7f)))
i /= 128
return ''.join(o)
def decode_7bhm(s):
o = 0
for i in range(len(s)):
v = ord(s[i])
o = 128*o + (v & 0x7f)
if v & 0x80 == 0:
# found end of encoded value
break
else:
# out of string, and end not found - error!
raise TypeError
return o