ModelSim Memory Content import from Intel Hex

Hello,

I'm looking for an import utility from Intel Hex to the supported formats of ModelSim, e. g. MTI or Verilog (Hex).

Many thanks in advance Udo

Reply to
Udo
Loading thread data ...

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

formatting link
//

// 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

formatting link
||||||||||| 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

Reply to
Xilinx user

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.