Some AVR8 question of a newbie


Guest eddy

Recommended Posts

Hello Jack and forum visitors,

I'm very curious about this avr core. But in lack of any hardware I first tried a simulation of the core. It took me a will to get the simprim library working but eventually got a sign of life. This bring me to my first question. The core is executing the hardcoded pm_inst contents (program code space). But what is the intended functionality of the xpm8kx16.vhd? Is this on of the examples?

My next step could be to make my own test program and replace the xpm8kx16.vhd contents. Is there also a ready to use tool for placing the winavr hex output into the xpm8kx16 vhdl file?

An other question I have is about the JTAG functions. It is clear that the USB interface enables us to program the butterfly board. I assume that you mean that either the fpga or the SPI-FLASH-configurator can be programmed via JTAG. But is the AVR-JTAG interface also connected (chained) to this USB interface? I was not able to figure this out from the butterfly one schematic. This could enable JTAG debugging.

Thanks in advance.

Eddy

Link to comment
Share on other sites

Hello Eddy,

I'm glad you got the simulation working, I did some pretty extensive debugging with the simulator while I was getting the core to work and there is a lot you can learn about the design with the simulator.

The code that is hardcoded into the xpm8kx16.vhd file is a simple application that just blinks one of the PortA pins if I'm not mistaken. I hardcoded it into the vhd file while I was troubleshooting the core.

If you want to get your own code into the core for simulation then you will want to look at the Makefile, the one in the Arduino IDE is most up to date, and see how a mem file is generated from a hex file. Once you have a mem file you should be able to use data2mem to output the code into a vhd or ucf file. If you output to vhd you should be able to just replace the memory definition section in the xpm8kx16.vhd file with your own generated definition. Pepevi was working on a way to do this using a script, you might want to drop by the IRC chat channel and see how his progress has been.

It is possible to update the program memory using JTAG but the GadgetFactory implementation does not use that method. Instead the data2mem tool merges the hex file into the bitstream and then the Papilio Loader loads the bitstream to the FPGA over JTAG.

The open source version of the AVR8 does not have a JTAG debugger. Ruslan, the cores developer, does have a JTAG debugger module that he offers for sale. But you would have to purchase the Microchip JTAG module for this to work.

Jack.

Link to comment
Share on other sites

Hi,

Here is a very quick and dirty bit of 'C' that I wrote to convert a hex file to a format that can be cut and pasted into the ProgMem '.vdh' source.  It is only good for programs up to one BRAM in size, as the same contents is used for all BRAM instances.

It is by no means production quality (unsafe buffers, no limit checks and so on), but it works.

Couldn't upload it as an attachement, so here it is..

Mike

[tt]

// hex2mem.cpp

//

#include "stdafx.h"

#include <stdlib.h>

#include <string.h>

#include <stdio.h>

char buffer[1000];

FILE *f;

unsigned char data[256*256];

int maxaddr = 0;

int htoi(char c)

{

  if(c >= '0' && c <= '9') return c-'0';

  if(c >= 'a' && c <= 'f') return c-'a'+10;

  if(c >= 'A' && c <= 'F') return c-'A'+10;

  printf("Invalid hex\n");

  exit(0);

}

int readaline(char * buffer)

{

  int c;

  int i = 0;

  c=getc(f);

  while(c != EOF && c != '\n') {

    buffer[i++] = c;

    c=getc(f);

  }

  buffer = '\0';

  return i > 0;

}

void decodeBytes(char *buffer)

{

    int len, addr,type;

    int i;

    if(strlen(buffer) < 10)return;

    len  = (htoi(buffer[1])<<4) +htoi(buffer[2]);

    addr = (htoi(buffer[3])<<12)+(htoi(buffer[4])<<8)

        + (htoi(buffer[5])<<4) +htoi(buffer[6]);

    type = (htoi(buffer[7])<<4) +htoi(buffer[8]);

    if(type == 1) // EOF marker

return;

for(i = 0; i < len; i++) {

        data[addr+i] = htoi(buffer[9+i*2])*16+htoi(buffer[10+i*2]);

if(addr+i > maxaddr)

maxaddr = addr+i;

}

}

