Automatically detect hardware and devices like FPGAs and SoCs, read/write to memory, program, compile, archive projects, generate LUT masks, perform timing analyses, and more.

Quartus Shell and Device Detection

qshell[source]

qshell(func)

Function decorator that opens quartustcl shell if none open.

For the following I will use two DE-10 Nano SoC FPGAs attached via USB. Note that function wrappers disrupt the automatically generated doc strings created by nbdev. As such, we will show the source code for details.

get_fpgas[source]

get_fpgas(q:Optional[QuartusTcl]=None, parse:bool=False)

Get all connected FPGAs and SOCs as lists of hardware names hwnames and device names devnames. Uses q shell if given, otherwise opens new shell. If parse, extracts only the FPGA, ignoring SoCs. Returns a dict keyed by hardware port (e.g USB) and valued with devices (e.g FPGA/SOC).

get_fpgas()
{'DE-SoC [USB-1]': ['@1: SOCVHPS (0x4BA00477)',
  '@2: 5CSEBA6(.|ES)/5CSEMA6/.. (0x02D020DD)'],
 'DE-SoC [USB-2]': ['@1: SOCVHPS (0x4BA00477)',
  '@2: 5CSEBA6(.|ES)/5CSEMA6/.. (0x02D020DD)']}
get_fpgas(parse=True) #strip the SoC
{'DE-SoC [USB-1]': '@2: 5CSEBA6(.|ES)/5CSEMA6/.. (0x02D020DD)',
 'DE-SoC [USB-2]': '@2: 5CSEBA6(.|ES)/5CSEMA6/.. (0x02D020DD)'}

get_insts[source]

get_insts(q=None, N_levels=2, hwnames=None, devnames=None)

Get all memory instances from hwname and devname. See QuartusTcl doc for N_levels.

get_insts()
{'DE-SoC [USB-1]': [['0', '1', '1', 'RW', 'ROM/RAM', 'BIT'],
  ['1', '1', '3', 'RW', 'ROM/RAM', 'MULT'],
  ['2', '512', '1300', 'RW', 'ROM/RAM', 'READ'],
  ['3', '512', '1300', 'RW', 'ROM/RAM', 'READ'],
  ['4', '512', '1300', 'RW', 'ROM/RAM', 'READ']],
 'DE-SoC [USB-2]': [['0', '1', '1', 'RW', 'ROM/RAM', 'BIT'],
  ['1', '1', '3', 'RW', 'ROM/RAM', 'MULT'],
  ['2', '512', '1300', 'RW', 'ROM/RAM', 'READ'],
  ['3', '512', '1300', 'RW', 'ROM/RAM', 'READ'],
  ['4', '512', '1300', 'RW', 'ROM/RAM', 'READ']]}

The dict is keyed by port, and valued by a list of lists. Each sublist gives a memory address. The first entry is the memory index, the second is the number of words, the third is the size of each word, the fourth is the RW behavior, the 5th is the type of memory, and the last is the name of the memory module.

begin_mem[source]

begin_mem(q=None, hw='DE-SoC [USB-1]', dev='@2: 5CSEBA6(.|ES)/5CSEMA6/.. (0x02D020DD)')

Open a memory edit. If one is already open, pass.

end_mem[source]

end_mem(q=None)

End a memory edit. If there are none open, pass.

Reading / writing to memory

read[source]

read(q=None, inst=0, hw='DE-SoC [USB-1]', dev='@2: 5CSEBA6(.|ES)/5CSEMA6/.. (0x02D020DD)', begin=True, end=True, fname=None, delete_mif=True)

Reads memory from an instance inst into an array data. Option delete_mif will delete temporary .mif file if set to True.

read(inst=1,hw='DE-SoC [USB-1]',dev='@2: 5CSEBA6(.|ES)/5CSEMA6/.. (0x02D020DD)')
array([[0, 0, 0]])

format_mem[source]

format_mem(data, bits=None)

Format input data to nested array required for memory

