I'm trying to read an intel .hex file using the following VHDL code snippet. My synthesizer is having a problem with the part of the code that is supposed to check for and discard the ':' character at the start of a line. The synthesis tool gives this error "Call to procedure without body" (line marked with comment). I have never seen this error and don't know what it means. Is there a solution for this error (or an alternate way to discard the ':' character)?
function Load_Data(constant x: in integer) return ROM_Data is
use std.textio.all;
use ieee.std_logic_textio.all;
file ROMFILE: TEXT open READ_MODE is "IIU_Code.hex";
variable newline: line;
variable newchar: character;
variable newbyte: std_logic_vector(7 downto 0);
variable newword: std_logic_vector(15 downto 0);
variable NextAddr, ByteCount: integer;
variable NewROM: ROM_Data := (others => (others => '0'));
variable valid: boolean := True;
begin
while (valid) loop
readline(ROMFILE, newline);
read(newline,newchar,valid); --ERROR HERE!!!
if (newchar = ':') and (valid = True) then
hread(newline,newbyte);
ByteCount := to_integer(unsigned(newbyte));
hread(newline,newword);
NextAddr := to_integer(unsigned(newword));
hread(newline,newbyte);
if newbyte = X"01" then --check for EOF marker
valid := False;
end if;
for i in 1 to ByteCount loop
hread(newline,newbyte);
NewROM(NextAddr) := newbyte;
NextAddr := NextAddr + 1;
end loop;
end if;
end loop;
file_close(ROMFILE);
return NewROM;
end;
In lieu of trying to force synthesis to initialize ROM from a file I've been known to write C programs that convert data for models to constants, in this case by generating entity/architecture pairs:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define MAX_VECTOR 512
void rom_header (rom_name,array_size)
char *rom_name;
int array_size;
{
printf("library ieee;\nuse ieee.std_logic_1164.all;\n");
printf("\nentity %s is\n port (\n",rom_name);
printf("\tindex:\t\tin integer range 0 to %d;\n",array_size*8-1);
printf("\tOE:\t\tin std_logic;\n");
printf("\toutput:\t\tout std_logic_vector (7 downto 0)\n");
printf(" );\nend ;\n");
printf("\narchitecture behave of %s is\n\n",rom_name);
printf(" subtype bytestring is bit_vector( 7 downto 0);\n");
printf(" type bytestream is array (0 to %d) of bytestring;\n\n",
array_size*8-1);
printf(" constant byte_array:\tbytestream := (\n\t ");
}
void rom_tail() {
printf(" begin\n\n");
printf(" output <= To_StdLogicVector(byte_array(index)) ");
printf("when OE = '1' else\n");
printf(" (others => 'Z') ");
printf("when OE = '0' else\n");
printf(" (others => 'X');\n");
printf("\n\nend behave;\n\n");
}
int main (argc,argv)
int argc;
char *argv[];
{
extern char *optarg;
extern int optind, opterr;
extern int getopt();
char *infile;
char key_vector[MAX_VECTOR][16];
char plain_vector[MAX_VECTOR][16];
char cipher_vector[MAX_VECTOR][16];
char testinput[2047];
char testkey[17];
char testplain[17];
char testcipher[17];
int encrypt[MAX_VECTOR];
int i;
int len;
int testcount = 0;
int totalcount = 0;
int linenumber = 0;
int vector = 0;
int encode = 1;
while ( (i=getopt(argc,argv,"i:")) != -1 ) {
switch (i) {
case 'i':
infile = optarg;
if((freopen(optarg,"r",stdin)) == NULL) {
fprintf(stderr,"ERROR:%s, can't open %s for input\n",
argv[0],optarg);
exit(-1);
}
break;
case '?':
fprintf(stderr,"usage: %s [-i infile] \n",argv[0]);
fprintf(stderr,"\ngenerates VHDL arrays for DES test vectors:\n");
fprintf(stderr,"\tcipher_vector.vhdl\n");
fprintf(stderr,"\tencrypt_vector.vhdl\n");
fprintf(stderr,"\tkey_vector.vhdl\n");
fprintf(stderr,"\tplain_vector.vhdl\n");
exit (-1);
break;
}
}
while (fgets(testinput,(sizeof testinput) -1, stdin) != NULL ) {
linenumber++;
if ( strncmp(testinput,"encrypt",7) == 0) { /* mode = encode */
encode = 1;
fprintf(stderr,"%s",testinput);
}
else
if ( strncmp(testinput,"decrypt",7) == 0) { /* mode = decode */
fprintf(stderr,"%s",testinput);
encode = 0;
}
else
if ( strncmp(testinput," ",1) == 0) { /* key, plain & cipher */
testcount++;
len = sscanf(testinput,"%s%s%s*", testkey, testplain, testcipher);
if (len != 3) {
fprintf(stderr,"ERROR: %s, wrong vector count, line %d\n",
argv[0], linenumber);
exit(-1);
}
else if (strlen(testkey) != 16) {
fprintf(stderr,"ERROR: %s wrong byte count testkey, line %d\n",
argv[0],linenumber);
exit(-1);
}
else if (strlen(testplain) != 16) {
fprintf(stderr,"ERROR: %s wrong byte count testplain, line %d\n",
argv[0],linenumber);
exit(-1);
}
else if (strlen(testcipher) != 16) {
fprintf(stderr,"ERROR: %s wrong byte count testcipher, line %d\n",
argv[0],linenumber);
exit(-1);
}
else {
encrypt[vector] = encode;
strncpy( key_vector[vector], testkey,16);
strncpy( plain_vector[vector], testplain,16);
strncpy(cipher_vector[vector],testcipher,16);
for ( i = 0; i < 16; i++) {
if ( !isxdigit(key_vector[vector][i]) ||
!isxdigit(plain_vector[vector][i]) ||
!isxdigit(cipher_vector[vector][i]) ) {
fprintf(stderr,"ERROR: %s, Vector: %d contains nonhex\n",
argv[0], vector+1);
fprintf(stderr,"\t%s\n",testinput);
exit(-1);
}
}
}
vector++;
if (vector == MAX_VECTOR) {
fprintf(stderr,"%s: Maximum number of vectors = %d\n",
argv[0],MAX_VECTOR);
exit(0);
}
}
else { /* nothing but eyewash */
if ( testcount ) {
fprintf(stderr," %d test vectors\n",testcount);
totalcount +=testcount;
testcount = 0;
}
}
}
fprintf(stderr," Total: %d test vectors\n",totalcount);
if (freopen("key_vector.vhdl","w",stdout) == NULL){
fprintf(stderr,"ERROR: %s can write to key_vector.vhdl\n",argv[0]);
exit (-1);
}
rom_header("key_vector",totalcount);
for(vector = 0; vector < totalcount; vector++) {
for ( i = 0; i <= 15; i++) {
if ( !(i & 1)) {
printf("x\"%c",key_vector[vector][i]);
}
else {
if ( i < 15) {
printf("%c\",",key_vector[vector][i]);
}
else {
printf("%c\"",key_vector[vector][i]); // no comma
}
}
}
if (vector != totalcount-1)
printf(",\n\t ");
else
printf("\n\t);\n");
}
rom_tail();
if (freopen("plain_vector.vhdl","w",stdout) == NULL){
fprintf(stderr,"ERROR: %s can write to plain_vector.vhdl\n",argv[0]);
exit (-1);
}
rom_header("plain_vector",totalcount);
for(vector = 0; vector < totalcount; vector++) {
for ( i = 0; i <= 15; i++) {
if ( !(i & 1)) {
printf("x\"%c",plain_vector[vector][i]);
}
else {
if ( i < 15) {
printf("%c\",",plain_vector[vector][i]);
}
else {
printf("%c\"",plain_vector[vector][i]); // no comma
}
}
}
if (vector != totalcount-1)
printf(",\n\t ");
else
printf("\n\t);\n");
}
rom_tail();
if (freopen("cipher_vector.vhdl","w",stdout) == NULL){
fprintf(stderr,"ERROR: %s can write to cipher_vector.vhdl\n",argv[0]);
exit (-1);
}
rom_header("cipher_vector",totalcount);
for(vector = 0; vector < totalcount; vector++) {
for ( i = 0; i <= 15; i++) {
if ( !(i & 1)) {
printf("x\"%c",cipher_vector[vector][i]);
}
else {
if ( i < 15) {
printf("%c\",",cipher_vector[vector][i]);
}
else {
printf("%c\"",cipher_vector[vector][i]); // no comma
}
}
}
if (vector != totalcount-1)
printf(",\n\t ");
else
printf("\n\t);\n");
}
rom_tail();
if (freopen("encrypt_vector.vhdl","w",stdout) == NULL){
fprintf(stderr,"ERROR: %s can write to encrypt_vector.vhdl\n",argv[0]);
exit (-1);
}
printf("library ieee;\nuse ieee.std_logic_1164.all;\n");
printf("\nentity encrypt_vector is\n port (\n");
printf("\tindex:\t\tin integer range 0 to %d;\n",totalcount-1);
printf("\toutput:\t\tout std_logic\n");
printf(" );\nend ;\n");
printf("\narchitecture behave of encrypt_vector is\n\n");
printf(" constant bit_array:\tstd_logic_vector(0 to %d) := (\n\t ",
totalcount-1);
i = 0;
for(vector = 0; vector < totalcount; vector++) {
printf("'%1d'",encrypt[vector]);i++;
if ((i == 16) && (vector != totalcount-1)) {
printf(",\n\t ");
i = 0;
}
else if (vector == totalcount-1)
printf("\n\t);\n");
else
printf(",");
}
printf(" begin\n\n");
printf(" output <= bit_array(index);");
printf("\n\nend behave;\n\n");
exit (0);
}
You could also do this for packages or even subprograms.
This particular conversion software uses a form of valid vectors preceded by an encryption mode switch and having a first column space, providing hex values of the right string length:
#
encrypt
#
0101010101010101 95F8A5E5DD31D900 8000000000000000
0101010101010101 DD7F121CA5015619 4000000000000000
0101010101010101 2E8653104F3834EA 2000000000000000
0101010101010101 4BD388FF6CD81D4F 1000000000000000
0101010101010101 20B9E767B2FB1456 0800000000000000
0101010101010101 55579380D77138EF 0400000000000000
0101010101010101 6CC5DEFAAF04512F 0200000000000000
#
It's the test vectors for a byte wide interfaced DES chip, and in this case only used in a test bench. There's nothing stopping you from embedding something like you want.
This little C program is quite old but I believe I updated it recently enough it would compile and run, it spits out several different 'vector' files for the test bench based on what the values are used for. It wants the input file to be concluded with a comment line ('#' in the first column), followed by a newline.
So the message here is don't count directly on your synthesis tools to initialize data (unless they handle it with explicitly supported routines).
See How to synthesis a rom and load initial data into it ?, for a hint thread in Xilinx, otherwise noting you haven't specified target platform.
addendum
The questioner has been forthcoming with additional information in comments, wherein automated software has exhorted us to Please avoid extended discussions in comments.
The target is a Microsemi ProASIC3, which also prompted another look at the provided Load_Data function, whose input argument x doesn't show up in the function body. While that indicates the author may have been battling uphill restrictions trying to read a file.
Looking at Microsemi's web site we see that a ProASIC3 can have an embedded 1K bit FLASHROM, which may or may not be the ROM in question. I'm an ASIC designer from way back and can appreciate the size range of these devices, intended for among other uses System on Chip applications. You'd expect the vendor would be able to supply information on how to use the FLASHROM.
For other ROM purposes in lieu of vendor supplied method of loading ROM it would seem that creating a synthesis compatible method of embedding an array of constants is in order (analogous to what's shown in the C programming example).
One characteristic of Read Only Memory in programmable devices is that the values are typically included as part of device programming.
Below is the code I am using for a program which is to be used for an airplane seating selection. It seats passengers based upon either a smoking or non-smoking preference.
I am using nested if else statements with 2 variables in each as counters and accumulators as well as nested if-then-else statements which should fill the assign[] array of structures.
Am I unable to copy arrays of structures directly into other arrays of structures using counters for the indexes? Help*/
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
using namespace System;
using namespace std;
struct passengers{
char plname[15] ;//passenger name in array
char pfname[15];
char stPref;// = seat preference, either S smoking or N non-smoking
int row;//row 0-40 (41 rows) index data, to be used later to match the index to the structure of array index
int col; //column 1-3
};struct passengers waiting[41];//Hard Coded Array of struct passengers waiting members for use with output testing
//= {{"WOODS","BILL",'S',10,2},{"BORAX","M T", 'S', 9, 2},{"THOMAS","LINDA",'N',7,2},{"HAYWARD","MARK",'N',7,3},{"SWIFT","TOM",'N',8,1},{"DOBBS","DR.",'N',8,2},{"GOLDEN","VINNIE",'N',8,3},{"HACKER","E",'N',5,3},{"RUSSEL","STEVE",'N',5,1},{"CHAMPION","SPARKY",'N',3,1},{"INNERMENTS","TEX",'S',8,2}};
//Hard Coded Array of struct passengers all[41]. This is a list of all people that want on the plane
struct passengers all[41] = {{"SMITH","JOHN",'N',3,2},{"STEVE","JOBS",'S',9,3},{"CAPONE","AL",'N',3,2},{"JACKSON","MICHAEL",'S',8,1},{"HUMPHREY","H",'S',8,2},{"RINEHART","JIM",'N',3,1},{"EASTMAN","KEN",'N',1,1},{"WINSTON","SALEM",'S',8,3},{"SMYTHE","SUSAN",'S',9,1},{"KENDRIKS","AL",'N',9,2},{"ALLISON","DENNIS",'S',9,3},{"GREENBLATT","RICHARD",'S',10,1},{"DAVIS","BOB",'S',10,3},{"WOODS","BILL",'S',10,2},{"BORAX","M T",'S',9,2},{"HENRY","JOHN",'N',1,2},{"STEVASON","E",'N',1,3},{"WILLIAMS","KEN",'N',2,1},{"SMITH","MARTHA",'N',2,2},{"KOCH","JOE",'N',2,3},{"PACKARD","H P",'N',3,3},{"RINEHART","JANE",'N',3,2},{"SWENSON","CECIL",'N',4,1},{"CORY","TROY",'N',4,2},{"BYES","NICKOLINE",'N',4,3},{"BYES","JENNIFER",'N',5,3},{"HARRIS","JOHN",'N',5,2},{"HARRIS","JUDY",'N',5,1},{"HARTMAN","F G",'N',6,1},{"SOUSE","D T",'N',6,2},{"JOHNSON","MAGIC",'N',6,3},{"LAMPTON","GEORGE",'N',7,1},{"THOMAS","LINDA",'N',7,2},{"HAYWARD","MARK",'N',7,3},{"SWIFT","TOM",'N',8,1},{"DOBBS","DR.",'N',8,2},{"GOLDEN","VINNIE",'N',8,3},{"HACKER","E.",'N',5,3},{"RUSSEL","STEVE.",'N',5,2},{"CHAMPION","SPARKY.",'N',3,1},{"INNERMENTS","TEX.",'S',8,2}};
struct passengers assign[30];//Array of structures for the actual seating assignment
//Initializes char array plane so all seats are empty
char plane[10][3] = { {'E','E','E'},{'E','E','E'},{'E','E','E'},{'E','E','E'},{'E','E','E'},{'E','E','E'},{'E','E','E'},{'E','E','E'},{'E','E','E'},{'E','E','E'} };
int x,y,z,a,b,c,count = 0;//Declares integer variables for use with accumulators and counters.
void entList();//Enter function prototype
void prtList();//Print function prototype
void seatPrgm();//Enters Passengers based on seat availability
/******************************************* Main Program ********************************************************************/
int main()
{
/********** Decision, Selection, Iteration Section... Assigns Seats based on Availability **********/
while (z<41)
{
//seatPrgm();
//************************************ User Case Selection Menu *******************************************/
char menu = '#';//Declares menu a character variable.This variable will be used for the menu selections and has a default value
//of # to ensure no problems with it's buffer.
printf("\t\t\tWelcome to Fast Flights.\n\n\t\tPlease Make a selection from thew menu\n\n");//User Prompt
printf("\t\tE to Enter Passenger Seating Information\n\t\tP to Print the Assigned Seating Report\n\t\tQ to quit.\n\n");
scanf("%c",&menu);//scans in the menu selection
while(menu !='Q')//While variable menu does not equal Q...
{
menu =(toupper(menu));
switch(menu)//Switch Statement generates a case selection menu...
{
case 'E' : entList();
printf("\n\t\t\n\n");
system("pause");
scanf("%c",&menu);
break;
case 'P' : prtList();
printf("\n\t\t\n\n");
system("pause");
scanf("%c",&menu);
break;
default : if (menu!= 'Q')
printf("\n\t\nPlease enter one of the selections\n");
else printf("\n");
scanf("%c",&menu);
system("pause");
break;
}
}
system("pause");//namespace system pause Pauses the program long enough to display data
return 0;//returns null value to int main()
}
}
void entList()
{ /*count=0;
printf("\tPlease enter passenger name and seating preferences\n");
printf("\nPassenger Name:");
gets(assign[count].pname);
// scanf("%c"); // this gets the enter key left over in the buffer - do not need this after a gets
printf("\nSeating Preference Smoking or Non-Smoking? Please enter S or N:");
scanf("%c",&assign[count].stPref);
// it was skipping because I had formatting in the scanf statement
printf("\nEnter the Seat Row Number:");
scanf("%c",&assign[count].row);
printf("\nEnter the Seat Column Number:");
scanf("%c",&assign[count].col);
count++;*/
}
//Print Function Header
void prtList()
{
/************** This section prints the first header for the Non-Smoking Section ***********************/
printf("\n\n");
for (x = 0; x<80; x++)
printf("*"); //Prints the asterisks in the heading
printf("\n");
for (x = 0; x<6; x++)
printf("*");
printf("\n");
printf("*\t\t\tNon Smoking Section\n");
printf("*\n");
for (x = 0; x<80; x++)
printf("*");
for (x = 0; x<6; x++)
printf("*");
printf("*\n");
/****************** Prints the Non-Smoking Section Seating Assignments ****************************************/
printf("\n");
x=0;
for(a=0;a<7;a++)
{
for(b=0;b<3;b++) //Prints passengers assign.[30] structure of arrays Non Smoking Section last name and first name members
{
printf("\t%s %s\t", all[x].plname,all[x].pfname);
x++;
}
printf("\n");
}
/*************************************************************************************/
/************** This section prints the second header for the Smoking Section ***********************/
printf("\n\n");
for (x = 0; x<80; x++)
printf("*"); //Prints the asterisks in the heading
printf("\n");
for (x = 0; x<6; x++)
printf("*");
printf("\n");
printf("*\t\t\tSmoking Section\n");
printf("*\n");
for (x = 0; x<80; x++)
printf(".");
/******************** Prints the Smoking Section Seating Assignments ********************************************/
for(x=0;x<10;x++)
{
for(y=0;y<3;y++) //print tests output for plane array
printf("%c ",plane[x][y]);
printf("\n");
}
x=0;
for(a=0;a<10;a++)
{
for(b=0;b<3;b++) //print test for all array of structures
{
printf("%s %s\t", all[x].pfname,all[x].plname);
x++;
}
printf("\n");
}
printf("\n");
x=0;
for(a=8;a<11;a++)
{
for(b=0;b<3;b++)
{
printf("\t%s %s\t", assign[x].plname,assign[x].pfname);
x++;
}
printf("\n");
}
/********************** This section prints the third header for the Waiting List *******************************/
printf("\n\n");
for (x = 0; x<80; x++)
printf("*"); //Prints the asterisks in the heading
printf("\n");
for (x = 0; x<6; x++)
printf("*");
printf("\n");
printf("*\t\t\t\tWaiting List\n");
printf("*\n");
printf("*\tNAME\t\tSMOKING CHOICE\t\tROW\t\tCOLUMN\n");
printf("*\n");
for (x = 0; x<80; x++)
printf(".");
/****************************** Prints the Waiting List Info ********************************************************/
printf("\n");
x = 0;
for(a=0;a<11;a++)
{
printf("%i\t%s %s\t\t%c\t\t%i\t\t%i",(a+1),waiting[x].plname,waiting[x].pfname,waiting[x].stPref,waiting[x].row,waiting[x].col);
x++;
printf("\n");
}
/************************************ End of Function *************************************************/
}
void seatPrgm()
{
a=0;
z=0;
for(x=0;x<10;x++)
{
for(y=0;y<3;y++) //FIX THIS!!!!!!!!!!!!!!!!
{
while((plane[x][y]) == 'E') //While empty
{
if((all[z].stPref)=='N')
{
(all[z] = assign[a+1]); //Fills the assigned seats
(plane[x][y] == 'F');
z++;
a++;
}
else
{
(all[z] = assign[a+1]);
(plane[x][y] == 'F');
z++;
a++;
};
};
while(plane[x][y] == 'F') //Puts them on the waiting list if that seat is already occupied or 'F' FULL.
{
while(z<41)
{
(all[z] = waiting[z]);
z++;
a++;
};
};
};
};
}