void dump(void)

{

int addr = 0;

int line = 0;

while(addr < maxaddr) {

int i;

    printf("INIT_%02X => X\"",line);

for(i = 31; i >=0; i--)

printf("%02x",data[addr+i]);

addr += 32;

line++;

    printf("\",\n");

}

}

int main(int c, char *v[])

{

  int line = 0;

  f = fopen(v[1],"r");

  if(f == NULL) {

    printf("Unable to open file\n");

    return 0;

  }

  while(readaline(buffer))

    decodeBytes(buffer);

  fclose(f);

  dump(); 

  return 0;

}

[/tt]

Link to comment
Share on other sites

Guest pepevi

@eddy:

FYI, I'm working on a way to simulate directly from Arduino (butterflyarduino) to ModelSim. Basically it generates the xpm8kx16.vhd file after compiling.

Link to comment
Share on other sites

Here is a very quick and dirty bit of 'C' that I wrote to convert a hex file to a format that can be cut and pasted into the ProgMem '.vdh' source.  It is only good for programs up to one BRAM in size, as the same contents is used for all BRAM instances.

Awesome, I am going to post this to the playground at http://papilio.cc.

Link to comment
Share on other sites

@eddy:

FYI, I'm working on a way to simulate directly from Arduino (butterflyarduino) to ModelSim. Basically it generates the xpm8kx16.vhd file after compiling.

That sounds very good. Please keep us updated  :)

Link to comment
Share on other sites

Guest pepevi

More or less the same as the above c++ code, I'm generating the XPM8Kx16.vhd with a python script using the vhdl output from data2mem.

It merges a template file (program.vhd) with the vhdl file generated from data2mem (out.vhd).

Usage:

python HexVHDLConverter.py <program.vhd> <out.vhd> <number of BRAM (8k) modules>

I've removed the generate loop for programs over 8K.

It's only been tested once... so please post your comments.

I'm close to generating everything and setting up a ModelSim project with a click from arduinobutterfly.

PS: I can't attach documents, so here they are:

HexVHDLConverter.py


#--************************************************************************************************
#-- Hex VHDL Converter
#-- Version 0.2
#-- Designed by J. Alcerreca (ppvi)
#-- For use with Papilio Platform (gadgetfactory.net)
#-- Modified 21 March 2011
#--************************************************************************************************

import getopt, sys

def usage():
print "Usage: python HexVHDLConverter.py program.vhd out.vhd <number of BRAM (8k) modules>"

def writeLine(line, outfile):
#print line
outfile.write(line+"\n")

def writeMemory(num_instance, outfile, invhd):
#print "----Writing memory----"
init = """
RAM_Word%d:component RAMB16_S18
generic map (
INIT => X"00000", -- Value of output RAM registers at startup
SRVAL => X"00000", -- Ouput value upon SSR assertion
WRITE_MODE => "WRITE_FIRST", -- WRITE_FIRST, READ_FIRST or NO_CHANGE
-- The following INIT_xx declarations specify the intial contents of the RAM""" % (num_instance,)

for line in init.split("\n"):
writeLine(line, outfile)
writeLine("-- Address " + str(num_instance*256) + " to " + str(num_instance*256 + 255), outfile)
count = 0
for line in invhd:
if count == 64: break
if line.find("constant PM_Inst_RAM_Inst["+str(num_instance)+"]") != -1:
index = line.find("\"")
writeLine("\tINIT_" + "%02X" % count + " => X\"" + line[index+1:index+65] + "\",", outfile)
count += 1
finish = """
-- The next set of INITP_xx are for the parity bits
-- Address 0 to 255
INITP_00 => X"0000000000000000000000000000000000000000000000000000000000000000",
INITP_01 => X"0000000000000000000000000000000000000000000000000000000000000000",
-- Address 256 to 511
INITP_02 => X"0000000000000000000000000000000000000000000000000000000000000000",
INITP_03 => X"0000000000000000000000000000000000000000000000000000000000000000",
-- Address 512 to 767
INITP_04 => X"0000000000000000000000000000000000000000000000000000000000000000",
INITP_05 => X"0000000000000000000000000000000000000000000000000000000000000000",
-- Address 768 to 1023
INITP_06 => X"0000000000000000000000000000000000000000000000000000000000000000",
INITP_07 => X"0000000000000000000000000000000000000000000000000000000000000000")
port map(
  DO  => RAMBlDOut(%d)(15 downto 0),
  ADDR => address(9 downto 0),
  DI  => din(15 downto 0),
  DIP  => DIP,
  EN  => ce,
  SSR  => SSR,
  CLK  => cp2,
  WE  => WEB(%d)
  );""" % (num_instance, num_instance)