format_mem(0)
array([[0]])
format_mem(10)
array([[1, 0, 1, 0]])
format_mem([0,1,2])
array([[0, 1, 2]])

write[source]

write(q=None, inst=0, data=1, hw='DE-SoC [USB-1]', dev='@2: 5CSEBA6(.|ES)/5CSEMA6/.. (0x02D020DD)', bits=None, begin=True, end=True, fname=None, delete_mif=True)

Writes data array to memory instance inst. Option delete_mif will delete temporary .mif file if set to True.

write(inst=1,data=[1,0,1])
read(inst=1)
array([[1, 0, 1]])

read_write[source]

read_write(q=None, args=[[0, 'w', 1, 1], [0, 'r']], hw='DE-SoC [USB-1]', dev='@2: 5CSEBA6(.|ES)/5CSEMA6/.. (0x02D020DD)', reps=1, begin=True, end=True)

Read/write using args, a list of lists/tuples each of the form (instance index, 'r' or 'w', data to write if 'w', bits to use if 'w'). Can repeat operation up to reps.

read_write(args=[(1,'w',0,3),(1,'r')])
array([0, 0, 0])
read_write(args=[(1,'w',[1,1,1]),(1,'r')])
array([1, 1, 1])
read_write(args=[(1,'w',[1,1,1]),(1,'r')],reps=2)
array([[1, 1, 1],
       [1, 1, 1]])
read_write(args=[(1,'w',[1,1,1]),(1,'r'),(1,'w',0,3),(1,'r')])
array([[1, 1, 1],
       [0, 0, 0]])

read_write_all[source]

read_write_all(q=None, args=[[0, 'w', 1, 1], [0, 'r']], fpgas=[['DE-SoC [USB-1]', '@2: 5CSEBA6(.|ES)/5CSEMA6/.. (0x02D020DD)']], reps=1, begin=False, end=False)

read_write_all(fpgas=[('DE-SoC [USB-1]','@2: 5CSEBA6(.|ES)/5CSEMA6/.. (0x02D020DD)'),
                     ('DE-SoC [USB-2]','@2: 5CSEBA6(.|ES)/5CSEMA6/.. (0x02D020DD)')],
              args=[(1,'w',[1,1,1]),(1,'r'),(1,'w',0,3),(1,'r')])
array([[[1, 1, 1],
        [0, 0, 0]],

       [[1, 1, 1],
        [0, 0, 0]]])

Programming, compiling, archiving

program_proj[source]

program_proj(projectname, hw=None, path='output_files')

Program a single FPGA using a .cdf file.

compile_proj[source]

compile_proj(projectname)

Compiles Quartus project projectname.

archive_proj[source]

archive_proj(projectname, filename, path='')

Generates a projectname-date.qar file which Quartus can use to restore all project files.

Location and routing annotation and QSF file appending

back_annotate[source]

back_annotate(projectname, routing=True, logic=True)

Writes all routing and logic to the qsf file.

write_qsf[source]

write_qsf(txt='', style='w', projectname='DE10', sourcename='qsf_source.qsf', set_source=False)

Writes assignments txt to sourcename and includes them in projectname.qsf.

LUT Masks

lut_mask[source]

lut_mask(lut=<lambda>, N=4)

Quartus LUT mask for primitive logic cell, takes function to input and returns hex encoding in: lut (callable or list or numpy.array or dict) : function mapping over the port entry. N (int) : number of ports. for standard 4-input LUT, 0=d, 1=c, 2=b, 3=a out: mask (str) : hex string encoding of the given mask

lut_mask(lambda s:1 if s[0]==1 else 0)
'0x00ff'

Timing analysis

analyze_timing[source]

analyze_timing(projectname, _from='[get_clocks {MyClock}]', _to='[get_cells {MyCell}]', detail='summary', filename='timing.txt', npaths=1)

Runs the timing analyzer, getting path information from _from to _to. Gives detail (summary or full_path) on npaths and generates filename. Returns text of that file.