"Udo" <WeikEngOff@aol.com> wrote in message
news:1180024409.822436.36850@h2g2000hsg.googlegroups.com...
> Hello,
>
> I'm looking for an import utility from Intel Hex to the supported
> formats of ModelSim,
> e. g. MTI or Verilog (Hex).
Well, here's a Systemverilog program to read HEX-80 format into a reg[]
array. Are there different variations of the HEX format? I wrote this
one for Keil's C51 (8051) compiler. You can modify it for your needs:
//
//
// Author: R***** L***
//
// Filename: keil_hex2bin.sv
//
// Date of Creation: Sun May 20 12:14:48 2007
//
// Version: $Revision: 1.1 $
//
// Date of Latest Version: $Date: 2007/05/20 12:14:48 $
//
//
// Description: This is a utility to convert Keil-C51's HEX-80
(*.hex)
// output into a $readmemb compatible ASCII-file.
// For HEX-80 info, see
http://www.keil.com/support/docs/1584.htm
//
// requires Modelsim 6.1g or later (Systemverilog 3.1a)
///////////////////////////////////////////////////////////////////////////////
//
//
// This library is free software; you can redistribute it and/or
//
// modify it under the terms of the GNU Lesser General Public
//
// License as published by the Free Software Foundation; either
//
// version 2.1 of the License, or (at your option) any later version.
//
//
//
// This library is distributed in the hope that it will be useful,
//
// but WITHOUT ANY WARRANTY; without even the implied warranty of
//
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
//
// Lesser General Public License for more details.
//
//
//
// Full details of the license can be found in the file LGPL.TXT.
//
//
//
// You should have received a copy of the GNU Lesser General Public
//
// License along with this library; if not, write to the Free Software
//
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
//
//
///////////////////////////////////////////////////////////////////////////////
/*
from http://www.keil.com/support/docs/1584.htm
:10246200464C5549442050524F46494C4500464C33
||||||||||| CC->Checksum
|||||||||DD->Data
|||||||TT->Record Type
|||AAAA->Address
|LL->Record Length
:->Colon
*/
`ifndef INFILENAME
`define INFILENAME "keil.hex"
`endif
module keil_hex2bin();
parameter string infilename = `INFILENAME; // default input filename
localparam int BUFFER_SIZE = 65536; // # address-locations
localparam int LINE_SIZE = 500; // max# bytes per textline
bit [7:0] memory [0:BUFFER_SIZE-1];
typedef struct {
bit flag_eof; // end-of-file
bit flag_colon; // TRUE==valid record, FALSE==no entry
int length; // # bytes in entry
bit [15:0] address;
bit [7:0] checksum;
bit [7:0] record_type;
bit [7:0] data [0:LINE_SIZE-1]; // data
} t_hex80entry;
int fh_in = 0;
int fh_bin_out = 0;
int fh_hex_out = 0; // FILE-pointers
///////////////////////////////////////////////////////////////////////////////
function void open_file( input string name );
// make sure we aren't in the middle of processing another file
assert ( fh_in == 0 ) else
$fatal( 1, "%m(): a file is already open for reading!", name );
fh_in = $fopen( name, "r" );
assert ( fh_in != 0 )
$info( "%m(): initiating read of '%0s'", name ); else
$fatal( 1, "%m(): $fopen( \"%0s\", \"r\" ) failed!", name );
endfunction : open_file
///////////////////////////////////////////////////////////////////////////////
function void close_file( int fhandle );
// make sure we aren't in the middle of processing another file
assert ( fhandle != 0 )
$info( "%m(): closing file-handle 'h%h", fhandle ); else
$error( "%m(): no file was open for reading!" );
$fclose( fhandle );
endfunction : close_file
///////////////////////////////////////////////////////////////////////////////
function t_hex80entry parse_line( input string line );
int error;
int data_byte_count;
bit [7:0] temp_byte, sum;
string phrase; // substring of line[]
int length; // # bytes in entry
bit [15:0] address;
bit [7:0] record_type;
bit [7:0] checksum;
begin
parse_line = '{default:'0};
if ( line.len() < 10 )
return parse_line; // too short, can't possibly be a valid entry
else if ( line[0] !== ":" )
return parse_line; // no starting colon
else if ( line == ":00000001FF\n" )
begin
parse_line.flag_eof = 1'b1; // got end of file!
return parse_line;
end
/* get first few fields
:LLAAAATT
|||||||TT->Record Type
|||AAAA->Address
|LL->Record Length
*/
// if we made it this far, entry appears to be valid!
parse_line.flag_colon = 1'b1;
/*
error = 0;
phrase = line.substr( 1, 2 );
error += $sscanf( phrase, "%02h", parse_line.length );
phrase = line.substr( 3, 6 );
error += $sscanf( phrase, "%04h", parse_line.address );
phrase = line.substr( 7, 8 );
error += $sscanf( phrase, "%02h", parse_line.record_type );
*/
// Modelsim 6.1g workaround - $sscanf can't output to struct/union
error = $sscanf( line, ":%02h%04h%02h", length,
address, record_type );
parse_line.length = length;
parse_line.address = address;
parse_line.record_type = record_type;
// error = $sscanf( line, ":%02h%04h%02h", parse_line.length,
// parse_line.address, parse_line.record_type );
assert ( error == 3 ) else begin
$error("%m(): '%0s' (%0d)", line, error );
parse_line.flag_colon = 1'b0;
end
// now get checksum (last 2 chars of line[])
phrase = line.substr( line.len()-3, line.len()-2 );
// error = $sscanf( phrase, "%02h", parse_line.checksum );
error = $sscanf( phrase, "%02h", checksum );
parse_line.checksum = checksum;
assert ( error == 1 ) else begin
$error("%m(): checksum: '%0s' (%0d)", phrase, error );
parse_line.flag_colon = 1'b0;
end
// now extract the data-payload
error = 0;
for ( int i = 0; i < data_byte_count; ++i ) begin
phrase = line.substr( (i*2)+9, (i*2)+10 );
error += $sscanf( phrase, "%02h", parse_line.data[i] );
end
assert ( error == data_byte_count ) else begin
$error("%m(): DATA: '%0s' (%0d!=%0d)", phrase, error,
data_byte_count );
parse_line.flag_colon = 1'b0;
end
// finally, validate the checksum
sum = 0;
error = 0;
for ( int i = 1; i < (line.len()-1); i=i+2 ) begin
phrase = line.substr( i, i+1 );
error += $sscanf( phrase, "%02h", temp_byte );
sum += temp_byte;
end
assert ( sum == 0 ) else
$error( "%m(): Checksum (%0d bytes) mismatch (%h!=%h)", error, sum,
parse_line.checksum );
end
endfunction : parse_line
///////////////////////////////////////////////////////////////////////////////
task create_file( output int fhandle, input string filename );
assert ( fhandle == 0 ) else begin
$warning( "%m( '%0s' ): fhandle(0x%h) is already in use, overwriting!",
filename, fhandle );
$fclose( fhandle );
end
fhandle = $fopen( filename, "w" );
assert ( fhandle != 0 )
$info( "%m(): creating file '%0s'", filename ); else
$fatal( 1, "%m(): could not create file '%0s'!", filename );
endtask : create_file
initial begin : main
t_hex80entry h;
int n;
string line;
string outfilename_bin, outfilename_hex;
// standalone mode
// assume the last 5-letters of the filename are '.xyz'
// (If that's not the case, then we'll accidentally truncate the
filename!)
outfilename_bin = infilename.substr(0, infilename.len()-5) ;
outfilename_hex = infilename.substr(0, infilename.len()-5) ;
outfilename_bin = {outfilename_bin, ".dua"}; // $readmemb-compat output
outfilename_hex = {outfilename_bin, ".dhx"}; // $readmemh-compat output
open_file( infilename );
n = $fgets( line, fh_in );
while ( n > 0 ) begin
h = parse_line( line );
assert ( n < (LINE_SIZE*2) ) else
$fatal( 1, "Line exceeded internal line-buffer size (%0d chars) !",
LINE_SIZE*2 );
if ( h.flag_colon && (!h.flag_eof) )
$display( "0x%h: %0d bytes, CHK=%h", h.address, h.length,
h.checksum );
n = $fgets( line, fh_in );
// copy entry-data to internal-memory
for ( int j = 0; j < h.length; ++j )
memory[ h.address+j ] = h.data[j];
end
close_file( fh_in );
// Create and dump the contents to $readmemb and readmemh files
create_file( fh_bin_out, outfilename_bin );
create_file( fh_hex_out, outfilename_hex );
for ( int i = 0; i < BUFFER_SIZE; ++i ) begin
$fdisplay( fh_bin_out, "%08b", memory[ i ] );
$fdisplay( fh_hex_out, "%02h", memory[ i ] );
end
$fclose( fh_bin_out );
$fclose( fh_hex_out );
$finish;
end : main
endmodule : keil_hex2bin
|