for line in finish.split("\n"):
writeLine(line, outfile)
 

def generateVHDL():
try:
num_instances = int(sys.argv[3])
except:
print sys.argv[3] + " is not a number"
sys.exit(2)
try:
r = open(sys.argv[1], 'r')
except:
print "Can't open template file " + sys.argv[1]
sys.exit(2)
try:
invhd = open(sys.argv[2], 'r')
except:
print "Can't open VHDL input file " + sys.argv[2]
sys.exit(2)
try:
w = open("XPM8Kx16.vhd", 'w')
except:
print "Can't open write file out.vhd"
sys.exit(2)
for line in r:
#line = r.readline()
#print line
if(line.find("<%RAM_Inst%>") != -1):
for i in range(num_instances):
writeMemory(i, w, invhd)
else:
w.write(line)

def main():
if len(sys.argv) != 4:
usage()
sys.exit(2)
#print "Hello"
generateVHDL()


if __name__ == "__main__":
main()



program.vhd

--************************************************************************************************
-- 8Kx16(8 KB) PM RAM for AVR Core(Xilinx)
-- Version 0.1
-- Designed by Ruslan Lepetenok
-- Modified by Jack Gassett for use with Papilio
-- Modified 11.06.2009
-- Generated by HexVHDLConverter for Papilio Platform by J. Alcerreca
--************************************************************************************************

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;

use WORK.SynthCtrlPack.all; -- Synthesis control

-- For Synplicity Synplify
--library virtexe;
--use virtexe.components.all;

-- Aldec
library unisim;
use unisim.vcomponents.all;

entity XPM8Kx16 is port(
                  cp2    : in  std_logic;
  ce      : in  std_logic;
                  address : in  std_logic_vector(CPROGMEMSIZE downto 0);
  din    : in  std_logic_vector(15 downto 0);                
  dout    : out std_logic_vector(15 downto 0);
  we    : in  std_logic
  );
end XPM8Kx16;

architecture RTL of XPM8Kx16 is

type  RAMBlDOut_Type is array(2**(address'length-10)-1 downto 0) of  std_logic_vector(dout'range);
signal RAMBlDOut    : RAMBlDOut_Type;

signal WEB    : std_logic_vector(2**(address'length-10)-1 downto 0);
signal gnd      : std_logic;
signal DIP : STD_LOGIC_VECTOR(1 downto 0) := "11";
signal SSR : STD_LOGIC := '0'; -- Don't use the output resets.



begin

gnd <= '0';

WEB_Dcd:for i in WEB'range generate
WEB(i) <= '1' when (we='1' and address(address'high downto 10)=i) else '0';
end generate ;

<%RAM_Inst%>

-- Output data mux
dout <= RAMBlDOut(CONV_INTEGER(address(address'high downto 10)));



end RTL;

Link to comment
Share on other sites

Hi,

Here is a very quick and dirty bit of 'C' that I wrote to convert a hex file to a format that can be cut and pasted into the ProgMem '.vdh' source.  It is only good for programs up to one BRAM in size, as the same contents is used for all BRAM instances.

It is by no means production quality (unsafe buffers, no limit checks and so on), but it works.

Couldn't upload it as an attachement, so here it is..

Mike

Thanks to all your input I was able to run the AVR8 in a FPGA. Because I do not have any xilinx hardware yet I first had to port the design to an Altera FPGA. Which was quite a chalenge for my rusty vhdl. But in the end succes! :D :D

To be able to load the winavr-hex file into the design I used Mike's converter code and wrote a MIF (memory initialisation file) converter.

If someone is interested I can clean up the code and share it with you all.

Eddy

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.