URL
https://opencores.org/ocsvn/light8080/light8080/trunk
Subversion Repositories light8080
Compare Revisions
- This comparison shows the changes necessary to convert path
/light8080
- from Rev 72 to Rev 73
- ↔ Reverse comparison
Rev 72 → Rev 73
/trunk/tools/obj2hdl/.project
0,0 → 1,17
<?xml version="1.0" encoding="UTF-8"?> |
<projectDescription> |
<name>obj2hdl</name> |
<comment></comment> |
<projects> |
</projects> |
<buildSpec> |
<buildCommand> |
<name>org.python.pydev.PyDevBuilder</name> |
<arguments> |
</arguments> |
</buildCommand> |
</buildSpec> |
<natures> |
<nature>org.python.pydev.pythonNature</nature> |
</natures> |
</projectDescription> |
/trunk/tools/obj2hdl/build.bat
0,0 → 1,17
python src/obj2hdl.py -f ../../test/cpu_test/bin/tb51_cpu.hex -o ../../vhdl/obj_code_pkg.vhdl |
/trunk/tools/obj2hdl/src/obj2hdl.py
0,0 → 1,236
|
|
import sys |
import getopt |
|
default_template = ( |
"-- @obj_pkg_name@ -- Object code in VHDL constant table for "\ |
"BRAM initialization.", |
"-- Generated automatically with script 'build_rom.py'.", |
"", |
"library ieee;", |
"use ieee.std_logic_1164.all;", |
"use ieee.numeric_std.all;", |
"use work.l80pkg.all;", |
"", |
"package @obj_pkg_name@ is", |
"", |
"constant @constant@ : obj_code_t(0 to @obj_size@) := (", |
" @obj_bytes@", |
" );", |
"", |
"end package @obj_pkg_name@;", |
) |
|
|
class command_line_params(): |
def __init__(self): |
self.template_file = None |
self.package_name = None |
self.constant_name = "object_code" |
self.indent = 2 |
self.proj_name = None |
|
|
|
def usage(): |
"""Print usage instructions""" |
print "" |
print "usage:" |
print "python build_rom.py [arguments]\n" |
print "Builds VHDL ROM constant from template and Intel HEX object file.\n" |
print "ALL of the following arguments should be given, in any order:" |
print "{f|file} <filename> Object code file name" |
print "{c|constant} <name> Name of target VHDL constant" |
print "{p|package} <name> Name of target VHDL package" |
print "{n|name} <name> Name of project (used only in comment)" |
print "{o|output} <filename> Target VHDL file name" |
print "" |
print "Additionally, any of these arguments can be given:" |
print "{v|vhdl} <filename> VHDL template" |
print " (defaults to templates/obj_code_kg_template.vhdl)" |
print "{i|indent} <number> Indentation in VHDL tables (decimal)" |
print " (defaults to 4)" |
|
|
def help(): |
"""Print help message a bit longer than usage message.""" |
print "\nPurpose:\n" |
print "Reads the code and data binary files and 'slices' them in byte" |
print "columns." |
print "The data columns are converted to VHDL strings and then inserted" |
print "into the vhdl template, in place of tags @code0@ .. @code3@ and " |
print "@data0@ .. @data3@. Column 0 is LSB and column3 is MSB.\n" |
print "Tags like @data31@ and @data20@ etc. can be used to initialize" |
print "memories in 16-bit buses, also split in byte columns.\n" |
print "Template tags are replaced as follows:" |
print "@obj_pkg_name@ : Name of package in target vhdl file" |
print "@const_name@ : Name of constant (VHDL table)" |
print "@obj_size@ : Total size of code table in bytes" |
|
|
def parse_hex_line(line): |
"""Parse code line in HEX object file.""" |
line = line.strip() |
slen = int(line[1:3],16) |
sloc = int(line[3:7],16) |
stype = line[7:9] |
sdata = line[9:len(line)-2] |
schk = int(line[len(line)-2:],16) |
|
csum = slen + int(sloc / 256) + (sloc % 256) + int(stype,16) |
bytes = [0, ] * slen |
for i in range(slen): |
sbyte = int(sdata[i*2:i*2+2],16) |
bytes[i] = sbyte; |
csum = csum + sbyte |
|
csum = ~csum |
csum = csum + 1 |
csum = csum % 256 |
if csum != schk: |
return (None, None) |
|
return (sloc, bytes) |
|
|
def read_ihex_file(ihex_filename): |
""" |
""" |
xcode = [0, ] * 65536 |
bottom = 100000 |
top = -1 |
(xcode, top, bottom) |
|
fin = open(ihex_filename, "r") |
ihex_lines = fin.readlines() |
fin.close() |
|
total_bytes = 0 |
for line in ihex_lines: |
(address, bytes) = parse_hex_line(line) |
if address == None: |
print "Checksum error!" |
sys.exit(1) |
total_bytes = total_bytes + len(bytes) |
for i in range(len(bytes)): |
xcode[address + i] = bytes[i] |
|
if address < bottom: |
bottom = address |
|
if (address + len(bytes)) > top: |
top = (address + len(bytes)) |
|
print "Read %d bytes from file '%s'" % (total_bytes, ihex_filename) |
print "Code range %04xh to %04xh" % (bottom, top) |
return (xcode, total_bytes, bottom, top) |
|
|
def build_vhdl_code(template_filename, xcode, rom_size, params): |
|
if not template_filename: |
lines = default_template |
else: |
fin = open(template_filename, "r") |
lines = fin.readlines() |
fin.close() |
|
vhdl_code = "" |
|
for line in lines: |
line = line.strip() |
|
if line.rfind("@obj_bytes@") >= 0: |
obj_str = " " |
for i in range(rom_size): |
if i != (rom_size-1): |
sbyte = "X\"%02x\", " % xcode[i] |
else: |
sbyte = "X\"%02x\" " % xcode[i] |
obj_str = obj_str + sbyte |
if (i % 8) == 7: |
obj_str = obj_str + "\n " |
|
line = line.replace("@obj_bytes@",obj_str) |
|
if line.rfind("@obj_size@") >= 0: |
line = line.replace("@obj_size@","%d" % (rom_size-1)) |
|
if line.rfind("@constant@") >= 0: |
line = line.replace("@constant@", params.constant_name) |
|
if line.rfind("@obj_pkg_name@") >= 0: |
line = line.replace("@obj_pkg_name@","obj_code_pkg") |
|
vhdl_code = vhdl_code + line + "\n" |
|
return vhdl_code |
|
|
def main(argv): |
|
try: |
opts, _ = getopt.getopt(argv, "hf:n:p:c:o:i:v:", |
["help", "file=", "name=", "package=", "constant=", |
"output=", "indent=", "vhdl=", ]) |
except getopt.GetoptError, err: |
print "" |
print err |
usage() |
sys.exit(2) |
|
# Give default values to command line parameters |
params = command_line_params() |
|
# Parse coommand line parameters |
for opt, arg in opts: |
if opt in ("-h", "--help"): |
usage() |
help() |
exit(1) |
if opt in ("-v", "--vhdl"): |
params.template_file = arg |
elif opt in ("-o", "--output"): |
target_filename = arg |
elif opt in ("-c", "--constant"): |
params.constant_name = arg |
elif opt in ("-f", "--file"): |
hex_filename = arg |
elif opt in ("-p", "--package"): |
params.package_name = arg |
elif opt in ("-n", "--name"): |
params.proj_name = arg |
elif opt in ("-i", "--indent"): |
params.indent = int(arg) |
|
if not target_filename: |
print "Missing target file name." |
usage() |
sys.exit(2) |
|
|
(xcode, total_bytes, bottom, top) = read_ihex_file(hex_filename); |
vhdl_code = build_vhdl_code(params.template_file, xcode, top, params); |
|
fout = None |
try: |
fout = open(target_filename, "w") |
fout.write(vhdl_code) |
fout.close() |
print "VHDL code table written to %s" % target_filename |
except: |
print "Trouble opening %s for output" % target_filename |
finally: |
if fout: fout.close() |
|
|
|
|
|
if __name__ == "__main__": |
main(sys.argv[1:]) |
|
sys.exit(0) |
|
|
/trunk/tools/obj2hdl/.pydevproject
0,0 → 1,10
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
<?eclipse-pydev version="1.0"?> |
|
<pydev_project> |
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property> |
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property> |
<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH"> |
<path>/obj2hdl/src</path> |
</pydev_pathproperty> |
</pydev_project> |
/trunk/tools/obj2hdl/templates/obj_code_pkg_template.vhdl
0,0 → 1,45
-------------------------------------------------------------------------------- |
-- obj_code_pkg.vhdl -- Application object code in vhdl constant string format. |
-------------------------------------------------------------------------------- |
-- This is where the application code lives. |
-- FIXME should only be used from top level entity |
-- FIXME name of package should be application-related |
-- FIXME convert to vhdl template |
-------------------------------------------------------------------------------- |
-- Copyright (C) 2011 Jose A. Ruiz |
-- |
-- This source file may be used and distributed without |
-- restriction provided that this copyright statement is not |
-- removed from the file and that any derivative work contains |
-- the original copyright notice and the associated disclaimer. |
-- |
-- This source file 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 source 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. |
-- |
-- You should have received a copy of the GNU Lesser General |
-- Public License along with this source; if not, download it |
-- from http://www.opencores.org/lgpl.shtml |
-------------------------------------------------------------------------------- |
|
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.numeric_std.all; |
|
package @obj_pkg_name@ is |
|
constant object_code : |
array(0 to @obj_size@) of std_logic_vector(7 downto 0) := ( |
@obj_bytes@ |
); |
|
|
end package @obj_pkg_name@; |
/trunk/tools/hexconv/hexconv.pl
0,0 → 1,172
################################################################################ |
# hexconv.pl -- inserts object code in HEX format into an VHDL template. |
# |
# This program reads an Intel HEX file with 8-bit object code and inserts it |
# into a VHDL template, in the form of a VHDL std_logic_vector array |
# initializer. This is meant to initialize FPGA ROM/RAM blocks with object code. |
# When the program finds a template line which begins with "--@rom_data", it |
# replaces the whole line with the VHDL table. |
# When it finds the text @PROGNAME@ in a line, it replaces that text with the |
# file name (without path or extension) of the hex file. |
# Otherwise, it just copies the template to stdout verbatim. |
# |
# See usage details below, and examples in the BAT file in the asm directory. |
################################################################################ |
|
$usage = "Use: hexconv.pl <hexfile> <template file> <start addr> <table size>"; |
|
# read command line arguments; HEX file name... |
$file = shift(@ARGV); |
if($file eq ''){die $usage}; |
# ...VHDL template file name... |
$template = shift(@ARGV); |
if($template eq ''){die $usage}; |
# ...object code start address... |
$start_addr = shift(@ARGV); |
if($start_addr eq ''){die $usage}; |
$start_addr = hex $start_addr; |
# ...and VHDL table size |
$table_size = shift(@ARGV); |
if($table_size eq ''){die $usage}; |
$table_size = hex $table_size; |
|
# read HEX file... |
open(INFO, $file) or die "file $file not found"; |
@lines = <INFO>; |
close(INFO); |
|
# ...and VHDL template |
open(INFO, $template) or die "file $template not found"; |
@vhdl_lines = <INFO>; |
close(INFO); |
|
$min_address = 65536; |
$max_address = 0; |
$bytes_read = 0; |
|
# make up a 'ram image' table of 64K bytes where the object code will be put. |
@data_array = (); |
for($i=0;$i<65536;$i++){ $data_array[$i] = 0; }; |
|
# read input HEX file into ram image table |
$line_no = 0; |
foreach $line (@lines){ |
|
chomp($line); |
$line_no++; |
|
if(length($line)>=11 and substr($line, 0, 1) eq ':'){ |
$total_length = length($line); |
$len = substr($line, 1,2); |
$addr = substr($line, 3,4); |
$type = substr($line, 7,2); |
$csum = substr($line, $total_length-3,2); |
$data = substr($line, 9,$total_length-11); |
|
# Process data records and utterly ignore all others. |
# Note that the checksum field is ignored too; we rely on the correctness |
# of the hex file. |
if($type eq '00'){ |
$len = hex $len; |
$first_addr = hex $addr; |
$last_addr = $first_addr + $len - 1; |
|
if($first_addr < $min_address){ |
$min_address = $first_addr; |
}; |
if($last_addr > $max_address){ |
$max_address = $last_addr; |
}; |
|
$chksum = 0; |
for($i=0;$i<$len;$i++){ |
$data_byte = substr($line, 9+$i*2, 2); |
$data_byte = hex $data_byte; |
$chksum += $data_byte; |
$data_array[$first_addr+$i] = $data_byte; |
$bytes_read++; |
} |
} |
} |
else{ |
die "Wrong format in line $line_no\n"; |
} |
} |
|
# Make sure all the object code we read from the hex file will fit in the VHDL |
# memory; this is a typo-catcher. |
|
if($min_address < $start_addr or $max_address < $start_addr){ |
die "Hex data out of bounds"; |
} |
|
$upper_bound = $start_addr + $table_size; |
|
if($min_address > $upper_bound or |
$max_address > $upper_bound){ |
die "Hex data out of bounds: ".$upper_bound; |
} |
|
# debug output |
#printf "Data address span [%04x : %04x]\n", $min_address, $max_address; |
#$bytes_defaulted = ($max_address-$min_address+1)-$bytes_read; |
#if($bytes_defaulted > 0){ |
# printf "(%d bytes defaulted to 0)\n", $bytes_defaulted; |
#} |
|
#### Now process the template inserting the ROM bytes where necessary |
|
# display only the template filename, cut away any path that may be present |
if($template =~ /^.*[\\\/](.*\..*)/){ $template = $1; } |
# put a reminder in the 1st lines of the VHDL output |
$comm = "--------------------"; |
print $comm.$comm.$comm.$comm."\n"; |
print "-- Generated from template $template by hexconv.pl\n"; |
|
# Extract program name from the hex file name, stripping path and extension |
if($file =~ /^.*[\\\/](.*)\..*/){ |
$file = $1; |
} |
elsif($file =~ /^(.*)\..*/){ |
$file = $1; |
} |
|
# Output template file contents to stdout, line by line, inserting the object |
# code when we find the 'data tag' "@rom_data". |
foreach $vhdl (@vhdl_lines){ |
if($vhdl =~ /^\s*--\@rom_data/){ |
# if we find the ROM data tag in a comment line, replace line |
# with VHDL table. |
print_rom_code($start_addr, $table_size, @data_array); |
} |
else{ |
# otherwise, output template line |
$vhdl =~ s/\@PROGNAME\@/$file/; |
printf $vhdl; |
}; |
} |
|
# Prints a chunk of bytes as a VHDL table of std_logic_vectors, formatted as |
# 8 bytes per column. |
# |
# print_rom_code ($obj_code_table, $obj_code_start, $obj_code_size) |
# $obj_code_start : address of the 1st byte that we want to put in the VHDL RAM. |
# $obj_code_size : number of bytes to put in the VHDL memory. |
# @obj_code_table : image of the CPU 64K memory map with the object code in it. |
sub print_rom_code { |
my($obj_code_start, $obj_code_size, @obj_code_table) = @_; |
$col = 0; |
for($i=0;$i<$obj_code_size;$i++){ |
$q = $obj_code_table[$obj_code_start+$i]; |
print $q |
printf "X\"%02x\"", $q; |
if($i<$obj_code_size-1){ |
printf ","; |
} |
$col++; |
if($col eq 8){ |
print "\n"; |
$col = 0; |
} |
} |
} |
/trunk/tools/hexconv/tb_template.vhdl
0,0 → 1,320
-------------------------------------------------------------------------------- |
-- Light8080 simulation test bench. |
-------------------------------------------------------------------------------- |
-- This test bench was built from a generic template. The details on what tests |
-- are performed by this test bench can be found in the assembly source for the |
-- 8080 program, in file asm\exer.asm. |
-------------------------------------------------------------------------------- |
-- |
-- This test bench provides a simulated CPU system to test programs. This test |
-- bench does not do any assertions or checks, all assertions are left to the |
-- software. |
-- |
-- The simulated environment has 64KB of RAM covering the whole address map. |
-- The simulated RAM is initialized with the contents of constant 'obj_code'. |
-- This constant's contents are generated from some .HEX object code file using |
-- a helper script. See the perl script 'util\hexconv.pl' and BAT files in the |
-- asm directory. |
-- |
-- This simulated system provides some means to trigger hardware irq from |
-- software, including the specification of the instructions fed to the CPU as |
-- interrupt vectors during inta cycles. This is only meant to test interrupt |
-- response of the CPU. |
-- |
-- We will simulate 8 possible irq sources. The software can trigger any one of |
-- them by writing at ports 0x010 to 0x011. Port 0x010 holds the irq source to |
-- be triggered (0 to 7) and port 0x011 holds the number of clock cycles that |
-- will elapse from the end of the instruction that writes to the register to |
-- the assertion of intr. Port 0x012 holds the number of cycles intr will remain |
-- high. Intr will be asserted for 1 cycle at least, so writing a 0 here is the |
-- same as writing 1. |
-- |
-- When the interrupt is acknowledged and inta is asserted, the test bench reads |
-- the value at register 0x010 as the irq source, and feeds an instruction to |
-- the CPU starting from the RAM address 0040h+source*4. |
-- That is, address range 0040h-005fh is reserved for the simulated 'interrupt |
-- vectors', a total of 4 bytes for each of the 8 sources. This allows the |
-- software to easily test different interrupt vectors without any hand |
-- assembly. All of this is strictly simulation-only stuff. |
-- |
-- Upon completion, the software must write a value to register 0x020. Writing |
-- a 0x055 means 'success', writing a 0x0aa means 'failure'. The write operation |
-- will stop the simulation. Success and failure conditions are defined by the |
-- software. |
-- |
-- If a time period defined as constant MAX_SIM_LENGTH passes before anything |
-- is written to io address 0x020, the test bench assumes the software ran away |
-- and quits with an error message. |
-------------------------------------------------------------------------------- |
|
library ieee; |
use ieee.std_logic_1164.ALL; |
use ieee.std_logic_unsigned.all; |
use ieee.numeric_std.ALL; |
|
entity light8080_@PROGNAME@ is |
end entity light8080_@PROGNAME@; |
|
architecture behavior of light8080_@PROGNAME@ is |
|
-------------------------------------------------------------------------------- |
-- Simulation parameters |
|
-- T: simulated clock period |
constant T : time := 100 ns; |
|
-- MAX_SIM_LENGTH: maximum simulation time |
constant MAX_SIM_LENGTH : time := T*7000; -- enough for the tb0 |
|
|
-------------------------------------------------------------------------------- |
|
signal data_i : std_logic_vector(7 downto 0) := (others=>'0'); |
signal vma_o : std_logic; |
signal rd_o : std_logic; |
signal wr_o : std_logic; |
signal io_o : std_logic; |
signal data_o : std_logic_vector(7 downto 0); |
signal data_mem : std_logic_vector(7 downto 0); |
signal addr_o : std_logic_vector(15 downto 0); |
signal fetch_o : std_logic; |
signal inta_o : std_logic; |
signal inte_o : std_logic; |
signal intr_i : std_logic := '0'; |
signal halt_o : std_logic; |
|
signal reset : std_logic := '0'; |
signal clk : std_logic := '1'; |
signal done : std_logic := '0'; |
|
type t_obj_code is array(integer range <>) of std_logic_vector(7 downto 0); |
|
-- |
signal obj_code : t_obj_code(0 to 6143) := ( |
|
--@rom_data |
|
); |
|
signal irq_vector_byte: std_logic_vector(7 downto 0); |
signal irq_source : integer range 0 to 7; |
signal cycles_to_intr : integer range -10 to 255; |
signal intr_width : integer range 0 to 255; |
signal int_vector_index : integer range 0 to 3; |
signal addr_vector_table: integer range 0 to 65535; |
|
signal con_line_buf : string(1 to 80); |
signal con_line_ix : integer; |
|
|
|
type t_ram is array(0 to 65536-1) of std_logic_vector(7 downto 0); |
|
-- Using shared variables for big memory arrays speeds up simulation a lot; |
-- see Modelsim 6.3 User Manual, section on 'Modelling Memory'. |
-- WARNING: I have only tested this construct with Modelsim SE 6.3. |
shared variable ram : t_ram := ( others => X"00"); |
|
procedure load_object_code( |
signal obj : in t_obj_code; |
memory : inout t_ram) is |
variable i : integer; |
begin |
|
-- (Assume the array is defined with ascending indices) |
for i in obj'left to obj'right loop |
memory(i) := obj(i); |
end loop; |
|
end procedure load_object_code; |
|
|
|
begin |
|
-- Instantiate the Unit Under Test (UUT) |
cpu: entity work.light8080 |
port map ( |
clk => clk, |
reset => reset, |
vma => vma_o, |
rd => rd_o, |
wr => wr_o, |
io => io_o, |
fetch => fetch_o, |
addr_out => addr_o, |
data_in => data_i, |
data_out => data_o, |
|
intr => intr_i, |
inte => inte_o, |
inta => inta_o, |
halt => halt_o |
); |
|
|
-- clock: run clock until test is done |
clock: |
process(done, clk) |
begin |
if done = '0' then |
clk <= not clk after T/2; |
end if; |
end process clock; |
|
|
-- Drive reset and done |
main_test: |
process |
begin |
-- Load object code on memory -- note this comsumes no simulated time |
load_object_code(obj_code, ram); |
|
-- Assert reset for at least one full clk period |
reset <= '1'; |
wait until clk = '1'; |
wait for T/2; |
reset <= '0'; |
|
-- Remember to 'cut away' the preceding 3 clk semiperiods from |
-- the wait statement... |
wait for (MAX_SIM_LENGTH - T*1.5); |
|
-- Maximum sim time elapsed, assume the program ran away and |
-- stop the clk process asserting 'done' (which will stop the simulation) |
done <= '1'; |
|
assert (done = '1') |
report "Test timed out." |
severity failure; |
|
wait; |
end process main_test; |
|
|
-- Synchronous RAM covering the whole address map |
synchronous_ram: |
process(clk) |
begin |
if (clk'event and clk='1') then |
data_mem <= ram(conv_integer(addr_o)); |
if wr_o = '1' then |
ram(conv_integer(addr_o)) := data_o; |
end if; |
end if; |
end process synchronous_ram; |
|
|
irq_trigger_register: |
process(clk) |
begin |
if (clk'event and clk='1') then |
if reset='1' then |
cycles_to_intr <= -10; -- meaning no interrupt pending |
else |
if io_o='1' and wr_o='1' and addr_o(7 downto 0)=X"11" then |
cycles_to_intr <= conv_integer(data_o) + 1; |
else |
if cycles_to_intr >= 0 then |
cycles_to_intr <= cycles_to_intr - 1; |
end if; |
end if; |
end if; |
end if; |
end process irq_trigger_register; |
|
irq_pulse_width_register: |
process(clk) |
variable intr_pulse_countdown : integer; |
begin |
if (clk'event and clk='1') then |
if reset='1' then |
intr_width <= 1; |
intr_pulse_countdown := 0; |
intr_i <= '0'; |
else |
if io_o='1' and wr_o='1' and addr_o(7 downto 0)=X"12" then |
intr_width <= conv_integer(data_o) + 1; |
end if; |
|
if cycles_to_intr = 0 then |
intr_i <= '1'; |
intr_pulse_countdown := intr_width; |
elsif intr_pulse_countdown <= 1 then |
intr_i <= '0'; |
else |
intr_pulse_countdown := intr_pulse_countdown - 1; |
end if; |
end if; |
end if; |
end process irq_pulse_width_register; |
|
irq_source_register: |
process(clk) |
begin |
if (clk'event and clk='1') then |
if reset='1' then |
irq_source <= 0; |
else |
if io_o='1' and wr_o='1' and addr_o(7 downto 0)=X"10" then |
irq_source <= conv_integer(data_o(2 downto 0)); |
end if; |
end if; |
end if; |
end process irq_source_register; |
|
|
-- 'interrupt vector' logic. |
irq_vector_table: |
process(clk) |
begin |
if (clk'event and clk='1') then |
if vma_o = '1' and rd_o='1' then |
if inta_o = '1' then |
int_vector_index <= int_vector_index + 1; |
else |
int_vector_index <= 0; |
end if; |
end if; |
-- this is the address of the byte we'll feed to the CPU |
addr_vector_table <= 64+irq_source*4+int_vector_index; |
end if; |
end process irq_vector_table; |
irq_vector_byte <= ram(addr_vector_table); |
|
data_i <= data_mem when inta_o='0' else irq_vector_byte; |
|
|
test_outcome_register: |
process(clk) |
variable outcome : std_logic_vector(7 downto 0); |
begin |
if (clk'event and clk='1') then |
if io_o='1' and wr_o='1' and addr_o(7 downto 0)=X"20" then |
assert (data_o /= X"55") report "Software reports SUCCESS" severity failure; |
assert (data_o /= X"aa") report "Software reports FAILURE" severity failure; |
assert ((data_o = X"aa") or (data_o = X"55")) |
report "Software reports unexpected outcome value." |
severity failure; |
end if; |
end if; |
end process test_outcome_register; |
|
|
dummy_uart_output_reg: |
process(clk) |
variable outcome : std_logic_vector(7 downto 0); |
begin |
if (clk'event and clk='1') then |
if io_o='1' and wr_o='1' and addr_o(7 downto 0)=X"21" then |
-- append char to output string |
if con_line_ix < con_line_buf'high then |
con_line_buf(con_line_ix) <= character'val(conv_integer(data_o)); |
con_line_ix <= con_line_ix + 1; |
end if; |
end if; |
end if; |
end process dummy_uart_output_reg; |
|
|
end; |
/trunk/tools/readme.txt
0,0 → 1,41
This directory contains support tools meant for software development on the |
light8080 SoC. |
|
|
ihex2vlog: Object code to Verilog constant conversion. |
|
Reads an Intel HEX file and generates memory Verilog module or Xilinx |
RAMB16/RAMB4 verilog initialization vectors. |
Run 'ihex2vlog' with no arguments to get usage instructions. |
|
Supplied as C source and Windows precompiled binary. |
|
c80: Small C compiler modified to support the light8080 SoC. |
|
This is a port of the classic Small C compiler, with some new features and |
including support files for the light8080 SoC. |
|
Supplied as C source and precompiled Windows binary. |
|
obj2hdl: Object code to VHDL |
|
Reads an Intel HEX file and produces an VHDL package used to initialize |
the SoC internal memory. |
Invoke without arguments to get some usage help. |
|
Supplied as portable Python source plus helper DOS BATCH script. |
|
hexconv: Insertion of HEX object code into VHDL template. |
|
Reads an Intel HEX file and inserts the object code into an VHDL test |
bench template whose name is given as parameter. |
|
Invoke without arguments to get some usage help. |
|
This program was used in the early versions of the project to build the |
VHDL test benches from a common template. It is no longer used. The old |
template is included in the hexconv directory; it may be useful as an usage |
example. |
|
Supplied as portable Perl script. |
|