Compare commits
60
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1df213b6a7 | ||
|
|
55ac1b23c6 | ||
|
|
f168a4f183 | ||
|
|
b21e3c580b | ||
|
|
08e1a114c4 | ||
|
|
f9539b5992 | ||
|
|
3b5ccc5280 | ||
|
|
609e7bf64d | ||
|
|
518af7c679 | ||
|
|
132bbf0991 | ||
|
|
9e346d7894 | ||
|
|
0e235ab598 | ||
|
|
ddabf14706 | ||
|
|
d3beeb0538 | ||
|
|
cbc093e6e7 | ||
|
|
858948adb6 | ||
|
|
fdf80ae302 | ||
|
|
fb4ca98ad3 | ||
|
|
d54a810a4a | ||
|
|
fb82e4a702 | ||
|
|
ca8011bfc4 | ||
|
|
b039ae7c14 | ||
|
|
ac878a877d | ||
|
|
4d35c766e0 | ||
|
|
e4acf4af81 | ||
|
|
cf0e2229f5 | ||
|
|
288ed8d40c | ||
|
|
3202f415fb | ||
|
|
31d67095da | ||
|
|
c2f02e6eed | ||
|
|
87282eccec | ||
|
|
bcc18b973c | ||
|
|
f0d6f26adf | ||
|
|
0e278ee393 | ||
|
|
228ae4e3e9 | ||
|
|
e834c61493 | ||
|
|
eaf4a7765e | ||
|
|
becba12800 | ||
|
|
158baf8330 | ||
|
|
79b31d80c7 | ||
|
|
7a140c617c | ||
|
|
6085b37907 | ||
|
|
2c6a0b9c99 | ||
|
|
9148ac7087 | ||
|
|
110c3a24b4 | ||
|
|
be1195f618 | ||
|
|
1e2b78f766 | ||
|
|
52a04ee67d | ||
|
|
904023f9d6 | ||
|
|
83b54469b6 | ||
|
|
96ae71d192 | ||
|
|
84c2d09cf4 | ||
|
|
e42a97f5a0 | ||
|
|
de6be19c12 | ||
|
|
a38a63fb9e | ||
|
|
33c3c31353 | ||
|
|
240c12126a | ||
|
|
4e55a80489 | ||
|
|
5e84a0851c | ||
|
|
326bda000e |
@@ -49,7 +49,7 @@ SIM_FILE-fst := $(BUILD_DIR)/$(TARGET).fst
|
||||
GTK_OPTS-fst := --fst=$(SIM_FILE-fst)
|
||||
|
||||
SIM_FILE-ghw := $(BUILD_DIR)/$(TARGET).ghw
|
||||
GTK_OPTS-ghw := --wave=$(SIM_FILE-ghw)
|
||||
GTK_OPTS-ghw := --wave=$(SIM_FILE-ghw) --read-wave-opt=$(TARGET).wopt
|
||||
|
||||
SIM_FILE := $(SIM_FILE-$(WAVE_FORMAT))
|
||||
GTK_OPTS := $(GTK_OPTS-$(WAVE_FORMAT))
|
||||
@@ -62,8 +62,6 @@ all: analyze
|
||||
|
||||
$(WORK_DIR):
|
||||
mkdir -p $@
|
||||
touch $(TARGET).gtkw
|
||||
cp -n $(TARGET).gtkw $(BUILD_DIR)
|
||||
|
||||
syntax:
|
||||
$(GHDL) -s $(GHDL_OPTS) $(SRCS)
|
||||
@@ -96,15 +94,19 @@ synth: analyze
|
||||
$(GHDL) --synth $(GHDL_OPTS) $(ENTITY)
|
||||
|
||||
wave: run_wave
|
||||
exec gtkwave -f $(SIM_FILE) -a $(BUILD_DIR)/$(TARGET).gtkw &
|
||||
exec gtkwave -f $(SIM_FILE) -a $(TARGET).gtkw &
|
||||
|
||||
result:
|
||||
exec gtkwave -f $(SIM_FILE) -a $(BUILD_DIR)/$(TARGET).gtkw &
|
||||
exec gtkwave -f $(SIM_FILE) -a $(TARGET).gtkw &
|
||||
|
||||
tree: analyze
|
||||
$(GHDL) -r $(GHDL_OPTS) $(ENTITY) $(RUN_OPTS) --no-run --disp-tree=inst
|
||||
|
||||
|
||||
genwopt: analyze
|
||||
rm -rf $(TARGET).wopt.templ
|
||||
$(GHDL) -r $(GHDL_OPTS) $(ENTITY) --stop-time=0ps --write-wave-opt=$(TARGET).wopt.templ --wave=$(BUILD_DIR)/$(TARGET).ghw
|
||||
|
||||
|
||||
.PHONY: list
|
||||
INSTR = $(foreach number,$(SRCS),echo $(number);)
|
||||
list:
|
||||
@@ -13,6 +13,10 @@ NETLIST_DIR ?= ./
|
||||
MAP_EFFORT ?= high
|
||||
PAR_EFFORT ?= high
|
||||
|
||||
BUILD_DIR := ./
|
||||
XST_DIR := $(BUILD_DIR)/xst/tmp
|
||||
DIRS := $(XST_DIR)
|
||||
|
||||
# Netlist
|
||||
$(PRJ).ngc: $(DIRS) $(PREQ) ./project/$(PRJ).ucf
|
||||
xst -intstyle xflow -ifn ./project/$(PRJ).xst
|
||||
@@ -0,0 +1,4 @@
|
||||
.gitignore
|
||||
build/
|
||||
.gitignore
|
||||
build/
|
||||
@@ -1,7 +1,7 @@
|
||||
# -------------------------------------------------
|
||||
# Compile script for GHDL
|
||||
# -------------------------------------------------
|
||||
include ../make/defs.mk
|
||||
include $(VHDL_HOME)/make/defs.mk
|
||||
|
||||
# -------------------------------------------------
|
||||
# Global options
|
||||
@@ -9,20 +9,21 @@ include ../make/defs.mk
|
||||
LANG_STD := 93c
|
||||
IEEE_STD := standard
|
||||
WORK_LIB := ieee_proposed
|
||||
TARGET := ieee_proposed
|
||||
TARGET := ghdl
|
||||
|
||||
STD_LIB_PATH := ieee_proposed/modelsim
|
||||
# -------------------------------------------------
|
||||
# Target options
|
||||
# -------------------------------------------------
|
||||
SRCS := $(LIB_PATH)/standard_additions_c.vhdl
|
||||
SRCS += $(LIB_PATH)/standard_textio_additions_c.vhdl
|
||||
SRCS += $(LIB_PATH)/env_c.vhdl
|
||||
SRCS += $(LIB_PATH)/std_logic_1164_additions.vhdl
|
||||
SRCS += $(LIB_PATH)/numeric_std_additions.vhdl
|
||||
SRCS += $(LIB_PATH)/numeric_std_unsigned_c.vhdl
|
||||
SRCS += $(LIB_PATH)/fixed_float_types_c.vhdl
|
||||
SRCS += $(LIB_PATH)/fixed_pkg_c.vhdl
|
||||
SRCS += $(LIB_PATH)/float_pkg_c.vhdl
|
||||
SRCS := $(STD_LIB_PATH)/standard_additions_c.vhdl
|
||||
SRCS += $(STD_LIB_PATH)/standard_textio_additions_c.vhdl
|
||||
SRCS += $(STD_LIB_PATH)/env_c.vhdl
|
||||
SRCS += $(STD_LIB_PATH)/std_logic_1164_additions.vhdl
|
||||
SRCS += $(STD_LIB_PATH)/numeric_std_additions.vhdl
|
||||
SRCS += $(STD_LIB_PATH)/numeric_std_unsigned_c.vhdl
|
||||
SRCS += $(STD_LIB_PATH)/fixed_float_types_c.vhdl
|
||||
SRCS += $(STD_LIB_PATH)/fixed_pkg_c.vhdl
|
||||
SRCS += $(STD_LIB_PATH)/float_pkg_c.vhdl
|
||||
|
||||
include ../make/ghdl.mk
|
||||
include $(VHDL_HOME)/make/ghdl.mk
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# -------------------------------------------------
|
||||
# Compile script for GHDL
|
||||
# -------------------------------------------------
|
||||
include ../make/defs.mk
|
||||
include $(VHDL_HOME)/make/defs.mk
|
||||
|
||||
# -------------------------------------------------
|
||||
# Global options
|
||||
@@ -9,18 +9,19 @@ include ../make/defs.mk
|
||||
LANG_STD := 93c
|
||||
IEEE_STD := standard
|
||||
WORK_LIB := unisim
|
||||
TARGET := unisim
|
||||
TARGET := ghdl
|
||||
|
||||
STD_LIB_PATH := xilinx/libsrc/unisims
|
||||
# -------------------------------------------------
|
||||
# Target options
|
||||
# -------------------------------------------------
|
||||
SRCS := $(LIB_PATH)/unisims/unisim_VPKG.vhd
|
||||
SRCS += $(LIB_PATH)/unisims/unisim_VCOMP.vhd
|
||||
SRCS += $(LIB_PATH)/unisims/unisim_SMODEL.vhd
|
||||
SRCS += $(LIB_PATH)/unisims/unisim_VITAL.vhd
|
||||
SRCS := $(STD_LIB_PATH)/unisim_VPKG.vhd
|
||||
SRCS += $(STD_LIB_PATH)/unisim_VCOMP.vhd
|
||||
SRCS += $(STD_LIB_PATH)/unisim_SMODEL.vhd
|
||||
SRCS += $(STD_LIB_PATH)/unisim_VITAL.vhd
|
||||
|
||||
GHDL_OPTS := -fsynopsys -fexplicit
|
||||
|
||||
include ../make/ghdl.mk
|
||||
include $(VHDL_HOME)/make/ghdl.mk
|
||||
|
||||
|
||||
|
||||
Executable
+42
@@ -0,0 +1,42 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
str1 = %Q!lbl: dc "Hallo", ", ", 0, 1, " der","Jens"!
|
||||
|
||||
i=0;
|
||||
|
||||
def get_stri_lit (str)
|
||||
res = [""];
|
||||
state = "out"
|
||||
|
||||
j = 0;
|
||||
k = 0;
|
||||
for i in (0..str.length-1)
|
||||
c = str[i];
|
||||
nstate = state
|
||||
case state
|
||||
when "out"
|
||||
if c == "\""[0]
|
||||
nstate = "in"
|
||||
end
|
||||
when "in"
|
||||
if c == "\""[0]
|
||||
nstate = "out"
|
||||
if j > 0
|
||||
k = k + 1;
|
||||
res[k] = ""
|
||||
end
|
||||
else
|
||||
res[k] = res[k] + format("%c", c);
|
||||
j = j + 1;
|
||||
end
|
||||
end
|
||||
state = nstate
|
||||
end;
|
||||
return res
|
||||
end
|
||||
|
||||
get_stri_lit(str1).each do |word|
|
||||
puts word
|
||||
end
|
||||
|
||||
|
||||
Executable
+46
@@ -0,0 +1,46 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Project: JCPU, a portable 8-bit RISC CPU written in VHDL
|
||||
# This file: Insertion of code fragments into templates
|
||||
#
|
||||
# Copyright (C) 2007 J. Ahrensfeld
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# For questions and ideas, please contact the author at jens@jayfield.org
|
||||
#
|
||||
# ---------------------------------------------------------------------
|
||||
|
||||
arg = $*
|
||||
rom_filename = arg[0].to_s
|
||||
tpl_filename = arg[1].to_s
|
||||
|
||||
subst_pattern = "JASM_ROM_INSERT_HERE"
|
||||
|
||||
# --------------------------------------------------------
|
||||
# Open file
|
||||
# --------------------------------------------------------
|
||||
romfile = File.open(rom_filename, "r")
|
||||
tplfile = File.open(tpl_filename, "r")
|
||||
re = Regexp.new(subst_pattern)
|
||||
|
||||
while (line = tplfile.gets)
|
||||
puts line
|
||||
line.scan(re).each do |word|
|
||||
romfile.each do |raw_line|
|
||||
puts raw_line
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,32 @@
|
||||
-------------------------------------------------------------------------
|
||||
-- Project: JCPU, a portable 8-bit RISC CPU written in VHDL
|
||||
-- This file: The ROM file for use in your VHDL design
|
||||
--
|
||||
-- Copyright (C) 2007 J. Ahrensfeld
|
||||
--
|
||||
-- This program is free software: you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation, either version 3 of the License, or
|
||||
-- (at your option) any later version.
|
||||
--
|
||||
-- This program 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 General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
--
|
||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||
--
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
LIBRARY ieee;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
USE ieee.numeric_std.ALL;
|
||||
|
||||
library work;
|
||||
use work.cpu_pkg.all;
|
||||
|
||||
-- JASM_ROM_INSERT_HERE
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
-------------------------------------------------------------------------
|
||||
-- Project: JCPU, a portable 8-bit RISC CPU written in VHDL
|
||||
-- This file: loadable ROM
|
||||
--
|
||||
-- Copyright (C) 2007 J. Ahrensfeld
|
||||
--
|
||||
-- This program is free software: you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation, either version 3 of the License, or
|
||||
-- (at your option) any later version.
|
||||
--
|
||||
-- This program 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 General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
--
|
||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||
--
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
LIBRARY ieee;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
USE ieee.numeric_std.ALL;
|
||||
|
||||
library UNISIM;
|
||||
use UNISIM.VComponents.all;
|
||||
|
||||
library work;
|
||||
use work.cpu_pkg.all;
|
||||
|
||||
ENTITY irom IS
|
||||
Port (
|
||||
clk : in STD_LOGIC;
|
||||
ce : in STD_LOGIC;
|
||||
addr : in inst_addr_t;
|
||||
dout : out inst_t
|
||||
);
|
||||
|
||||
END irom;
|
||||
|
||||
ARCHITECTURE loadable OF irom IS
|
||||
|
||||
-- JASM_ROM_INSERT_HERE
|
||||
|
||||
signal jtag_ld_clk : STD_LOGIC;
|
||||
signal jtag_ld_we : STD_LOGIC;
|
||||
signal jtag_ld_addr : inst_addr_t;
|
||||
signal jtag_ld_dout : inst_t;
|
||||
signal jtag_ld_din : inst_t;
|
||||
signal bs_rst, bs_sel, bs_shift, bs_tdi, bs_tdo : std_logic;
|
||||
signal bs_capture, bs_clk0, bs_clk1, bs_update0, bs_update1 : std_logic;
|
||||
signal user_regi, user_rego : unsigned (31 downto 0);
|
||||
constant id : unsigned (31 downto 0) := X"BABE" & X"BEEF";
|
||||
|
||||
begin
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
-- Virtex-4: JTAG Loader
|
||||
--------------------------------------------------------------------------
|
||||
i00_BUFG : BUFG
|
||||
port map
|
||||
(
|
||||
O => bs_clk1,
|
||||
I => bs_clk0
|
||||
);
|
||||
|
||||
i01_BUFG : BUFG
|
||||
port map
|
||||
(
|
||||
O => bs_update1,
|
||||
I => bs_update0
|
||||
);
|
||||
|
||||
BSCAN_VIRTEX4_inst1 : BSCAN_VIRTEX4
|
||||
generic map
|
||||
(
|
||||
JTAG_CHAIN => 1 -- Value to set BSCAN site of device. Possible values: (1,2,3 or 4)
|
||||
)
|
||||
port map
|
||||
(
|
||||
CAPTURE => bs_capture, -- CAPTURE output from TAP controller
|
||||
DRCK => bs_clk0, -- Data register output for USER functions
|
||||
RESET => bs_rst, -- Reset output from TAP controller
|
||||
SEL => bs_sel, -- USER active output
|
||||
SHIFT => bs_shift, -- SHIFT output from TAP controller
|
||||
TDI => bs_tdi, -- TDI output from TAP controller
|
||||
UPDATE => bs_update0, -- UPDATE output from TAP controller
|
||||
TDO => bs_tdo -- Data input for USER function
|
||||
);
|
||||
|
||||
jtag_ld_addr <= user_regi(user_regi'left downto user_regi'left-inst_addr_t'length+1);
|
||||
jtag_ld_din <= user_regi(inst_t'length-1 downto 0);
|
||||
jtag_ld_clk <= bs_update1;
|
||||
jtag_ld_we <= bs_sel;
|
||||
|
||||
sipo:
|
||||
process (bs_rst, bs_clk1, bs_tdi, bs_shift)
|
||||
begin
|
||||
if bs_rst = '1' then
|
||||
user_regi <= (others => '0');
|
||||
elsif rising_edge(bs_clk1) then
|
||||
if bs_shift = '1' then
|
||||
user_regi <= bs_tdi & user_regi(user_regi'left downto 1);
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
piso:
|
||||
process (bs_rst, bs_clk1, bs_shift, user_rego)
|
||||
begin
|
||||
bs_tdo <= user_rego(0);
|
||||
if bs_rst = '1' then
|
||||
user_rego <= (others => '0');
|
||||
elsif rising_edge(bs_clk1) then
|
||||
if bs_shift = '1' then
|
||||
user_rego <= user_rego(0) & user_rego(user_rego'left downto 1);
|
||||
else
|
||||
user_rego <= (user_rego'left downto inst_t'length => '0') & jtag_ld_dout;
|
||||
-- user_rego <= id;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
-- ROM Read/Write
|
||||
--------------------------------------------------------------------------
|
||||
PROM_READ:
|
||||
process(clk, ce)
|
||||
begin
|
||||
if rising_edge(clk) and ce = '1' then
|
||||
dout <= imem_rom(to_integer(addr));
|
||||
end if;
|
||||
end process;
|
||||
|
||||
PROM_WRITE:
|
||||
process(jtag_ld_clk, jtag_ld_we)
|
||||
begin
|
||||
if rising_edge(jtag_ld_clk) then
|
||||
if jtag_ld_we = '1' then
|
||||
imem_rom(to_integer(jtag_ld_addr)) <= jtag_ld_din;
|
||||
else
|
||||
jtag_ld_dout <= imem_rom(to_integer(jtag_ld_addr));
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
end loadable;
|
||||
Executable
+494
@@ -0,0 +1,494 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Project: JCPU, a portable 8-bit RISC CPU written in VHDL
|
||||
# This file: A small assembler for the JCPU
|
||||
|
||||
# Copyright (C) 2007 J. Ahrensfeld
|
||||
|
||||
# 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.
|
||||
|
||||
# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
# For questions and ideas, please contact the author at jens@jayfield.org
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
|
||||
arg = $*
|
||||
MAX_SIZE_ROM = 1024
|
||||
PROJECT_NAME = arg.to_s.gsub(/\..*/, "")
|
||||
ENTITY_NAME = "rom"
|
||||
ENTITY_DATA_TYPE = "inst_t"
|
||||
ENTITY_ADDR_TYPE = "inst_addr_t"
|
||||
OPC_LIST_NAME = "/cygdrive/w/vhdl/lib/CPUs/JCpu/tools/opc.list"
|
||||
|
||||
# --------------------------------------------------------
|
||||
# Open file
|
||||
# --------------------------------------------------------
|
||||
filename = arg.to_s
|
||||
if !File.exists?(filename)
|
||||
STDERR.puts "#{filename} does not exist"
|
||||
exit 1
|
||||
end
|
||||
|
||||
# --------------------------------------------------------
|
||||
# Pass 1
|
||||
# --------------------------------------------------------
|
||||
lc = 0 # Line counter
|
||||
pc = 0 # Program counter
|
||||
chip_dc = [0,0,0,0] # chip data counter
|
||||
xmem_dc = 0 # xmem data counter
|
||||
curr_segment = "UNDEF";
|
||||
page = 0
|
||||
|
||||
label_list=[[],[]]
|
||||
instr_list=[nil]
|
||||
file = File.open(filename, "r")
|
||||
file.each do |raw_line|
|
||||
lc += 1
|
||||
|
||||
# Make all upper case
|
||||
iline = "#{raw_line}".strip.upcase
|
||||
|
||||
# Remove comments
|
||||
iline = iline.gsub(/;.*/, "")
|
||||
|
||||
# Split instruction at spaces
|
||||
iline_member = iline.split(" ")
|
||||
|
||||
if iline_member[0] == nil
|
||||
next
|
||||
end
|
||||
|
||||
mc = 0;
|
||||
label = nil
|
||||
clean_line = nil
|
||||
if (iline_member[0] =~ /\w+:/)
|
||||
mc += 1
|
||||
label = iline_member[0].delete(":")
|
||||
if label_list.rindex(label) != nil
|
||||
STDERR.puts format("Error in line %d: Duplicate label \"%s\" found", lc, label)
|
||||
exit 1
|
||||
end
|
||||
end
|
||||
|
||||
case iline_member[mc]
|
||||
when nil
|
||||
value = format("0x%3.3X",pc)
|
||||
when "EQU"
|
||||
if 0 == (iline_member[mc+1] =~ /\d+/)
|
||||
value = format("0x%2.2X",eval(iline_member[mc+1..iline_member.nitems].to_s))
|
||||
else
|
||||
value = iline_member[mc+1]
|
||||
end
|
||||
when "ORG", "CODE"
|
||||
pc = eval(iline_member[mc+1..iline_member.nitems].to_s)
|
||||
value = format("0x%3.3X",pc)
|
||||
when "CDATA", "CMEM"
|
||||
if iline_member[mc+1] == nil
|
||||
STDERR.puts format("Error in line %d: CDATA needs argument!", lc)
|
||||
exit 1
|
||||
end
|
||||
curr_segment = "CMEM";
|
||||
page = iline_member[mc+1].to_i(16)
|
||||
when "XDATA", "XMEM"
|
||||
curr_segment = "XMEM";
|
||||
when "DC"
|
||||
len = 0;
|
||||
iline.split("DC")[1].delete("0x").scan(/[0-9A-Fa-f]+/).each do |byte|
|
||||
len += 1
|
||||
end
|
||||
if curr_segment == "CMEM"
|
||||
STDERR.puts format("Error in line %d: CDATA cannot be initialized!", lc)
|
||||
exit 1
|
||||
else
|
||||
value = format("0x%2.2X",xmem_dc)
|
||||
puts format("Found DC defining %d bytes at 0x%4.4X in %s", len, xmem_dc, curr_segment);
|
||||
xmem_dc += len
|
||||
end
|
||||
when "DB"
|
||||
len = iline_member[mc+1].to_i
|
||||
if curr_segment == "CMEM"
|
||||
value = format("0x%2.2X",chip_dc[page])
|
||||
puts format("Found DB reserving %d bytes at 0x%4.4X in %s(%d)", len, chip_dc[page], curr_segment, page);
|
||||
chip_dc[page] += len
|
||||
else
|
||||
value = format("0x%2.2X",xmem_dc)
|
||||
puts format("Found DB reserving %d bytes at 0x%4.4X in %s", len, xmem_dc, curr_segment);
|
||||
xmem_dc += len
|
||||
end
|
||||
else
|
||||
op_line = iline_member[mc+1..iline_member.nitems].to_s
|
||||
value = format("0x%3.3X",pc)
|
||||
opc = iline_member[mc]
|
||||
if iline_member[mc+1] != nil
|
||||
op1 = op_line.gsub(/,+.*$/, "")
|
||||
end
|
||||
if iline_member[mc+2] != nil
|
||||
op2 = op_line.scan(/,.+$/).to_s.delete(", ")
|
||||
end
|
||||
if instr_list[pc] == nil
|
||||
instr_list[pc] = [lc, pc, opc , op1 , op2]
|
||||
pc += 1
|
||||
else
|
||||
STDERR.puts format("Error in line %d: Overlapping sections at %3.3X", lc, pc)
|
||||
exit 1
|
||||
end
|
||||
end;
|
||||
|
||||
# Push labels
|
||||
if label
|
||||
label_list = label_list + [label, value]
|
||||
end
|
||||
end
|
||||
file.close
|
||||
|
||||
# --------------------------------------------------------
|
||||
def instr(opcode)
|
||||
return format("\"%6.6B\" & X\"%3.3X\"",opcode ,0)
|
||||
end
|
||||
|
||||
def tcl_bits(pc, opcode)
|
||||
return format("%10.10B%6.6B%12.12B",pc, opcode ,0)
|
||||
end
|
||||
|
||||
def instr_k(opcode, k)
|
||||
return format("\"%6.6B\" & X\"%3.3X\"",opcode ,k)
|
||||
end
|
||||
|
||||
def tcl_bits_k(pc, opcode, k)
|
||||
return format("%10.10B%6.6B%12.12B",pc, opcode ,k)
|
||||
end
|
||||
|
||||
def instr_r(opcode, r)
|
||||
return format("\"%6.6B\" & X\"%2.2X%X\"",opcode ,0, r)
|
||||
end
|
||||
|
||||
def tcl_bits_r(pc, opcode, r)
|
||||
return format("%10.10B%6.6B%8.8B%4.4B",pc, opcode ,0,r)
|
||||
end
|
||||
|
||||
def instr_kr(opcode, k, r)
|
||||
return format("\"%6.6B\" & X\"%2.2X%X\"",opcode,k, r)
|
||||
end
|
||||
|
||||
def tcl_bits_kr(pc, opcode, k, r)
|
||||
return format("%10.10B%6.6B%8.8B%4.4B",pc, opcode, k, r)
|
||||
end
|
||||
|
||||
def instr_rk(opcode, r, k)
|
||||
return format("\"%6.6B\" & X\"%2.2X%X\"",opcode,k, r)
|
||||
end
|
||||
|
||||
def tcl_bits_rk(pc, opcode, r, k)
|
||||
return format("%10.10B%6.6B%8.8B%4.4B",pc, opcode, k, r)
|
||||
end
|
||||
|
||||
def instr_rr(opcode, ra, rb)
|
||||
return format("\"%6.6B\" & X\"%X%X%X\"",opcode,0, rb, ra)
|
||||
end
|
||||
|
||||
def tcl_bits_rr(pc, opcode, ra, rb)
|
||||
return format("%10.10B%6.6B%4.4B%4.4B%4.4B",pc, opcode, 0, rb, ra)
|
||||
end
|
||||
|
||||
# --------------------------------------------------------
|
||||
# Read mnemonic set
|
||||
# --------------------------------------------------------
|
||||
filename = OPC_LIST_NAME
|
||||
if !File.exists?(filename)
|
||||
STDERR.puts "#{filename} does not exist"
|
||||
exit 1
|
||||
end
|
||||
|
||||
mnemo_list = []
|
||||
num_opcodes = 0
|
||||
file = File.open(filename, "r")
|
||||
file.each do |raw_line|
|
||||
mnemo_list[num_opcodes] = raw_line.split(" ")[1]
|
||||
num_opcodes += 1
|
||||
end
|
||||
|
||||
# --------------------------------------------------------
|
||||
# Pass 2
|
||||
# --------------------------------------------------------
|
||||
pc = 0
|
||||
opc_start = 2
|
||||
num_errors = 0
|
||||
vhdl_trans_list = [nil]
|
||||
vhdl_comment_list = [nil]
|
||||
vhdl_tcl_list = [nil]
|
||||
instr_list.each do |instruct|
|
||||
|
||||
# puts instruct
|
||||
if instruct == nil
|
||||
vhdl_trans_list[pc] = format("\"%6.6B\" & X\"%3.3X\"",0 ,0)
|
||||
vhdl_comment_list[pc] = format("0x%3.3X:", pc)
|
||||
vhdl_tcl_list[pc] = tcl_bits(pc, 0)
|
||||
pc += 1
|
||||
next
|
||||
end
|
||||
|
||||
# determine arglen of instruction
|
||||
ilen = 0
|
||||
if instruct[opc_start+1] == nil
|
||||
arglen = 0
|
||||
elsif instruct[opc_start+2] == nil
|
||||
arglen = 1
|
||||
elsif instruct[opc_start+3] == nil
|
||||
arglen = 2
|
||||
end
|
||||
|
||||
# Symbol substitution
|
||||
error = false
|
||||
for i in (1..3)
|
||||
subst_pos = opc_start+i
|
||||
if instruct[subst_pos] == nil
|
||||
next
|
||||
end
|
||||
expr_token = ""
|
||||
expr_subst = nil
|
||||
is_direct = true;
|
||||
|
||||
# instruct[subst_pos] = instruct[subst_pos].delete(" ")
|
||||
|
||||
# checks R0 .. R16, Mnemonics
|
||||
instr_str = instruct[subst_pos]
|
||||
if 0 == (instr_str =~ /\(.+\)/)
|
||||
instr_str = instr_str.delete("()")
|
||||
is_direct = false;
|
||||
end
|
||||
|
||||
expr_token = instr_str.split(/\+|\-|\*|\//)[0]
|
||||
if (0 != (expr_token =~ /R[0-9]+/)) && (0 != (expr_token =~ /\d+/))
|
||||
idx = label_list.rindex(expr_token)
|
||||
if idx != nil
|
||||
expr_subst = label_list[idx+1]
|
||||
instruct[subst_pos] = instruct[subst_pos].gsub(expr_token, expr_subst)
|
||||
else
|
||||
STDERR.puts format("Error in line %d: Symbol \"%s\" not found", instruct[0], expr_token)
|
||||
error = true
|
||||
end
|
||||
end
|
||||
|
||||
if expr_subst != nil
|
||||
if 0 == (expr_subst =~ /\d+/)
|
||||
if is_direct == true
|
||||
instruct[subst_pos] = format("0x%2.2X", eval(instruct[subst_pos]))
|
||||
else
|
||||
instruct[subst_pos] = format("(0x%2.2X)", eval(instruct[subst_pos]))
|
||||
end
|
||||
else
|
||||
if 0 != (expr_subst =~ /R[0-9]+/)
|
||||
STDERR.puts format("Error in line %d: Invalid expression \"%s\"", instruct[0], expr_subst)
|
||||
error = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Parse operands
|
||||
reg = [0,0]
|
||||
kk = 0
|
||||
format = instruct[opc_start]
|
||||
for i in (0..1)
|
||||
if instruct[opc_start+i+1] =~ Regexp.new("R[0-9]+")
|
||||
# Check indirect addressing
|
||||
reg[i] = instruct[opc_start+i+1].delete("R()").to_i
|
||||
format += "|R"
|
||||
if reg[i] > 15
|
||||
STDERR.puts format("Error in line %d: Invalid register \"R%d\" specified", instruct[0], reg[i])
|
||||
error = true
|
||||
end
|
||||
else
|
||||
if instruct[opc_start+i+1] =~ Regexp.new("[0-9A-F]+")
|
||||
kk = instruct[opc_start+i+1].delete("()").to_i(16)
|
||||
format += "|K"
|
||||
end
|
||||
end
|
||||
if instruct[opc_start+i+1] =~ Regexp.new("\\(.+\\)")
|
||||
format += "i";
|
||||
end
|
||||
end
|
||||
|
||||
# Output instruction
|
||||
opcode = mnemo_list.rindex(format).to_i
|
||||
mnemo = instruct[2];
|
||||
|
||||
case format
|
||||
when "NOP", "HALT", "RET", "RETI"
|
||||
vhdl_trans_list[pc] = instr(opcode)
|
||||
vhdl_tcl_list[pc] = tcl_bits(pc, opcode)
|
||||
minstr_comment = format("0x%3.3X: %s", pc, mnemo)
|
||||
when "MOVC|R|Ri", "MOVX|R|Ri"
|
||||
vhdl_trans_list[pc] = instr_rr(opcode, reg[0], reg[1]);
|
||||
vhdl_tcl_list[pc] = tcl_bits_rr(pc, opcode, reg[0], reg[1])
|
||||
minstr_comment = format("0x%3.3X: %s R%2.2d, (R%2.2d)", pc, mnemo, reg[0], reg[1])
|
||||
when "MOV|R|R", "SUB|R|R", "ADD|R|R", "AND|R|R", "OR|R|R", "XOR|R|R", "CMP|R|R"
|
||||
vhdl_trans_list[pc] = instr_rr(opcode, reg[0], reg[1]);
|
||||
vhdl_tcl_list[pc] = tcl_bits_rr(pc, opcode, reg[0], reg[1])
|
||||
minstr_comment = format("0x%3.3X: %s R%2.2d, R%2.2d", pc, mnemo, reg[0], reg[1])
|
||||
when "MOVC|Ri|R", "MOVX|Ri|R"
|
||||
vhdl_trans_list[pc] = instr_rr(opcode, reg[1], reg[0]);
|
||||
vhdl_tcl_list[pc] = tcl_bits_rr(pc, opcode, reg[1], reg[0])
|
||||
minstr_comment = format("0x%3.3X: %s (R%2.2d), R%2.2d", pc, mnemo, reg[1], reg[0])
|
||||
when "MOVC|Ri|K", "MOVX|Ri|K", "COUT|Ri|K", "XOUT|Ri|K"
|
||||
vhdl_trans_list[pc] = instr_rk(opcode, reg[0], kk);
|
||||
vhdl_tcl_list[pc] = tcl_bits_rk(pc, opcode, reg[0], kk)
|
||||
minstr_comment = format("0x%3.3X: %s (R%2.2d), 0x%2.2X", pc, mnemo, reg[0], kk)
|
||||
when "MOVC|R|Ki", "MOVX|R|Ki", "CIN|R|Ki", "XIN|R|Ki"
|
||||
vhdl_trans_list[pc] = instr_rk(opcode, reg[0], kk);
|
||||
vhdl_tcl_list[pc] = tcl_bits_rk(pc, opcode, reg[0], kk)
|
||||
minstr_comment = format("0x%3.3X: %s R%2.2d, (0x%2.2X)", pc, mnemo, reg[0], kk)
|
||||
when "MOV|R|K", "SUB|R|K", "ADD|R|K", "AND|R|K", "OR|R|K", "XOR|R|K", "CMP|R|K"
|
||||
vhdl_trans_list[pc] = instr_rk(opcode, reg[0], kk);
|
||||
vhdl_tcl_list[pc] = tcl_bits_rk(pc, opcode, reg[0], kk)
|
||||
minstr_comment = format("0x%3.3X: %s R%2.2d, 0x%2.2X", pc, mnemo, reg[0], kk)
|
||||
when "MOVC|Ki|R", "MOVC|Ki|R", "MOVX|Ki|R", "MOVX|Ki|R", "COUT|Ki|R", "XOUT|Ki|R"
|
||||
vhdl_trans_list[pc] = instr_kr(opcode, kk, reg[1]);
|
||||
vhdl_tcl_list[pc] = tcl_bits_kr(pc, opcode, kk, reg[1])
|
||||
minstr_comment = format("0x%3.3X: %s (0x%2.2X), R%2.2d", pc, mnemo, kk, reg[1])
|
||||
when "CALL|K", "JMP|K", "JNZ|K", "JZ|K","JNC|K", "JC|K", "JLT|K", "JGT|K", "JLE|K", "JGE|K", "JEQ|K", "JNE|K"
|
||||
vhdl_trans_list[pc] = instr_k(opcode, kk)
|
||||
vhdl_tcl_list[pc] = tcl_bits_k(pc, opcode, kk)
|
||||
minstr_comment = format("0x%3.3X: %s 0x%3.3X", pc, mnemo, kk)
|
||||
when "PUSH|R", "POP|R", "SHR|R", "SHL|R", "ROR|R", "ROL|R", "RORC|R", "ROLC|R"
|
||||
vhdl_trans_list[pc] = instr_r(opcode, reg[0])
|
||||
vhdl_tcl_list[pc] = tcl_bits_r(pc, opcode, reg[0])
|
||||
minstr_comment = format("0x%3.3X: %s R%2.2d", pc, mnemo, reg[0])
|
||||
when "TST|R"
|
||||
kk = 0
|
||||
minstr_comment = format("0x%3.3X: %s R%2.2d", pc, mnemo, reg[0])
|
||||
opcode = mnemo_list.rindex("CMP|R|K").to_i
|
||||
vhdl_trans_list[pc] = instr_rk(opcode, reg[0], kk);
|
||||
vhdl_tcl_list[pc] = tcl_bits_rk(pc, opcode, reg[0], kk)
|
||||
when "INC|R"
|
||||
kk = 1
|
||||
minstr_comment = format("0x%3.3X: %s R%2.2d", pc, mnemo, reg[0])
|
||||
opcode = mnemo_list.rindex("ADD|R|K").to_i
|
||||
vhdl_trans_list[pc] = instr_rk(opcode, reg[0], kk);
|
||||
vhdl_tcl_list[pc] = tcl_bits_rk(pc, opcode, reg[0], kk)
|
||||
when "DEC|R"
|
||||
kk = 1
|
||||
minstr_comment = format("0x%3.3X: %s R%2.2d", pc, mnemo, reg[0])
|
||||
opcode = mnemo_list.rindex("SUB|R|K").to_i
|
||||
vhdl_trans_list[pc] = instr_rk(opcode, reg[0], kk);
|
||||
vhdl_tcl_list[pc] = tcl_bits_rk(pc, opcode, reg[0], kk)
|
||||
else
|
||||
STDERR.puts format("Error in line %d: Not yet implemented %s", instruct[0], format)
|
||||
error = true
|
||||
end
|
||||
|
||||
if error
|
||||
num_errors += 1
|
||||
break
|
||||
end
|
||||
vhdl_comment_list[pc] = minstr_comment
|
||||
|
||||
puts vhdl_trans_list[pc] + " -- " + minstr_comment
|
||||
|
||||
pc += 1
|
||||
end
|
||||
|
||||
# --------------------------------------------------------
|
||||
# Output ROM file
|
||||
# --------------------------------------------------------
|
||||
if num_errors == 0
|
||||
|
||||
filename = format("rom_%s.vhdl.snip", PROJECT_NAME)
|
||||
file = File.open(filename, "w")
|
||||
|
||||
file.puts format("ENTITY %s IS\n", ENTITY_NAME)
|
||||
file.puts format("\tPort (\n")
|
||||
file.puts format("\tclk\t\t\t: in STD_LOGIC;\n")
|
||||
file.puts format("\tce\t\t\t: in STD_LOGIC;\n")
|
||||
file.puts format("\taddr\t\t: in %s;\n", ENTITY_ADDR_TYPE)
|
||||
file.puts format("\tdout\t\t: out %s\n", ENTITY_DATA_TYPE)
|
||||
file.puts format("\t);\n")
|
||||
file.puts format("END %s;\n", ENTITY_NAME)
|
||||
file.puts format("\n")
|
||||
file.puts format("ARCHITECTURE %s OF %s IS \n", PROJECT_NAME, ENTITY_NAME)
|
||||
file.puts format("\n")
|
||||
file.puts format("\ttype instruction_rom_t is array (0 to %d) of %s;\n", pc-1, ENTITY_DATA_TYPE)
|
||||
file.puts format("\n")
|
||||
file.puts format("\tconstant instruction_rom : instruction_rom_t :=\n")
|
||||
file.puts format("\t(\n");
|
||||
for i in (0..pc-2)
|
||||
file.puts "\t\t" + vhdl_trans_list[i] + ", -- " + vhdl_comment_list[i] + "\n"
|
||||
end;
|
||||
file.puts "\t\t" + vhdl_trans_list[pc-1] + " -- " + vhdl_comment_list[pc-1] + "\n"
|
||||
file.puts format("\t);\n")
|
||||
file.puts format("\n")
|
||||
file.puts format("begin")
|
||||
file.puts format("\n")
|
||||
file.puts format("PROM_READ:")
|
||||
file.puts format("\tprocess(clk, ce)\n")
|
||||
file.puts format("\tbegin\n")
|
||||
file.puts format("\t\tif rising_edge(clk) and ce = '1' then\n")
|
||||
file.puts format("\t\t\tdout <= instruction_rom(to_integer(addr));\n")
|
||||
file.puts format("\t\tend if;\n")
|
||||
file.puts format("\tend process;\n")
|
||||
file.puts format("\n")
|
||||
file.puts format("end %s;\n", PROJECT_NAME)
|
||||
puts format("ROM file written to \"%s\"\n",filename)
|
||||
file.close
|
||||
end
|
||||
if num_errors == 0
|
||||
|
||||
filename = format("preinit_%s.vhdl.snip", PROJECT_NAME)
|
||||
file = File.open(filename, "w")
|
||||
|
||||
file.puts format("\tsignal instruction_rom : instruction_rom_t :=\n")
|
||||
file.puts format("\t(\n");
|
||||
for i in (0..pc-2)
|
||||
file.puts "\t\t" + vhdl_trans_list[i] + ", -- " + vhdl_comment_list[i] + "\n"
|
||||
end;
|
||||
if pc < (MAX_SIZE_ROM-1)
|
||||
file.puts "\t\t" + vhdl_trans_list[pc-1] + ", -- " + vhdl_comment_list[pc-1] + "\n"
|
||||
for i in (pc..(MAX_SIZE_ROM-2))
|
||||
file.puts "\t\t" + instr(0) + ",\n"
|
||||
end;
|
||||
file.puts "\t\t" + instr(0) + "\n"
|
||||
else
|
||||
file.puts "\t\t" + vhdl_trans_list[pc-1] + " -- " + vhdl_comment_list[pc-1] + "\n"
|
||||
end
|
||||
file.puts format("\t);\n")
|
||||
puts format("PREINIT file written to \"%s\"\n",filename)
|
||||
file.close
|
||||
end
|
||||
if num_errors == 0
|
||||
filename = format("rom_%s.tcl.snip", PROJECT_NAME)
|
||||
file = File.open(filename, "w")
|
||||
for i in (0..pc-1)
|
||||
# Chipscope 8.1
|
||||
# file.puts format("jtag_shiftdr $handle -buffer \"%s\" -endstate RTI -device $devid", vhdl_tcl_list[i].reverse);
|
||||
|
||||
# Chipscope 9.1
|
||||
file.puts format("\# %s", vhdl_comment_list[i])
|
||||
file.puts format("::chipscope::csejtag_tap shift_device_dr $handle $devid $CSEJTAG_SHIFT_READWRITE $CSEJTAG_RUN_TEST_IDLE 0 %d \"%8.8X\"\n\n", vhdl_tcl_list[i].length, vhdl_tcl_list[i].to_i(2));
|
||||
end;
|
||||
puts format("TCL snippet written to \"%s\"\n",filename)
|
||||
file.close
|
||||
end
|
||||
|
||||
# --------------------------------------------------------
|
||||
# Output final statistics
|
||||
# --------------------------------------------------------
|
||||
if num_errors == 0
|
||||
puts "Program uses #{pc} instruction addresses"
|
||||
puts "No errors found"
|
||||
exit 0
|
||||
else
|
||||
puts "#{num_errors} errors found"
|
||||
exit 1
|
||||
end
|
||||
Executable
+811
@@ -0,0 +1,811 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Project: JCPU, a portable 8-bit RISC CPU written in VHDL
|
||||
# This file: A small assembler for the JCPU
|
||||
#
|
||||
# Copyright (C) 2007 J. Ahrensfeld
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# For questions and ideas, please contact the author at jens@jayfield.org
|
||||
#
|
||||
# ---------------------------------------------------------------------
|
||||
|
||||
arg = $*
|
||||
FILE_SUFFIX = "jsm"
|
||||
IROM_MAX_SIZE = 1024
|
||||
IROM_ENTITY_NAME = "irom"
|
||||
IROM_DATA_TYPE = "inst_t"
|
||||
IROM_ADDR_TYPE = "inst_addr_t"
|
||||
XROM_MAX_SIZE = 256
|
||||
XROM_DATA_TYPE = "dmem_data_t"
|
||||
XROM_ADDR_TYPE = "dmem_addr_t"
|
||||
XROM_ENTITY_NAME = "xrom"
|
||||
OPC_LIST_NAME = __dir__ + "/opc.list"
|
||||
|
||||
# --------------------------------------------------------
|
||||
class Parser
|
||||
def curr_segment
|
||||
@curr_segment
|
||||
end
|
||||
def curr_segment=(arg)
|
||||
@curr_segment=arg
|
||||
end
|
||||
def add_label(labelname, addr)
|
||||
@label_list = @label_list + [labelname, addr]
|
||||
end
|
||||
def getLabelIdByName(label)
|
||||
return @label_list.rindex(label)
|
||||
end
|
||||
def getLabelNameById(id)
|
||||
return @label_list[id]
|
||||
end
|
||||
def put_instr(name, lc, opc , op1 , op2)
|
||||
if get_instr != nil
|
||||
STDERR.puts format("Error in line %d: Overlapping sections at %3.3X", lc, @pc)
|
||||
exit 1
|
||||
end
|
||||
@instr_list[@pc] = [lc, @pc, opc , op1 , op2, name]
|
||||
end
|
||||
def get_instr
|
||||
return @instr_list[@pc]
|
||||
end
|
||||
def put_xmem(value, lc)
|
||||
if get_xmem != nil
|
||||
STDERR.puts format("Error in line %d: Overlapping sections at %3.3X (%s)", lc, xmem_dc, curr_segment)
|
||||
exit 1
|
||||
end
|
||||
@xmem[xmem_dc] = value
|
||||
@xmem_dc = xmem_dc + 1
|
||||
end
|
||||
def get_xmem
|
||||
return @xmem[xmem_dc]
|
||||
end
|
||||
def xmem
|
||||
return @xmem
|
||||
end
|
||||
def put_cmem(value, lc)
|
||||
if get_cmem(page) != nil
|
||||
STDERR.puts format("Error in line %d: Overlapping sections at %3.3X (%s)", lc, cmem_dc, curr_segment)
|
||||
exit 1
|
||||
end
|
||||
@cmem[page][cmem_dc] = value
|
||||
@cmem_dc[page] = cmem_dc + 1
|
||||
end
|
||||
def get_cmem(pg)
|
||||
return @cmem[pg][cmem_dc]
|
||||
end
|
||||
def cmem(page)
|
||||
return @cmem[page]
|
||||
end
|
||||
def cmem_dc=(addr)
|
||||
@cmem_dc[page] = addr
|
||||
end
|
||||
def cmem_dc
|
||||
@cmem_dc[page]
|
||||
end
|
||||
def xmem_dc=(addr)
|
||||
@xmem_dc = addr
|
||||
end
|
||||
def xmem_dc
|
||||
@xmem_dc
|
||||
end
|
||||
def page=(page)
|
||||
@page = page;
|
||||
end
|
||||
def page
|
||||
@page;
|
||||
end
|
||||
def pc=(pc)
|
||||
@pc = pc;
|
||||
if (pc > @pc_max)
|
||||
@pc_max = pc
|
||||
end
|
||||
end
|
||||
def pc
|
||||
@pc;
|
||||
end
|
||||
def pc_max
|
||||
@pc_max;
|
||||
end
|
||||
def instr_list
|
||||
@instr_list
|
||||
end
|
||||
def label_list
|
||||
@label_list
|
||||
end
|
||||
|
||||
def initialize()
|
||||
@pc_max = 0
|
||||
@pc = 0 # Program counter
|
||||
@cmem_dc = [0,0,0,0] # chip data counter
|
||||
@xmem_dc = 0 # xmem data counter
|
||||
@curr_segment = "UNDEF";
|
||||
@page = 0
|
||||
@label_list=[[],[]]
|
||||
@instr_list=[nil]
|
||||
@cmem = [[],[]];
|
||||
@xmem = [];
|
||||
end
|
||||
def method_missing(name, *args)
|
||||
puts "I don't know the method #{name}"
|
||||
end
|
||||
end
|
||||
|
||||
# --------------------------------------------------------
|
||||
def parse(name, obj)
|
||||
|
||||
lc = 0 # Line counter
|
||||
file = File.open(name, "r")
|
||||
|
||||
file.each do |raw_line|
|
||||
lc += 1
|
||||
|
||||
# Make all upper case
|
||||
iline = "#{raw_line}".strip
|
||||
|
||||
# Remove comments
|
||||
iline = iline.gsub(/;.*/, "")
|
||||
|
||||
# Split instruction at spaces
|
||||
iline_member = iline.split(" ")
|
||||
|
||||
if iline_member[0] == nil
|
||||
next
|
||||
end
|
||||
|
||||
mc = 0;
|
||||
label = nil
|
||||
clean_line = nil
|
||||
if (iline_member[0] =~ /\w+:/)
|
||||
mc += 1
|
||||
label = iline_member[0].delete(":")
|
||||
if obj.getLabelIdByName(label) != nil
|
||||
STDERR.puts format("Error in line %d: Duplicate label \"%s\" found", lc, label)
|
||||
exit 1
|
||||
end
|
||||
end
|
||||
|
||||
token = iline_member[mc]
|
||||
mcnt = iline_member.count{|x| !x.nil?}
|
||||
if token
|
||||
token = token.upcase
|
||||
end
|
||||
|
||||
case token
|
||||
when nil
|
||||
if obj.curr_segment == "CMEM"
|
||||
curr_addr = format("0x%3.3X",obj.cmem_dc)
|
||||
elsif obj.curr_segment == "XMEM"
|
||||
curr_addr = format("0x%3.3X",obj.xmem_dc)
|
||||
elsif obj.curr_segment == "CODE"
|
||||
curr_addr = format("0x%3.3X",obj.pc)
|
||||
else
|
||||
STDERR.puts format("Error in line %d: Undefined segment", lc)
|
||||
exit 1
|
||||
end
|
||||
when "INCLUDE"
|
||||
if iline_member[mc+1] == nil
|
||||
STDERR.puts format("Error in line %d: %s needs argument!", lc, token)
|
||||
exit 1
|
||||
end
|
||||
inc_name = iline_member[mc+1].delete("\"")
|
||||
puts format("Inserting \"%s\" into \"%s\" at line %d", inc_name, name, lc);
|
||||
parse(inc_name, obj)
|
||||
when "EQU"
|
||||
if iline_member[mc+1] == nil
|
||||
STDERR.puts format("Error in line %d: %s needs argument!", lc, token)
|
||||
exit 1
|
||||
end
|
||||
if 0 == (iline_member[mc+1] =~ /\d+/)
|
||||
curr_addr = format("0x%2.2X",eval(iline_member[mc+1..mcnt][0].to_s))
|
||||
else
|
||||
curr_addr = iline_member[mc+1]
|
||||
end
|
||||
when "ORG"
|
||||
if iline_member[mc+1] == nil
|
||||
STDERR.puts format("Error in line %d: %s needs argument!", lc, token)
|
||||
exit 1
|
||||
end
|
||||
offset = eval(iline_member[mc+1..mcnt][0].to_s)
|
||||
case obj.curr_segment
|
||||
when "CODE"
|
||||
obj.pc = offset
|
||||
curr_addr = format("0x%3.3X",obj.pc)
|
||||
when "CMEM"
|
||||
obj.cmem_dc = offset
|
||||
when "XMEM"
|
||||
obj.xmem_dc = offset
|
||||
|
||||
end
|
||||
when "CODE"
|
||||
curr_addr = format("0x%3.3X",obj.pc)
|
||||
obj.curr_segment = "CODE";
|
||||
when "CDATA", "CMEM"
|
||||
if iline_member[mc+1] == nil
|
||||
STDERR.puts format("Error in line %d: %s needs argument!", lc, token)
|
||||
exit 1
|
||||
end
|
||||
obj.curr_segment = "CMEM";
|
||||
obj.page = iline_member[mc+1].to_i(16)
|
||||
when "XDATA", "XMEM"
|
||||
obj.curr_segment = "XMEM";
|
||||
when "DC"
|
||||
len = 0;
|
||||
if iline_member[mc+1] == nil
|
||||
STDERR.puts format("Error in line %d: %s needs argument!", lc, token)
|
||||
exit 1
|
||||
end
|
||||
if obj.curr_segment == "CMEM"
|
||||
STDERR.puts format("Error in line %d: %s cannot be initialized!", lc, obj.curr_segment)
|
||||
exit 1
|
||||
elsif obj.curr_segment == "XMEM"
|
||||
curr_addr = format("0x%2.2X",obj.xmem_dc)
|
||||
dc_old = obj.xmem_dc;
|
||||
val_array = raw_line.split(/dc|DC|Dc|dC/)[1].delete("\t").gsub(/;.*/, "").split(",")
|
||||
|
||||
# Parse string literals
|
||||
val_array.each do |item|
|
||||
if 0 == (item =~ /.*\".*\"/)
|
||||
str = item.delete("\"")
|
||||
for nn in (0..str.length-1)
|
||||
value = str[nn].ord
|
||||
obj.put_xmem(value, lc);
|
||||
len += 1
|
||||
end;
|
||||
else
|
||||
argument = item
|
||||
obj.put_xmem(eval(argument), lc);
|
||||
len += 1
|
||||
end
|
||||
end
|
||||
puts format("Found DC defining %d bytes at 0x%4.4X in %s", len, dc_old, obj.curr_segment);
|
||||
else
|
||||
STDERR.puts format("Error in line %d: Invalid segment %s for \"%s\"", lc, obj.curr_segment, token)
|
||||
exit 1
|
||||
end
|
||||
when "DB"
|
||||
if iline_member[mc+1] == nil
|
||||
STDERR.puts format("Error in line %d: %s needs argument!", lc, token)
|
||||
exit 1
|
||||
end
|
||||
len = eval(iline_member[mc+1]).to_i
|
||||
if obj.curr_segment == "CMEM"
|
||||
curr_addr = format("0x%2.2X",obj.cmem_dc)
|
||||
puts format("Found DB reserving %d bytes at 0x%4.4X in %s(%d)", len, obj.cmem_dc, obj.curr_segment, obj.page);
|
||||
for nn in (1..len)
|
||||
obj.put_cmem(0, lc)
|
||||
end
|
||||
elsif obj.curr_segment == "XMEM"
|
||||
curr_addr = format("0x%2.2X",obj.xmem_dc)
|
||||
puts format("Found DB reserving %d bytes at 0x%4.4X in %s", len, obj.xmem_dc, obj.curr_segment);
|
||||
for nn in (1..len)
|
||||
obj.put_xmem(0, lc)
|
||||
end
|
||||
else
|
||||
STDERR.puts format("Error in line %d: Invalid segment %s for \"%s\"", lc, obj.curr_segment, token)
|
||||
exit 1
|
||||
end
|
||||
else
|
||||
if obj.curr_segment != "CODE"
|
||||
STDERR.puts format("Error in line %d: Invalid segment %s for \"%s\"", lc, obj.curr_segment, token)
|
||||
exit 1
|
||||
end
|
||||
|
||||
op_line = iline_member[mc+1..mcnt]
|
||||
curr_addr = format("0x%3.3X",obj.pc)
|
||||
opc = token
|
||||
if iline_member[mc+1] != nil
|
||||
op1 = op_line[0].to_s.gsub(/,+.*$/, "")
|
||||
end
|
||||
if iline_member[mc+2] != nil
|
||||
op2 = op_line[1].to_s.gsub(/,+.*$/, "")
|
||||
end
|
||||
obj.put_instr(name, lc, opc, op1, op2)
|
||||
obj.pc = obj.pc + 1
|
||||
end;
|
||||
|
||||
# Push labels
|
||||
if label
|
||||
obj.add_label(label, curr_addr)
|
||||
end
|
||||
end
|
||||
file.close
|
||||
return obj
|
||||
end
|
||||
|
||||
# --------------------------------------------------------
|
||||
# Instruction formatting
|
||||
# --------------------------------------------------------
|
||||
def instr(opcode)
|
||||
return format("\"%6.6B\" & X\"%3.3X\"",opcode ,0)
|
||||
end
|
||||
|
||||
def tcl_bits(pc, opcode)
|
||||
return format("%12.12B%8.8B%12.12B",pc, opcode ,0)
|
||||
end
|
||||
|
||||
def instr_k(opcode, k)
|
||||
return format("\"%6.6B\" & X\"%3.3X\"",opcode ,k)
|
||||
end
|
||||
|
||||
def tcl_bits_k(pc, opcode, k)
|
||||
return format("%12.12B%8.8B%12.12B",pc, opcode ,k)
|
||||
end
|
||||
|
||||
def instr_r(opcode, r)
|
||||
return format("\"%6.6B\" & X\"%2.2X%X\"",opcode ,0, r)
|
||||
end
|
||||
|
||||
def tcl_bits_r(pc, opcode, r)
|
||||
return format("%12.12B%8.8B%8.8B%4.4B",pc, opcode ,0,r)
|
||||
end
|
||||
|
||||
def instr_kr(opcode, k, r)
|
||||
return format("\"%6.6B\" & X\"%2.2X%X\"",opcode,k, r)
|
||||
end
|
||||
|
||||
def tcl_bits_kr(pc, opcode, k, r)
|
||||
return format("%12.12B%8.8B%8.8B%4.4B",pc, opcode, k, r)
|
||||
end
|
||||
|
||||
def instr_rk(opcode, r, k)
|
||||
return format("\"%6.6B\" & X\"%2.2X%X\"",opcode,k, r)
|
||||
end
|
||||
|
||||
def tcl_bits_rk(pc, opcode, r, k)
|
||||
return format("%12.12B%8.8B%8.8B%4.4B",pc, opcode, k, r)
|
||||
end
|
||||
|
||||
def instr_rr(opcode, ra, rb)
|
||||
return format("\"%6.6B\" & X\"%X%X%X\"",opcode,0, rb, ra)
|
||||
end
|
||||
|
||||
def tcl_bits_rr(pc, opcode, ra, rb)
|
||||
return format("%12.12B%8.8B%4.4B%4.4B%4.4B",pc, opcode, 0, rb, ra)
|
||||
end
|
||||
|
||||
# --------------------------------------------------------
|
||||
# Open file
|
||||
# --------------------------------------------------------
|
||||
filename = arg[0].to_s
|
||||
if !File.exists?(filename)
|
||||
STDERR.puts "#{filename} does not exist"
|
||||
exit 1
|
||||
end
|
||||
PROJECT_NAME = File.basename(filename, "." + FILE_SUFFIX)
|
||||
|
||||
# --------------------------------------------------------
|
||||
# Pass 1
|
||||
# --------------------------------------------------------
|
||||
first_pass = Parser.new();
|
||||
parse(filename, first_pass)
|
||||
|
||||
# --------------------------------------------------------
|
||||
# Read mnemonic set
|
||||
# --------------------------------------------------------
|
||||
filename = OPC_LIST_NAME
|
||||
if !File.exists?(filename)
|
||||
STDERR.puts "#{filename} does not exist"
|
||||
exit 1
|
||||
end
|
||||
|
||||
mnemo_list = []
|
||||
num_opcodes = 0
|
||||
file = File.open(filename, "r")
|
||||
file.each do |raw_line|
|
||||
mnemo_list[num_opcodes] = raw_line.split(" ")[1]
|
||||
num_opcodes += 1
|
||||
end
|
||||
|
||||
# --------------------------------------------------------
|
||||
# Pass 2
|
||||
# --------------------------------------------------------
|
||||
pc = 0
|
||||
opc_start = 2
|
||||
num_errors = 0
|
||||
vhdl_trans_list = [nil]
|
||||
vhdl_comment_list = [nil]
|
||||
vhdl_tcl_list = [nil]
|
||||
|
||||
# ToDo: Use class-methods
|
||||
label_list = first_pass.label_list
|
||||
instr_list = first_pass.instr_list
|
||||
|
||||
instr_list.each do |instruct|
|
||||
|
||||
# puts instruct
|
||||
if instruct == nil
|
||||
vhdl_trans_list[pc] = format("\"%6.6B\" & X\"%3.3X\"",0 ,0)
|
||||
vhdl_comment_list[pc] = format("0x%3.3X:", pc)
|
||||
vhdl_tcl_list[pc] = tcl_bits(pc, 0)
|
||||
pc += 1
|
||||
next
|
||||
end
|
||||
|
||||
# determine arglen of instruction
|
||||
ilen = 0
|
||||
if instruct[opc_start+1] == nil
|
||||
arglen = 0
|
||||
elsif instruct[opc_start+2] == nil
|
||||
arglen = 1
|
||||
elsif instruct[opc_start+3] == nil
|
||||
arglen = 2
|
||||
end
|
||||
|
||||
# Symbol substitution
|
||||
error = false
|
||||
for i in (1..2)
|
||||
subst_pos = opc_start+i
|
||||
if instruct[subst_pos] == nil
|
||||
next
|
||||
end
|
||||
expr_token = ""
|
||||
expr_subst = nil
|
||||
is_direct = true;
|
||||
|
||||
# checks R0 .. R16, Mnemonics
|
||||
instruct[subst_pos] = instruct[subst_pos].gsub(/'low/, "")
|
||||
if (nil != (instruct[subst_pos] =~ /'high/))
|
||||
instruct[subst_pos]= format("%s/256", instruct[subst_pos].gsub(/'high/, ""))
|
||||
end
|
||||
instr_str = instruct[subst_pos]
|
||||
if 0 == (instr_str =~ /\(.+\)/)
|
||||
instr_str = instr_str.delete("()")
|
||||
is_direct = false;
|
||||
end
|
||||
|
||||
expr_token = instr_str.split(/\+|\-|\*|\/|\||\&/)[0]
|
||||
if (0 != (expr_token =~ /R[0-9]+/)) && (0 != (expr_token =~ /\d+/))
|
||||
idx = label_list.rindex(expr_token)
|
||||
if idx != nil
|
||||
expr_subst = label_list[idx+1]
|
||||
instruct[subst_pos] = instruct[subst_pos].gsub(expr_token, expr_subst)
|
||||
else
|
||||
STDERR.puts format("%s: Error in line %d: Symbol \"%s\" not found", instruct[5], instruct[0], expr_token)
|
||||
error = true
|
||||
end
|
||||
end
|
||||
|
||||
if expr_subst != nil
|
||||
if 0 == (expr_subst =~ /\d+/)
|
||||
if is_direct == true
|
||||
instruct[subst_pos] = format("0x%2.2X", eval(instruct[subst_pos]))
|
||||
else
|
||||
instruct[subst_pos] = format("(0x%2.2X)", eval(instruct[subst_pos]))
|
||||
end
|
||||
else
|
||||
if 0 != (expr_subst =~ /R[0-9]+/)
|
||||
STDERR.puts format("%s: Error in line %d: Invalid expression \"%s\"", instruct[5], instruct[0], expr_subst)
|
||||
error = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Parse operands
|
||||
reg = [0,0]
|
||||
kk = 0
|
||||
format = instruct[opc_start]
|
||||
for i in (0..1)
|
||||
if instruct[opc_start+i+1] =~ Regexp.new("R[0-9]+")
|
||||
# Check indirect addressing
|
||||
reg[i] = instruct[opc_start+i+1].delete("R()").to_i
|
||||
format += "|R"
|
||||
if reg[i] > 15
|
||||
STDERR.puts format("%s: Error in line %d: Invalid register \"R%d\" specified", instruct[5], instruct[0], reg[i])
|
||||
error = true
|
||||
end
|
||||
else
|
||||
if instruct[opc_start+i+1] =~ Regexp.new("[0-9A-F]+")
|
||||
kk = eval(instruct[opc_start+i+1].delete("()"))
|
||||
format += "|K"
|
||||
end
|
||||
end
|
||||
if instruct[opc_start+i+1] =~ Regexp.new("\\(.+\\)")
|
||||
format += "i";
|
||||
end
|
||||
end
|
||||
|
||||
if error
|
||||
num_errors += 1
|
||||
break
|
||||
end
|
||||
|
||||
# Output instruction
|
||||
opcode = mnemo_list.rindex(format).to_i
|
||||
mnemo = instruct[2];
|
||||
|
||||
case format
|
||||
# Native instructions
|
||||
when "NOP", "HALT", "RET", "RETI", "SETC"
|
||||
vhdl_trans_list[pc] = instr(opcode)
|
||||
vhdl_tcl_list[pc] = tcl_bits(pc, opcode)
|
||||
minstr_comment = format("0x%3.3X: %s", pc, mnemo)
|
||||
when "MOVC|R|Ri", "MOVX|R|Ri"
|
||||
vhdl_trans_list[pc] = instr_rr(opcode, reg[0], reg[1]);
|
||||
vhdl_tcl_list[pc] = tcl_bits_rr(pc, opcode, reg[0], reg[1])
|
||||
minstr_comment = format("0x%3.3X: %s R%2.2d, (R%2.2d)", pc, mnemo, reg[0], reg[1])
|
||||
when "MOV|R|R", "SUB|R|R", "SUBC|R|R", "ADD|R|R", "ADDC|R|R", "AND|R|R", "OR|R|R", "XOR|R|R", "CMP|R|R"
|
||||
vhdl_trans_list[pc] = instr_rr(opcode, reg[0], reg[1]);
|
||||
vhdl_tcl_list[pc] = tcl_bits_rr(pc, opcode, reg[0], reg[1])
|
||||
minstr_comment = format("0x%3.3X: %s R%2.2d, R%2.2d", pc, mnemo, reg[0], reg[1])
|
||||
when "MOVC|Ri|R", "MOVX|Ri|R"
|
||||
vhdl_trans_list[pc] = instr_rr(opcode, reg[1], reg[0]);
|
||||
vhdl_tcl_list[pc] = tcl_bits_rr(pc, opcode, reg[1], reg[0])
|
||||
minstr_comment = format("0x%3.3X: %s (R%2.2d), R%2.2d", pc, mnemo, reg[1], reg[0])
|
||||
when "MOVC|Ri|K", "MOVX|Ri|K", "COUT|Ri|K", "XOUT|Ri|K"
|
||||
kk = kk % 256;
|
||||
vhdl_trans_list[pc] = instr_rk(opcode, reg[0], kk);
|
||||
vhdl_tcl_list[pc] = tcl_bits_rk(pc, opcode, reg[0], kk)
|
||||
minstr_comment = format("0x%3.3X: %s (R%2.2d), 0x%2.2X", pc, mnemo, reg[0], kk)
|
||||
when "MOVC|R|Ki", "MOVX|R|Ki", "CIN|R|Ki", "XIN|R|Ki"
|
||||
vhdl_trans_list[pc] = instr_rk(opcode, reg[0], kk);
|
||||
vhdl_tcl_list[pc] = tcl_bits_rk(pc, opcode, reg[0], kk)
|
||||
minstr_comment = format("0x%3.3X: %s R%2.2d, (0x%2.2X)", pc, mnemo, reg[0], kk)
|
||||
when "MOV|R|K", "SUB|R|K", "SUBC|R|K", "ADD|R|K", "ADDC|R|K", "AND|R|K", "OR|R|K", "XOR|R|K", "CMP|R|K"
|
||||
kk = kk % 256;
|
||||
vhdl_trans_list[pc] = instr_rk(opcode, reg[0], kk);
|
||||
vhdl_tcl_list[pc] = tcl_bits_rk(pc, opcode, reg[0], kk)
|
||||
minstr_comment = format("0x%3.3X: %s R%2.2d, 0x%2.2X", pc, mnemo, reg[0], kk)
|
||||
when "SUB|K|R", "SUBC|K|R"
|
||||
kk = kk % 256;
|
||||
vhdl_trans_list[pc] = instr_kr(opcode, kk, reg[1]);
|
||||
vhdl_tcl_list[pc] = tcl_bits_kr(pc, opcode, kk, reg[1])
|
||||
minstr_comment = format("0x%3.3X: %s 0x%2.2d, R%2.2X", pc, mnemo, kk, reg[1])
|
||||
when "MOVC|Ki|R", "MOVC|Ki|R", "MOVX|Ki|R", "MOVX|Ki|R", "COUT|Ki|R", "XOUT|Ki|R"
|
||||
vhdl_trans_list[pc] = instr_kr(opcode, kk, reg[1]);
|
||||
vhdl_tcl_list[pc] = tcl_bits_kr(pc, opcode, kk, reg[1])
|
||||
minstr_comment = format("0x%3.3X: %s (0x%2.2X), R%2.2d", pc, mnemo, kk, reg[1])
|
||||
when "CALL|K", "JMP|K", "JNZ|K", "JZ|K","JNC|K", "JC|K", "JLT|K", "JGT|K", "JLE|K", "JGE|K", "JEQ|K", "JNE|K"
|
||||
vhdl_trans_list[pc] = instr_k(opcode, kk)
|
||||
vhdl_tcl_list[pc] = tcl_bits_k(pc, opcode, kk)
|
||||
minstr_comment = format("0x%3.3X: %s 0x%3.3X", pc, mnemo, kk)
|
||||
when "PUSH|R", "POP|R", "SHR|R", "SHL|R", "ROR|R", "ROL|R", "RORC|R", "ROLC|R", "SWAP|R"
|
||||
vhdl_trans_list[pc] = instr_r(opcode, reg[0])
|
||||
vhdl_tcl_list[pc] = tcl_bits_r(pc, opcode, reg[0])
|
||||
minstr_comment = format("0x%3.3X: %s R%2.2d", pc, mnemo, reg[0])
|
||||
# Synthetic instructions
|
||||
when "CLRC"
|
||||
kk = 0;
|
||||
minstr_comment = format("0x%3.3X: %s", pc, mnemo)
|
||||
opcode = mnemo_list.rindex("SUB|R|K").to_i
|
||||
vhdl_trans_list[pc] = instr_rk(opcode, reg[0], kk);
|
||||
vhdl_tcl_list[pc] = tcl_bits_rk(pc, opcode, reg[0], kk)
|
||||
when "TST|R"
|
||||
kk = 0
|
||||
minstr_comment = format("0x%3.3X: %s R%2.2d", pc, mnemo, reg[0])
|
||||
opcode = mnemo_list.rindex("CMP|R|K").to_i
|
||||
vhdl_trans_list[pc] = instr_rk(opcode, reg[0], kk);
|
||||
vhdl_tcl_list[pc] = tcl_bits_rk(pc, opcode, reg[0], kk)
|
||||
when "NEG|R"
|
||||
kk = 0
|
||||
minstr_comment = format("0x%3.3X: %s R%2.2d", pc, mnemo, reg[0])
|
||||
opcode = mnemo_list.rindex("SUB|K|R").to_i
|
||||
vhdl_trans_list[pc] = instr_rk(opcode, reg[0], kk);
|
||||
vhdl_tcl_list[pc] = tcl_bits_rk(pc, opcode, reg[0], kk)
|
||||
when "NOT|R"
|
||||
kk = 0
|
||||
minstr_comment = format("0x%3.3X: %s R%2.2d", pc, mnemo, reg[0])
|
||||
opcode = mnemo_list.rindex("XOR|R|K").to_i
|
||||
vhdl_trans_list[pc] = instr_rk(opcode, reg[0], kk);
|
||||
vhdl_tcl_list[pc] = tcl_bits_rk(pc, opcode, reg[0], kk)
|
||||
when "INC|R"
|
||||
kk = 1
|
||||
minstr_comment = format("0x%3.3X: %s R%2.2d", pc, mnemo, reg[0])
|
||||
opcode = mnemo_list.rindex("ADD|R|K").to_i
|
||||
vhdl_trans_list[pc] = instr_rk(opcode, reg[0], kk);
|
||||
vhdl_tcl_list[pc] = tcl_bits_rk(pc, opcode, reg[0], kk)
|
||||
when "DEC|R"
|
||||
kk = 1
|
||||
minstr_comment = format("0x%3.3X: %s R%2.2d", pc, mnemo, reg[0])
|
||||
opcode = mnemo_list.rindex("SUB|R|K").to_i
|
||||
vhdl_trans_list[pc] = instr_rk(opcode, reg[0], kk);
|
||||
vhdl_tcl_list[pc] = tcl_bits_rk(pc, opcode, reg[0], kk)
|
||||
else
|
||||
STDERR.puts format("%s: Error in line %d: Not yet implemented %s", instruct[5], instruct[0], format)
|
||||
error = true
|
||||
end
|
||||
|
||||
if error
|
||||
num_errors += 1
|
||||
break
|
||||
end
|
||||
|
||||
vhdl_comment_list[pc] = minstr_comment
|
||||
|
||||
puts vhdl_trans_list[pc] + " -- " + minstr_comment
|
||||
|
||||
pc += 1
|
||||
end
|
||||
|
||||
# --------------------------------------------------------
|
||||
# Output ROM file
|
||||
# --------------------------------------------------------
|
||||
if num_errors == 0
|
||||
|
||||
# I-ROM VHDL-ROM
|
||||
filename = format("%s.irom.vhdl.snip", PROJECT_NAME)
|
||||
file = File.open(filename, "w")
|
||||
|
||||
file.puts format("ENTITY %s IS\n", IROM_ENTITY_NAME)
|
||||
file.puts format("\tPort (\n")
|
||||
file.puts format("\tclk\t\t\t: in STD_LOGIC;\n")
|
||||
file.puts format("\tce\t\t\t: in STD_LOGIC;\n")
|
||||
file.puts format("\taddr\t\t: in %s;\n", IROM_ADDR_TYPE)
|
||||
file.puts format("\tdout\t\t: out %s\n", IROM_DATA_TYPE)
|
||||
file.puts format("\t);\n")
|
||||
file.puts format("END %s;\n", IROM_ENTITY_NAME)
|
||||
file.puts format("\n")
|
||||
file.puts format("ARCHITECTURE %s OF %s IS \n", PROJECT_NAME, IROM_ENTITY_NAME)
|
||||
file.puts format("\n")
|
||||
file.puts format("\ttype imem_rom_t is array (0 to %d) of %s;\n", [IROM_MAX_SIZE, pc].min-1 , IROM_DATA_TYPE)
|
||||
file.puts format("\n")
|
||||
file.puts format("\t-- Assembled from %s.%s", PROJECT_NAME, FILE_SUFFIX)
|
||||
file.puts format("\tconstant imem_rom : imem_rom_t :=\n")
|
||||
file.puts format("\t(\n");
|
||||
for i in (0..[IROM_MAX_SIZE, pc].min-2)
|
||||
file.puts "\t\t" + vhdl_trans_list[i] + ", -- " + vhdl_comment_list[i] + "\n"
|
||||
end;
|
||||
file.puts "\t\t" + vhdl_trans_list[pc-1] + " -- " + vhdl_comment_list[pc-1] + "\n"
|
||||
file.puts format("\t);\n")
|
||||
file.puts format("\n")
|
||||
file.puts format("begin")
|
||||
file.puts format("\n")
|
||||
file.puts format("PROM_READ:")
|
||||
file.puts format("\tprocess(clk, ce)\n")
|
||||
file.puts format("\tbegin\n")
|
||||
file.puts format("\t\tif rising_edge(clk) and ce = '1' then\n")
|
||||
file.puts format("\t\t\tdout <= imem_rom(to_integer(addr));\n")
|
||||
file.puts format("\t\tend if;\n")
|
||||
file.puts format("\tend process;\n")
|
||||
file.puts format("\n")
|
||||
file.puts format("end %s;\n", PROJECT_NAME)
|
||||
puts format("I-ROM file written to \"%s\"\n",filename)
|
||||
file.close
|
||||
|
||||
# I-ROM VHDL-ROM (loadable)
|
||||
filename = format("%s.irom_ld.vhdl.snip", PROJECT_NAME)
|
||||
file = File.open(filename, "w")
|
||||
|
||||
file.puts format("\n\t-- Assembled from %s.%s", PROJECT_NAME, FILE_SUFFIX)
|
||||
file.puts format("\ttype imem_rom_t is array (0 to %d) of %s;\n", IROM_MAX_SIZE-1, IROM_DATA_TYPE)
|
||||
file.puts format("\tsignal imem_rom : imem_rom_t :=\n")
|
||||
file.puts format("\t(\n");
|
||||
for i in (0..pc-2)
|
||||
file.puts "\t\t" + vhdl_trans_list[i] + ", -- " + vhdl_comment_list[i] + "\n"
|
||||
end;
|
||||
if pc < (IROM_MAX_SIZE-1)
|
||||
file.puts "\t\t" + vhdl_trans_list[pc-1] + ", -- " + vhdl_comment_list[pc-1] + "\n"
|
||||
for i in (pc..(IROM_MAX_SIZE-2))
|
||||
file.puts "\t\t" + instr(0) + ",\n"
|
||||
end;
|
||||
file.puts "\t\t" + instr(0) + "\n"
|
||||
else
|
||||
file.puts "\t\t" + vhdl_trans_list[pc-1] + " -- " + vhdl_comment_list[pc-1] + "\n"
|
||||
end
|
||||
file.puts format("\t);\n")
|
||||
puts format("I-ROM (loadable) file written to \"%s\"\n",filename)
|
||||
file.close
|
||||
|
||||
# I-ROM TCL-Loader
|
||||
filename = format("%s.irom.tcl.snip", PROJECT_NAME)
|
||||
file = File.open(filename, "w")
|
||||
file.puts format("# Assembled from %s.%s", PROJECT_NAME, FILE_SUFFIX)
|
||||
file.puts format("# ---------------------------------------------------------------");
|
||||
file.puts format("# Shift the USER1 Instruction (b1111000010) into the Instruction Register of FPGA");
|
||||
file.puts format("# User 1")
|
||||
file.puts format("set result [::chipscope::csejtag_tap shift_device_ir $handle $devid $CSE_OP $CSE_ES 0 $irlength \"3C2\"]\n\n")
|
||||
for i in (0..pc-1)
|
||||
# Chipscope 8.1
|
||||
# file.puts format("jtag_shiftdr $handle -buffer \"%s\" -endstate RTI -device $devid", vhdl_tcl_list[i].reverse);
|
||||
|
||||
# Chipscope 9.1
|
||||
file.puts format("\# %s", vhdl_comment_list[i])
|
||||
file.puts format("::chipscope::csejtag_tap shift_device_dr $handle $devid $CSE_OP $CSE_ES 0 %d \"%8.8X\"\n\n", vhdl_tcl_list[i].length, vhdl_tcl_list[i].to_i(2));
|
||||
end;
|
||||
puts format("I-ROM TCL-loader written to \"%s\"\n",filename)
|
||||
file.close
|
||||
|
||||
# X-ROM VHDL-ROM
|
||||
filename = format("%s.xrom.vhdl.snip", PROJECT_NAME)
|
||||
file = File.open(filename, "w")
|
||||
|
||||
file.puts format("ENTITY %s IS\n", XROM_ENTITY_NAME)
|
||||
file.puts format("\tPort (\n")
|
||||
file.puts format("\tclk\t\t\t: in STD_LOGIC;\n")
|
||||
file.puts format("\tce\t\t\t: in STD_LOGIC;\n")
|
||||
file.puts format("\taddr\t\t: in %s;\n", XROM_ADDR_TYPE)
|
||||
file.puts format("\tdout\t\t: out %s\n", XROM_DATA_TYPE)
|
||||
file.puts format("\t);\n")
|
||||
file.puts format("END %s;\n", XROM_ENTITY_NAME)
|
||||
file.puts format("\n")
|
||||
file.puts format("ARCHITECTURE %s OF %s IS \n", PROJECT_NAME, XROM_ENTITY_NAME)
|
||||
file.puts format("\n")
|
||||
file.puts format("\ttype xmem_rom_t is array (0 to %d) of %s;\n", XROM_MAX_SIZE-1, XROM_DATA_TYPE)
|
||||
file.puts format("\n")
|
||||
file.puts format("\t-- Assembled from %s.%s", PROJECT_NAME, FILE_SUFFIX)
|
||||
file.puts format("\tconstant xmem_rom : xmem_rom_t :=\n")
|
||||
file.puts format("\t(\n");
|
||||
for i in (0..XROM_MAX_SIZE-2)
|
||||
file.puts format("\t\tX\"%2.2X\", -- 0x%2.2X\n", first_pass.xmem[i].to_i(), i)
|
||||
end;
|
||||
i = XROM_MAX_SIZE-1
|
||||
file.puts format("\t\tX\"%2.2X\" -- 0x%2.2X\n", first_pass.xmem[i].to_i(), i)
|
||||
file.puts format("\t);\n")
|
||||
file.puts format("\n")
|
||||
file.puts format("begin")
|
||||
file.puts format("\n")
|
||||
file.puts format("PROM_READ:")
|
||||
file.puts format("\tprocess(clk, ce)\n")
|
||||
file.puts format("\tbegin\n")
|
||||
file.puts format("\t\tif rising_edge(clk) and ce = '1' then\n")
|
||||
file.puts format("\t\t\tdout <= xmem_rom(to_integer(addr));\n")
|
||||
file.puts format("\t\tend if;\n")
|
||||
file.puts format("\tend process;\n")
|
||||
file.puts format("\n")
|
||||
file.puts format("end %s;\n", PROJECT_NAME)
|
||||
puts format("X-ROM file written to \"%s\"\n",filename)
|
||||
file.close
|
||||
|
||||
# X-ROM VHDL-ROM (loadable)
|
||||
filename = format("%s.xrom_ld.vhdl.snip", PROJECT_NAME)
|
||||
file = File.open(filename, "w")
|
||||
|
||||
file.puts format("\n\t-- Assembled from %s.%s", PROJECT_NAME, FILE_SUFFIX)
|
||||
file.puts format("\ttype xmem_rom_t is array (0 to %d) of %s;\n", XROM_MAX_SIZE-1, XROM_DATA_TYPE)
|
||||
file.puts format("\tsignal xmem_rom : xmem_rom_t :=\n")
|
||||
file.puts format("\t(\n");
|
||||
for i in (0..XROM_MAX_SIZE-2)
|
||||
file.puts format("\t\tX\"%2.2X\", -- 0x%2.2X\n", first_pass.xmem[i].to_i(), i)
|
||||
end;
|
||||
i = XROM_MAX_SIZE-1
|
||||
file.puts format("\t\tX\"%2.2X\" -- 0x%2.2X\n", first_pass.xmem[i].to_i(), i)
|
||||
file.puts format("\t);\n")
|
||||
puts format("X-ROM (loadable) file written to \"%s\"\n",filename)
|
||||
file.close
|
||||
|
||||
# X-ROM JTAG-Loader
|
||||
filename = format("%s.xrom.tcl.snip", PROJECT_NAME)
|
||||
file = File.open(filename, "w")
|
||||
file.puts format("# Assembled from %s.%s", PROJECT_NAME, FILE_SUFFIX)
|
||||
file.puts format("# ---------------------------------------------------------------");
|
||||
file.puts format("# Shift the USER2 Instruction (b1111000011) into the Instruction Register of FPGA");
|
||||
file.puts format("# User 2")
|
||||
file.puts format("set result [::chipscope::csejtag_tap shift_device_ir $handle $devid $CSE_OP $CSE_ES 0 $irlength \"3C3\"]\n\n")
|
||||
for i in (0..first_pass.xmem.length-1)
|
||||
# Chipscope 8.1
|
||||
# file.puts format("jtag_shiftdr $handle -buffer \"%s\" -endstate RTI -device $devid", vhdl_tcl_list[i].reverse);
|
||||
|
||||
# Chipscope 9.1
|
||||
file.puts format("::chipscope::csejtag_tap shift_device_dr $handle $devid $CSE_OP $CSE_ES 0 %d \"%2.2X%2.2X\"\n", 16, i, first_pass.xmem[i]);
|
||||
end;
|
||||
puts format("X-ROM TCL-loader written to \"%s\"\n",filename)
|
||||
file.close
|
||||
|
||||
end
|
||||
|
||||
# --------------------------------------------------------
|
||||
# Output final statistics
|
||||
# --------------------------------------------------------
|
||||
if num_errors == 0
|
||||
puts "Program uses #{first_pass.pc_max} instruction addresses"
|
||||
puts "No errors found"
|
||||
exit 0
|
||||
else
|
||||
puts "#{num_errors} errors found"
|
||||
exit 1
|
||||
end
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
; -------------------------------------------------
|
||||
; lcd.inc.jsm
|
||||
; -------------------------------------------------
|
||||
; needs xio-address equates for
|
||||
; reg_cg_char_addr: equ 0xXX ; RW
|
||||
; reg_cg_line_addr: equ 0xXX ; RW
|
||||
; reg_cg_data: equ 0xXX ; RW
|
||||
; reg_cg_ctrl: equ 0xXX ; WO
|
||||
|
||||
; needs delay.inc.jsm
|
||||
|
||||
; -------------------------------------------------
|
||||
cg_clr_line: push R0
|
||||
mov R0, 2
|
||||
xout (reg_cg_ctrl), R0
|
||||
pop R0
|
||||
ret
|
||||
|
||||
; -------------------------------------------------
|
||||
cg_clr_screen: push R0
|
||||
mov R0, 1
|
||||
xout (reg_cg_ctrl), R0
|
||||
pop R0
|
||||
ret
|
||||
|
||||
; -------------------------------------------------
|
||||
; R0 : char address
|
||||
; R1 : line address
|
||||
cg_set_addr: call cg_wait_rdy
|
||||
xout (reg_cg_line_addr), R1
|
||||
xout (reg_cg_char_addr), R0
|
||||
ret
|
||||
|
||||
; -------------------------------------------------
|
||||
; R0 : character
|
||||
cg_putchar: call cg_wait_rdy
|
||||
xout (reg_cg_data), R0
|
||||
ret
|
||||
|
||||
; -------------------------------------------------
|
||||
; R1 : ptr to string
|
||||
cg_puts: push R0
|
||||
cg_p_lp: movx R0, (R1)
|
||||
inc R1
|
||||
tst R0
|
||||
jz ex_cgp
|
||||
call cg_putchar
|
||||
jmp cg_p_lp
|
||||
ex_cgp: pop R0
|
||||
ret
|
||||
|
||||
; -------------------------------------------------
|
||||
; R1 : ptr to string
|
||||
cg_clr_puts: call cg_clr_line
|
||||
call cg_puts
|
||||
ret
|
||||
|
||||
; -------------------------------------------------
|
||||
; R1 : ptr to string
|
||||
cg_puts_clr: call cg_puts
|
||||
call cg_clr_line
|
||||
ret
|
||||
|
||||
; -------------------------------------------------
|
||||
cg_wait_rdy: push R0
|
||||
cg_wr_lp: xin R0, (reg_hwstat)
|
||||
and R0, 0x02
|
||||
jz cg_wr_lp
|
||||
pop R0
|
||||
ret
|
||||
|
||||
; -------------------------------------------------
|
||||
@@ -0,0 +1,7 @@
|
||||
; JCPU On-Chip register
|
||||
cpu_revision: equ 0x00 ; RO
|
||||
cpu_control: equ 0x01 ; R/W
|
||||
cpu_status: equ 0x02 ; RO
|
||||
cpu_int_ctrl: equ 0x03 ; RW
|
||||
cpu_cmem_high: equ 0x04 ; RW
|
||||
cpu_stack_high: equ 0x05 ; RW
|
||||
@@ -0,0 +1,64 @@
|
||||
; -------------------------------------------------
|
||||
; Delays
|
||||
; -------------------------------------------------
|
||||
delay1s: push R15
|
||||
mov R15, 10
|
||||
loop1s: call delay100ms
|
||||
dec R15
|
||||
jnz loop1s
|
||||
pop R15
|
||||
ret
|
||||
|
||||
delay100ms: push R15
|
||||
mov R15, 10
|
||||
loop100ms: call delay10ms
|
||||
dec R15
|
||||
jnz loop100ms
|
||||
pop R15
|
||||
ret
|
||||
|
||||
delay10ms: push R15
|
||||
mov R15, 10
|
||||
loop10ms: call delay1ms
|
||||
dec R15
|
||||
jnz loop10ms
|
||||
pop R15
|
||||
ret
|
||||
|
||||
delay1ms: push R15
|
||||
mov R15, 10
|
||||
loop1ms: call delay100us
|
||||
dec R15
|
||||
jnz loop1ms
|
||||
pop R15
|
||||
ret
|
||||
|
||||
delay100us: push R15
|
||||
mov R15, 10
|
||||
loop100us: call delay10us
|
||||
dec R15
|
||||
jnz loop100us
|
||||
pop R15
|
||||
ret
|
||||
|
||||
delay10us: push R15
|
||||
mov R15, 99
|
||||
loop10us: nop
|
||||
nop
|
||||
nop
|
||||
dec R15
|
||||
jnz loop10us
|
||||
pop R15
|
||||
ret
|
||||
|
||||
delay1us: push R15
|
||||
mov R15, 9
|
||||
loop1us: nop
|
||||
nop
|
||||
nop
|
||||
dec R15
|
||||
jnz loop1us
|
||||
pop R15
|
||||
ret
|
||||
|
||||
; -------------------------------------------------
|
||||
@@ -0,0 +1,208 @@
|
||||
; -------------------------------------------------
|
||||
; lcd.inc.jsm
|
||||
; -------------------------------------------------
|
||||
; needs xmem-address definition for
|
||||
; - lcd_port (LCD-Base)
|
||||
|
||||
; needs delay.inc.jsm
|
||||
|
||||
; -------------------------------------------------
|
||||
lcd_cmd: equ 0x00
|
||||
lcd_rd: equ 0x20
|
||||
lcd_data: equ 0x40
|
||||
lcd_enable: equ 0x80
|
||||
|
||||
LCD_CMD_Z1: equ 0x80
|
||||
LCD_CMD_Z2: equ 0xC0
|
||||
LCD_CMD_CLEAR: equ 0x01
|
||||
|
||||
; -------------------------------------------------
|
||||
; Init LCD
|
||||
; -------------------------------------------------
|
||||
LCD_init: mov R2, 0x00
|
||||
mov R0, 0x03
|
||||
call _write_lcd
|
||||
call delay10ms
|
||||
mov R2, 0x00
|
||||
mov R0, 0x03
|
||||
call _write_lcd
|
||||
call delay10ms
|
||||
|
||||
mov R2, 0x00
|
||||
mov R0, 0x02
|
||||
call _write_lcd
|
||||
call delay1ms
|
||||
|
||||
; 1. Function set: 4-Bit mode, two display lines
|
||||
mov R0, 0x28
|
||||
call LCD_writecmd
|
||||
|
||||
; 2. Display on, no cursor
|
||||
mov R0, 0x0C
|
||||
call LCD_writecmd
|
||||
|
||||
; 3. Cursor shift during write
|
||||
mov R0, 0x06
|
||||
call LCD_writecmd
|
||||
|
||||
; 4. Display clear
|
||||
mov R0, 0x01
|
||||
call LCD_writecmd
|
||||
|
||||
ret
|
||||
|
||||
; -------------------------------------------------
|
||||
; LCD_waitbsy
|
||||
; -------------------------------------------------
|
||||
LCD_waitbsy: push R0
|
||||
bsy_loop: call LCD_readstat
|
||||
and R0, 0x80
|
||||
jz ex_bsy
|
||||
call delay1us
|
||||
jmp bsy_loop
|
||||
ex_bsy: pop R0
|
||||
ret
|
||||
|
||||
; -------------------------------------------------
|
||||
; LCD_writecmd
|
||||
; -------------------------------------------------
|
||||
; R0 = cmd
|
||||
LCD_writeaddr:
|
||||
LCD_writecmd: push R2
|
||||
mov R2, lcd_cmd
|
||||
call LCD_write
|
||||
pop R2
|
||||
ret
|
||||
|
||||
; -------------------------------------------------
|
||||
; LCD_putsx
|
||||
; -------------------------------------------------
|
||||
; R1 = address of null-terminated string in XMEM
|
||||
LCD_putsx: push R0
|
||||
putsx_loop: movx R0, (R1)
|
||||
inc R1
|
||||
tst R0
|
||||
jz putsx_ex
|
||||
call LCD_writechar
|
||||
jmp putsx_loop
|
||||
putsx_ex: pop R0
|
||||
ret
|
||||
|
||||
; -------------------------------------------------
|
||||
; LCD_putsc
|
||||
; -------------------------------------------------
|
||||
; R1 = address of null-terminated string in CMEM
|
||||
LCD_putsc: push R0
|
||||
putsc_loop: movc R0, (R1)
|
||||
inc R1
|
||||
tst R0
|
||||
jz putsc_ex
|
||||
call LCD_writechar
|
||||
jmp putsc_loop
|
||||
putsc_ex: pop R0
|
||||
ret
|
||||
|
||||
; -------------------------------------------------
|
||||
; LCD_writechar
|
||||
; -------------------------------------------------
|
||||
; R0 = char
|
||||
LCD_writedata:
|
||||
LCD_writechar: push R2
|
||||
mov R2, lcd_data
|
||||
call LCD_write
|
||||
pop R2
|
||||
ret
|
||||
|
||||
; -------------------------------------------------
|
||||
; LCD_write
|
||||
; -------------------------------------------------
|
||||
; R0 = input
|
||||
; R2 = register
|
||||
LCD_write: call LCD_waitbsy
|
||||
push R0
|
||||
swap R0
|
||||
call _write_lcd
|
||||
pop R0
|
||||
call _write_lcd
|
||||
ret
|
||||
|
||||
; -------------------------------------------------
|
||||
; LCD_readstat
|
||||
; -------------------------------------------------
|
||||
; R0 = status
|
||||
LCD_readstat: push R2
|
||||
mov R2, lcd_cmd
|
||||
call LCD_read
|
||||
pop R2
|
||||
ret
|
||||
|
||||
; -------------------------------------------------
|
||||
; LCD_read
|
||||
; -------------------------------------------------
|
||||
; R0 = output
|
||||
; R2 = register
|
||||
LCD_read: call _read_lcd
|
||||
swap R0
|
||||
push R0
|
||||
call _read_lcd
|
||||
pop R2
|
||||
or R0, R2
|
||||
ret
|
||||
|
||||
; -------------------------------------------------
|
||||
; _write
|
||||
; -------------------------------------------------
|
||||
; R0 = input
|
||||
_write_lcd: push R1
|
||||
|
||||
and R0, 0x0F
|
||||
mov R1, R0
|
||||
or R1, R2
|
||||
xout (lcd_port), R1
|
||||
call delay1us
|
||||
|
||||
mov R1, R0
|
||||
or R1, R2
|
||||
or R1, lcd_enable
|
||||
xout (lcd_port), R1
|
||||
call delay1us
|
||||
|
||||
mov R1, R0
|
||||
or R1, R2
|
||||
xout (lcd_port), R1
|
||||
call delay1us
|
||||
|
||||
or R1, lcd_rd
|
||||
xout (lcd_port), R1
|
||||
|
||||
pop R1
|
||||
ret
|
||||
|
||||
; -------------------------------------------------
|
||||
; _read
|
||||
; -------------------------------------------------
|
||||
; R0 = output
|
||||
_read_lcd: push R1
|
||||
|
||||
mov R1, lcd_rd
|
||||
or R1, R2
|
||||
xout (lcd_port), R1
|
||||
call delay1us
|
||||
|
||||
mov R1, lcd_rd
|
||||
or R1, R2
|
||||
or R1, lcd_enable
|
||||
xout (lcd_port), R1
|
||||
call delay1us
|
||||
xin R0, (lcd_port)
|
||||
and R0, 0x0F
|
||||
|
||||
mov R1, lcd_rd
|
||||
or R1, R2
|
||||
xout (lcd_port), R1
|
||||
call delay1us
|
||||
|
||||
pop R1
|
||||
ret
|
||||
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
; -------------------------------------------------
|
||||
; mul8x8.inc.jsm
|
||||
; -------------------------------------------------
|
||||
|
||||
; -------------------------------------------------
|
||||
; Parameter:
|
||||
; R0 : operand 1
|
||||
; R1 : operand 2
|
||||
; Return:
|
||||
; R0 : product low
|
||||
; R1 : product high
|
||||
mul8x8: push R2
|
||||
push R3
|
||||
push R4
|
||||
|
||||
mov R4, R1
|
||||
mov R1, 0
|
||||
mov R2, 0
|
||||
mov R3, 0
|
||||
|
||||
loop1: cmp R4, 0x01
|
||||
jeq ende1
|
||||
|
||||
shr R4
|
||||
jnc next1
|
||||
|
||||
add R2, R0
|
||||
addc R3, R1
|
||||
|
||||
next1: shl R0
|
||||
rolc R1
|
||||
jmp loop1
|
||||
|
||||
ende1: add R0, R2
|
||||
addc R1, R3
|
||||
|
||||
pop R4
|
||||
pop R3
|
||||
pop R2
|
||||
ret
|
||||
|
||||
; -------------------------------------------------
|
||||
@@ -0,0 +1,58 @@
|
||||
; -------------------------------------------------
|
||||
; uart.inc.jsm
|
||||
; -------------------------------------------------
|
||||
; needs xmem-address definition for
|
||||
; - uart_status (Status register)
|
||||
; - uart_data (Data register)
|
||||
UART_TX_EMPTY: equ 0x01
|
||||
UART_TX_FULL: equ 0x02
|
||||
UART_TX_CMPL: equ 0x04
|
||||
UART_RX_PRESENT: equ 0x10
|
||||
|
||||
; -------------------------------------------------
|
||||
; uart_puts
|
||||
; -------------------------------------------------
|
||||
; R1 : ptr to string
|
||||
uart_puts: push R0
|
||||
u_p_lp: movx R0, (R1)
|
||||
inc R1
|
||||
tst R0
|
||||
jz ex_ugp
|
||||
call uart_putchar
|
||||
jmp u_p_lp
|
||||
ex_ugp: pop R0
|
||||
ret
|
||||
|
||||
|
||||
; -------------------------------------------------
|
||||
; uart_putchar
|
||||
; -------------------------------------------------
|
||||
; R0 = input
|
||||
uart_putchar: jmp sout
|
||||
|
||||
; -------------------------------------------------
|
||||
; sout
|
||||
; -------------------------------------------------
|
||||
; R0 = input
|
||||
sout: push R1
|
||||
sout1: xin R1, (uart_status)
|
||||
and R1, UART_TX_FULL
|
||||
jnz sout1
|
||||
xout (uart_data), R0
|
||||
pop R1
|
||||
ret
|
||||
|
||||
; -------------------------------------------------
|
||||
; sin
|
||||
; -------------------------------------------------
|
||||
; R0 = output
|
||||
sin: push R1
|
||||
sin1: xin R1, (uart_status)
|
||||
and R1, UART_RX_PRESENT
|
||||
jnz sin1
|
||||
xin R0, (uart_data)
|
||||
pop R1
|
||||
ret
|
||||
|
||||
; -------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
; -------------------------------------------------
|
||||
; utils.inc.jsm
|
||||
; -------------------------------------------------
|
||||
|
||||
|
||||
; -------------------------------------------------
|
||||
; Parameter
|
||||
; R0 : Bin value in lower nibble
|
||||
; Return
|
||||
; R0 : Hex character representing lower nibble
|
||||
nibble2hex: and R0, 0x0F
|
||||
cmp R0, 0x0A
|
||||
jlt isNum1
|
||||
add R0, 0x07
|
||||
isNum1: add R0, 0x30
|
||||
ret
|
||||
|
||||
; -------------------------------------------------
|
||||
; Parameter
|
||||
; R0 : Bin value
|
||||
; Return
|
||||
; R0 : Hex character high
|
||||
; R1 : Hex character low
|
||||
bin2hex: push R0
|
||||
call nibble2hex
|
||||
mov R1, R0
|
||||
pop R0
|
||||
swap R0
|
||||
call nibble2hex
|
||||
ret
|
||||
|
||||
; -------------------------------------------------
|
||||
@@ -0,0 +1,64 @@
|
||||
0 NOP
|
||||
1 HALT
|
||||
2 MOV|R|R
|
||||
3 MOV|R|K
|
||||
4 MOVX|R|Ri
|
||||
5 MOVX|R|Ki
|
||||
6 MOVX|Ri|R
|
||||
7 MOVX|Ri|K
|
||||
8 MOVX|Ki|R
|
||||
9 MOVC|R|Ri
|
||||
10 MOVC|R|Ki
|
||||
11 MOVC|Ri|R
|
||||
12 MOVC|Ri|K
|
||||
13 MOVC|Ki|R
|
||||
14 CMP|R|R
|
||||
15 CMP|R|K
|
||||
16 ADD|R|R
|
||||
17 ADD|R|K
|
||||
18 ADDC|R|R
|
||||
19 ADDC|R|K
|
||||
20 SUB|R|R
|
||||
21 SUB|R|K
|
||||
22 SUBC|R|R
|
||||
23 SUBC|R|K
|
||||
24 AND|R|R
|
||||
25 AND|R|K
|
||||
26 OR|R|R
|
||||
27 OR|R|K
|
||||
28 XOR|R|R
|
||||
29 XOR|R|K
|
||||
30 SHL|R
|
||||
31 SHR|R
|
||||
32 ROL|R
|
||||
33 ROR|R
|
||||
34 ROLC|R
|
||||
35 RORC|R
|
||||
36 XOUT|Ki|R
|
||||
37 XOUT|Ri|K
|
||||
38 COUT|Ki|R
|
||||
39 COUT|Ri|K
|
||||
40 XIN|R|Ki
|
||||
41 CIN|R|Ki
|
||||
42 SWAP|R
|
||||
43 SETC
|
||||
44 UNDEF
|
||||
45 UNDEF
|
||||
46 SUB|K|R
|
||||
47 SUBC|K|R
|
||||
48 JMP|K
|
||||
49 JZ|K
|
||||
50 JNZ|K
|
||||
51 JC|K
|
||||
52 JNC|K
|
||||
53 JLT|K
|
||||
54 JGT|K
|
||||
55 JLE|K
|
||||
56 JGE|K
|
||||
57 JEQ|K
|
||||
58 JNE|K
|
||||
59 CALL|K
|
||||
60 PUSH|R
|
||||
61 POP|R
|
||||
62 RET
|
||||
63 RETI
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
st = "\033[7m"
|
||||
en = "\033[m"
|
||||
|
||||
while TRUE
|
||||
print "str> "
|
||||
STDOUT.flush
|
||||
str = gets
|
||||
break if not str
|
||||
str.chop!
|
||||
print "pat> "
|
||||
STDOUT.flush
|
||||
re = gets
|
||||
break if not re
|
||||
re.chop!
|
||||
str.gsub! re, "#{st}\\&#{en}"
|
||||
print str, "\n"
|
||||
end
|
||||
print "\n"
|
||||
@@ -0,0 +1,61 @@
|
||||
# ----------------------------------------------------------------------
|
||||
# Project: JCPU, a portable 8-bit RISC CPU written in VHDL
|
||||
# This file: The ROM file for upload to target over JTAG
|
||||
#
|
||||
# Copyright (C) 2007 J. Ahrensfeld
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# For questions and ideas, please contact the author at jens@jayfield.org
|
||||
#
|
||||
# ---------------------------------------------------------------------
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
# For Chipscope 9.1
|
||||
# ---------------------------------------------------------------------
|
||||
# Source JTAG/TCL frame work
|
||||
cd $env(CHIPSCOPE)\\bin\\nt
|
||||
source csejtag.tcl
|
||||
|
||||
namespace import ::chipscope::*
|
||||
|
||||
# Platform USB Cable
|
||||
set PLATFORM_USB_CABLE_ARGS [list "port=USB2" "frequency=6000000"]
|
||||
# frequency="24000000 | 12000000 | 6000000 | 3000000 | 1500000 | 750000"
|
||||
|
||||
# Create session
|
||||
set handle [::chipscope::csejtag_session create 0]
|
||||
|
||||
# Open JTAG and lock
|
||||
set open_result [::chipscope::csejtag_target open $handle $CSEJTAG_TARGET_PLATFORMUSB 0 $PLATFORM_USB_CABLE_ARGS]
|
||||
set lock_result [::chipscope::csejtag_target lock $handle 1000]
|
||||
|
||||
set devlist [::chipscope::csejtag_tap autodetect_chain $handle $CSEJTAG_SCAN_DEFAULT]
|
||||
|
||||
# Get Device ID
|
||||
set devtype "Virtex-4SX"
|
||||
set devid 2
|
||||
set irlength [::chipscope::csejtag_tap get_irlength $handle $devid]
|
||||
set idcode [::chipscope::csejtag_tap get_device_idcode $handle $devid]
|
||||
|
||||
set CSE_OP $CSEJTAG_SHIFT_READWRITE
|
||||
set CSE_ES $CSEJTAG_RUN_TEST_IDLE
|
||||
|
||||
# Write Program
|
||||
# JASM_ROM_INSERT_HERE
|
||||
|
||||
::chipscope::csejtag_target unlock $handle
|
||||
::chipscope::csejtag_target close $handle
|
||||
::chipscope::csejtag_session destroy $handle
|
||||
exit
|
||||
Executable
+44
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
|
||||
template = <<'END'
|
||||
-- (tv #1342) read output FIFO
|
||||
(
|
||||
cycles => 1,
|
||||
cm_i => bus_read_init(addr => ADDR_KS_OFIFO_DOUT),
|
||||
sep => msg(""),
|
||||
cm_o => bus_no_ack,
|
||||
irq => (others => '0')
|
||||
),
|
||||
|
||||
-- (tv #1343) wait while FIFO is read
|
||||
(
|
||||
cycles => 2,
|
||||
cm_i => bus_wait_ack,
|
||||
sep => msg(""),
|
||||
cm_o => bus_no_ack,
|
||||
irq => (others => '0')
|
||||
),
|
||||
|
||||
-- (tv #1343) wait for ack
|
||||
(
|
||||
cycles => 1,
|
||||
cm_i => bus_wait_ack,
|
||||
sep => msg(""),
|
||||
cm_o => bus_read_ack(dat => #{exp_data}),
|
||||
irq => (others => '0')
|
||||
),
|
||||
|
||||
END
|
||||
|
||||
puts "KS-128 testvectors:\n"
|
||||
puts "\n" * 3
|
||||
|
||||
|
||||
0.upto(10) { |sk_no|
|
||||
3.downto(0) { |sl_no|
|
||||
exp_data = "slice_32(TC1_SUBKEYS(#{sk_no}), #{sl_no})"
|
||||
t = template.gsub(/"/, '\\"')
|
||||
puts eval("format(\"#{t}\")")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
-------------------------------------------------------------------------
|
||||
-- Project: JCPU, a portable 8-bit RISC CPU written in VHDL
|
||||
-- This file: The ROM file for use in your VHDL design
|
||||
--
|
||||
-- Copyright (C) 2007 J. Ahrensfeld
|
||||
--
|
||||
-- This program is free software: you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation, either version 3 of the License, or
|
||||
-- (at your option) any later version.
|
||||
--
|
||||
-- This program 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 General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
--
|
||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||
--
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
LIBRARY ieee;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
USE ieee.numeric_std.ALL;
|
||||
|
||||
library work;
|
||||
use work.cpu_pkg.all;
|
||||
|
||||
-- JASM_ROM_INSERT_HERE
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
-------------------------------------------------------------------------
|
||||
-- Project: JCPU, a portable 8-bit RISC CPU written in VHDL
|
||||
-- This file: loadable ROM
|
||||
--
|
||||
-- Copyright (C) 2007 J. Ahrensfeld
|
||||
--
|
||||
-- This program is free software: you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation, either version 3 of the License, or
|
||||
-- (at your option) any later version.
|
||||
--
|
||||
-- This program 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 General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
--
|
||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||
--
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
LIBRARY ieee;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
USE ieee.numeric_std.ALL;
|
||||
|
||||
library UNISIM;
|
||||
use UNISIM.VComponents.all;
|
||||
|
||||
library work;
|
||||
use work.cpu_pkg.all;
|
||||
|
||||
ENTITY xrom IS
|
||||
Port (
|
||||
clk : in STD_LOGIC;
|
||||
ce : in STD_LOGIC;
|
||||
addr : in dmem_addr_t;
|
||||
dout : out dmem_data_t
|
||||
);
|
||||
|
||||
END xrom;
|
||||
|
||||
ARCHITECTURE loadable OF xrom IS
|
||||
|
||||
-- JASM_ROM_INSERT_HERE
|
||||
|
||||
signal jtag_ld_clk : STD_LOGIC;
|
||||
signal jtag_ld_we : STD_LOGIC;
|
||||
signal jtag_ld_addr : dmem_addr_t;
|
||||
signal jtag_ld_dout : dmem_data_t;
|
||||
signal jtag_ld_din : dmem_data_t;
|
||||
signal bs_rst, bs_sel, bs_shift, bs_tdi, bs_tdo : std_logic;
|
||||
signal bs_capture, bs_clk0, bs_clk1, bs_update0, bs_update1 : std_logic;
|
||||
signal user_regi, user_rego : unsigned (15 downto 0);
|
||||
constant id : unsigned (15 downto 0) := X"BEEF";
|
||||
|
||||
begin
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
-- Virtex-4: JTAG Loader
|
||||
--------------------------------------------------------------------------
|
||||
i00_BUFG : BUFG
|
||||
port map
|
||||
(
|
||||
O => bs_clk1,
|
||||
I => bs_clk0
|
||||
);
|
||||
|
||||
i01_BUFG : BUFG
|
||||
port map
|
||||
(
|
||||
O => bs_update1,
|
||||
I => bs_update0
|
||||
);
|
||||
|
||||
BSCAN_VIRTEX4_inst2 : BSCAN_VIRTEX4
|
||||
generic map
|
||||
(
|
||||
JTAG_CHAIN => 2 -- Value to set BSCAN site of device. Possible values: (1,2,3 or 4)
|
||||
)
|
||||
port map
|
||||
(
|
||||
CAPTURE => bs_capture, -- CAPTURE output from TAP controller
|
||||
DRCK => bs_clk0, -- Data register output for USER functions
|
||||
RESET => bs_rst, -- Reset output from TAP controller
|
||||
SEL => bs_sel, -- USER active output
|
||||
SHIFT => bs_shift, -- SHIFT output from TAP controller
|
||||
TDI => bs_tdi, -- TDI output from TAP controller
|
||||
UPDATE => bs_update0, -- UPDATE output from TAP controller
|
||||
TDO => bs_tdo -- Data input for USER function
|
||||
);
|
||||
|
||||
jtag_ld_addr <= user_regi(user_regi'left downto user_regi'left-dmem_data_t'length+1);
|
||||
jtag_ld_din <= user_regi(dmem_data_t'left downto 0);
|
||||
jtag_ld_clk <= bs_update1;
|
||||
jtag_ld_we <= bs_sel;
|
||||
|
||||
sipo:
|
||||
process (bs_rst, bs_clk1, bs_tdi, bs_shift)
|
||||
begin
|
||||
if bs_rst = '1' then
|
||||
user_regi <= (others => '0');
|
||||
elsif rising_edge(bs_clk1) then
|
||||
if bs_shift = '1' then
|
||||
user_regi <= bs_tdi & user_regi(user_regi'left downto 1);
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
piso:
|
||||
process (bs_rst, bs_clk1, bs_shift, user_rego)
|
||||
begin
|
||||
bs_tdo <= user_rego(0);
|
||||
if bs_rst = '1' then
|
||||
user_rego <= (others => '0');
|
||||
elsif rising_edge(bs_clk1) then
|
||||
if bs_shift = '1' then
|
||||
user_rego <= user_rego(0) & user_rego(user_rego'left downto 1);
|
||||
else
|
||||
user_rego <= (user_rego'left downto dmem_data_t'length => '0') & jtag_ld_dout;
|
||||
-- user_rego <= id;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
-- ROM Read/Write
|
||||
--------------------------------------------------------------------------
|
||||
PROM_READ:
|
||||
process(clk, ce)
|
||||
begin
|
||||
if rising_edge(clk) and ce = '1' then
|
||||
dout <= xmem_rom(to_integer(addr));
|
||||
end if;
|
||||
end process;
|
||||
|
||||
PROM_WRITE:
|
||||
process(jtag_ld_clk, jtag_ld_we)
|
||||
begin
|
||||
if rising_edge(jtag_ld_clk) then
|
||||
if jtag_ld_we = '1' then
|
||||
xmem_rom(to_integer(jtag_ld_addr)) <= jtag_ld_din;
|
||||
else
|
||||
jtag_ld_dout <= xmem_rom(to_integer(jtag_ld_addr));
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
end loadable;
|
||||
@@ -0,0 +1,26 @@
|
||||
CFLAGS=-O2
|
||||
CC=gcc
|
||||
PREFIX=/usr/local
|
||||
all: romgen ramgen flashgen flashgen_tlb packhex
|
||||
|
||||
romgen: ./src/romgen.c
|
||||
$(CC) $(CFLAGS) ./src/romgen.c -lm -o ./romgen
|
||||
|
||||
ramgen: ./src/ramgen.c
|
||||
$(CC) $(CFLAGS) ./src/ramgen.c -lm -o ./ramgen
|
||||
|
||||
flashgen: ./src/flashgen.c
|
||||
$(CC) $(CFLAGS) ./src/flashgen.c -lm -o ./flashgen
|
||||
|
||||
flashgen_tlb: ./src/flashgen.c
|
||||
$(CC) $(CFLAGS) -DSDRAM_BASE=0x80000000 -DFLASH_BASE_MEM=0x88000000 ./src/flashgen.c -lm -o ./flashgen_tlb
|
||||
|
||||
packhex: ./src/packhex.c
|
||||
$(CC) $(CFLAGS) ./src/packhex.c -lm -o ./packhex
|
||||
|
||||
install:
|
||||
cp romgen $(PREFIX)/bin
|
||||
cp ramgen $(PREFIX)/bin
|
||||
cp flashgen $(PREFIX)/bin
|
||||
clean:
|
||||
rm -rf romgen* ramgen* flashgen*
|
||||
@@ -0,0 +1,187 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef SDRAM_BASE
|
||||
#define SDRAM_BASE 0x40000000
|
||||
#endif
|
||||
#ifndef FLASH_BASE_MEM
|
||||
#define FLASH_BASE_MEM 0x00000000
|
||||
#endif
|
||||
|
||||
#define MAGIC 0x4A464931 // "JFI1" in big-endian;
|
||||
|
||||
uint8_t _g_bytes[4] = {0x12, 0x34, 0x56, 0x78};
|
||||
uint8_t _g_bytes2[4] = {0};
|
||||
|
||||
int IsEndianBig(void)
|
||||
{
|
||||
int i, result;
|
||||
|
||||
uint8_t *pBuf8;
|
||||
uint16_t *pBuf16;
|
||||
uint32_t *pBuf32;
|
||||
uint16_t halve;
|
||||
uint32_t word;
|
||||
|
||||
|
||||
halve = 0x1234;
|
||||
word = 0x12345678;
|
||||
|
||||
result = -1;
|
||||
|
||||
for (i=0; i < 4; i++)
|
||||
_g_bytes2[i] = _g_bytes[i];
|
||||
|
||||
pBuf8 = (uint8_t*)&word;
|
||||
if (((*pBuf8+0) == 0x12) && (*(pBuf8+1) == 0x34) && (*(pBuf8+2) == 0x56) && (*(pBuf8+3) == 0x78))
|
||||
{
|
||||
pBuf8 = (uint8_t*)&halve;
|
||||
if (((*pBuf8+0) == 0x12) && (*(pBuf8+1) == 0x34))
|
||||
{
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
|
||||
pBuf8 = (uint8_t*)&word;
|
||||
if (((*pBuf8+0) == 0x78) && (*(pBuf8+1) == 0x56) && (*(pBuf8+2) == 0x34) && (*(pBuf8+3) == 0x12))
|
||||
{
|
||||
pBuf8 = (uint8_t*)&halve;
|
||||
if (((*pBuf8+0) == 0x34) && (*(pBuf8+1) == 0x12))
|
||||
{
|
||||
result = 0;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t conv_endian32(uint32_t src)
|
||||
{
|
||||
uint32_t dst;
|
||||
|
||||
dst = (0xFF000000 & (src << 24))
|
||||
| (0x00FF0000 & (src << 8))
|
||||
| (0x0000FF00 & (src >> 8))
|
||||
| (0x000000FF & (src >> 24));
|
||||
|
||||
return dst;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------
|
||||
typedef struct _sflash_img_hdr_t
|
||||
{
|
||||
uint32_t magic;
|
||||
uint32_t target_addr;
|
||||
uint32_t img_offset;
|
||||
uint32_t img_size;
|
||||
uint32_t hdr_next;
|
||||
uint8_t img_name[128];
|
||||
uint8_t res[108];
|
||||
|
||||
} flash_img_hdr_t;
|
||||
|
||||
// --------------------------------------------------------------
|
||||
void basename(char *pSrc, char *pDst)
|
||||
{
|
||||
int i, size;
|
||||
|
||||
size = strlen(pSrc);
|
||||
|
||||
while(pSrc[size] != '.')
|
||||
size--;
|
||||
|
||||
for (i=0; i < size; i++)
|
||||
pDst[i] = pSrc[i];
|
||||
|
||||
pDst[i] = 0;
|
||||
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *pFilenameIn;
|
||||
char name_flash[1024];
|
||||
char name_prj[1024];
|
||||
char *pBuf;
|
||||
uint32_t *pBuf32;
|
||||
flash_img_hdr_t img_hdr = {0};
|
||||
|
||||
FILE *pFile;
|
||||
int filesize;
|
||||
long start, end;
|
||||
int i;
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
fprintf(stderr, "Usage: flashgen <input file> [-{EL|EB}]\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
pFilenameIn = argv[1];
|
||||
pFile = fopen(pFilenameIn, "rb");
|
||||
if (!pFile)
|
||||
{
|
||||
fprintf(stderr, "Error opening file %s\n", pFilenameIn);
|
||||
return 1;
|
||||
}
|
||||
|
||||
basename(pFilenameIn, name_prj);
|
||||
sprintf(name_flash, "%s.flash.bin", name_prj);
|
||||
|
||||
// determine filesize
|
||||
fseek(pFile, 0, SEEK_SET);
|
||||
start = ftell(pFile);
|
||||
fseek(pFile, 0, SEEK_END);
|
||||
end = ftell(pFile);
|
||||
fseek(pFile, 0, SEEK_SET);
|
||||
filesize = (end-start);
|
||||
|
||||
pBuf = (char*)malloc(filesize);
|
||||
filesize = fread(pBuf, 1, filesize, pFile);
|
||||
|
||||
fclose(pFile);
|
||||
|
||||
pFile = fopen(name_flash, "wb");
|
||||
if (!pFile)
|
||||
{
|
||||
fprintf(stderr, "Error opening file %s\n", name_flash);
|
||||
return 1;
|
||||
}
|
||||
|
||||
img_hdr.magic = MAGIC;
|
||||
|
||||
img_hdr.target_addr = SDRAM_BASE;
|
||||
img_hdr.img_size = filesize;
|
||||
img_hdr.img_offset = FLASH_BASE_MEM + sizeof(flash_img_hdr_t);
|
||||
img_hdr.hdr_next = FLASH_BASE_MEM;
|
||||
|
||||
if (argc == 3)
|
||||
{
|
||||
if ((argv[2][0] == '-') && (toupper(argv[2][1]) == 'E') && (toupper(argv[2][2]) == 'B'))
|
||||
{
|
||||
if (1 == IsEndianBig())
|
||||
{
|
||||
img_hdr.magic = conv_endian32(MAGIC);
|
||||
pBuf32 = (uint32_t*)pBuf;
|
||||
for (i=0; i < filesize/4; i ++)
|
||||
pBuf32[i] = pBuf32[i]; // don't convert data
|
||||
}
|
||||
else
|
||||
{
|
||||
pBuf32 = (uint32_t*)pBuf;
|
||||
for (i=0; i < filesize/4; i ++)
|
||||
pBuf32[i] = conv_endian32(pBuf32[i]); // convert data
|
||||
}
|
||||
}
|
||||
}
|
||||
fwrite(&img_hdr, sizeof(flash_img_hdr_t), 1, pFile);
|
||||
fwrite(pBuf, 1, filesize, pFile);
|
||||
|
||||
fclose(pFile);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,568 @@
|
||||
|
||||
/***** P A C K H E X . C ************************************************
|
||||
*
|
||||
* Packhex is a hex-file compaction utility. It attempts to concatenate
|
||||
* hex records to produce more size-efficient packaging.
|
||||
*
|
||||
* Limitations: Input files must be correctly formatted. This utility
|
||||
* is not robust enough to detect hex-record formatting
|
||||
* errors.
|
||||
*
|
||||
* Published: May 1993 Embedded Systems Programming magazine
|
||||
* "Creating Faster Hex Files"
|
||||
*
|
||||
* URL: ESP magazine: http://www.embedded.com
|
||||
* Source Code: ftp://ftp.mfi.com/pub/espmag/1993/pakhex.zip
|
||||
*
|
||||
* Author: Mark Gringrich
|
||||
*
|
||||
* Compiler: Microsoft C 6.0
|
||||
* cl /F 1000 packhex.c
|
||||
*
|
||||
*
|
||||
* $Id: packhex.c,v 1.9 2004/04/20 07:07:08 ralf Exp $
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
/* #define SMALLER_RECORDS */
|
||||
#ifdef SMALLER_RECORDS
|
||||
#define MAX_LEN_S1_RECS 128
|
||||
#define MAX_LEN_S2_RECS 128
|
||||
#define MAX_LEN_S3_RECS 128
|
||||
#else
|
||||
#define MAX_LEN_S1_RECS 252
|
||||
#define MAX_LEN_S2_RECS 251
|
||||
#define MAX_LEN_S3_RECS 250
|
||||
#endif
|
||||
|
||||
|
||||
/*--------------------------------- includes ---------------------------------*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if 0
|
||||
#include "config.h"
|
||||
|
||||
#ifndef VMS
|
||||
#ifndef HAVE_STRERROR
|
||||
extern int sys_nerr;
|
||||
extern char *sys_errlist[];
|
||||
|
||||
#define strerror( _err ) \
|
||||
((_err) < sys_nerr) ? sys_errlist [(_err)] : "unknown error"
|
||||
|
||||
#else /* HAVE_STRERROR */
|
||||
char *strerror ();
|
||||
#endif
|
||||
#else /* VMS */
|
||||
char *strerror (int,...);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__unix__) && !defined(EXIT_FAILURE)
|
||||
#define EXIT_FAILURE -1
|
||||
#define EXIT_SUCCESS 0
|
||||
#endif
|
||||
|
||||
/*--------------------------------- defines ----------------------------------*/
|
||||
|
||||
#define YES 1
|
||||
#define MAX_LINE_SIZE 600
|
||||
#define EOS '\0'
|
||||
|
||||
|
||||
/*---------------------------------- macros ----------------------------------*/
|
||||
|
||||
/* Convert ASCII hexadecimal digit to value. */
|
||||
|
||||
#define HEX_DIGIT( C ) ( ( ( ( C ) > '9' ) ? ( C ) + 25 : ( C ) ) & 0xF )
|
||||
|
||||
|
||||
/*--------------------------------- typedefs ---------------------------------*/
|
||||
|
||||
typedef unsigned char Boolean;
|
||||
typedef unsigned char Uchar;
|
||||
typedef unsigned int Uint;
|
||||
typedef unsigned long Ulong;
|
||||
|
||||
typedef struct /* Functions and constant returning Hex-record vital stats. */
|
||||
{
|
||||
Boolean ( *is_data_record )( char * );
|
||||
Ulong ( *get_address )( char * );
|
||||
Uint ( *get_data_count )( char * );
|
||||
const Uint max_data_count;
|
||||
char *( *get_data_start )( char * );
|
||||
void ( *put_data_record )( Uint, Ulong, char * );
|
||||
} Rec_vitals;
|
||||
|
||||
|
||||
/*--------------------------- function prototypes ----------------------------*/
|
||||
|
||||
Rec_vitals * identify_first_data_record( char *, int );
|
||||
Ulong get_ndigit_hex( char *, int );
|
||||
|
||||
|
||||
/*----------------------------- Intel Hex format -----------------------------*/
|
||||
|
||||
/*
|
||||
* Intel Hex data-record layout
|
||||
*
|
||||
* :aabbbbccd...dee
|
||||
*
|
||||
* : - header character
|
||||
* aa - record data byte count, a 2-digit hex value
|
||||
* bbbb - record address, a 4-digit hex value
|
||||
* cc - record type, a 2-digit hex value:
|
||||
* "00" is a data record
|
||||
* "01" is an end-of-data record
|
||||
* "02" is an extended-address record
|
||||
* "03" is a start record
|
||||
* d...d - data (always an even number of chars)
|
||||
* ee - record checksum, a 2-digit hex value
|
||||
* checksum = 2's complement
|
||||
* [ (sum of bytes: aabbbbccd...d) modulo 256 ]
|
||||
*/
|
||||
|
||||
|
||||
Boolean is_intel_data_rec( char * rec_str )
|
||||
{
|
||||
return( ( rec_str[ 0 ] == ':' ) && ( rec_str[ 8 ] == '0' ) );
|
||||
}
|
||||
|
||||
Uint get_intel_rec_data_count( char * rec_str )
|
||||
{
|
||||
return( ( Uint ) get_ndigit_hex( rec_str + 1, 2 ) );
|
||||
}
|
||||
|
||||
Ulong get_intel_rec_address( char * rec_str )
|
||||
{
|
||||
return( get_ndigit_hex( rec_str + 3, 4 ) );
|
||||
}
|
||||
|
||||
char * get_intel_rec_data_start( char * rec_str )
|
||||
{
|
||||
return( rec_str + 9 );
|
||||
}
|
||||
|
||||
void put_intel_data_rec( Uint count, Ulong address, char * data_str )
|
||||
{
|
||||
char *ptr;
|
||||
Uint sum = count + ( address >> 8 & 0xff ) + ( address & 0xff );
|
||||
|
||||
for ( ptr = data_str ; *ptr != EOS ; ptr += 2 )
|
||||
sum += ( Uint ) get_ndigit_hex( ptr, 2 );
|
||||
|
||||
printf(
|
||||
":%02X%04lX00%s%02X\n", count, address, data_str, (~sum + 1) & 0xff
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Rec_vitals intel_hex =
|
||||
{
|
||||
is_intel_data_rec,
|
||||
get_intel_rec_address,
|
||||
get_intel_rec_data_count,
|
||||
255, /* Maximum data bytes in a record. */
|
||||
get_intel_rec_data_start,
|
||||
put_intel_data_rec
|
||||
};
|
||||
|
||||
|
||||
/*------------------------- Motorola S1-record format ------------------------*/
|
||||
|
||||
/*
|
||||
* Motorola S-record data-record layout
|
||||
*
|
||||
* Sabbc...cd...dee
|
||||
*
|
||||
* S - header character
|
||||
* a - record type, a 1-digit value:
|
||||
* "0" is a header record
|
||||
* "1" is a 2-byte-address data record
|
||||
* "2" is a 3-byte-address data record
|
||||
* "3" is a 4-byte-address data record
|
||||
* "7" is a 4-byte-address end-of-data record
|
||||
* "8" is a 3-byte-address end-of-data record
|
||||
* "9" is a 2-byte-address end-of-data record
|
||||
* bb - record length in bytes, a 2-digit hex value
|
||||
* (record length doesn't count the header/type
|
||||
* chars and checksum byte)
|
||||
* c...c - record address, a 4-, 6-, or 8-digit value,
|
||||
* depending on record type
|
||||
* d...d - data (always an even number of chars)
|
||||
* ee - record checksum, a 2-digit hex value
|
||||
* checksum = 1's complement
|
||||
* [ (sum of all bytes: bbc..cd...d) modulo 256 ]
|
||||
*/
|
||||
|
||||
#define S1_COUNT_OFFSET 3
|
||||
|
||||
|
||||
Boolean is_moto_s1_data_rec( char * rec_str )
|
||||
{
|
||||
return ( ( rec_str[ 0 ] == 'S' ) && ( rec_str[ 1 ] == '1' ) );
|
||||
}
|
||||
|
||||
Uint get_moto_s1_rec_data_count( char * rec_str )
|
||||
{
|
||||
return( ( Uint ) get_ndigit_hex( rec_str + 2, 2 ) - S1_COUNT_OFFSET );
|
||||
}
|
||||
|
||||
Ulong get_moto_s1_rec_address( char * rec_str )
|
||||
{
|
||||
return( get_ndigit_hex( rec_str + 4, 4 ) );
|
||||
}
|
||||
|
||||
char * get_moto_s1_rec_data_start( char * rec_str )
|
||||
{
|
||||
return( rec_str + 8 );
|
||||
}
|
||||
|
||||
void put_moto_s1_data_rec( Uint count, Ulong address, char * data_str )
|
||||
{
|
||||
char *ptr;
|
||||
Uint sum = S1_COUNT_OFFSET + count +
|
||||
( address >> 8 & 0xff ) + ( address & 0xff );
|
||||
|
||||
for ( ptr = data_str ; *ptr != EOS ; ptr += 2 )
|
||||
sum += ( Uint ) get_ndigit_hex( ptr, 2 );
|
||||
|
||||
printf(
|
||||
"S1%02X%04lX%s%02X\n",
|
||||
count + S1_COUNT_OFFSET, address, data_str, ~sum & 0xff
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Rec_vitals motorola_s1_rec =
|
||||
{
|
||||
is_moto_s1_data_rec,
|
||||
get_moto_s1_rec_address,
|
||||
get_moto_s1_rec_data_count,
|
||||
MAX_LEN_S1_RECS, /* Maximum data bytes in a record. */
|
||||
get_moto_s1_rec_data_start,
|
||||
put_moto_s1_data_rec
|
||||
};
|
||||
|
||||
|
||||
/*------------------------- Motorola S2-record format ------------------------*/
|
||||
|
||||
#define S2_COUNT_OFFSET 4
|
||||
|
||||
Boolean is_moto_s2_data_rec( char * rec_str )
|
||||
{
|
||||
return ( ( rec_str[ 0 ] == 'S' ) && ( rec_str[ 1 ] == '2' ) );
|
||||
}
|
||||
|
||||
Uint get_moto_s2_rec_data_count( char * rec_str )
|
||||
{
|
||||
return( ( Uint ) get_ndigit_hex( rec_str + 2, 2 ) - S2_COUNT_OFFSET );
|
||||
}
|
||||
|
||||
Ulong get_moto_s2_rec_address( char * rec_str )
|
||||
{
|
||||
return( get_ndigit_hex( rec_str + 4, 6 ) );
|
||||
}
|
||||
|
||||
char * get_moto_s2_rec_data_start( char * rec_str )
|
||||
{
|
||||
return( rec_str + 10 );
|
||||
}
|
||||
|
||||
void put_moto_s2_data_rec( Uint count, Ulong address, char * data_str )
|
||||
{
|
||||
char *ptr;
|
||||
Uint sum = S2_COUNT_OFFSET + count + ( address >> 16 & 0xff ) +
|
||||
( address >> 8 & 0xff ) +
|
||||
( address & 0xff );
|
||||
|
||||
for ( ptr = data_str ; *ptr != EOS ; ptr += 2 )
|
||||
sum += ( Uint ) get_ndigit_hex( ptr, 2 );
|
||||
|
||||
printf(
|
||||
"S2%02X%06lX%s%02X\n",
|
||||
count + S2_COUNT_OFFSET, address, data_str, ~sum & 0xff
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Rec_vitals motorola_s2_rec =
|
||||
{
|
||||
is_moto_s2_data_rec,
|
||||
get_moto_s2_rec_address,
|
||||
get_moto_s2_rec_data_count,
|
||||
MAX_LEN_S2_RECS, /* Maximum data bytes in a record. */
|
||||
get_moto_s2_rec_data_start,
|
||||
put_moto_s2_data_rec
|
||||
};
|
||||
|
||||
|
||||
/*------------------------- Motorola S3-record format ------------------------*/
|
||||
|
||||
#define S3_COUNT_OFFSET 5
|
||||
|
||||
Boolean is_moto_s3_data_rec( char * rec_str )
|
||||
{
|
||||
return ( ( rec_str[ 0 ] == 'S' ) && ( rec_str[ 1 ] == '3' ) );
|
||||
}
|
||||
|
||||
Uint get_moto_s3_rec_data_count( char * rec_str )
|
||||
{
|
||||
return( ( Uint ) get_ndigit_hex( rec_str + 2, 2 ) - S3_COUNT_OFFSET );
|
||||
}
|
||||
|
||||
Ulong get_moto_s3_rec_address( char * rec_str )
|
||||
{
|
||||
return( get_ndigit_hex( rec_str + 4, 8 ) );
|
||||
}
|
||||
|
||||
char * get_moto_s3_rec_data_start( char * rec_str )
|
||||
{
|
||||
return( rec_str + 12 );
|
||||
}
|
||||
|
||||
void put_moto_s3_data_rec( Uint count, Ulong address, char * data_str )
|
||||
{
|
||||
char *ptr;
|
||||
Uint sum = S3_COUNT_OFFSET + count + ( address >> 24 & 0xff ) +
|
||||
( address >> 16 & 0xff ) +
|
||||
( address >> 8 & 0xff ) +
|
||||
( address & 0xff );
|
||||
|
||||
for ( ptr = data_str ; *ptr != EOS ; ptr += 2 )
|
||||
sum += ( Uint ) get_ndigit_hex( ptr, 2 );
|
||||
|
||||
printf(
|
||||
"S3%02X%08lX%s%02X\n",
|
||||
count + S3_COUNT_OFFSET, address, data_str, ~sum & 0xff
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Rec_vitals motorola_s3_rec =
|
||||
{
|
||||
is_moto_s3_data_rec,
|
||||
get_moto_s3_rec_address,
|
||||
get_moto_s3_rec_data_count,
|
||||
MAX_LEN_S3_RECS, /* Maximum data bytes in a record. */
|
||||
get_moto_s3_rec_data_start,
|
||||
put_moto_s3_data_rec
|
||||
};
|
||||
|
||||
|
||||
/*-------------------- Put your favorite hex format here ---------------------*/
|
||||
|
||||
/*
|
||||
* * * * The following is a template for an additional hex format: * * *
|
||||
*
|
||||
*
|
||||
* Boolean is_X_data_rec( char * rec_str ) {}
|
||||
*
|
||||
* Uint get_X_rec_data_count( char * rec_str ) {}
|
||||
*
|
||||
* Ulong get_X_rec_address( char * rec_str ) {}
|
||||
*
|
||||
* char * get_X_rec_data_start( char * rec_str ) {}
|
||||
*
|
||||
* void put_X_data_rec( Uint count, Ulong address, char * data_str ) {}
|
||||
*
|
||||
* Rec_vitals X_rec =
|
||||
* {
|
||||
* is_X_data_rec,
|
||||
* get_X_rec_address,
|
||||
* get_X_rec_data_count,
|
||||
* MAXIMUM DATA BYTES IN A RECORD,
|
||||
* get_X_rec_data_start,
|
||||
* put_X_data_rec
|
||||
* };
|
||||
*
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/*
|
||||
* Put address of additional Rec_vitals structures
|
||||
* in this array, before the NULL entry.
|
||||
*/
|
||||
|
||||
Rec_vitals *formats[] =
|
||||
{
|
||||
&intel_hex,
|
||||
&motorola_s1_rec,
|
||||
&motorola_s2_rec,
|
||||
&motorola_s3_rec,
|
||||
( Rec_vitals * ) NULL
|
||||
};
|
||||
|
||||
|
||||
/**** main *****************************************************************
|
||||
*
|
||||
*
|
||||
* Expects: Nothing (no command-line parameters).
|
||||
*
|
||||
* Returns: Exit status (EXIT_SUCCESS or EXIT_FAILURE).
|
||||
*
|
||||
* Reads hex records on the standard input and attempts to
|
||||
* splice adjacent data fields together. Results appear on
|
||||
* the standard output.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
int main(
|
||||
int argc,
|
||||
char **argv
|
||||
)
|
||||
{
|
||||
|
||||
char inbuff[ MAX_LINE_SIZE ], outbuff[ MAX_LINE_SIZE ];
|
||||
char *in_dptr, *out_dptr;
|
||||
int d_total, d_count, d_excess, n;
|
||||
int length;
|
||||
Ulong in_rec_addr, out_rec_addr = 0;
|
||||
Rec_vitals *rptr;
|
||||
|
||||
|
||||
/* Sift through file until first hex record is identified. */
|
||||
|
||||
rptr = identify_first_data_record( inbuff, MAX_LINE_SIZE );
|
||||
if ( rptr == NULL )
|
||||
{
|
||||
fputs( "No hex records found.\n", stderr );
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
|
||||
|
||||
/* Attempt data-record splicing until end-of-file is reached. */
|
||||
d_total = 0;
|
||||
for (;;) {
|
||||
if ( rptr->is_data_record( inbuff ) == YES )
|
||||
{ /* Input record is a data record. */
|
||||
d_count = rptr->get_data_count( inbuff );
|
||||
in_rec_addr = rptr->get_address( inbuff );
|
||||
in_dptr = rptr->get_data_start( inbuff );
|
||||
|
||||
if ( d_total == 0 || in_rec_addr != out_rec_addr + d_total )
|
||||
{ /* Begin a new output record. */
|
||||
if ( d_total != 0 )
|
||||
rptr->put_data_record( d_total, out_rec_addr, outbuff );
|
||||
out_dptr = outbuff;
|
||||
n = d_total = d_count;
|
||||
out_rec_addr = in_rec_addr;
|
||||
}
|
||||
else if
|
||||
( ( d_excess = d_total + d_count - rptr->max_data_count ) > 0 )
|
||||
{ /* Output a maximum-length record, then start a new record. */
|
||||
strncat( outbuff, in_dptr, 2 * ( d_count - d_excess ) );
|
||||
rptr->put_data_record(
|
||||
rptr->max_data_count, out_rec_addr, outbuff
|
||||
);
|
||||
in_dptr += 2 * ( d_count - d_excess );
|
||||
out_dptr = outbuff;
|
||||
n = d_total = d_excess;
|
||||
out_rec_addr += rptr->max_data_count;
|
||||
}
|
||||
else
|
||||
{ /* Append input record's data field with accumulated data. */
|
||||
out_dptr = outbuff + ( 2 * d_total );
|
||||
d_total += n = d_count;
|
||||
}
|
||||
strncpy( out_dptr, in_dptr, 2 * n );
|
||||
out_dptr[ 2 * n ] = EOS;
|
||||
}
|
||||
else
|
||||
{ /* Not a data record;
|
||||
* flush accumulated data then echo non-data record.
|
||||
*/
|
||||
if ( d_total != 0 )
|
||||
{
|
||||
rptr->put_data_record( d_total, out_rec_addr, outbuff );
|
||||
d_total = 0;
|
||||
}
|
||||
puts( inbuff );
|
||||
}
|
||||
|
||||
inbuff[ MAX_LINE_SIZE - 1 ] = '\0';
|
||||
if ( !fgets( inbuff, MAX_LINE_SIZE, stdin ) )
|
||||
break;
|
||||
if ( inbuff[ MAX_LINE_SIZE - 1 ] ) {
|
||||
fprintf( stderr, "Input line too long" );
|
||||
exit( 1 );
|
||||
}
|
||||
length = strlen(inbuff);
|
||||
inbuff[length - 1] = '\0';
|
||||
|
||||
}
|
||||
|
||||
|
||||
return ( EXIT_SUCCESS );
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**** identify_first_data_record *******************************************
|
||||
*
|
||||
* Expects: Pointer to hex-record line buffer.
|
||||
*
|
||||
* Returns: Pointer to hex-record structure (NULL if no match found).
|
||||
*
|
||||
* Reads the standard input, line by line, searching for a valid
|
||||
* record header character. If a valid header is found, a pointer
|
||||
* to the hex-record's type structure is returned, otherwise NULL.
|
||||
*
|
||||
* The input-stream pointer is left pointing to the first valid hex record.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
Rec_vitals * identify_first_data_record( char * buff_ptr, int max_length )
|
||||
{
|
||||
Rec_vitals ** ptr;
|
||||
int length;
|
||||
|
||||
|
||||
|
||||
for ( ;; ) {
|
||||
|
||||
buff_ptr[ max_length - 1 ] = '\0';
|
||||
if ( !fgets( buff_ptr, max_length, stdin ) )
|
||||
break;
|
||||
if ( buff_ptr[ max_length - 1 ] ) {
|
||||
fprintf( stderr, "Input line too long" );
|
||||
exit( 1 );
|
||||
}
|
||||
length = strlen(buff_ptr);
|
||||
buff_ptr[length - 1] = '\0';
|
||||
|
||||
for ( ptr = formats ; *ptr != ( Rec_vitals * ) NULL ; ptr++ )
|
||||
if ( ( *ptr )->is_data_record( buff_ptr ) == YES )
|
||||
return( *ptr ); /* Successful return. */
|
||||
|
||||
puts( buff_ptr ); /* Echo non-hex-record line. */
|
||||
}
|
||||
|
||||
return( ( Rec_vitals * ) NULL ); /* Unsuccessful return. */
|
||||
}
|
||||
|
||||
|
||||
/**** get_ndigit_hex *******************************************************
|
||||
*
|
||||
* Expects: Pointer to first ASCII hexadecimal digit, number of digits.
|
||||
*
|
||||
* Returns: Value of hexadecimal string as an unsigned long.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
Ulong get_ndigit_hex( char * cptr, int digits )
|
||||
{
|
||||
Ulong value;
|
||||
|
||||
for ( value = 0 ; --digits >= 0 ; cptr++ )
|
||||
value = ( value * 16L ) + HEX_DIGIT( *cptr );
|
||||
|
||||
return( value );
|
||||
}
|
||||
|
||||
@@ -0,0 +1,387 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#define ARCH_NAME "data"
|
||||
#define ENT_NAME "ram"
|
||||
#define JTAG_ADDR_WIDTH 16
|
||||
|
||||
// --------------------------------------------------------------
|
||||
void basename(char *pSrc, char *pDst)
|
||||
{
|
||||
int i, size;
|
||||
|
||||
size = strlen(pSrc);
|
||||
|
||||
while(pSrc[size] != '.')
|
||||
size--;
|
||||
|
||||
for (i=0; i < size; i++)
|
||||
pDst[i] = pSrc[i];
|
||||
|
||||
pDst[i] = 0;
|
||||
|
||||
}
|
||||
|
||||
int SaveRAM(char *pFilenameIn, char *pFilenameOut, char *pArchName, char *pEntName, int nbits_addr, int nbits_data)
|
||||
{
|
||||
FILE *pFileIn, *pFileOut;
|
||||
long start, end;
|
||||
int i, word, filesize, romsize;
|
||||
|
||||
pFileIn = fopen(pFilenameIn, "rb");
|
||||
if (!pFileIn)
|
||||
{
|
||||
fprintf(stderr, "Error opening file %s\n", pFilenameIn);
|
||||
return 1;
|
||||
}
|
||||
|
||||
pFileOut = fopen(pFilenameOut, "wb");
|
||||
if (!pFileOut)
|
||||
{
|
||||
fprintf(stderr, "Error opening file %s\n", pFilenameOut);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fseek(pFileIn, 0, SEEK_SET);
|
||||
start = ftell(pFileIn);
|
||||
fseek(pFileIn, 0, SEEK_END);
|
||||
end = ftell(pFileIn);
|
||||
fseek(pFileIn, 0, SEEK_SET);
|
||||
|
||||
filesize = (end-start);
|
||||
romsize = (int)pow(2, nbits_addr+2);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Header
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
fprintf(pFileOut, "LIBRARY IEEE;\n");
|
||||
fprintf(pFileOut, "USE IEEE.STD_LOGIC_1164.ALL;\n");
|
||||
fprintf(pFileOut, "USE IEEE.NUMERIC_STD.ALL;\n");
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
fprintf(pFileOut, "ENTITY %s IS\n", ENT_NAME);
|
||||
fprintf(pFileOut, "\tPort\n");
|
||||
fprintf(pFileOut, "\t(\n");
|
||||
fprintf(pFileOut, "\t\tclk\t\t: in STD_LOGIC;\n");
|
||||
fprintf(pFileOut, "\t\tce\t\t: in STD_LOGIC;\n");
|
||||
fprintf(pFileOut, "\t\twe\t\t: in unsigned(%d downto 0);\n", nbits_data/8-1);
|
||||
fprintf(pFileOut, "\t\taddr\t\t: in unsigned(%d downto 0);\n", nbits_data-1);
|
||||
fprintf(pFileOut, "\t\tdin\t\t: in unsigned(%d downto 0);\n", nbits_data-1);
|
||||
fprintf(pFileOut, "\t\tdout\t\t: out unsigned(%d downto 0)\n", nbits_data-1);
|
||||
fprintf(pFileOut, "\t);\n");
|
||||
fprintf(pFileOut, "END %s;\n", ENT_NAME);
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
|
||||
fprintf(pFileOut, "ARCHITECTURE %s OF %s IS\n", ARCH_NAME, ENT_NAME);
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
fprintf(pFileOut, "\tconstant depth : natural := %d;\n", romsize/4);
|
||||
fprintf(pFileOut, "\tsubtype word_t is unsigned(%d downto 0);\n", nbits_data-1);
|
||||
fprintf(pFileOut, "\ttype word_array_t is array (0 to %d) of word_t;\n", romsize/4-1);
|
||||
|
||||
fprintf(pFileOut, "\tsignal sram : word_array_t :=\n");
|
||||
fprintf(pFileOut, "\t(\n");
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// ROM part
|
||||
// -------------------------------------------------------------------------
|
||||
for (i=0; i < filesize; i += sizeof(int))
|
||||
{
|
||||
fread(&word, 1, sizeof(int), pFileIn);
|
||||
fprintf(pFileOut, "\t\tX\"%8.8X\"", word);
|
||||
if (i < (romsize-sizeof(int)))
|
||||
fprintf(pFileOut, ", -- %8.8X\n", i);
|
||||
else
|
||||
fprintf(pFileOut, " -- %8.8X\n", i);
|
||||
}
|
||||
word = 0;
|
||||
for (; i < romsize; i += sizeof(int))
|
||||
{
|
||||
fprintf(pFileOut, "\t\tX\"%8.8X\"", word);
|
||||
if (i < (romsize-sizeof(int)))
|
||||
fprintf(pFileOut, ", -- %8.8X\n", i);
|
||||
else
|
||||
fprintf(pFileOut, " -- %8.8X\n", i);
|
||||
}
|
||||
fprintf(pFileOut, "\t);\n");
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Trailer
|
||||
// -------------------------------------------------------------------------
|
||||
fprintf(pFileOut, "begin\n", ARCH_NAME);
|
||||
fprintf(pFileOut, "\n");
|
||||
fprintf(pFileOut, "RAM_RW:\n", ARCH_NAME);
|
||||
fprintf(pFileOut, "\tprocess(clk)\n");
|
||||
fprintf(pFileOut, "\tvariable index : natural range 0 to depth-1;\n");
|
||||
fprintf(pFileOut, "\tbegin\n");
|
||||
fprintf(pFileOut, "\t\tif rising_edge(clk) and ce = '1' then\n");
|
||||
fprintf(pFileOut, "\t\t\tindex := to_integer(addr(%d downto 2));\n", nbits_addr+1);
|
||||
fprintf(pFileOut, "\t\t\tif we(0) = '1' then\n");
|
||||
fprintf(pFileOut, "\t\t\t\tsram(index)(7 downto 0)\t\t<= din(7 downto 0);\n");
|
||||
fprintf(pFileOut, "\t\t\tend if;\n");
|
||||
fprintf(pFileOut, "\t\t\tif we(1) = '1' then\n");
|
||||
fprintf(pFileOut, "\t\t\t\tsram(index)(15 downto 8)\t<= din(15 downto 8);\n");
|
||||
fprintf(pFileOut, "\t\t\tend if;\n");
|
||||
fprintf(pFileOut, "\t\t\tif we(2) = '1' then\n");
|
||||
fprintf(pFileOut, "\t\t\t\tsram(index)(23 downto 16)\t<= din(23 downto 16);\n");
|
||||
fprintf(pFileOut, "\t\t\tend if;\n");
|
||||
fprintf(pFileOut, "\t\t\tif we(3) = '1' then\n");
|
||||
fprintf(pFileOut, "\t\t\t\tsram(index)(31 downto 24)\t\t<= din(31 downto 24);\n");
|
||||
fprintf(pFileOut, "\t\t\tend if;\n");
|
||||
fprintf(pFileOut, "\t\t\tdout <= sram(index);\n");
|
||||
fprintf(pFileOut, "\t\tend if;\n");
|
||||
fprintf(pFileOut, "\tend process;\n");
|
||||
fprintf(pFileOut, "\n");
|
||||
fprintf(pFileOut, "end %s;\n", ARCH_NAME);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SaveRAM_V4LD(char *pFilenameIn, char *pFilenameOut, char *pArchName, char *pEntName, int nbits_addr, int nbits_data)
|
||||
{
|
||||
FILE *pFileIn, *pFileOut;
|
||||
long start, end;
|
||||
int i, word, filesize, romsize;
|
||||
|
||||
char tpl[] = {"--------------------------------------------------------------------------\n-- Virtex-4: JTAG Loader\n--------------------------------------------------------------------------\n\ti00_BUFG : BUFG\n\tport map\n\t(\n\t\tO => bs_clk1,\n I => bs_clk0\n\t);\n\t\n\ti01_BUFG : BUFG\n\tport map\n\t(\n\t\tO => bs_update1,\n I => bs_update0\n\t);\n\n\tBSCAN_VIRTEX4_inst1 : BSCAN_VIRTEX4 \n\tgeneric map\n\t(\n\t\tJTAG_CHAIN => 1 -- Value to set BSCAN site of device. Possible values: (1,2,3 or 4)\n\t)\n\tport map \n\t(\n\t\tCAPTURE => bs_capture, -- CAPTURE output from TAP controller\n\t\tDRCK => bs_clk0, -- Data register output for USER functions\n\t\tRESET => bs_rst, -- Reset output from TAP controller\n\t\tSEL => bs_sel, -- USER active output\n\t\tSHIFT => bs_shift, -- SHIFT output from TAP controller\n\t\tTDI => bs_tdi, -- TDI output from TAP controller\n\t\tUPDATE => bs_update0, -- UPDATE output from TAP controller\n\t\tTDO => bs_tdo -- Data input for USER function\n\t);\n\n\tjtag_ld_addr <= user_regi(user_regi'left downto jtag_ld_dout'length);\n\tjtag_ld_din <= user_regi(jtag_ld_dout'length-1 downto 0);\n\tjtag_ld_clk <= bs_update1;\n\tjtag_ld_we <= bs_sel;\n\t\nsipo:\n\tprocess (bs_rst, bs_clk1, bs_tdi, bs_shift)\n\tbegin\n\t\tif bs_rst = '1' then\n\t\t\tuser_regi <= (others => '0');\n\t\telsif rising_edge(bs_clk1) then\n\t\t\tif bs_shift = '1' then\n\t\t\t\tuser_regi <= bs_tdi & user_regi(user_regi'left downto 1);\n\t\t\tend if;\n\t\tend if;\n\tend process;\t\n\npiso:\n\tprocess (bs_rst, bs_clk1, bs_shift, user_rego)\n\tbegin\n\t\tbs_tdo <= user_rego(0);\n\t\tif bs_rst = '1' then\n\t\t\tuser_rego <= (others => '0');\n\t\telsif rising_edge(bs_clk1) then\n\t\t\tif bs_shift = '1' then\n\t\t\t\tuser_rego <= user_rego(0) & user_rego(user_rego'left downto 1);\n\t\t\telse\n\t\t\t\tuser_rego <= (user_rego'left downto jtag_ld_dout'length => '0') & jtag_ld_dout;\t\n\t\n\t\t\tend if;\n\t\tend if;\n\tend process;\n\n"};
|
||||
|
||||
pFileIn = fopen(pFilenameIn, "rb");
|
||||
if (!pFileIn)
|
||||
{
|
||||
fprintf(stderr, "Error opening file %s\n", pFilenameIn);
|
||||
return 1;
|
||||
}
|
||||
|
||||
pFileOut = fopen(pFilenameOut, "wb");
|
||||
if (!pFileOut)
|
||||
{
|
||||
fprintf(stderr, "Error opening file %s\n", pFilenameOut);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fseek(pFileIn, 0, SEEK_SET);
|
||||
start = ftell(pFileIn);
|
||||
fseek(pFileIn, 0, SEEK_END);
|
||||
end = ftell(pFileIn);
|
||||
fseek(pFileIn, 0, SEEK_SET);
|
||||
|
||||
filesize = (end-start);
|
||||
romsize = (int)pow(2, nbits_addr+2);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Header
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
fprintf(pFileOut, "LIBRARY IEEE;\n");
|
||||
fprintf(pFileOut, "USE IEEE.STD_LOGIC_1164.ALL;\n");
|
||||
fprintf(pFileOut, "USE IEEE.NUMERIC_STD.ALL;\n");
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
fprintf(pFileOut, "library UNISIM;\n");
|
||||
fprintf(pFileOut, "use UNISIM.VComponents.all;\n");
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
fprintf(pFileOut, "ENTITY %s IS\n", ENT_NAME);
|
||||
fprintf(pFileOut, "\tPort\n");
|
||||
fprintf(pFileOut, "\t(\n");
|
||||
fprintf(pFileOut, "\t\tclk\t\t: in STD_LOGIC;\n");
|
||||
fprintf(pFileOut, "\t\tce\t\t: in STD_LOGIC;\n");
|
||||
fprintf(pFileOut, "\t\taddr\t\t: in unsigned(%d downto 0);\n", nbits_data-1);
|
||||
fprintf(pFileOut, "\t\tdout\t\t: out unsigned(%d downto 0)\n", nbits_data-1);
|
||||
fprintf(pFileOut, "\t);\n");
|
||||
fprintf(pFileOut, "END %s;\n", ENT_NAME);
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
|
||||
fprintf(pFileOut, "ARCHITECTURE %s OF %s IS\n", ARCH_NAME, ENT_NAME);
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
fprintf(pFileOut, "\tsubtype word_t is unsigned(%d downto 0);\n", nbits_data-1);
|
||||
fprintf(pFileOut, "\ttype word_array_t is array (0 to %d) of word_t;\n", romsize/4-1);
|
||||
|
||||
fprintf(pFileOut, "\tsignal jtag_ld_clk\t\t: STD_LOGIC;\n");
|
||||
fprintf(pFileOut, "\tsignal jtag_ld_we\t\t: STD_LOGIC;\n");
|
||||
fprintf(pFileOut, "\tsignal jtag_ld_addr\t\t: unsigned (%d downto 0);\n", JTAG_ADDR_WIDTH-1);
|
||||
fprintf(pFileOut, "\tsignal jtag_ld_dout\t\t: unsigned (%d downto 0);\n", nbits_data-1);
|
||||
fprintf(pFileOut, "\tsignal jtag_ld_din\t\t: unsigned (%d downto 0);\n", nbits_data-1);
|
||||
fprintf(pFileOut, "\tsignal bs_rst, bs_sel, bs_shift, bs_tdi, bs_tdo : std_logic;\n");
|
||||
fprintf(pFileOut, "\tsignal bs_capture, bs_clk0, bs_clk1, bs_update0, bs_update1 : std_logic;\n");
|
||||
fprintf(pFileOut, "\tsignal user_regi, user_rego : unsigned (%d downto 0);\n", 31 + JTAG_ADDR_WIDTH);
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
fprintf(pFileOut, "\tsignal word_array : word_array_t :=\n");
|
||||
fprintf(pFileOut, "\t(\n");
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// ROM part
|
||||
// -------------------------------------------------------------------------
|
||||
for (i=0; i < filesize; i += sizeof(int))
|
||||
{
|
||||
fread(&word, 1, sizeof(int), pFileIn);
|
||||
fprintf(pFileOut, "\t\tX\"%8.8X\"", word);
|
||||
if (i < (romsize-sizeof(int)))
|
||||
fprintf(pFileOut, ", -- %8.8X\n", i);
|
||||
else
|
||||
fprintf(pFileOut, " -- %8.8X\n", i);
|
||||
}
|
||||
word = 0;
|
||||
for (; i < romsize; i += sizeof(int))
|
||||
{
|
||||
fprintf(pFileOut, "\t\tX\"%8.8X\"", word);
|
||||
if (i < (romsize-sizeof(int)))
|
||||
fprintf(pFileOut, ", -- %8.8X\n", i);
|
||||
else
|
||||
fprintf(pFileOut, " -- %8.8X\n", i);
|
||||
}
|
||||
fprintf(pFileOut, "\t);\n");
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
fprintf(pFileOut, "begin\n", ARCH_NAME);
|
||||
|
||||
fprintf(pFileOut, "\n");
|
||||
fprintf(pFileOut, "PROM_READ:\n", ARCH_NAME);
|
||||
fprintf(pFileOut, "\tprocess(clk)\n");
|
||||
fprintf(pFileOut, "\tbegin\n");
|
||||
fprintf(pFileOut, "\t\tif rising_edge(clk) then\n");
|
||||
fprintf(pFileOut, "\t\t\tif ce = '1' then\n");
|
||||
fprintf(pFileOut, "\t\t\tdout <= word_array(to_integer(addr(%d downto 2)));\n", nbits_addr+1);
|
||||
fprintf(pFileOut, "\t\t\tend if;\n");
|
||||
fprintf(pFileOut, "\t\tend if;\n");
|
||||
fprintf(pFileOut, "\tend process;\n");
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Trailer
|
||||
// -------------------------------------------------------------------------
|
||||
fprintf(pFileOut, "\n");
|
||||
fputs(tpl, pFileOut);
|
||||
|
||||
fprintf(pFileOut, "PROM_WRITE:\n", ARCH_NAME);
|
||||
fprintf(pFileOut, "\tprocess(jtag_ld_clk, jtag_ld_we)\n");
|
||||
fprintf(pFileOut, "\tbegin\n");
|
||||
fprintf(pFileOut, "\t\tif rising_edge(jtag_ld_clk) then\n");
|
||||
fprintf(pFileOut, "\t\t\tif jtag_ld_we = '1' then\n");
|
||||
fprintf(pFileOut, "\t\t\t\tword_array(to_integer(jtag_ld_addr(%d downto 0))) <= jtag_ld_din;\n", nbits_addr-1);
|
||||
fprintf(pFileOut, "\t\t\telse\n");
|
||||
fprintf(pFileOut, "\t\t\t\tjtag_ld_dout <= word_array(to_integer(jtag_ld_addr(%d downto 0)));\n", nbits_addr-1);
|
||||
fprintf(pFileOut, "\t\t\tend if;\n");
|
||||
fprintf(pFileOut, "\t\tend if;\n");
|
||||
fprintf(pFileOut, "\tend process;\n");
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
fprintf(pFileOut, "end %s;\n", ARCH_NAME);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SaveRAM_TCL(char *pFilenameIn, char *pFilenameOut, char *pArchName, char *pEntName, int nbits_addr, int nbits_data)
|
||||
{
|
||||
FILE *pFileIn, *pFileOut;
|
||||
long start, end;
|
||||
int i, word, word_addr, filesize, romsize;
|
||||
char binstr_addr[33];
|
||||
char binstr_data[33];
|
||||
|
||||
char tpl[] = {"# ---------------------------------------------------------------------\n# For Chipscope 9.1\n# ---------------------------------------------------------------------\n# Source JTAG/TCL frame work\ncd $env(CHIPSCOPE)\\\\bin\\\\nt\nsource csejtag.tcl\n\nnamespace import ::chipscope::*\n\n# Platform USB Cable\nset PLATFORM_USB_CABLE_ARGS [list \"port=USB2\" \"frequency=6000000\"]\n# frequency=\"24000000 | 12000000 | 6000000 | 3000000 | 1500000 | 750000\"\n\n# Create session\nset handle [::chipscope::csejtag_session create 0]\n\n# Open JTAG and lock\nset open_result [::chipscope::csejtag_target open $handle $CSEJTAG_TARGET_PLATFORMUSB 0 $PLATFORM_USB_CABLE_ARGS]\nset lock_result [::chipscope::csejtag_target lock $handle 1000]\n\nset devlist [::chipscope::csejtag_tap autodetect_chain $handle $CSEJTAG_SCAN_DEFAULT]\n\n# Get Device ID\nset devtype \"Virtex-4SX\"\nset devid 2\nset irlength [::chipscope::csejtag_tap get_irlength $handle $devid]\nset idcode [::chipscope::csejtag_tap get_device_idcode $handle $devid]\n\nset CSE_OP $CSEJTAG_SHIFT_READWRITE\nset CSE_ES $CSEJTAG_RUN_TEST_IDLE\n\n# Write Program\n"};
|
||||
|
||||
pFileIn = fopen(pFilenameIn, "rb");
|
||||
if (!pFileIn)
|
||||
{
|
||||
fprintf(stderr, "Error opening file %s\n", pFilenameIn);
|
||||
return 1;
|
||||
}
|
||||
|
||||
pFileOut = fopen(pFilenameOut, "wb");
|
||||
if (!pFileOut)
|
||||
{
|
||||
fprintf(stderr, "Error opening file %s\n", pFilenameOut);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fseek(pFileIn, 0, SEEK_SET);
|
||||
start = ftell(pFileIn);
|
||||
fseek(pFileIn, 0, SEEK_END);
|
||||
end = ftell(pFileIn);
|
||||
fseek(pFileIn, 0, SEEK_SET);
|
||||
|
||||
filesize = (end-start);
|
||||
romsize = (int)pow(2, nbits_addr+2);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Header
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
fputs(tpl, pFileOut);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// ROM part
|
||||
// -------------------------------------------------------------------------
|
||||
fprintf(pFileOut, "# Assembled from %s\n", pFilenameIn);
|
||||
fprintf(pFileOut, "# ---------------------------------------------------------------\n");
|
||||
fprintf(pFileOut, "# Shift the USER2 Instruction (b1111000011) into the Instruction Register of FPGA\n");
|
||||
fprintf(pFileOut, "# User 2\n");
|
||||
fprintf(pFileOut, "set result [::chipscope::csejtag_tap shift_device_ir $handle $devid $CSE_OP $CSE_ES 0 $irlength \"3C3\"]\n\n");
|
||||
|
||||
word_addr = 0;
|
||||
for (i=0; i < filesize; i += sizeof(int))
|
||||
{
|
||||
fread(&word, 1, sizeof(int), pFileIn);
|
||||
fprintf(pFileOut, "::chipscope::csejtag_tap shift_device_dr $handle $devid $CSE_OP $CSE_ES 0 %d \"%4.4X%8.8X\"\n", nbits_data + JTAG_ADDR_WIDTH, word_addr, word);
|
||||
word_addr++;
|
||||
}
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Trailer
|
||||
// -------------------------------------------------------------------------
|
||||
fprintf(pFileOut, "::chipscope::csejtag_target unlock $handle\n");
|
||||
fprintf(pFileOut, "::chipscope::csejtag_target close $handle\n");
|
||||
fprintf(pFileOut, "::chipscope::csejtag_session destroy $handle\n");
|
||||
fprintf(pFileOut, "exit\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *pFilenameIn;
|
||||
char name_prj[1024];
|
||||
char name_rom_tcl[1024];
|
||||
char name_rom[1024];
|
||||
char name_rom_v4ld[1024];
|
||||
|
||||
FILE *pFileIn;
|
||||
int filesize, romsize, nbits_addr, nbits_data;
|
||||
long start, end;
|
||||
int word, i;
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
fprintf(stderr, "Usage: ramgen <input file> <num. word address bits>\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
pFilenameIn = argv[1];
|
||||
if (argc == 3)
|
||||
nbits_addr = atoi(argv[2]);
|
||||
|
||||
|
||||
basename(pFilenameIn, name_prj);
|
||||
sprintf(name_rom, "%s.vhd", name_prj);
|
||||
sprintf(name_rom_v4ld, "%s_ld.vhd", name_prj);
|
||||
sprintf(name_rom_tcl, "%s.tcl", name_prj);
|
||||
|
||||
SaveRAM(pFilenameIn, name_rom, ARCH_NAME, ENT_NAME, nbits_addr, 32);
|
||||
// SaveROM_V4LD(pFilenameIn, name_rom_v4ld, ARCH_NAME, ENT_NAME, nbits_addr, 32);
|
||||
SaveRAM_TCL(pFilenameIn, name_rom_tcl, ARCH_NAME, ENT_NAME, nbits_addr, 32);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,430 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#define INT8 char
|
||||
#define INT16 short
|
||||
#define INT32 long
|
||||
#define UINT8 unsigned char
|
||||
#define UINT16 unsigned short
|
||||
#define UINT32 unsigned long
|
||||
#define INT int
|
||||
#define UINT unsigned int
|
||||
#define FLOAT32 float
|
||||
#define FLOAT64 double
|
||||
|
||||
#define ARCH_NAME "data"
|
||||
#define ENT_NAME "rom"
|
||||
#define JTAG_ADDR_WIDTH 16
|
||||
|
||||
UINT32 g_endianess_EB;
|
||||
|
||||
// --------------------------------------------------------------
|
||||
UINT32 conv_endian32(UINT32 src)
|
||||
{
|
||||
UINT32 dst;
|
||||
|
||||
dst = (0xFF000000 & (src << 24))
|
||||
| (0x00FF0000 & (src << 8))
|
||||
| (0x0000FF00 & (src >> 8))
|
||||
| (0x000000FF & (src >> 24));
|
||||
|
||||
return dst;
|
||||
};
|
||||
|
||||
UINT32 to_big_endian32(UINT32 src)
|
||||
{
|
||||
#ifndef NATIVE_IS_BIG_ENDIAN
|
||||
return conv_endian32(src);
|
||||
#else
|
||||
return src;
|
||||
#endif
|
||||
}
|
||||
|
||||
UINT32 from_big_endian32(UINT32 src)
|
||||
{
|
||||
#ifndef NATIVE_IS_BIG_ENDIAN
|
||||
return conv_endian32(src);
|
||||
#else
|
||||
return src;
|
||||
#endif
|
||||
}
|
||||
|
||||
void basename(char *pSrc, char *pDst)
|
||||
{
|
||||
int i, size;
|
||||
|
||||
size = strlen(pSrc);
|
||||
|
||||
while(pSrc[size] != '.')
|
||||
size--;
|
||||
|
||||
for (i=0; i < size; i++)
|
||||
pDst[i] = pSrc[i];
|
||||
|
||||
pDst[i] = 0;
|
||||
|
||||
}
|
||||
|
||||
int SaveROM(char *pFilenameIn, char *pFilenameOut, char *pArchName, char *pEntName, int nbits_addr, int nbits_data)
|
||||
{
|
||||
FILE *pFileIn, *pFileOut;
|
||||
long start, end;
|
||||
int i, word, filesize, romsize;
|
||||
|
||||
pFileIn = fopen(pFilenameIn, "rb");
|
||||
if (!pFileIn)
|
||||
{
|
||||
fprintf(stderr, "Error opening file %s\n", pFilenameIn);
|
||||
return 1;
|
||||
}
|
||||
|
||||
pFileOut = fopen(pFilenameOut, "wb");
|
||||
if (!pFileOut)
|
||||
{
|
||||
fprintf(stderr, "Error opening file %s\n", pFilenameOut);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fseek(pFileIn, 0, SEEK_SET);
|
||||
start = ftell(pFileIn);
|
||||
fseek(pFileIn, 0, SEEK_END);
|
||||
end = ftell(pFileIn);
|
||||
fseek(pFileIn, 0, SEEK_SET);
|
||||
|
||||
filesize = (end-start);
|
||||
romsize = (int)pow(2, nbits_addr+2);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Header
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
fprintf(pFileOut, "LIBRARY IEEE;\n");
|
||||
fprintf(pFileOut, "USE IEEE.STD_LOGIC_1164.ALL;\n");
|
||||
fprintf(pFileOut, "USE IEEE.NUMERIC_STD.ALL;\n");
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
fprintf(pFileOut, "ENTITY %s IS\n", ENT_NAME);
|
||||
fprintf(pFileOut, "\tPort\n");
|
||||
fprintf(pFileOut, "\t(\n");
|
||||
fprintf(pFileOut, "\t\tclk\t\t: in STD_LOGIC;\n");
|
||||
fprintf(pFileOut, "\t\tce\t\t: in STD_LOGIC;\n");
|
||||
fprintf(pFileOut, "\t\taddr\t\t: in unsigned(%d downto 0);\n", nbits_data-1);
|
||||
fprintf(pFileOut, "\t\tdout\t\t: out unsigned(%d downto 0)\n", nbits_data-1);
|
||||
fprintf(pFileOut, "\t);\n");
|
||||
fprintf(pFileOut, "END %s;\n", ENT_NAME);
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
|
||||
fprintf(pFileOut, "ARCHITECTURE %s OF %s IS\n", ARCH_NAME, ENT_NAME);
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
fprintf(pFileOut, "\tsubtype word_t is unsigned(%d downto 0);\n", nbits_data-1);
|
||||
fprintf(pFileOut, "\ttype word_array_t is array (0 to %d) of word_t;\n", romsize/4-1);
|
||||
|
||||
fprintf(pFileOut, "\tconstant word_array : word_array_t :=\n");
|
||||
fprintf(pFileOut, "\t(\n");
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// ROM part
|
||||
// -------------------------------------------------------------------------
|
||||
for (i=0; i < filesize; i += sizeof(int))
|
||||
{
|
||||
fread(&word, 1, sizeof(int), pFileIn);
|
||||
if (g_endianess_EB)
|
||||
fprintf(pFileOut, "\t\tX\"%8.8X\"", to_big_endian32(word));
|
||||
else
|
||||
fprintf(pFileOut, "\t\tX\"%8.8X\"", word);
|
||||
|
||||
if (i < (romsize-sizeof(int)))
|
||||
fprintf(pFileOut, ", -- %8.8X\n", i);
|
||||
else
|
||||
fprintf(pFileOut, " -- %8.8X\n", i);
|
||||
}
|
||||
word = 0;
|
||||
for (; i < romsize; i += sizeof(int))
|
||||
{
|
||||
fprintf(pFileOut, "\t\tX\"%8.8X\"", word);
|
||||
if (i < (romsize-sizeof(int)))
|
||||
fprintf(pFileOut, ", -- %8.8X\n", i);
|
||||
else
|
||||
fprintf(pFileOut, " -- %8.8X\n", i);
|
||||
}
|
||||
fprintf(pFileOut, "\t);\n");
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Trailer
|
||||
// -------------------------------------------------------------------------
|
||||
fprintf(pFileOut, "begin\n", ARCH_NAME);
|
||||
fprintf(pFileOut, "\n");
|
||||
fprintf(pFileOut, "PROM_READ:\n", ARCH_NAME);
|
||||
fprintf(pFileOut, "\tprocess(clk)\n");
|
||||
fprintf(pFileOut, "\tbegin\n");
|
||||
fprintf(pFileOut, "\t\tif rising_edge(clk) then\n");
|
||||
fprintf(pFileOut, "\t\t\tif ce = '1' then\n");
|
||||
fprintf(pFileOut, "\t\t\t\tdout <= word_array(to_integer(addr(%d downto 2)));\n", nbits_addr+1);
|
||||
fprintf(pFileOut, "\t\t\tend if;\n");
|
||||
fprintf(pFileOut, "\t\tend if;\n");
|
||||
fprintf(pFileOut, "\tend process;\n");
|
||||
fprintf(pFileOut, "\n");
|
||||
fprintf(pFileOut, "end %s;\n", ARCH_NAME);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SaveROM_V4LD(char *pFilenameIn, char *pFilenameOut, char *pArchName, char *pEntName, int nbits_addr, int nbits_data)
|
||||
{
|
||||
FILE *pFileIn, *pFileOut;
|
||||
long start, end;
|
||||
int i, word, filesize, romsize;
|
||||
|
||||
char tpl[] = {"--------------------------------------------------------------------------\n-- Virtex-4: JTAG Loader\n--------------------------------------------------------------------------\n\ti00_BUFG : BUFG\n\tport map\n\t(\n\t\tO => bs_clk1,\n I => bs_clk0\n\t);\n\t\n\ti01_BUFG : BUFG\n\tport map\n\t(\n\t\tO => bs_update1,\n I => bs_update0\n\t);\n\n\tBSCAN_VIRTEX4_inst1 : BSCAN_VIRTEX4 \n\tgeneric map\n\t(\n\t\tJTAG_CHAIN => 1 -- Value to set BSCAN site of device. Possible values: (1,2,3 or 4)\n\t)\n\tport map \n\t(\n\t\tCAPTURE => bs_capture, -- CAPTURE output from TAP controller\n\t\tDRCK => bs_clk0, -- Data register output for USER functions\n\t\tRESET => bs_rst, -- Reset output from TAP controller\n\t\tSEL => bs_sel, -- USER active output\n\t\tSHIFT => bs_shift, -- SHIFT output from TAP controller\n\t\tTDI => bs_tdi, -- TDI output from TAP controller\n\t\tUPDATE => bs_update0, -- UPDATE output from TAP controller\n\t\tTDO => bs_tdo -- Data input for USER function\n\t);\n\n\tjtag_ld_addr <= user_regi(user_regi'left downto jtag_ld_dout'length);\n\tjtag_ld_din <= user_regi(jtag_ld_dout'length-1 downto 0);\n\tjtag_ld_clk <= bs_update1;\n\tjtag_ld_we <= bs_sel;\n\t\nsipo:\n\tprocess (bs_rst, bs_clk1, bs_tdi, bs_shift)\n\tbegin\n\t\tif bs_rst = '1' then\n\t\t\tuser_regi <= (others => '0');\n\t\telsif rising_edge(bs_clk1) then\n\t\t\tif bs_shift = '1' then\n\t\t\t\tuser_regi <= bs_tdi & user_regi(user_regi'left downto 1);\n\t\t\tend if;\n\t\tend if;\n\tend process;\t\n\npiso:\n\tprocess (bs_rst, bs_clk1, bs_shift, user_rego)\n\tbegin\n\t\tbs_tdo <= user_rego(0);\n\t\tif bs_rst = '1' then\n\t\t\tuser_rego <= (others => '0');\n\t\telsif rising_edge(bs_clk1) then\n\t\t\tif bs_shift = '1' then\n\t\t\t\tuser_rego <= user_rego(0) & user_rego(user_rego'left downto 1);\n\t\t\telse\n\t\t\t\tuser_rego <= (user_rego'left downto jtag_ld_dout'length => '0') & jtag_ld_dout;\t\n\t\n\t\t\tend if;\n\t\tend if;\n\tend process;\n\n"};
|
||||
|
||||
pFileIn = fopen(pFilenameIn, "rb");
|
||||
if (!pFileIn)
|
||||
{
|
||||
fprintf(stderr, "Error opening file %s\n", pFilenameIn);
|
||||
return 1;
|
||||
}
|
||||
|
||||
pFileOut = fopen(pFilenameOut, "wb");
|
||||
if (!pFileOut)
|
||||
{
|
||||
fprintf(stderr, "Error opening file %s\n", pFilenameOut);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fseek(pFileIn, 0, SEEK_SET);
|
||||
start = ftell(pFileIn);
|
||||
fseek(pFileIn, 0, SEEK_END);
|
||||
end = ftell(pFileIn);
|
||||
fseek(pFileIn, 0, SEEK_SET);
|
||||
|
||||
filesize = (end-start);
|
||||
romsize = (int)pow(2, nbits_addr+2);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Header
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
fprintf(pFileOut, "LIBRARY IEEE;\n");
|
||||
fprintf(pFileOut, "USE IEEE.STD_LOGIC_1164.ALL;\n");
|
||||
fprintf(pFileOut, "USE IEEE.NUMERIC_STD.ALL;\n");
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
fprintf(pFileOut, "library UNISIM;\n");
|
||||
fprintf(pFileOut, "use UNISIM.VComponents.all;\n");
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
fprintf(pFileOut, "ENTITY %s IS\n", ENT_NAME);
|
||||
fprintf(pFileOut, "\tPort\n");
|
||||
fprintf(pFileOut, "\t(\n");
|
||||
fprintf(pFileOut, "\t\tclk\t\t: in STD_LOGIC;\n");
|
||||
fprintf(pFileOut, "\t\tce\t\t: in STD_LOGIC;\n");
|
||||
fprintf(pFileOut, "\t\taddr\t\t: in unsigned(%d downto 0);\n", nbits_data-1);
|
||||
fprintf(pFileOut, "\t\tdout\t\t: out unsigned(%d downto 0)\n", nbits_data-1);
|
||||
fprintf(pFileOut, "\t);\n");
|
||||
fprintf(pFileOut, "END %s;\n", ENT_NAME);
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
|
||||
fprintf(pFileOut, "ARCHITECTURE %s OF %s IS\n", ARCH_NAME, ENT_NAME);
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
fprintf(pFileOut, "\tsubtype word_t is unsigned(%d downto 0);\n", nbits_data-1);
|
||||
fprintf(pFileOut, "\ttype word_array_t is array (0 to %d) of word_t;\n", romsize/4-1);
|
||||
|
||||
fprintf(pFileOut, "\tsignal jtag_ld_clk\t\t: STD_LOGIC;\n");
|
||||
fprintf(pFileOut, "\tsignal jtag_ld_we\t\t: STD_LOGIC;\n");
|
||||
fprintf(pFileOut, "\tsignal jtag_ld_addr\t\t: unsigned (%d downto 0);\n", JTAG_ADDR_WIDTH-1);
|
||||
fprintf(pFileOut, "\tsignal jtag_ld_dout\t\t: unsigned (%d downto 0);\n", nbits_data-1);
|
||||
fprintf(pFileOut, "\tsignal jtag_ld_din\t\t: unsigned (%d downto 0);\n", nbits_data-1);
|
||||
fprintf(pFileOut, "\tsignal bs_rst, bs_sel, bs_shift, bs_tdi, bs_tdo : std_logic;\n");
|
||||
fprintf(pFileOut, "\tsignal bs_capture, bs_clk0, bs_clk1, bs_update0, bs_update1 : std_logic;\n");
|
||||
fprintf(pFileOut, "\tsignal user_regi, user_rego : unsigned (%d downto 0);\n", 31 + JTAG_ADDR_WIDTH);
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
fprintf(pFileOut, "\tsignal word_array : word_array_t :=\n");
|
||||
fprintf(pFileOut, "\t(\n");
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// ROM part
|
||||
// -------------------------------------------------------------------------
|
||||
for (i=0; i < filesize; i += sizeof(int))
|
||||
{
|
||||
fread(&word, 1, sizeof(int), pFileIn);
|
||||
if (g_endianess_EB)
|
||||
fprintf(pFileOut, "\t\tX\"%8.8X\"", to_big_endian32(word));
|
||||
else
|
||||
fprintf(pFileOut, "\t\tX\"%8.8X\"", word);
|
||||
|
||||
if (i < (romsize-sizeof(int)))
|
||||
fprintf(pFileOut, ", -- %8.8X\n", i);
|
||||
else
|
||||
fprintf(pFileOut, " -- %8.8X\n", i);
|
||||
}
|
||||
word = 0;
|
||||
for (; i < romsize; i += sizeof(int))
|
||||
{
|
||||
fprintf(pFileOut, "\t\tX\"%8.8X\"", word);
|
||||
if (i < (romsize-sizeof(int)))
|
||||
fprintf(pFileOut, ", -- %8.8X\n", i);
|
||||
else
|
||||
fprintf(pFileOut, " -- %8.8X\n", i);
|
||||
}
|
||||
fprintf(pFileOut, "\t);\n");
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
fprintf(pFileOut, "begin\n", ARCH_NAME);
|
||||
|
||||
fprintf(pFileOut, "\n");
|
||||
fprintf(pFileOut, "PROM_READ:\n", ARCH_NAME);
|
||||
fprintf(pFileOut, "\tprocess(clk)\n");
|
||||
fprintf(pFileOut, "\tbegin\n");
|
||||
fprintf(pFileOut, "\t\tif rising_edge(clk) and ce = '1' then\n");
|
||||
fprintf(pFileOut, "\t\t\tdout <= word_array(to_integer(addr(%d downto 2)));\n", nbits_addr+1);
|
||||
fprintf(pFileOut, "\t\tend if;\n");
|
||||
fprintf(pFileOut, "\tend process;\n");
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Trailer
|
||||
// -------------------------------------------------------------------------
|
||||
fprintf(pFileOut, "\n");
|
||||
fputs(tpl, pFileOut);
|
||||
|
||||
fprintf(pFileOut, "PROM_WRITE:\n", ARCH_NAME);
|
||||
fprintf(pFileOut, "\tprocess(jtag_ld_clk, jtag_ld_we)\n");
|
||||
fprintf(pFileOut, "\tbegin\n");
|
||||
fprintf(pFileOut, "\t\tif rising_edge(jtag_ld_clk) then\n");
|
||||
fprintf(pFileOut, "\t\t\tif jtag_ld_we = '1' then\n");
|
||||
fprintf(pFileOut, "\t\t\t\tword_array(to_integer(jtag_ld_addr(%d downto 0))) <= jtag_ld_din;\n", nbits_addr-1);
|
||||
fprintf(pFileOut, "\t\t\telse\n");
|
||||
fprintf(pFileOut, "\t\t\t\tjtag_ld_dout <= word_array(to_integer(jtag_ld_addr(%d downto 0)));\n", nbits_addr-1);
|
||||
fprintf(pFileOut, "\t\t\tend if;\n");
|
||||
fprintf(pFileOut, "\t\tend if;\n");
|
||||
fprintf(pFileOut, "\tend process;\n");
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
fprintf(pFileOut, "end %s;\n", ARCH_NAME);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SaveROM_TCL(char *pFilenameIn, char *pFilenameOut, char *pArchName, char *pEntName, int nbits_addr, int nbits_data)
|
||||
{
|
||||
FILE *pFileIn, *pFileOut;
|
||||
long start, end;
|
||||
int i, word, word_addr, filesize, romsize;
|
||||
char binstr_addr[33];
|
||||
char binstr_data[33];
|
||||
|
||||
char tpl[] =
|
||||
{"# ---------------------------------------------------------------------\n# For Chipscope 10.1\n# ---------------------------------------------------------------------\n# Source JTAG/TCL frame work\nsource $env(CS_PATH)\\\\csejtag.tcl\n\nnamespace import ::chipscope::*\n\n# Platform USB Cable\n# Create session\nset handle [::chipscope::csejtag_session create 0]\n\n# Open JTAG and lock\nset open_result [::chipscope::csejtag_target open $handle $CSEJTAG_TARGET_PLATFORMUSB 0 \"port=USB2\" \"frequency=6000000\"]\n# frequency=\"24000000 | 12000000 | 6000000 | 3000000 | 1500000 | 750000\"\n\nset lock_result [::chipscope::csejtag_target lock $handle 1000]\n\nset devlist [::chipscope::csejtag_tap autodetect_chain $handle $CSEJTAG_SCAN_DEFAULT]\n\n# Get Device ID\nset devtype \"Virtex-4SX\"\nset devid 2\nset irlength [::chipscope::csejtag_tap get_irlength $handle $devid]\nset idcode [::chipscope::csejtag_tap get_device_idcode $handle $devid]\n\nset CSE_OP $CSEJTAG_SHIFT_READWRITE\nset CSE_ES $CSEJTAG_RUN_TEST_IDLE\n\n# Write Program\n"};
|
||||
|
||||
pFileIn = fopen(pFilenameIn, "rb");
|
||||
if (!pFileIn)
|
||||
{
|
||||
fprintf(stderr, "Error opening file %s\n", pFilenameIn);
|
||||
return 1;
|
||||
}
|
||||
|
||||
pFileOut = fopen(pFilenameOut, "wb");
|
||||
if (!pFileOut)
|
||||
{
|
||||
fprintf(stderr, "Error opening file %s\n", pFilenameOut);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fseek(pFileIn, 0, SEEK_SET);
|
||||
start = ftell(pFileIn);
|
||||
fseek(pFileIn, 0, SEEK_END);
|
||||
end = ftell(pFileIn);
|
||||
fseek(pFileIn, 0, SEEK_SET);
|
||||
|
||||
filesize = (end-start);
|
||||
romsize = (int)pow(2, nbits_addr+2);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Header
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
fputs(tpl, pFileOut);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// ROM part
|
||||
// -------------------------------------------------------------------------
|
||||
fprintf(pFileOut, "# Assembled from %s\n", pFilenameIn);
|
||||
fprintf(pFileOut, "# ---------------------------------------------------------------\n");
|
||||
fprintf(pFileOut, "# Shift the USER1 Instruction (b1111000010) into the Instruction Register of FPGA\n");
|
||||
fprintf(pFileOut, "# User 1\n");
|
||||
fprintf(pFileOut, "set result [::chipscope::csejtag_tap shift_device_ir $handle $devid $CSE_OP $CSE_ES 0 $irlength \"3C2\"]\n\n");
|
||||
|
||||
word_addr = 0;
|
||||
for (i=0; i < filesize; i += sizeof(int))
|
||||
{
|
||||
fread(&word, 1, sizeof(int), pFileIn);
|
||||
if (g_endianess_EB)
|
||||
fprintf(pFileOut, "::chipscope::csejtag_tap shift_device_dr $handle $devid $CSE_OP $CSE_ES 0 %d \"%4.4X%8.8X\"\n", nbits_data + JTAG_ADDR_WIDTH, word_addr, to_big_endian32(word));
|
||||
else
|
||||
fprintf(pFileOut, "::chipscope::csejtag_tap shift_device_dr $handle $devid $CSE_OP $CSE_ES 0 %d \"%4.4X%8.8X\"\n", nbits_data + JTAG_ADDR_WIDTH, word_addr, word);
|
||||
word_addr++;
|
||||
}
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Trailer
|
||||
// -------------------------------------------------------------------------
|
||||
fprintf(pFileOut, "::chipscope::csejtag_target unlock $handle\n");
|
||||
fprintf(pFileOut, "::chipscope::csejtag_target close $handle\n");
|
||||
fprintf(pFileOut, "::chipscope::csejtag_session destroy $handle\n");
|
||||
fprintf(pFileOut, "exit\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *pFilenameIn;
|
||||
char name_prj[1024];
|
||||
char name_rom[1024];
|
||||
char name_rom_v4ld[1024];
|
||||
char name_rom_tcl[1024];
|
||||
|
||||
FILE *pFileIn;
|
||||
int filesize, romsize, nbits_addr, nbits_data;
|
||||
long start, end;
|
||||
int word, i;
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
fprintf(stderr, "Usage: romgen <input file> <num. word address bits> [-{EL|EB}]\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
pFilenameIn = argv[1];
|
||||
nbits_addr = atoi(argv[2]);
|
||||
|
||||
g_endianess_EB = 0;
|
||||
if (argc == 4)
|
||||
{
|
||||
if ((argv[3][0] == '-') && (toupper(argv[3][1]) == 'E') && (toupper(argv[3][2]) == 'B'))
|
||||
g_endianess_EB = 1;
|
||||
}
|
||||
|
||||
basename(pFilenameIn, name_prj);
|
||||
sprintf(name_rom, "%s.vhd", name_prj);
|
||||
sprintf(name_rom_v4ld, "%s_ld.vhd", name_prj);
|
||||
sprintf(name_rom_tcl, "%s.tcl", name_prj);
|
||||
|
||||
SaveROM(pFilenameIn, name_rom, ARCH_NAME, ENT_NAME, nbits_addr, 32);
|
||||
SaveROM_V4LD(pFilenameIn, name_rom_v4ld, ARCH_NAME, ENT_NAME, nbits_addr, 32);
|
||||
SaveROM_TCL(pFilenameIn, name_rom_tcl, ARCH_NAME, ENT_NAME, nbits_addr, 32);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
LIB_PATH := $(VHDL_HOME)/lib
|
||||
VHDL_MAKE_HOME := $(VHDL_HOME)/Common/make
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
include $(VHDL_HOME)/make/defs.mk
|
||||
include $(VHDL_HOME)/defs.mk
|
||||
TOOL_PATH := $(VHDL_HOME)/tools/jcpu
|
||||
|
||||
.PHONY: install uninstall
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
.gitignore
|
||||
build/
|
||||
.gitignore
|
||||
build/
|
||||
@@ -1,24 +0,0 @@
|
||||
[*]
|
||||
[*] GTKWave Analyzer v3.3.104 (w)1999-2020 BSI
|
||||
[*] Sun Mar 21 20:24:10 2021
|
||||
[*]
|
||||
[dumpfile] "/home/jens/work/vhdl/trunk/lib/CPUs/JCpu/ghdl/build/cpu_embedded/cpu_embedded.ghw"
|
||||
[dumpfile_mtime] "Sun Mar 21 20:24:02 2021"
|
||||
[dumpfile_size] 23928
|
||||
[savefile] "/home/jens/work/vhdl/trunk/lib/CPUs/JCpu/ghdl/build/cpu_embedded/cpu_embedded.gtkw"
|
||||
[timestart] 0
|
||||
[size] 1000 600
|
||||
[pos] -1 -1
|
||||
*-28.221537 367000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
|
||||
[treeopen] top.
|
||||
[treeopen] top.tb_cpu_embedded.
|
||||
[sst_width] 233
|
||||
[signals_width] 78
|
||||
[sst_expanded] 1
|
||||
[sst_vpaned_height] 144
|
||||
@28
|
||||
top.tb_cpu_embedded.uut.clk
|
||||
@29
|
||||
top.tb_cpu_embedded.uut.rst
|
||||
[pattern_trace] 1
|
||||
[pattern_trace] 0
|
||||
@@ -1,5 +1,5 @@
|
||||
# -----------------------------------------------------------
|
||||
include $(VHDL_HOME)/make/defs.mk
|
||||
include $(VHDL_HOME)/defs.mk
|
||||
# -----------------------------------------------------------
|
||||
include jcpu_core.inc
|
||||
|
||||
@@ -12,6 +12,7 @@ SRCS += ../src/tb_cpu_itest.vhd
|
||||
# Compile
|
||||
TARGET := cpu_itest
|
||||
ENTITY := tb_cpu
|
||||
WAVE_FORMAT := ghw
|
||||
|
||||
include $(VHDL_HOME)/make/ghdl.mk
|
||||
include $(VHDL_MAKE_HOME)/ghdl.mk
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# -----------------------------------------------------------
|
||||
include $(VHDL_HOME)/make/defs.mk
|
||||
include $(VHDL_HOME)/defs.mk
|
||||
# -----------------------------------------------------------
|
||||
PKG_NAME := JCPU_CORE
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# -----------------------------------------------------------
|
||||
include $(VHDL_HOME)/make/defs.mk
|
||||
include $(VHDL_HOME)/defs.mk
|
||||
# -----------------------------------------------------------
|
||||
include jcpu_core.inc
|
||||
|
||||
@@ -11,6 +11,7 @@ SRCS += ../src/tb_cpu_embedded.vhd
|
||||
# Compile
|
||||
TARGET := mul8x8
|
||||
ENTITY := tb_cpu_embedded
|
||||
WAVE_FORMAT := ghw
|
||||
|
||||
include $(VHDL_HOME)/make/ghdl.mk
|
||||
include $(VHDL_MAKE_HOME)/ghdl.mk
|
||||
|
||||
|
||||
@@ -1,24 +1,33 @@
|
||||
[*]
|
||||
[*] GTKWave Analyzer v3.3.104 (w)1999-2020 BSI
|
||||
[*] Sun Mar 21 20:25:04 2021
|
||||
[*] Sat Jul 2 11:00:05 2022
|
||||
[*]
|
||||
[dumpfile] "/home/jens/work/vhdl/trunk/lib/CPUs/JCpu/ghdl/build/reti_issue/reti_issue.ghw"
|
||||
[dumpfile_mtime] "Sun Mar 21 20:25:01 2021"
|
||||
[dumpfile] "/home/jens/work/projects/vhdl/lib/CPUs/JCpu/ghdl/build/reti_issue/reti_issue.ghw"
|
||||
[dumpfile_mtime] "Sat Jul 2 10:56:29 2022"
|
||||
[dumpfile_size] 22085
|
||||
[savefile] "/home/jens/work/vhdl/trunk/lib/CPUs/JCpu/ghdl/build/reti_issue/reti_issue.gtkw"
|
||||
[savefile] "/home/jens/work/projects/vhdl/lib/CPUs/JCpu/ghdl/reti_issue.gtkw"
|
||||
[timestart] 0
|
||||
[size] 1000 600
|
||||
[pos] -1 -1
|
||||
*-28.221537 563000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
|
||||
[size] 1854 1136
|
||||
[pos] -51 -51
|
||||
*-28.221537 446000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
|
||||
[treeopen] top.
|
||||
[treeopen] top.tb_cpu.
|
||||
[sst_width] 233
|
||||
[signals_width] 78
|
||||
[signals_width] 266
|
||||
[sst_expanded] 1
|
||||
[sst_vpaned_height] 144
|
||||
[sst_vpaned_height] 330
|
||||
@28
|
||||
top.tb_cpu.uut.clk
|
||||
@29
|
||||
top.tb_cpu.uut.rst
|
||||
top.tb_cpu.uut.cio_sel
|
||||
top.tb_cpu.uut.stk_pop
|
||||
top.tb_cpu.uut.stk_push
|
||||
top.tb_cpu.uut.was_pop2pc
|
||||
top.tb_cpu.uut.was_pcld
|
||||
@420
|
||||
top.tb_cpu.uut.ctrl_iphase
|
||||
@22
|
||||
#{top.tb_cpu.irom_addr[11:0]} top.tb_cpu.irom_addr[11] top.tb_cpu.irom_addr[10] top.tb_cpu.irom_addr[9] top.tb_cpu.irom_addr[8] top.tb_cpu.irom_addr[7] top.tb_cpu.irom_addr[6] top.tb_cpu.irom_addr[5] top.tb_cpu.irom_addr[4] top.tb_cpu.irom_addr[3] top.tb_cpu.irom_addr[2] top.tb_cpu.irom_addr[1] top.tb_cpu.irom_addr[0]
|
||||
#{top.tb_cpu.irom_data[17:0]} top.tb_cpu.irom_data[17] top.tb_cpu.irom_data[16] top.tb_cpu.irom_data[15] top.tb_cpu.irom_data[14] top.tb_cpu.irom_data[13] top.tb_cpu.irom_data[12] top.tb_cpu.irom_data[11] top.tb_cpu.irom_data[10] top.tb_cpu.irom_data[9] top.tb_cpu.irom_data[8] top.tb_cpu.irom_data[7] top.tb_cpu.irom_data[6] top.tb_cpu.irom_data[5] top.tb_cpu.irom_data[4] top.tb_cpu.irom_data[3] top.tb_cpu.irom_data[2] top.tb_cpu.irom_data[1] top.tb_cpu.irom_data[0]
|
||||
[pattern_trace] 1
|
||||
[pattern_trace] 0
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# -----------------------------------------------------------
|
||||
include $(VHDL_HOME)/make/defs.mk
|
||||
include $(VHDL_HOME)/defs.mk
|
||||
# -----------------------------------------------------------
|
||||
include jcpu_core.inc
|
||||
|
||||
@@ -12,6 +12,7 @@ SRCS += ../src/tb_cpu_itest.vhd
|
||||
# Compile
|
||||
TARGET := reti_issue
|
||||
ENTITY := tb_cpu
|
||||
WAVE_FORMAT := ghw
|
||||
|
||||
include $(VHDL_HOME)/make/ghdl.mk
|
||||
include $(VHDL_MAKE_HOME)/ghdl.mk
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
[*]
|
||||
[*] GTKWave Analyzer v3.3.104 (w)1999-2020 BSI
|
||||
[*] Sat Jul 2 11:01:23 2022
|
||||
[*]
|
||||
[dumpfile] "/home/jens/work/projects/vhdl/lib/CPUs/JCpu/ghdl/build/tb_cpu_embedded/tb_cpu_embedded.fst"
|
||||
[dumpfile_mtime] "Sat Jul 2 11:00:48 2022"
|
||||
[dumpfile_size] 3297
|
||||
[savefile] "/home/jens/work/projects/vhdl/lib/CPUs/JCpu/ghdl/tb_cpu_embedded.gtkw"
|
||||
[timestart] 0
|
||||
[size] 1854 1136
|
||||
[pos] -51 -51
|
||||
*-28.221537 367000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
|
||||
[sst_width] 233
|
||||
[signals_width] 242
|
||||
[sst_expanded] 1
|
||||
[sst_vpaned_height] 330
|
||||
@28
|
||||
uut.clk
|
||||
uut.rst
|
||||
@22
|
||||
uut.irom_addr[11:0]
|
||||
uut.irom_data[17:0]
|
||||
uut.xmem_addr[7:0]
|
||||
uut.xmem_din[7:0]
|
||||
uut.xmem_dout[7:0]
|
||||
@28
|
||||
uut.xmem_we
|
||||
@29
|
||||
uut.xmem_re
|
||||
[pattern_trace] 1
|
||||
[pattern_trace] 0
|
||||
@@ -1,5 +1,5 @@
|
||||
# -----------------------------------------------------------
|
||||
include $(VHDL_HOME)/make/defs.mk
|
||||
include $(VHDL_HOME)/defs.mk
|
||||
# -----------------------------------------------------------
|
||||
include jcpu_core.inc
|
||||
|
||||
@@ -9,8 +9,8 @@ SRCS += ../src/cpu_embedded.vhd
|
||||
SRCS += ../src/tb_cpu_embedded.vhd
|
||||
|
||||
# Compile
|
||||
TARGET := cpu_embedded
|
||||
TARGET := tb_cpu_embedded
|
||||
ENTITY := tb_cpu_embedded
|
||||
|
||||
include $(VHDL_HOME)/make/ghdl.mk
|
||||
include $(VHDL_MAKE_HOME)/ghdl.mk
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
# -----------------------------------------------------------
|
||||
include $(VHDL_HOME)/make/defs.mk
|
||||
include $(VHDL_HOME)/defs.mk
|
||||
# -----------------------------------------------------------
|
||||
include $(VHDL_HOME)/lib/uart/ghdl/uart_sim.inc
|
||||
include jcpu_core.inc
|
||||
@@ -16,5 +16,5 @@ TARGET := tb_cpu_embedded_with_uart
|
||||
ENTITY := tb_cpu_embedded_with_uart
|
||||
RUN_TIME := 100us
|
||||
|
||||
include $(VHDL_HOME)/make/ghdl.mk
|
||||
include $(VHDL_MAKE_HOME)/ghdl.mk
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
.gitignore
|
||||
build/
|
||||
.gitignore
|
||||
build/
|
||||
@@ -1,7 +1,8 @@
|
||||
# -----------------------------------------------------------
|
||||
include $(VHDL_HOME)/make/defs.mk
|
||||
include $(VHDL_HOME)/defs.mk
|
||||
include $(LIB_PATH)/FIFO/ghdl/fifo_sync.inc
|
||||
include $(LIB_PATH)/FIFO/ghdl/fifo_async.inc
|
||||
include $(LIB_PATH)/JBUS/busmaster/ghdl/busmaster_async.inc
|
||||
|
||||
# -----------------------------------------------------------
|
||||
PKG_NAME := MIPS_CORE
|
||||
@@ -10,20 +11,24 @@ PKG_NAME := MIPS_CORE
|
||||
MOD_PATH := $(LIB_PATH)/CPUs/MIPS/src/core
|
||||
$(PKG_NAME)_SRCS += $(FIFO_SYNC_SRCS)
|
||||
$(PKG_NAME)_SRCS += $(FIFO_ASYNC_SRCS)
|
||||
|
||||
$(PKG_NAME)_SRCS += $(BUSMASTER_ASYNC_SRCS)
|
||||
$(PKG_NAME)_SRCS += $(LIB_PATH)/rams/sim/src/dpram_2w2r2c_ra.vhd
|
||||
$(PKG_NAME)_SRCS += $(LIB_PATH)/rams/sim/src/dpram_1w1r2c_ra.vhd
|
||||
$(PKG_NAME)_SRCS += $(MOD_PATH)/mips_util_pkg.vhd
|
||||
$(PKG_NAME)_SRCS += $(MOD_PATH)/mips_types.vhd
|
||||
$(PKG_NAME)_SRCS += $(MOD_PATH)/mips_func_pkg.vhd
|
||||
$(PKG_NAME)_SRCS += $(MOD_PATH)/mips_instr.vhd
|
||||
$(PKG_NAME)_SRCS += $(MOD_PATH)/mips_alu.vhd
|
||||
$(PKG_NAME)_SRCS += $(MOD_PATH)/mips_bcu.vhd
|
||||
$(PKG_NAME)_SRCS += $(MOD_PATH)/mips_biu.vhd
|
||||
$(PKG_NAME)_SRCS += $(MOD_PATH)/mips_cop.vhd
|
||||
$(PKG_NAME)_SRCS += $(MOD_PATH)/mips_reg.vhd
|
||||
$(PKG_NAME)_SRCS += $(MOD_PATH)/mips_cam.vhd
|
||||
$(PKG_NAME)_SRCS += $(MOD_PATH)/mips_tlb.vhd
|
||||
$(PKG_NAME)_SRCS += $(MOD_PATH)/mips_dcache.vhd
|
||||
$(PKG_NAME)_SRCS += $(MOD_PATH)/mips_icache.vhd
|
||||
$(PKG_NAME)_SRCS += $(MOD_PATH)/mips_biu.vhd
|
||||
$(PKG_NAME)_SRCS += $(MOD_PATH)/mips_cop.vhd
|
||||
$(PKG_NAME)_SRCS += $(MOD_PATH)/mips_muldiv.vhd
|
||||
$(PKG_NAME)_SRCS += $(MOD_PATH)/mips_pipeline.vhd
|
||||
$(PKG_NAME)_SRCS += $(MOD_PATH)/mips_reg.vhd
|
||||
$(PKG_NAME)_SRCS += $(MOD_PATH)/mips_shifter.vhd
|
||||
$(PKG_NAME)_SRCS += $(MOD_PATH)/mips_top.vhd
|
||||
|
||||
|
||||
@@ -1,30 +1,74 @@
|
||||
[*]
|
||||
[*] GTKWave Analyzer v3.3.104 (w)1999-2020 BSI
|
||||
[*] Tue Mar 23 20:38:28 2021
|
||||
[*] Thu Sep 8 14:06:03 2022
|
||||
[*]
|
||||
[dumpfile] "/home/jens/work/vhdl/trunk/lib/CPUs/MIPS/ghdl/build/tb_mips_top/tb_mips_top.vcd"
|
||||
[dumpfile_mtime] "Tue Mar 23 20:38:01 2021"
|
||||
[dumpfile_size] 395823834
|
||||
[savefile] "/home/jens/work/vhdl/trunk/lib/CPUs/MIPS/ghdl/build/tb_mips_top/tb_mips_top.gtkw"
|
||||
[dumpfile] "/home/jens/work/projects/vhdl-BRANCH_MIPS_R14/lib/CPUs/MIPS/ghdl/build/tb_mips_top/tb_mips_top.ghw"
|
||||
[dumpfile_mtime] "Thu Sep 8 09:48:46 2022"
|
||||
[dumpfile_size] 16383435
|
||||
[savefile] "/home/jens/work/projects/vhdl-BRANCH_MIPS_R14/lib/CPUs/MIPS/ghdl/tb_mips_top.gtkw"
|
||||
[timestart] 0
|
||||
[size] 1856 1136
|
||||
[pos] -51 -51
|
||||
*-37.625370 355000000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
|
||||
[treeopen] tb_mips_top.
|
||||
[treeopen] tb_mips_top.inst_uart.
|
||||
[size] 1854 1136
|
||||
[pos] -1 -1
|
||||
*-34.382011 10815000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
|
||||
[treeopen] top.
|
||||
[treeopen] top.tb_mips_top.
|
||||
[treeopen] top.tb_mips_top.uut.
|
||||
[treeopen] top.tb_mips_top.uut.inst_pipeline.
|
||||
[treeopen] top.tb_mips_top.uut.inst_pipeline.id_stage.
|
||||
[sst_width] 233
|
||||
[signals_width] 288
|
||||
[signals_width] 228
|
||||
[sst_expanded] 1
|
||||
[sst_vpaned_height] 330
|
||||
[sst_vpaned_height] 488
|
||||
@200
|
||||
-MIPS_R14
|
||||
@28
|
||||
tb_mips_top.clk
|
||||
tb_mips_top.rst
|
||||
top.tb_mips_top.uut.inst_pipeline.clk_1
|
||||
top.tb_mips_top.uut.inst_pipeline.clk_2
|
||||
top.tb_mips_top.uut.clk_i
|
||||
top.tb_mips_top.uut.stb_o
|
||||
@22
|
||||
tb_mips_top.flash_a[16:0]
|
||||
tb_mips_top.flash_d[31:0]
|
||||
tb_mips_top.gpi_0[31:0]
|
||||
tb_mips_top.gpo_0[31:0]
|
||||
@23
|
||||
tb_mips_top.inst_uart.reg_uart_tx[7:0]
|
||||
#{top.tb_mips_top.uut.addr_o[31:0]} top.tb_mips_top.uut.addr_o[31] top.tb_mips_top.uut.addr_o[30] top.tb_mips_top.uut.addr_o[29] top.tb_mips_top.uut.addr_o[28] top.tb_mips_top.uut.addr_o[27] top.tb_mips_top.uut.addr_o[26] top.tb_mips_top.uut.addr_o[25] top.tb_mips_top.uut.addr_o[24] top.tb_mips_top.uut.addr_o[23] top.tb_mips_top.uut.addr_o[22] top.tb_mips_top.uut.addr_o[21] top.tb_mips_top.uut.addr_o[20] top.tb_mips_top.uut.addr_o[19] top.tb_mips_top.uut.addr_o[18] top.tb_mips_top.uut.addr_o[17] top.tb_mips_top.uut.addr_o[16] top.tb_mips_top.uut.addr_o[15] top.tb_mips_top.uut.addr_o[14] top.tb_mips_top.uut.addr_o[13] top.tb_mips_top.uut.addr_o[12] top.tb_mips_top.uut.addr_o[11] top.tb_mips_top.uut.addr_o[10] top.tb_mips_top.uut.addr_o[9] top.tb_mips_top.uut.addr_o[8] top.tb_mips_top.uut.addr_o[7] top.tb_mips_top.uut.addr_o[6] top.tb_mips_top.uut.addr_o[5] top.tb_mips_top.uut.addr_o[4] top.tb_mips_top.uut.addr_o[3] top.tb_mips_top.uut.addr_o[2] top.tb_mips_top.uut.addr_o[1] top.tb_mips_top.uut.addr_o[0]
|
||||
#{top.tb_mips_top.uut.dat_o[31:0]} top.tb_mips_top.uut.dat_o[31] top.tb_mips_top.uut.dat_o[30] top.tb_mips_top.uut.dat_o[29] top.tb_mips_top.uut.dat_o[28] top.tb_mips_top.uut.dat_o[27] top.tb_mips_top.uut.dat_o[26] top.tb_mips_top.uut.dat_o[25] top.tb_mips_top.uut.dat_o[24] top.tb_mips_top.uut.dat_o[23] top.tb_mips_top.uut.dat_o[22] top.tb_mips_top.uut.dat_o[21] top.tb_mips_top.uut.dat_o[20] top.tb_mips_top.uut.dat_o[19] top.tb_mips_top.uut.dat_o[18] top.tb_mips_top.uut.dat_o[17] top.tb_mips_top.uut.dat_o[16] top.tb_mips_top.uut.dat_o[15] top.tb_mips_top.uut.dat_o[14] top.tb_mips_top.uut.dat_o[13] top.tb_mips_top.uut.dat_o[12] top.tb_mips_top.uut.dat_o[11] top.tb_mips_top.uut.dat_o[10] top.tb_mips_top.uut.dat_o[9] top.tb_mips_top.uut.dat_o[8] top.tb_mips_top.uut.dat_o[7] top.tb_mips_top.uut.dat_o[6] top.tb_mips_top.uut.dat_o[5] top.tb_mips_top.uut.dat_o[4] top.tb_mips_top.uut.dat_o[3] top.tb_mips_top.uut.dat_o[2] top.tb_mips_top.uut.dat_o[1] top.tb_mips_top.uut.dat_o[0]
|
||||
#{top.tb_mips_top.uut.dat_i[31:0]} top.tb_mips_top.uut.dat_i[31] top.tb_mips_top.uut.dat_i[30] top.tb_mips_top.uut.dat_i[29] top.tb_mips_top.uut.dat_i[28] top.tb_mips_top.uut.dat_i[27] top.tb_mips_top.uut.dat_i[26] top.tb_mips_top.uut.dat_i[25] top.tb_mips_top.uut.dat_i[24] top.tb_mips_top.uut.dat_i[23] top.tb_mips_top.uut.dat_i[22] top.tb_mips_top.uut.dat_i[21] top.tb_mips_top.uut.dat_i[20] top.tb_mips_top.uut.dat_i[19] top.tb_mips_top.uut.dat_i[18] top.tb_mips_top.uut.dat_i[17] top.tb_mips_top.uut.dat_i[16] top.tb_mips_top.uut.dat_i[15] top.tb_mips_top.uut.dat_i[14] top.tb_mips_top.uut.dat_i[13] top.tb_mips_top.uut.dat_i[12] top.tb_mips_top.uut.dat_i[11] top.tb_mips_top.uut.dat_i[10] top.tb_mips_top.uut.dat_i[9] top.tb_mips_top.uut.dat_i[8] top.tb_mips_top.uut.dat_i[7] top.tb_mips_top.uut.dat_i[6] top.tb_mips_top.uut.dat_i[5] top.tb_mips_top.uut.dat_i[4] top.tb_mips_top.uut.dat_i[3] top.tb_mips_top.uut.dat_i[2] top.tb_mips_top.uut.dat_i[1] top.tb_mips_top.uut.dat_i[0]
|
||||
@200
|
||||
-PC
|
||||
@28
|
||||
top.tb_mips_top.uut.inst_pipeline.branch_ce
|
||||
top.tb_mips_top.uut.inst_pipeline.pc.branch_not_taken
|
||||
top.tb_mips_top.uut.inst_pipeline.pc.branch_take
|
||||
@22
|
||||
#{top.tb_mips_top.uut.inst_pipeline.pc.pc_branch[31:0]} top.tb_mips_top.uut.inst_pipeline.pc.pc_branch[31] top.tb_mips_top.uut.inst_pipeline.pc.pc_branch[30] top.tb_mips_top.uut.inst_pipeline.pc.pc_branch[29] top.tb_mips_top.uut.inst_pipeline.pc.pc_branch[28] top.tb_mips_top.uut.inst_pipeline.pc.pc_branch[27] top.tb_mips_top.uut.inst_pipeline.pc.pc_branch[26] top.tb_mips_top.uut.inst_pipeline.pc.pc_branch[25] top.tb_mips_top.uut.inst_pipeline.pc.pc_branch[24] top.tb_mips_top.uut.inst_pipeline.pc.pc_branch[23] top.tb_mips_top.uut.inst_pipeline.pc.pc_branch[22] top.tb_mips_top.uut.inst_pipeline.pc.pc_branch[21] top.tb_mips_top.uut.inst_pipeline.pc.pc_branch[20] top.tb_mips_top.uut.inst_pipeline.pc.pc_branch[19] top.tb_mips_top.uut.inst_pipeline.pc.pc_branch[18] top.tb_mips_top.uut.inst_pipeline.pc.pc_branch[17] top.tb_mips_top.uut.inst_pipeline.pc.pc_branch[16] top.tb_mips_top.uut.inst_pipeline.pc.pc_branch[15] top.tb_mips_top.uut.inst_pipeline.pc.pc_branch[14] top.tb_mips_top.uut.inst_pipeline.pc.pc_branch[13] top.tb_mips_top.uut.inst_pipeline.pc.pc_branch[12] top.tb_mips_top.uut.inst_pipeline.pc.pc_branch[11] top.tb_mips_top.uut.inst_pipeline.pc.pc_branch[10] top.tb_mips_top.uut.inst_pipeline.pc.pc_branch[9] top.tb_mips_top.uut.inst_pipeline.pc.pc_branch[8] top.tb_mips_top.uut.inst_pipeline.pc.pc_branch[7] top.tb_mips_top.uut.inst_pipeline.pc.pc_branch[6] top.tb_mips_top.uut.inst_pipeline.pc.pc_branch[5] top.tb_mips_top.uut.inst_pipeline.pc.pc_branch[4] top.tb_mips_top.uut.inst_pipeline.pc.pc_branch[3] top.tb_mips_top.uut.inst_pipeline.pc.pc_branch[2] top.tb_mips_top.uut.inst_pipeline.pc.pc_branch[1] top.tb_mips_top.uut.inst_pipeline.pc.pc_branch[0]
|
||||
#{top.tb_mips_top.uut.inst_pipeline.pc.nxt[31:0]} top.tb_mips_top.uut.inst_pipeline.pc.nxt[31] top.tb_mips_top.uut.inst_pipeline.pc.nxt[30] top.tb_mips_top.uut.inst_pipeline.pc.nxt[29] top.tb_mips_top.uut.inst_pipeline.pc.nxt[28] top.tb_mips_top.uut.inst_pipeline.pc.nxt[27] top.tb_mips_top.uut.inst_pipeline.pc.nxt[26] top.tb_mips_top.uut.inst_pipeline.pc.nxt[25] top.tb_mips_top.uut.inst_pipeline.pc.nxt[24] top.tb_mips_top.uut.inst_pipeline.pc.nxt[23] top.tb_mips_top.uut.inst_pipeline.pc.nxt[22] top.tb_mips_top.uut.inst_pipeline.pc.nxt[21] top.tb_mips_top.uut.inst_pipeline.pc.nxt[20] top.tb_mips_top.uut.inst_pipeline.pc.nxt[19] top.tb_mips_top.uut.inst_pipeline.pc.nxt[18] top.tb_mips_top.uut.inst_pipeline.pc.nxt[17] top.tb_mips_top.uut.inst_pipeline.pc.nxt[16] top.tb_mips_top.uut.inst_pipeline.pc.nxt[15] top.tb_mips_top.uut.inst_pipeline.pc.nxt[14] top.tb_mips_top.uut.inst_pipeline.pc.nxt[13] top.tb_mips_top.uut.inst_pipeline.pc.nxt[12] top.tb_mips_top.uut.inst_pipeline.pc.nxt[11] top.tb_mips_top.uut.inst_pipeline.pc.nxt[10] top.tb_mips_top.uut.inst_pipeline.pc.nxt[9] top.tb_mips_top.uut.inst_pipeline.pc.nxt[8] top.tb_mips_top.uut.inst_pipeline.pc.nxt[7] top.tb_mips_top.uut.inst_pipeline.pc.nxt[6] top.tb_mips_top.uut.inst_pipeline.pc.nxt[5] top.tb_mips_top.uut.inst_pipeline.pc.nxt[4] top.tb_mips_top.uut.inst_pipeline.pc.nxt[3] top.tb_mips_top.uut.inst_pipeline.pc.nxt[2] top.tb_mips_top.uut.inst_pipeline.pc.nxt[1] top.tb_mips_top.uut.inst_pipeline.pc.nxt[0]
|
||||
#{top.tb_mips_top.uut.inst_pipeline.pc.last[31:0]} top.tb_mips_top.uut.inst_pipeline.pc.last[31] top.tb_mips_top.uut.inst_pipeline.pc.last[30] top.tb_mips_top.uut.inst_pipeline.pc.last[29] top.tb_mips_top.uut.inst_pipeline.pc.last[28] top.tb_mips_top.uut.inst_pipeline.pc.last[27] top.tb_mips_top.uut.inst_pipeline.pc.last[26] top.tb_mips_top.uut.inst_pipeline.pc.last[25] top.tb_mips_top.uut.inst_pipeline.pc.last[24] top.tb_mips_top.uut.inst_pipeline.pc.last[23] top.tb_mips_top.uut.inst_pipeline.pc.last[22] top.tb_mips_top.uut.inst_pipeline.pc.last[21] top.tb_mips_top.uut.inst_pipeline.pc.last[20] top.tb_mips_top.uut.inst_pipeline.pc.last[19] top.tb_mips_top.uut.inst_pipeline.pc.last[18] top.tb_mips_top.uut.inst_pipeline.pc.last[17] top.tb_mips_top.uut.inst_pipeline.pc.last[16] top.tb_mips_top.uut.inst_pipeline.pc.last[15] top.tb_mips_top.uut.inst_pipeline.pc.last[14] top.tb_mips_top.uut.inst_pipeline.pc.last[13] top.tb_mips_top.uut.inst_pipeline.pc.last[12] top.tb_mips_top.uut.inst_pipeline.pc.last[11] top.tb_mips_top.uut.inst_pipeline.pc.last[10] top.tb_mips_top.uut.inst_pipeline.pc.last[9] top.tb_mips_top.uut.inst_pipeline.pc.last[8] top.tb_mips_top.uut.inst_pipeline.pc.last[7] top.tb_mips_top.uut.inst_pipeline.pc.last[6] top.tb_mips_top.uut.inst_pipeline.pc.last[5] top.tb_mips_top.uut.inst_pipeline.pc.last[4] top.tb_mips_top.uut.inst_pipeline.pc.last[3] top.tb_mips_top.uut.inst_pipeline.pc.last[2] top.tb_mips_top.uut.inst_pipeline.pc.last[1] top.tb_mips_top.uut.inst_pipeline.pc.last[0]
|
||||
#{top.tb_mips_top.uut.inst_pipeline.pc.curr[31:0]} top.tb_mips_top.uut.inst_pipeline.pc.curr[31] top.tb_mips_top.uut.inst_pipeline.pc.curr[30] top.tb_mips_top.uut.inst_pipeline.pc.curr[29] top.tb_mips_top.uut.inst_pipeline.pc.curr[28] top.tb_mips_top.uut.inst_pipeline.pc.curr[27] top.tb_mips_top.uut.inst_pipeline.pc.curr[26] top.tb_mips_top.uut.inst_pipeline.pc.curr[25] top.tb_mips_top.uut.inst_pipeline.pc.curr[24] top.tb_mips_top.uut.inst_pipeline.pc.curr[23] top.tb_mips_top.uut.inst_pipeline.pc.curr[22] top.tb_mips_top.uut.inst_pipeline.pc.curr[21] top.tb_mips_top.uut.inst_pipeline.pc.curr[20] top.tb_mips_top.uut.inst_pipeline.pc.curr[19] top.tb_mips_top.uut.inst_pipeline.pc.curr[18] top.tb_mips_top.uut.inst_pipeline.pc.curr[17] top.tb_mips_top.uut.inst_pipeline.pc.curr[16] top.tb_mips_top.uut.inst_pipeline.pc.curr[15] top.tb_mips_top.uut.inst_pipeline.pc.curr[14] top.tb_mips_top.uut.inst_pipeline.pc.curr[13] top.tb_mips_top.uut.inst_pipeline.pc.curr[12] top.tb_mips_top.uut.inst_pipeline.pc.curr[11] top.tb_mips_top.uut.inst_pipeline.pc.curr[10] top.tb_mips_top.uut.inst_pipeline.pc.curr[9] top.tb_mips_top.uut.inst_pipeline.pc.curr[8] top.tb_mips_top.uut.inst_pipeline.pc.curr[7] top.tb_mips_top.uut.inst_pipeline.pc.curr[6] top.tb_mips_top.uut.inst_pipeline.pc.curr[5] top.tb_mips_top.uut.inst_pipeline.pc.curr[4] top.tb_mips_top.uut.inst_pipeline.pc.curr[3] top.tb_mips_top.uut.inst_pipeline.pc.curr[2] top.tb_mips_top.uut.inst_pipeline.pc.curr[1] top.tb_mips_top.uut.inst_pipeline.pc.curr[0]
|
||||
@200
|
||||
-REG
|
||||
@22
|
||||
#{top.tb_mips_top.uut.inst_pipeline.reg_a[31:0]} top.tb_mips_top.uut.inst_pipeline.reg_a[31] top.tb_mips_top.uut.inst_pipeline.reg_a[30] top.tb_mips_top.uut.inst_pipeline.reg_a[29] top.tb_mips_top.uut.inst_pipeline.reg_a[28] top.tb_mips_top.uut.inst_pipeline.reg_a[27] top.tb_mips_top.uut.inst_pipeline.reg_a[26] top.tb_mips_top.uut.inst_pipeline.reg_a[25] top.tb_mips_top.uut.inst_pipeline.reg_a[24] top.tb_mips_top.uut.inst_pipeline.reg_a[23] top.tb_mips_top.uut.inst_pipeline.reg_a[22] top.tb_mips_top.uut.inst_pipeline.reg_a[21] top.tb_mips_top.uut.inst_pipeline.reg_a[20] top.tb_mips_top.uut.inst_pipeline.reg_a[19] top.tb_mips_top.uut.inst_pipeline.reg_a[18] top.tb_mips_top.uut.inst_pipeline.reg_a[17] top.tb_mips_top.uut.inst_pipeline.reg_a[16] top.tb_mips_top.uut.inst_pipeline.reg_a[15] top.tb_mips_top.uut.inst_pipeline.reg_a[14] top.tb_mips_top.uut.inst_pipeline.reg_a[13] top.tb_mips_top.uut.inst_pipeline.reg_a[12] top.tb_mips_top.uut.inst_pipeline.reg_a[11] top.tb_mips_top.uut.inst_pipeline.reg_a[10] top.tb_mips_top.uut.inst_pipeline.reg_a[9] top.tb_mips_top.uut.inst_pipeline.reg_a[8] top.tb_mips_top.uut.inst_pipeline.reg_a[7] top.tb_mips_top.uut.inst_pipeline.reg_a[6] top.tb_mips_top.uut.inst_pipeline.reg_a[5] top.tb_mips_top.uut.inst_pipeline.reg_a[4] top.tb_mips_top.uut.inst_pipeline.reg_a[3] top.tb_mips_top.uut.inst_pipeline.reg_a[2] top.tb_mips_top.uut.inst_pipeline.reg_a[1] top.tb_mips_top.uut.inst_pipeline.reg_a[0]
|
||||
#{top.tb_mips_top.uut.inst_pipeline.reg_b[31:0]} top.tb_mips_top.uut.inst_pipeline.reg_b[31] top.tb_mips_top.uut.inst_pipeline.reg_b[30] top.tb_mips_top.uut.inst_pipeline.reg_b[29] top.tb_mips_top.uut.inst_pipeline.reg_b[28] top.tb_mips_top.uut.inst_pipeline.reg_b[27] top.tb_mips_top.uut.inst_pipeline.reg_b[26] top.tb_mips_top.uut.inst_pipeline.reg_b[25] top.tb_mips_top.uut.inst_pipeline.reg_b[24] top.tb_mips_top.uut.inst_pipeline.reg_b[23] top.tb_mips_top.uut.inst_pipeline.reg_b[22] top.tb_mips_top.uut.inst_pipeline.reg_b[21] top.tb_mips_top.uut.inst_pipeline.reg_b[20] top.tb_mips_top.uut.inst_pipeline.reg_b[19] top.tb_mips_top.uut.inst_pipeline.reg_b[18] top.tb_mips_top.uut.inst_pipeline.reg_b[17] top.tb_mips_top.uut.inst_pipeline.reg_b[16] top.tb_mips_top.uut.inst_pipeline.reg_b[15] top.tb_mips_top.uut.inst_pipeline.reg_b[14] top.tb_mips_top.uut.inst_pipeline.reg_b[13] top.tb_mips_top.uut.inst_pipeline.reg_b[12] top.tb_mips_top.uut.inst_pipeline.reg_b[11] top.tb_mips_top.uut.inst_pipeline.reg_b[10] top.tb_mips_top.uut.inst_pipeline.reg_b[9] top.tb_mips_top.uut.inst_pipeline.reg_b[8] top.tb_mips_top.uut.inst_pipeline.reg_b[7] top.tb_mips_top.uut.inst_pipeline.reg_b[6] top.tb_mips_top.uut.inst_pipeline.reg_b[5] top.tb_mips_top.uut.inst_pipeline.reg_b[4] top.tb_mips_top.uut.inst_pipeline.reg_b[3] top.tb_mips_top.uut.inst_pipeline.reg_b[2] top.tb_mips_top.uut.inst_pipeline.reg_b[1] top.tb_mips_top.uut.inst_pipeline.reg_b[0]
|
||||
@200
|
||||
-ID
|
||||
@28
|
||||
top.tb_mips_top.uut.inst_pipeline.sdu.dmem_dep
|
||||
@29
|
||||
top.tb_mips_top.uut.inst_pipeline.sdu.imem_dep
|
||||
@28
|
||||
top.tb_mips_top.uut.inst_pipeline.id_stage.nop
|
||||
@22
|
||||
#{top.tb_mips_top.uut.inst_pipeline.id_stage.ir[31:0]} top.tb_mips_top.uut.inst_pipeline.id_stage.ir[31] top.tb_mips_top.uut.inst_pipeline.id_stage.ir[30] top.tb_mips_top.uut.inst_pipeline.id_stage.ir[29] top.tb_mips_top.uut.inst_pipeline.id_stage.ir[28] top.tb_mips_top.uut.inst_pipeline.id_stage.ir[27] top.tb_mips_top.uut.inst_pipeline.id_stage.ir[26] top.tb_mips_top.uut.inst_pipeline.id_stage.ir[25] top.tb_mips_top.uut.inst_pipeline.id_stage.ir[24] top.tb_mips_top.uut.inst_pipeline.id_stage.ir[23] top.tb_mips_top.uut.inst_pipeline.id_stage.ir[22] top.tb_mips_top.uut.inst_pipeline.id_stage.ir[21] top.tb_mips_top.uut.inst_pipeline.id_stage.ir[20] top.tb_mips_top.uut.inst_pipeline.id_stage.ir[19] top.tb_mips_top.uut.inst_pipeline.id_stage.ir[18] top.tb_mips_top.uut.inst_pipeline.id_stage.ir[17] top.tb_mips_top.uut.inst_pipeline.id_stage.ir[16] top.tb_mips_top.uut.inst_pipeline.id_stage.ir[15] top.tb_mips_top.uut.inst_pipeline.id_stage.ir[14] top.tb_mips_top.uut.inst_pipeline.id_stage.ir[13] top.tb_mips_top.uut.inst_pipeline.id_stage.ir[12] top.tb_mips_top.uut.inst_pipeline.id_stage.ir[11] top.tb_mips_top.uut.inst_pipeline.id_stage.ir[10] top.tb_mips_top.uut.inst_pipeline.id_stage.ir[9] top.tb_mips_top.uut.inst_pipeline.id_stage.ir[8] top.tb_mips_top.uut.inst_pipeline.id_stage.ir[7] top.tb_mips_top.uut.inst_pipeline.id_stage.ir[6] top.tb_mips_top.uut.inst_pipeline.id_stage.ir[5] top.tb_mips_top.uut.inst_pipeline.id_stage.ir[4] top.tb_mips_top.uut.inst_pipeline.id_stage.ir[3] top.tb_mips_top.uut.inst_pipeline.id_stage.ir[2] top.tb_mips_top.uut.inst_pipeline.id_stage.ir[1] top.tb_mips_top.uut.inst_pipeline.id_stage.ir[0]
|
||||
@420
|
||||
top.tb_mips_top.uut.inst_pipeline.id_stage.op
|
||||
@28
|
||||
top.tb_mips_top.uut.inst_pipeline.id_stage.exc
|
||||
top.tb_mips_top.uut.inst_pipeline.id_stage.reg_write
|
||||
@22
|
||||
#{top.tb_mips_top.uut.inst_pipeline.id_stage.pcn[31:0]} top.tb_mips_top.uut.inst_pipeline.id_stage.pcn[31] top.tb_mips_top.uut.inst_pipeline.id_stage.pcn[30] top.tb_mips_top.uut.inst_pipeline.id_stage.pcn[29] top.tb_mips_top.uut.inst_pipeline.id_stage.pcn[28] top.tb_mips_top.uut.inst_pipeline.id_stage.pcn[27] top.tb_mips_top.uut.inst_pipeline.id_stage.pcn[26] top.tb_mips_top.uut.inst_pipeline.id_stage.pcn[25] top.tb_mips_top.uut.inst_pipeline.id_stage.pcn[24] top.tb_mips_top.uut.inst_pipeline.id_stage.pcn[23] top.tb_mips_top.uut.inst_pipeline.id_stage.pcn[22] top.tb_mips_top.uut.inst_pipeline.id_stage.pcn[21] top.tb_mips_top.uut.inst_pipeline.id_stage.pcn[20] top.tb_mips_top.uut.inst_pipeline.id_stage.pcn[19] top.tb_mips_top.uut.inst_pipeline.id_stage.pcn[18] top.tb_mips_top.uut.inst_pipeline.id_stage.pcn[17] top.tb_mips_top.uut.inst_pipeline.id_stage.pcn[16] top.tb_mips_top.uut.inst_pipeline.id_stage.pcn[15] top.tb_mips_top.uut.inst_pipeline.id_stage.pcn[14] top.tb_mips_top.uut.inst_pipeline.id_stage.pcn[13] top.tb_mips_top.uut.inst_pipeline.id_stage.pcn[12] top.tb_mips_top.uut.inst_pipeline.id_stage.pcn[11] top.tb_mips_top.uut.inst_pipeline.id_stage.pcn[10] top.tb_mips_top.uut.inst_pipeline.id_stage.pcn[9] top.tb_mips_top.uut.inst_pipeline.id_stage.pcn[8] top.tb_mips_top.uut.inst_pipeline.id_stage.pcn[7] top.tb_mips_top.uut.inst_pipeline.id_stage.pcn[6] top.tb_mips_top.uut.inst_pipeline.id_stage.pcn[5] top.tb_mips_top.uut.inst_pipeline.id_stage.pcn[4] top.tb_mips_top.uut.inst_pipeline.id_stage.pcn[3] top.tb_mips_top.uut.inst_pipeline.id_stage.pcn[2] top.tb_mips_top.uut.inst_pipeline.id_stage.pcn[1] top.tb_mips_top.uut.inst_pipeline.id_stage.pcn[0]
|
||||
#{top.tb_mips_top.uut.inst_pipeline.id_stage.epc[31:0]} top.tb_mips_top.uut.inst_pipeline.id_stage.epc[31] top.tb_mips_top.uut.inst_pipeline.id_stage.epc[30] top.tb_mips_top.uut.inst_pipeline.id_stage.epc[29] top.tb_mips_top.uut.inst_pipeline.id_stage.epc[28] top.tb_mips_top.uut.inst_pipeline.id_stage.epc[27] top.tb_mips_top.uut.inst_pipeline.id_stage.epc[26] top.tb_mips_top.uut.inst_pipeline.id_stage.epc[25] top.tb_mips_top.uut.inst_pipeline.id_stage.epc[24] top.tb_mips_top.uut.inst_pipeline.id_stage.epc[23] top.tb_mips_top.uut.inst_pipeline.id_stage.epc[22] top.tb_mips_top.uut.inst_pipeline.id_stage.epc[21] top.tb_mips_top.uut.inst_pipeline.id_stage.epc[20] top.tb_mips_top.uut.inst_pipeline.id_stage.epc[19] top.tb_mips_top.uut.inst_pipeline.id_stage.epc[18] top.tb_mips_top.uut.inst_pipeline.id_stage.epc[17] top.tb_mips_top.uut.inst_pipeline.id_stage.epc[16] top.tb_mips_top.uut.inst_pipeline.id_stage.epc[15] top.tb_mips_top.uut.inst_pipeline.id_stage.epc[14] top.tb_mips_top.uut.inst_pipeline.id_stage.epc[13] top.tb_mips_top.uut.inst_pipeline.id_stage.epc[12] top.tb_mips_top.uut.inst_pipeline.id_stage.epc[11] top.tb_mips_top.uut.inst_pipeline.id_stage.epc[10] top.tb_mips_top.uut.inst_pipeline.id_stage.epc[9] top.tb_mips_top.uut.inst_pipeline.id_stage.epc[8] top.tb_mips_top.uut.inst_pipeline.id_stage.epc[7] top.tb_mips_top.uut.inst_pipeline.id_stage.epc[6] top.tb_mips_top.uut.inst_pipeline.id_stage.epc[5] top.tb_mips_top.uut.inst_pipeline.id_stage.epc[4] top.tb_mips_top.uut.inst_pipeline.id_stage.epc[3] top.tb_mips_top.uut.inst_pipeline.id_stage.epc[2] top.tb_mips_top.uut.inst_pipeline.id_stage.epc[1] top.tb_mips_top.uut.inst_pipeline.id_stage.epc[0]
|
||||
#{top.tb_mips_top.uut.inst_pipeline.id_stage.reg_a_rptr[4:0]} top.tb_mips_top.uut.inst_pipeline.id_stage.reg_a_rptr[4] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_a_rptr[3] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_a_rptr[2] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_a_rptr[1] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_a_rptr[0]
|
||||
#{top.tb_mips_top.uut.inst_pipeline.id_stage.reg_a[31:0]} top.tb_mips_top.uut.inst_pipeline.id_stage.reg_a[31] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_a[30] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_a[29] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_a[28] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_a[27] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_a[26] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_a[25] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_a[24] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_a[23] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_a[22] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_a[21] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_a[20] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_a[19] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_a[18] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_a[17] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_a[16] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_a[15] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_a[14] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_a[13] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_a[12] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_a[11] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_a[10] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_a[9] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_a[8] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_a[7] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_a[6] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_a[5] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_a[4] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_a[3] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_a[2] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_a[1] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_a[0]
|
||||
#{top.tb_mips_top.uut.inst_pipeline.id_stage.reg_b_rptr[4:0]} top.tb_mips_top.uut.inst_pipeline.id_stage.reg_b_rptr[4] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_b_rptr[3] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_b_rptr[2] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_b_rptr[1] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_b_rptr[0]
|
||||
#{top.tb_mips_top.uut.inst_pipeline.id_stage.reg_b[31:0]} top.tb_mips_top.uut.inst_pipeline.id_stage.reg_b[31] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_b[30] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_b[29] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_b[28] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_b[27] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_b[26] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_b[25] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_b[24] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_b[23] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_b[22] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_b[21] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_b[20] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_b[19] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_b[18] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_b[17] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_b[16] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_b[15] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_b[14] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_b[13] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_b[12] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_b[11] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_b[10] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_b[9] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_b[8] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_b[7] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_b[6] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_b[5] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_b[4] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_b[3] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_b[2] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_b[1] top.tb_mips_top.uut.inst_pipeline.id_stage.reg_b[0]
|
||||
@200
|
||||
-EX
|
||||
[pattern_trace] 1
|
||||
[pattern_trace] 0
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# -----------------------------------------------------------
|
||||
include $(VHDL_HOME)/make/defs.mk
|
||||
include $(VHDL_HOME)/defs.mk
|
||||
# -----------------------------------------------------------
|
||||
include mips_core.inc
|
||||
|
||||
@@ -32,7 +32,8 @@ SRCS += ../src/tb_mips_top.vhd
|
||||
# Compile
|
||||
TARGET := tb_mips_top
|
||||
ENTITY := tb_mips_top
|
||||
RUN_TIME ?= 1500us
|
||||
RUN_TIME := 150us
|
||||
WAVE_FORMAT := ghw
|
||||
|
||||
include $(VHDL_HOME)/make/ghdl.mk
|
||||
include $(VHDL_MAKE_HOME)/ghdl.mk
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+5973
-5128
File diff suppressed because it is too large
Load Diff
+236
-390
@@ -27,426 +27,282 @@ use IEEE.numeric_std.ALL;
|
||||
|
||||
library work;
|
||||
use work.mips_types.all;
|
||||
use work.mips_util_pkg.all;
|
||||
use work.busmaster_types.all;
|
||||
|
||||
entity biu is
|
||||
Generic
|
||||
(
|
||||
icache_size : natural := 2048; -- words
|
||||
icache_line : natural := 8; -- words
|
||||
dcache_size : natural := 2048; -- words
|
||||
dcache_line : natural := 8 -- words
|
||||
ICACHE_SIZE : natural := 2048; -- words
|
||||
ICACHE_LINE : natural := 8; -- words
|
||||
DCACHE_SIZE : natural := 2048; -- words
|
||||
DCACHE_LINE : natural := 8; -- words
|
||||
WRITE_FIFO_SIZE : natural := 4; -- words
|
||||
WITH_TLB : boolean := true;
|
||||
TRANSLATE_KSEG0_1 : boolean := true
|
||||
);
|
||||
Port
|
||||
(
|
||||
clk : in STD_LOGIC;
|
||||
busy : out STD_LOGIC;
|
||||
|
||||
imem_err : out STD_LOGIC;
|
||||
dmem_err : out STD_LOGIC;
|
||||
|
||||
RST_I : in STD_LOGIC;
|
||||
CLK_I : in STD_LOGIC;
|
||||
ACK_I : in STD_LOGIC;
|
||||
SRDY_I : in STD_LOGIC;
|
||||
ADDR_O : out unsigned(31 downto 0);
|
||||
DAT_I : in unsigned(31 downto 0);
|
||||
DAT_O : out unsigned(31 downto 0);
|
||||
MDAT_I : in unsigned(31 downto 0);
|
||||
MDAT_O : out unsigned(31 downto 0);
|
||||
WE_O : out STD_LOGIC;
|
||||
SEL_O : out unsigned(3 downto 0);
|
||||
CYC_O : out STD_LOGIC;
|
||||
STB_O : out STD_LOGIC;
|
||||
MRDY_O : out STD_LOGIC;
|
||||
cop0_ctrl_in : in cop0_ctrl_out_t;
|
||||
cpu_clk : in STD_LOGIC;
|
||||
cpu_imem_err : out STD_LOGIC;
|
||||
cpu_imem_rdy : out STD_LOGIC;
|
||||
cpu_imem_en : in STD_LOGIC;
|
||||
cpu_imem_addr : in word_t;
|
||||
cpu_imem_din : out word_t;
|
||||
cpu_dmem_err : out STD_LOGIC;
|
||||
cpu_dmem_rdy : out STD_LOGIC;
|
||||
cpu_dmem_en : in STD_LOGIC;
|
||||
cpu_dmem_we : in STD_LOGIC;
|
||||
cpu_dmem_be : in unsigned(3 downto 0);
|
||||
cpu_dmem_dout : in word_t;
|
||||
cpu_dmem_din : out word_t;
|
||||
cpu_dmem_addr : in word_t
|
||||
|
||||
ctrl_in : in biu_ctrl_in_t;
|
||||
ctrl_out : out biu_ctrl_out_t
|
||||
|
||||
);
|
||||
end biu;
|
||||
|
||||
architecture behavior of biu is
|
||||
|
||||
COMPONENT icache
|
||||
GENERIC
|
||||
(
|
||||
cache_size : natural; -- words
|
||||
line_size : natural -- words
|
||||
);
|
||||
PORT
|
||||
(
|
||||
RST_I : in STD_LOGIC;
|
||||
CLK_I : in STD_LOGIC;
|
||||
ACK_I : in STD_LOGIC;
|
||||
SRDY_I : in STD_LOGIC;
|
||||
MRDY_O : out STD_LOGIC;
|
||||
ADDR_O : out word_t;
|
||||
DAT_I : in word_t;
|
||||
STB_O : out STD_LOGIC;
|
||||
CYC_O : out STD_LOGIC;
|
||||
ctrl : in cache_ctrl_t;
|
||||
cpu_en : in STD_LOGIC;
|
||||
cpu_addr : in word_t;
|
||||
cpu_dout : out word_t;
|
||||
cpu_busy : out STD_LOGIC
|
||||
);
|
||||
END COMPONENT;
|
||||
|
||||
COMPONENT dcache
|
||||
GENERIC
|
||||
(
|
||||
cache_size : natural; -- words
|
||||
line_size : natural -- words
|
||||
);
|
||||
PORT
|
||||
(
|
||||
RST_I : in STD_LOGIC;
|
||||
CLK_I : in STD_LOGIC;
|
||||
ACK_I : in STD_LOGIC;
|
||||
SRDY_I : in STD_LOGIC;
|
||||
MRDY_O : out STD_LOGIC;
|
||||
ADDR_O : out word_t;
|
||||
DAT_I : in word_t;
|
||||
STB_O : out STD_LOGIC;
|
||||
CYC_O : out STD_LOGIC;
|
||||
ctrl : in cache_ctrl_t;
|
||||
cpu_en : in STD_LOGIC;
|
||||
cpu_we : in STD_LOGIC;
|
||||
cpu_be : in unsigned(3 downto 0);
|
||||
cpu_addr : in word_t;
|
||||
cpu_din : in word_t;
|
||||
cpu_dout : out word_t;
|
||||
cpu_busy : out STD_LOGIC
|
||||
);
|
||||
END COMPONENT;
|
||||
|
||||
type bus_state_t is (init, ready, icache_bus_access, dcache_bus_access, write_bus, read_bus, read_finish);
|
||||
|
||||
signal s, sn : bus_state_t;
|
||||
signal bus_idle : std_logic;
|
||||
signal busy : std_logic;
|
||||
signal dmem_be : unsigned(3 downto 0);
|
||||
signal dcache_dout : word_t;
|
||||
signal dcache_mem_gnt : std_logic;
|
||||
signal icache_mem_gnt : std_logic;
|
||||
signal dmem_mem_wr_gnt : std_logic;
|
||||
signal dmem_mem_rd_gnt : std_logic;
|
||||
signal dcache_busy : std_logic;
|
||||
signal icache_busy : std_logic;
|
||||
signal CYC_O_icache : std_logic;
|
||||
signal CYC_O_dcache : std_logic;
|
||||
signal CYC_O_dmem_rd : std_logic;
|
||||
signal CYC_O_dmem_wr : std_logic;
|
||||
signal SRDY_I_icache : std_logic;
|
||||
signal SRDY_I_dcache : std_logic;
|
||||
signal MRDY_O_icache : std_logic;
|
||||
signal MRDY_O_dcache : std_logic;
|
||||
signal ADDR_O_icache : word_t;
|
||||
signal ADDR_O_dcache : word_t;
|
||||
signal ADDR_O_dmem_rd : word_t;
|
||||
signal ADDR_O_dmem_wr : word_t;
|
||||
signal STB_O_icache : std_logic;
|
||||
signal STB_O_dcache : std_logic;
|
||||
signal STB_O_dmem_rd : std_logic;
|
||||
signal STB_O_dmem_wr : std_logic;
|
||||
signal DAT_I_dmem_rd : word_t;
|
||||
signal DAT_O_dmem_wr : word_t;
|
||||
signal SEL_O_dmem_wr : unsigned(3 downto 0);
|
||||
signal SEL_O_dmem_rd : unsigned(3 downto 0);
|
||||
signal dcached : std_logic;
|
||||
signal dcache_en2 : std_logic;
|
||||
signal dcache_en : std_logic;
|
||||
signal uncached_access : std_logic;
|
||||
signal ACK : std_logic;
|
||||
signal DAT : unsigned(31 downto 0);
|
||||
|
||||
type timeout_cnt_t is range 0 to 1E5-1;
|
||||
signal bus_timeout_cnt : timeout_cnt_t;
|
||||
signal bus_timeout : std_logic;
|
||||
|
||||
signal bout_fifo_din : unsigned(68 downto 0);
|
||||
signal bout_fifo_dout : unsigned(68 downto 0);
|
||||
signal bout_fifo_re : std_logic;
|
||||
signal bout_fifo_we : std_logic;
|
||||
signal bout_fifo_full : std_logic;
|
||||
signal bout_fifo_empty : std_logic;
|
||||
signal bout_rdy : std_logic;
|
||||
-------------------------------------------------
|
||||
signal RST : std_logic;
|
||||
signal CPU_CLK : std_logic;
|
||||
|
||||
signal bin_fifo_din : unsigned(31 downto 0);
|
||||
signal bin_fifo_dout : unsigned(31 downto 0);
|
||||
signal bin_fifo_re : std_logic;
|
||||
signal bin_fifo_we : std_logic;
|
||||
signal bin_fifo_full : std_logic;
|
||||
signal bin_fifo_empty : std_logic;
|
||||
-- busmaster signals
|
||||
signal bus_din : word_t;
|
||||
signal bus_din_rdy : std_logic;
|
||||
signal bus_din_we : std_logic;
|
||||
|
||||
alias bout_fifo_addr_in is bout_fifo_din(31 downto 0);
|
||||
alias bout_fifo_data_in is bout_fifo_din(63 downto 32);
|
||||
alias bout_fifo_sel_in is bout_fifo_din(67 downto 64);
|
||||
alias bout_fifo_we_in is bout_fifo_din(68);
|
||||
alias bout_fifo_addr_out is bout_fifo_dout(31 downto 0);
|
||||
alias bout_fifo_data_out is bout_fifo_dout(63 downto 32);
|
||||
alias bout_fifo_sel_out is bout_fifo_dout(67 downto 64);
|
||||
alias bout_fifo_we_out is bout_fifo_dout(68);
|
||||
signal bus_dout : word_t;
|
||||
signal bus_dout_vld : std_logic;
|
||||
signal bus_dout_re : std_logic;
|
||||
|
||||
signal write_fifo_din : unsigned(67 downto 0);
|
||||
signal write_fifo_dout : unsigned(67 downto 0);
|
||||
signal write_fifo_re : std_logic;
|
||||
signal write_fifo_we : std_logic;
|
||||
signal write_fifo_full : std_logic;
|
||||
signal write_fifo_empty : std_logic;
|
||||
signal bus_cmd_rdy : std_logic;
|
||||
signal bus_cmd_we : std_logic;
|
||||
signal bus_cmd_cycle_en : std_logic;
|
||||
signal bus_cmd : bm_cmd_t;
|
||||
signal bus_cyc_complete : std_logic;
|
||||
|
||||
alias write_fifo_addr_in is write_fifo_din(31 downto 0);
|
||||
alias write_fifo_data_in is write_fifo_din(63 downto 32);
|
||||
alias write_fifo_sel_in is write_fifo_din(67 downto 64);
|
||||
alias write_fifo_addr_out is write_fifo_dout(31 downto 0);
|
||||
alias write_fifo_data_out is write_fifo_dout(63 downto 32);
|
||||
alias write_fifo_sel_out is write_fifo_dout(67 downto 64);
|
||||
signal i_bus_din_rdy : std_logic;
|
||||
signal i_bus_cmd_rdy : std_logic;
|
||||
signal i_bus_cmd_we : std_logic;
|
||||
signal i_bus_cmd_cycle_en : std_logic;
|
||||
signal i_bus_cmd : bm_cmd_t;
|
||||
|
||||
signal read_cycle : std_logic;
|
||||
signal i_tlb_rdy : std_logic;
|
||||
signal i_cache_rdy : std_logic;
|
||||
|
||||
signal d_bus_din_rdy : std_logic;
|
||||
signal d_bus_cmd_rdy : std_logic;
|
||||
signal d_bus_cmd_we : std_logic;
|
||||
signal d_bus_cmd_cycle_en : std_logic;
|
||||
signal d_bus_cmd : bm_cmd_t;
|
||||
|
||||
signal d_tlb_rdy : std_logic;
|
||||
signal d_cache_rdy : std_logic;
|
||||
|
||||
signal icache_bus_gnt : std_logic;
|
||||
signal dcache_bus_gnt : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
read_cyc_register:
|
||||
process(cpu_clk)
|
||||
CPU_CLK <= clk;
|
||||
RST <= RST_I;
|
||||
|
||||
biu_busy_state:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(cpu_clk) then
|
||||
if rising_edge(clk) then
|
||||
if RST_I = '1' then
|
||||
read_cycle <= '0';
|
||||
else
|
||||
read_cycle <= (dmem_mem_rd_gnt and CYC_O_dmem_rd)
|
||||
or (dcache_mem_gnt and CYC_O_dcache)
|
||||
or (icache_mem_gnt and CYC_O_icache);
|
||||
busy <= '1';
|
||||
elsif (i_tlb_rdy and i_cache_rdy and d_cache_rdy and d_tlb_rdy) = '1' then
|
||||
busy <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
MRDY_O <= not bin_fifo_full;
|
||||
CYC_O <= not bout_fifo_empty or read_cycle;
|
||||
STB_O <= not bout_fifo_empty;
|
||||
ADDR_O <= bout_fifo_addr_out;
|
||||
DAT_O <= bout_fifo_data_out;
|
||||
SEL_O <= bout_fifo_sel_out;
|
||||
WE_O <= bout_fifo_we_out;
|
||||
|
||||
cpu_imem_rdy <= not icache_busy;
|
||||
busy <= CYC_O_dmem_rd or dcache_busy or (write_fifo_full);
|
||||
cpu_dmem_rdy <= not busy;
|
||||
|
||||
inst_icache : icache
|
||||
inst_busmaster : entity work.busmaster_async
|
||||
GENERIC MAP
|
||||
(
|
||||
cache_size => icache_size, -- words
|
||||
line_size => icache_line -- words
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
CLK_I => cpu_clk,
|
||||
RST_I => RST_I,
|
||||
STB_O => STB_O_icache,
|
||||
CYC_O => CYC_O_icache,
|
||||
ADDR_O => ADDR_O_icache,
|
||||
MRDY_O => MRDY_O_icache,
|
||||
DAT_I => DAT,
|
||||
ACK_I => ACK,
|
||||
SRDY_I => SRDY_I_icache,
|
||||
ctrl => cop0_ctrl_in.icache,
|
||||
cpu_en => cpu_imem_en,
|
||||
cpu_addr => cpu_imem_addr,
|
||||
cpu_dout => cpu_imem_din,
|
||||
cpu_busy => icache_busy
|
||||
);
|
||||
|
||||
SRDY_I_icache <= bout_rdy and icache_mem_gnt;
|
||||
|
||||
inst_dcache : dcache
|
||||
GENERIC MAP
|
||||
(
|
||||
cache_size => dcache_size, -- words
|
||||
line_size => dcache_line -- words
|
||||
DATA_WIDTH => 32,
|
||||
FIFO_DEPTH => 16
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
CLK_I => cpu_clk,
|
||||
RST_I => RST_I,
|
||||
CYC_O => CYC_O_dcache,
|
||||
STB_O => STB_O_dcache,
|
||||
ADDR_O => ADDR_O_dcache,
|
||||
MRDY_O => MRDY_O_dcache,
|
||||
DAT_I => DAT,
|
||||
ACK_I => ACK,
|
||||
SRDY_I => SRDY_I_dcache,
|
||||
ctrl => cop0_ctrl_in.dcache,
|
||||
cpu_en => dcache_en,
|
||||
cpu_we => cpu_dmem_we,
|
||||
cpu_be => cpu_dmem_be,
|
||||
cpu_addr => cpu_dmem_addr,
|
||||
cpu_din => cpu_dmem_dout,
|
||||
cpu_dout => dcache_dout,
|
||||
cpu_busy => dcache_busy
|
||||
-- System signals
|
||||
rst => RST,
|
||||
clk => CPU_CLK,
|
||||
|
||||
cmd_cycle_finished => bus_cyc_complete,
|
||||
cmd_cycle_en => bus_cmd_cycle_en,
|
||||
|
||||
cmd_rdy => bus_cmd_rdy,
|
||||
cmd_we => bus_cmd_we,
|
||||
cmd_in => bus_cmd,
|
||||
|
||||
din_rdy => bus_din_rdy,
|
||||
din_we => bus_din_we,
|
||||
din => bus_din,
|
||||
|
||||
dout => bus_dout,
|
||||
dout_vld => bus_dout_vld,
|
||||
dout_re => bus_dout_re,
|
||||
|
||||
-- JBUS Master signals
|
||||
RST_I => RST_I,
|
||||
CLK_I => CLK_I,
|
||||
CYC_O => CYC_O,
|
||||
STB_O => STB_O,
|
||||
WE_O => WE_O,
|
||||
SEL_O => SEL_O,
|
||||
ACK_I => ACK_I,
|
||||
SRDY_I => SRDY_I,
|
||||
MRDY_O => MRDY_O,
|
||||
ADDR_O => ADDR_O,
|
||||
MDAT_I => MDAT_I,
|
||||
MDAT_O => MDAT_O
|
||||
);
|
||||
|
||||
SRDY_I_dcache <= bout_rdy and dcache_mem_gnt;
|
||||
|
||||
dcached <= '1' when cpu_dmem_addr(31 downto 29) /= "101" else '0';
|
||||
cpu_dmem_din <= dcache_dout when uncached_access = '0' else DAT_I_dmem_rd;
|
||||
dcache_en <= dcached and cpu_dmem_en and dcache_en2; -- or write_fifo_full);
|
||||
|
||||
-- Instantiate synchronous FIFO
|
||||
inst_bin_fifo: entity work.fifo_async
|
||||
inst_i_tlb : entity work.tlb
|
||||
GENERIC MAP
|
||||
(
|
||||
addr_width => 4,
|
||||
data_width => 32,
|
||||
do_last_read_update => true
|
||||
NUM_ENTRIES => TLB_NUM_ENTRIES,
|
||||
CACHE_KSEG1 => false,
|
||||
TRANSLATE_KSEG0_1 => TRANSLATE_KSEG0_1,
|
||||
USE_TLB => WITH_TLB
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
rst => RST_I,
|
||||
clk_w => CLK_I,
|
||||
clk_r => cpu_clk,
|
||||
we => bin_fifo_we,
|
||||
re => bin_fifo_re,
|
||||
fifo_full => bin_fifo_full,
|
||||
fifo_empty => bin_fifo_empty,
|
||||
fifo_afull => open,
|
||||
fifo_aempty => open,
|
||||
data_w => bin_fifo_din,
|
||||
data_r => bin_fifo_dout
|
||||
-- System signals
|
||||
rst => RST,
|
||||
clk => CPU_CLK,
|
||||
ce => '1',
|
||||
|
||||
rdy => i_tlb_rdy,
|
||||
|
||||
ctrl_in => ctrl_in.itlb_ctrl,
|
||||
ctrl_out => ctrl_out.itlb_ctrl,
|
||||
|
||||
query_in => ctrl_in.itlb_qry,
|
||||
query_out => ctrl_out.itlb_qry
|
||||
|
||||
);
|
||||
|
||||
bin_fifo_din <= DAT_I;
|
||||
DAT <= bin_fifo_dout;
|
||||
ACK <= not bin_fifo_empty;
|
||||
bin_fifo_we <= ACK_I;
|
||||
bin_fifo_re <= dmem_mem_rd_gnt or MRDY_O_icache or MRDY_O_dcache;
|
||||
|
||||
-- Instantiate synchronous FIFO
|
||||
inst_bout_fifo: entity work.fifo_async
|
||||
|
||||
inst_icache: entity work.icache
|
||||
GENERIC MAP
|
||||
(
|
||||
addr_width => 4,
|
||||
data_width => 69,
|
||||
do_last_read_update => false,
|
||||
add_extra_read_register => true
|
||||
CACHE_SIZE => ICACHE_SIZE,
|
||||
LINE_SIZE => ICACHE_LINE
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
rst => RST_I,
|
||||
clk_w => cpu_clk,
|
||||
clk_r => CLK_I,
|
||||
we => bout_fifo_we,
|
||||
re => bout_fifo_re,
|
||||
fifo_full => bout_fifo_full,
|
||||
fifo_empty => bout_fifo_empty,
|
||||
fifo_afull => open,
|
||||
fifo_aempty => open,
|
||||
data_w => bout_fifo_din,
|
||||
data_r => bout_fifo_dout
|
||||
rst => RST,
|
||||
clk => CPU_CLK,
|
||||
rdy => i_cache_rdy,
|
||||
|
||||
-- CPU control/data
|
||||
query_in => ctrl_in.icache_qry,
|
||||
query_out => ctrl_out.icache_qry,
|
||||
|
||||
-- Cache control
|
||||
ctrl_in => ctrl_in.icache,
|
||||
|
||||
-- busmaster data
|
||||
bus_din => bus_dout,
|
||||
bus_din_rdy => i_bus_din_rdy,
|
||||
bus_din_vld => bus_dout_vld,
|
||||
|
||||
-- busmaster command
|
||||
bus_cmd_rdy => i_bus_cmd_rdy,
|
||||
bus_cmd_we => i_bus_cmd_we,
|
||||
bus_cmd_cycle_en => i_bus_cmd_cycle_en,
|
||||
bus_cmd_out => i_bus_cmd,
|
||||
bus_cyc_complete => bus_cyc_complete
|
||||
);
|
||||
bout_rdy <= not bout_fifo_full;
|
||||
bout_fifo_re <= SRDY_I and not bin_fifo_full;
|
||||
|
||||
|
||||
bout_fifo_we <= STB_O_dmem_wr or STB_O_dmem_rd or STB_O_dcache or STB_O_icache;
|
||||
|
||||
bout_fifo_data_in <= DAT_O_dmem_wr when dmem_mem_wr_gnt = '1' else (others => '-');
|
||||
|
||||
bout_fifo_addr_in <= ADDR_O_dmem_wr when dmem_mem_wr_gnt = '1' else
|
||||
ADDR_O_dmem_rd when dmem_mem_rd_gnt = '1' else
|
||||
ADDR_O_dcache when dcache_mem_gnt = '1' else
|
||||
ADDR_O_icache when icache_mem_gnt = '1' else (others => '-');
|
||||
|
||||
bout_fifo_sel_in <= SEL_O_dmem_wr when dmem_mem_wr_gnt = '1' else
|
||||
SEL_O_dmem_rd when dmem_mem_rd_gnt = '1' else (others => '1');
|
||||
|
||||
bout_fifo_we_in <= '1' when dmem_mem_wr_gnt = '1' else '0';
|
||||
|
||||
-- Instantiate synchronous FIFO
|
||||
inst_write_fifo: entity work.fifo_sync
|
||||
inst_d_tlb : entity work.tlb
|
||||
GENERIC MAP
|
||||
(
|
||||
addr_width => 4,
|
||||
data_width => 68,
|
||||
do_last_read_update => true
|
||||
NUM_ENTRIES => TLB_NUM_ENTRIES,
|
||||
CACHE_KSEG1 => false,
|
||||
TRANSLATE_KSEG0_1 => TRANSLATE_KSEG0_1,
|
||||
USE_TLB => WITH_TLB
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
rst => RST_I,
|
||||
clk => cpu_clk,
|
||||
we => write_fifo_we,
|
||||
re => write_fifo_re,
|
||||
fifo_full => write_fifo_full,
|
||||
fifo_empty => write_fifo_empty,
|
||||
fifo_afull => open,
|
||||
fifo_aempty => open,
|
||||
data_w => write_fifo_din,
|
||||
data_r => write_fifo_dout
|
||||
-- System signals
|
||||
rst => RST,
|
||||
clk => CPU_CLK,
|
||||
ce => '1',
|
||||
|
||||
rdy => d_tlb_rdy,
|
||||
|
||||
ctrl_in => ctrl_in.dtlb_ctrl,
|
||||
ctrl_out => ctrl_out.dtlb_ctrl,
|
||||
|
||||
query_in => ctrl_in.dtlb_qry,
|
||||
query_out => ctrl_out.dtlb_qry
|
||||
|
||||
);
|
||||
|
||||
inst_dcache: entity work.dcache
|
||||
GENERIC MAP
|
||||
(
|
||||
CACHE_SIZE => DCACHE_SIZE,
|
||||
LINE_SIZE => DCACHE_LINE,
|
||||
WRITE_FIFO_SIZE => WRITE_FIFO_SIZE
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
rst => RST,
|
||||
clk => CPU_CLK,
|
||||
rdy => d_cache_rdy,
|
||||
|
||||
-- CPU control/data
|
||||
query_in => ctrl_in.dcache_qry,
|
||||
query_out => ctrl_out.dcache_qry,
|
||||
|
||||
-- Cache control
|
||||
ctrl_in => ctrl_in.dcache,
|
||||
|
||||
-- busmaster data
|
||||
bus_din => bus_dout,
|
||||
bus_din_rdy => d_bus_din_rdy,
|
||||
bus_din_vld => bus_dout_vld,
|
||||
|
||||
bus_dout => bus_din,
|
||||
bus_dout_vld => bus_din_we,
|
||||
bus_dout_rdy => bus_din_rdy,
|
||||
|
||||
-- busmaster command
|
||||
bus_cmd_rdy => d_bus_cmd_rdy,
|
||||
bus_cmd_we => d_bus_cmd_we,
|
||||
bus_cmd_cycle_en => d_bus_cmd_cycle_en,
|
||||
bus_cmd_out => d_bus_cmd,
|
||||
bus_cyc_complete => bus_cyc_complete
|
||||
);
|
||||
|
||||
CYC_O_dmem_wr <= not write_fifo_empty;
|
||||
DAT_O_dmem_wr <= write_fifo_data_out;
|
||||
ADDR_O_dmem_wr <= write_fifo_addr_out;
|
||||
SEL_O_dmem_wr <= write_fifo_sel_out;
|
||||
|
||||
write_fifo_data_in <= cpu_dmem_dout;
|
||||
write_fifo_addr_in <= cpu_dmem_addr;
|
||||
write_fifo_sel_in <= cpu_dmem_be;
|
||||
write_fifo_re <= STB_O_dmem_wr;
|
||||
write_fifo_we <= cpu_dmem_en and not busy and cpu_dmem_we;
|
||||
|
||||
dmem_rd_flags:
|
||||
process(cpu_clk)
|
||||
begin
|
||||
if rising_edge(cpu_clk) then
|
||||
uncached_access <= '0';
|
||||
if RST_I = '1' then
|
||||
CYC_O_dmem_rd <= '0';
|
||||
dcache_en2 <= '1';
|
||||
else
|
||||
if ACK = '1' and dmem_mem_rd_gnt = '1' then
|
||||
uncached_access <= '1';
|
||||
CYC_O_dmem_rd <= '0';
|
||||
dcache_en2 <= '1';
|
||||
end if;
|
||||
if cpu_dmem_en = '1' and busy = '0' and cpu_dmem_we = '0' then
|
||||
if dcached = '0' then
|
||||
CYC_O_dmem_rd <= '1';
|
||||
dcache_en2 <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
dmem_rd_data:
|
||||
process(cpu_clk)
|
||||
begin
|
||||
if rising_edge(cpu_clk) then
|
||||
if RST_I = '1' then
|
||||
DAT_I_dmem_rd <= (others => '0');
|
||||
elsif ACK = '1' and CYC_O_dmem_rd = '1' then
|
||||
DAT_I_dmem_rd <= DAT;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
dmem_rd_regs:
|
||||
process(cpu_clk)
|
||||
begin
|
||||
if rising_edge(cpu_clk) then
|
||||
if cpu_dmem_en = '1' and busy = '0' then
|
||||
ADDR_O_dmem_rd <= cpu_dmem_addr;
|
||||
SEL_O_dmem_rd <= cpu_dmem_be;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
bus_state_next:
|
||||
process(cpu_clk)
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(cpu_clk) then
|
||||
if rising_edge(clk) then
|
||||
if RST_I = '1' then
|
||||
s <= init;
|
||||
else
|
||||
@@ -456,61 +312,51 @@ bus_state_next:
|
||||
end process;
|
||||
|
||||
bus_state:
|
||||
process(s, CYC_O_icache, CYC_O_dcache, CYC_O_dmem_wr, CYC_O_dmem_rd, bout_rdy, ACK)
|
||||
process(s, i_bus_cmd_cycle_en, d_bus_cmd_cycle_en, i_bus_cmd_we, i_bus_cmd, d_bus_cmd_we, d_bus_cmd, bus_cyc_complete, i_bus_din_rdy, d_bus_din_rdy, bus_cmd_rdy)
|
||||
begin
|
||||
|
||||
icache_mem_gnt <= '0';
|
||||
dcache_mem_gnt <= '0';
|
||||
dmem_mem_rd_gnt <= '0';
|
||||
dmem_mem_wr_gnt <= '0';
|
||||
STB_O_dmem_rd <= '0';
|
||||
STB_O_dmem_wr <= '0';
|
||||
icache_bus_gnt <= '0';
|
||||
dcache_bus_gnt <= '0';
|
||||
|
||||
i_bus_cmd_rdy <= '0';
|
||||
d_bus_cmd_rdy <= '0';
|
||||
|
||||
bus_cmd_cycle_en <= '0';
|
||||
bus_cmd_we <= '0';
|
||||
bus_cmd <= i_bus_cmd;
|
||||
bus_dout_re <= '0';
|
||||
bus_idle <= '0';
|
||||
|
||||
sn <= s;
|
||||
case s is
|
||||
when init =>
|
||||
sn <= ready;
|
||||
when ready =>
|
||||
bus_idle <= '1';
|
||||
if CYC_O_dmem_wr = '1' then
|
||||
sn <= write_bus;
|
||||
elsif CYC_O_dmem_rd = '1' then
|
||||
sn <= read_bus;
|
||||
elsif CYC_O_icache = '1' then
|
||||
if i_bus_cmd_cycle_en = '1' then
|
||||
sn <= icache_bus_access;
|
||||
elsif CYC_O_dcache = '1' then
|
||||
elsif d_bus_cmd_cycle_en = '1' then
|
||||
sn <= dcache_bus_access;
|
||||
end if;
|
||||
when icache_bus_access =>
|
||||
icache_mem_gnt <= '1';
|
||||
if CYC_O_icache = '0' then
|
||||
icache_bus_gnt <= '1';
|
||||
i_bus_cmd_rdy <= bus_cmd_rdy;
|
||||
bus_cmd_cycle_en <= i_bus_cmd_cycle_en;
|
||||
bus_cmd_we <= i_bus_cmd_we;
|
||||
bus_dout_re <= i_bus_din_rdy;
|
||||
if i_bus_cmd_cycle_en = '0' then
|
||||
sn <= ready;
|
||||
end if;
|
||||
when dcache_bus_access =>
|
||||
dcache_mem_gnt <= '1';
|
||||
if CYC_O_dcache = '0' then
|
||||
dcache_bus_gnt <= '1';
|
||||
d_bus_cmd_rdy <= bus_cmd_rdy;
|
||||
bus_cmd_cycle_en <= d_bus_cmd_cycle_en;
|
||||
bus_cmd <= d_bus_cmd;
|
||||
bus_cmd_we <= d_bus_cmd_we;
|
||||
bus_dout_re <= d_bus_din_rdy;
|
||||
if d_bus_cmd_cycle_en = '0' then
|
||||
sn <= ready;
|
||||
end if;
|
||||
when write_bus =>
|
||||
dmem_mem_wr_gnt <= '1';
|
||||
if CYC_O_dmem_wr = '1' then
|
||||
if bout_rdy = '1' then
|
||||
STB_O_dmem_wr <= '1';
|
||||
end if;
|
||||
else
|
||||
sn <= ready;
|
||||
end if;
|
||||
when read_bus =>
|
||||
dmem_mem_rd_gnt <= '1';
|
||||
if bout_rdy = '1' then
|
||||
STB_O_dmem_rd <= '1';
|
||||
sn <= read_finish;
|
||||
end if;
|
||||
when read_finish =>
|
||||
dmem_mem_rd_gnt <= '1';
|
||||
if ACK = '1' then
|
||||
sn <= ready;
|
||||
end if;
|
||||
when others =>
|
||||
sn <= ready;
|
||||
end case;
|
||||
@@ -518,9 +364,9 @@ bus_state:
|
||||
end process;
|
||||
|
||||
bus_timeout_counter:
|
||||
process(cpu_clk)
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(cpu_clk) then
|
||||
if rising_edge(clk) then
|
||||
if bus_idle = '0' then
|
||||
if bus_timeout_cnt /= 0 then
|
||||
bus_timeout_cnt <= bus_timeout_cnt - 1;
|
||||
@@ -535,15 +381,15 @@ bus_timeout_counter:
|
||||
end process;
|
||||
|
||||
bus_err:
|
||||
process(cpu_clk)
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(cpu_clk) then
|
||||
if rising_edge(clk) then
|
||||
if RST_I = '1' then
|
||||
cpu_imem_err <= '0';
|
||||
cpu_dmem_err <= '0';
|
||||
imem_err <= '0';
|
||||
dmem_err <= '0';
|
||||
elsif bus_timeout = '1' then
|
||||
cpu_imem_err <= icache_mem_gnt;
|
||||
cpu_dmem_err <= dcache_mem_gnt or dmem_mem_wr_gnt or dmem_mem_rd_gnt;
|
||||
imem_err <= icache_bus_gnt;
|
||||
dmem_err <= dcache_bus_gnt;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
@@ -0,0 +1,340 @@
|
||||
--------------------------------------------------------------------------
|
||||
-- Project: JIPS, a portable 32-bit RISC CPU written in VHDL
|
||||
-- This file: JIPS top file
|
||||
--
|
||||
-- Copyright (C) 2008 J. Ahrensfeld
|
||||
--
|
||||
-- This program is free software: you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation, either version 3 of the License, or
|
||||
-- (at your option) any later version.
|
||||
--
|
||||
-- This program 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 General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
--
|
||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||
--
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
LIBRARY IEEE;
|
||||
USE IEEE.MATH_REAL.ALL;
|
||||
USE IEEE.STD_LOGIC_1164.ALL;
|
||||
USE IEEE.NUMERIC_STD.ALL;
|
||||
|
||||
library work;
|
||||
use work.mips_types.all;
|
||||
use work.mips_util_pkg.all;
|
||||
|
||||
ENTITY cam IS
|
||||
Generic
|
||||
(
|
||||
NUM_ENTRIES : natural := 32;
|
||||
DATA_WIDTH : natural := 20;
|
||||
CAM_RAM_MAX_WIDTH : natural := 15
|
||||
);
|
||||
Port
|
||||
(
|
||||
rst : in STD_LOGIC;
|
||||
clk : in STD_LOGIC;
|
||||
clk_rd : in STD_LOGIC;
|
||||
|
||||
rdy : out STD_LOGIC;
|
||||
|
||||
re : in STD_LOGIC;
|
||||
we : in STD_LOGIC;
|
||||
vld : in STD_LOGIC;
|
||||
addr : in unsigned (lg2(NUM_ENTRIES)-1 downto 0);
|
||||
tag_wr : in unsigned (DATA_WIDTH-1 downto 0);
|
||||
|
||||
tag_rd : in unsigned (DATA_WIDTH-1 downto 0);
|
||||
hit : out unsigned (NUM_ENTRIES-1 downto 0);
|
||||
hit_vld : out STD_LOGIC
|
||||
|
||||
);
|
||||
END cam;
|
||||
|
||||
ARCHITECTURE behavior OF cam IS
|
||||
|
||||
type debug_t is record
|
||||
num_cam_rams : integer;
|
||||
cam_ram_data_width : integer;
|
||||
cam_ram_addr_width : integer;
|
||||
end record;
|
||||
|
||||
signal debug : debug_t;
|
||||
|
||||
constant NUM_BLOCKS : integer := integer(real(DATA_WIDTH)/real(CAM_RAM_MAX_WIDTH-lg2(NUM_ENTRIES)));
|
||||
constant BLOCK_ADDR_WIDTH : integer := CAM_RAM_MAX_WIDTH - lg2(NUM_ENTRIES);
|
||||
|
||||
type state_t is (init, ready, clear);
|
||||
signal state : state_t;
|
||||
signal state_next : state_t;
|
||||
|
||||
type pipe_stage_t is record
|
||||
re : std_logic;
|
||||
we : std_logic;
|
||||
vld : std_logic;
|
||||
addr : unsigned (lg2(NUM_ENTRIES)-1 downto 0);
|
||||
data : unsigned (DATA_WIDTH-1 downto 0);
|
||||
vld_cam : unsigned (NUM_ENTRIES-1 downto 0);
|
||||
end record;
|
||||
|
||||
signal pipe0 : pipe_stage_t;
|
||||
signal pipe1 : pipe_stage_t;
|
||||
signal pipe2 : pipe_stage_t;
|
||||
signal pipe3 : pipe_stage_t;
|
||||
signal pipe0_rd : pipe_stage_t;
|
||||
signal pipe1_rd : pipe_stage_t;
|
||||
signal pipe2_rd : pipe_stage_t;
|
||||
signal pipe3_rd : pipe_stage_t;
|
||||
signal busy : std_logic;
|
||||
signal vld_cam : unsigned (NUM_ENTRIES-1 downto 0);
|
||||
|
||||
signal cam_ram_re : std_logic;
|
||||
signal cam_ram_we : std_logic;
|
||||
|
||||
type cam_ram_array_t is array (0 to NUM_BLOCKS-1) of unsigned (NUM_ENTRIES-1 downto 0);
|
||||
signal cam_ram_din : cam_ram_array_t;
|
||||
signal cam_ram_dout : cam_ram_array_t;
|
||||
signal cam_ram_result : unsigned (NUM_ENTRIES-1 downto 0);
|
||||
|
||||
signal cam_ram_addr_wr : unsigned (DATA_WIDTH-1 downto 0);
|
||||
signal cam_ram_addr_rd : unsigned (DATA_WIDTH-1 downto 0);
|
||||
|
||||
signal track_ram_re : std_logic;
|
||||
signal track_ram_we : std_logic;
|
||||
signal track_ram_addr_wr : unsigned (lg2(NUM_ENTRIES)-1 downto 0);
|
||||
signal track_ram_addr_rd : unsigned (lg2(NUM_ENTRIES)-1 downto 0);
|
||||
signal track_ram_din : unsigned (DATA_WIDTH downto 0);
|
||||
signal track_ram_dout : unsigned (DATA_WIDTH downto 0);
|
||||
|
||||
signal clear_data : unsigned (DATA_WIDTH-1 downto 0);
|
||||
signal clear_addr : unsigned (BLOCK_ADDR_WIDTH-1 downto 0);
|
||||
signal clear_count_en : std_logic;
|
||||
signal clear_count_rdy : std_logic;
|
||||
signal over_write : std_logic;
|
||||
|
||||
|
||||
begin
|
||||
|
||||
over_write <= track_ram_dout(DATA_WIDTH) and pipe1.we;
|
||||
rdy <= not busy;
|
||||
hit_vld <= pipe1.re;
|
||||
|
||||
debug.num_cam_rams <= NUM_BLOCKS;
|
||||
debug.cam_ram_addr_width <= BLOCK_ADDR_WIDTH;
|
||||
debug.cam_ram_data_width <= NUM_ENTRIES;
|
||||
|
||||
track_ram_re <= '1';
|
||||
track_ram_we <= clear_count_en or pipe1.we;
|
||||
track_ram_addr_rd <= pipe0.addr;
|
||||
track_ram_addr_wr <= clear_data(lg2(NUM_ENTRIES)-1 downto 0) when clear_count_en = '1' else pipe1.addr;
|
||||
track_ram_din <= (others => '0') when clear_count_en = '1' else (pipe1.vld & pipe1.data);
|
||||
|
||||
cam_ram_re <= re when pipe1_rd.we = '0' else not busy;
|
||||
cam_ram_we <= clear_count_en or (pipe2.we and pipe2.vld) or over_write;
|
||||
cam_ram_addr_rd <= tag_rd when pipe1_rd.we = '0' else pipe1_rd.data; -- clk_rd same edge of clk
|
||||
-- cam_ram_addr_rd <= tag_rd when pipe2_rd.we = '0' else pipe2_rd.data; -- clk_rd opposite edge of clk
|
||||
cam_ram_addr_wr <= clear_data when clear_count_en = '1' else track_ram_dout(DATA_WIDTH-1 downto 0) when over_write = '1' else pipe2.data;
|
||||
|
||||
combine_cam_ram_din:
|
||||
process(clear_count_en, over_write, pipe2, cam_ram_dout)
|
||||
begin
|
||||
for i in 0 to NUM_BLOCKS-1 loop
|
||||
if clear_count_en = '1' or over_write = '1' then
|
||||
cam_ram_din(i) <= (others => '0');
|
||||
else
|
||||
cam_ram_din(i) <= (((NUM_ENTRIES-1 downto 0 => pipe2.vld) and pipe2.vld_cam) xor cam_ram_dout(i));
|
||||
end if;
|
||||
end loop;
|
||||
end process;
|
||||
|
||||
combine_clear_addr:
|
||||
process(clear_addr)
|
||||
begin
|
||||
for i in 0 to NUM_BLOCKS-1 loop
|
||||
clear_data((i+1)*BLOCK_ADDR_WIDTH-1 downto i*BLOCK_ADDR_WIDTH) <= clear_addr;
|
||||
end loop;
|
||||
end process;
|
||||
|
||||
combine_cam_ram_result:
|
||||
process(cam_ram_dout)
|
||||
variable result : unsigned (NUM_ENTRIES-1 downto 0);
|
||||
begin
|
||||
result := (others => '0');
|
||||
|
||||
for i in 0 to NUM_BLOCKS-1 loop
|
||||
result := result or cam_ram_dout(i);
|
||||
end loop;
|
||||
|
||||
cam_ram_result <= result;
|
||||
end process;
|
||||
|
||||
pipe0.re <= re and not busy;
|
||||
pipe0.vld <= vld;
|
||||
pipe0.we <= we and not busy;
|
||||
pipe0.addr <= addr;
|
||||
pipe0.data <= tag_wr;
|
||||
pipe0.vld_cam <= vld_cam;
|
||||
|
||||
pipe_line_wr:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
pipe3.we <= '0';
|
||||
pipe2.we <= '0';
|
||||
pipe1.we <= '0';
|
||||
else
|
||||
pipe3 <= pipe2;
|
||||
pipe2 <= pipe1;
|
||||
pipe1 <= pipe0;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
pipe0_rd <= pipe0;
|
||||
pipe_line_rd:
|
||||
process(clk_rd)
|
||||
begin
|
||||
if rising_edge(clk_rd) then
|
||||
if rst = '1' then
|
||||
pipe3_rd.we <= '0';
|
||||
pipe2_rd.we <= '0';
|
||||
pipe1_rd.we <= '0';
|
||||
else
|
||||
pipe3_rd <= pipe2_rd;
|
||||
pipe2_rd <= pipe1_rd;
|
||||
pipe1_rd <= pipe0_rd;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
combine_cam_hit:
|
||||
process(cam_ram_dout, clear_count_en)
|
||||
variable result : unsigned (NUM_ENTRIES-1 downto 0);
|
||||
begin
|
||||
result := (others => not clear_count_en);
|
||||
|
||||
for i in 0 to NUM_BLOCKS-1 loop
|
||||
result := result and cam_ram_dout(i);
|
||||
end loop;
|
||||
|
||||
hit <= result;
|
||||
end process;
|
||||
|
||||
vld_decode:
|
||||
process(vld, addr)
|
||||
begin
|
||||
vld_cam <= (others => '0');
|
||||
vld_cam(to_integer(addr)) <= vld;
|
||||
end process;
|
||||
|
||||
|
||||
inst_track_ram: entity work.dpram_1w1r2c_ra
|
||||
GENERIC MAP
|
||||
(
|
||||
addr_width => lg2(NUM_ENTRIES),
|
||||
data_width => DATA_WIDTH+1
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
clk_a => clk,
|
||||
clk_b => clk,
|
||||
we_a => track_ram_we,
|
||||
re_b => '1',
|
||||
addr_a => track_ram_addr_wr,
|
||||
addr_b => track_ram_addr_rd,
|
||||
din_a => track_ram_din,
|
||||
dout_b => track_ram_dout
|
||||
);
|
||||
|
||||
gen_cam_ram:
|
||||
for i in 0 to NUM_BLOCKS-1 generate
|
||||
|
||||
inst_cam_ram: entity work.dpram_1w1r2c_ra
|
||||
GENERIC MAP
|
||||
(
|
||||
addr_width => BLOCK_ADDR_WIDTH,
|
||||
data_width => NUM_ENTRIES
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
clk_a => clk,
|
||||
clk_b => clk_rd,
|
||||
we_a => cam_ram_we,
|
||||
re_b => cam_ram_re,
|
||||
addr_a => cam_ram_addr_wr((i+1)*BLOCK_ADDR_WIDTH-1 downto i*BLOCK_ADDR_WIDTH),
|
||||
addr_b => cam_ram_addr_rd((i+1)*BLOCK_ADDR_WIDTH-1 downto i*BLOCK_ADDR_WIDTH),
|
||||
din_a => cam_ram_din(i),
|
||||
dout_b => cam_ram_dout(i)
|
||||
);
|
||||
|
||||
end generate;
|
||||
|
||||
cam_state_next:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
state <= init;
|
||||
else
|
||||
state <= state_next;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
cam_state:
|
||||
process(state, clear_count_rdy, over_write)
|
||||
begin
|
||||
busy <= over_write;
|
||||
clear_count_en <= '0';
|
||||
|
||||
state_next <= state;
|
||||
|
||||
case state is
|
||||
|
||||
when init =>
|
||||
busy <= '1';
|
||||
state_next <= clear;
|
||||
|
||||
when clear =>
|
||||
busy <= '1';
|
||||
clear_count_en <= '1';
|
||||
if clear_count_rdy = '1' then
|
||||
state_next <= ready;
|
||||
end if;
|
||||
|
||||
when ready =>
|
||||
|
||||
when others =>
|
||||
state_next <= ready;
|
||||
|
||||
end case;
|
||||
|
||||
end process;
|
||||
|
||||
clear_counter:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if clear_count_en = '0' then
|
||||
clear_count_rdy <= '0';
|
||||
clear_addr <= (BLOCK_ADDR_WIDTH-1 downto 0 => '1');
|
||||
else
|
||||
if clear_addr /= (BLOCK_ADDR_WIDTH-1 downto 0 => '0') then
|
||||
clear_addr <= clear_addr - 1;
|
||||
else
|
||||
clear_count_rdy <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
end behavior;
|
||||
+599
-281
File diff suppressed because it is too large
Load Diff
@@ -26,33 +26,46 @@ USE IEEE.STD_LOGIC_1164.ALL;
|
||||
USE IEEE.NUMERIC_STD.ALL;
|
||||
|
||||
library work;
|
||||
use work.mips_util_pkg.all;
|
||||
use work.mips_types.all;
|
||||
use work.busmaster_types.all;
|
||||
|
||||
ENTITY dcache IS
|
||||
Generic
|
||||
(
|
||||
cache_size : natural := 2048; -- words
|
||||
line_size : natural := 8 -- words
|
||||
CACHE_SIZE : natural := 1024; -- words
|
||||
LINE_SIZE : natural := 8; -- words
|
||||
WRITE_FIFO_SIZE : natural := 4
|
||||
);
|
||||
Port
|
||||
(
|
||||
RST_I : in STD_LOGIC;
|
||||
CLK_I : in STD_LOGIC;
|
||||
ACK_I : in STD_LOGIC;
|
||||
SRDY_I : in STD_LOGIC;
|
||||
MRDY_O : out STD_LOGIC;
|
||||
ADDR_O : out word_t;
|
||||
DAT_I : in word_t;
|
||||
STB_O : out STD_LOGIC;
|
||||
CYC_O : out STD_LOGIC;
|
||||
ctrl : in cache_ctrl_t;
|
||||
cpu_en : in STD_LOGIC;
|
||||
cpu_we : in STD_LOGIC;
|
||||
cpu_be : in unsigned(3 downto 0);
|
||||
cpu_addr : in word_t;
|
||||
cpu_din : in word_t;
|
||||
cpu_dout : out word_t;
|
||||
cpu_busy : out STD_LOGIC
|
||||
rst : in STD_LOGIC;
|
||||
clk : in STD_LOGIC;
|
||||
rdy : out STD_LOGIC;
|
||||
|
||||
-- CPU control/data
|
||||
query_in : in dcache_query_in_t;
|
||||
query_out : out dcache_query_out_t;
|
||||
|
||||
-- Cache control
|
||||
ctrl_in : in cache_ctrl_t;
|
||||
|
||||
-- busmaster data
|
||||
bus_din : in word_t;
|
||||
bus_din_rdy : out std_logic;
|
||||
bus_din_vld : in std_logic;
|
||||
|
||||
bus_dout : out word_t;
|
||||
bus_dout_vld : out std_logic;
|
||||
bus_dout_rdy : in std_logic;
|
||||
|
||||
-- busmaster command
|
||||
bus_cmd_rdy : in std_logic;
|
||||
bus_cmd_we : out std_logic;
|
||||
bus_cmd_cycle_en : out std_logic;
|
||||
bus_cmd_out : out bm_cmd_t;
|
||||
bus_cyc_complete : in std_logic
|
||||
|
||||
);
|
||||
END dcache;
|
||||
|
||||
@@ -83,27 +96,26 @@ COMPONENT dpram_2w2r2c_ra is
|
||||
END COMPONENT;
|
||||
|
||||
constant addr_width : natural := 32;
|
||||
constant word_index_width : natural := lg2(line_size);
|
||||
constant cache_index_width : natural := lg2(cache_size) - word_index_width;
|
||||
constant tag_width : natural := addr_width - word_index_width - cache_index_width - 2;
|
||||
constant tag_parity_width : natural := 3;
|
||||
constant tag_ram_data_width : natural := 1 + tag_parity_width + tag_width;
|
||||
constant word_index_width : natural := lg2(LINE_SIZE);
|
||||
constant cache_index_width : natural := lg2(CACHE_SIZE) - word_index_width;
|
||||
constant tag_width : natural := addr_width - lg2(CACHE_SIZE) - 2;
|
||||
constant tag_ram_data_width : natural := 1 + tag_width + lg2(TLB_NUM_ENTRIES)+1;
|
||||
constant tag_ram_addr_width : natural := cache_index_width;
|
||||
|
||||
subtype tag_ram_data_t is unsigned (tag_ram_data_width-1 downto 0);
|
||||
|
||||
type dcache_entry_t is record
|
||||
valid : std_logic;
|
||||
tv_p : unsigned(tag_parity_width-1 downto 0);
|
||||
tag : unsigned(tag_width-1 downto 0);
|
||||
valid : std_logic;
|
||||
tag : unsigned(tag_width-1 downto 0);
|
||||
idx : unsigned(lg2(TLB_NUM_ENTRIES) downto 0);
|
||||
end record;
|
||||
|
||||
function to_dcache_entry(x : tag_ram_data_t) return dcache_entry_t is
|
||||
variable result : dcache_entry_t;
|
||||
begin
|
||||
result.valid := x(0);
|
||||
result.tv_p := x(3 downto 1);
|
||||
result.tag := x(tag_width+3 downto 4);
|
||||
result.tag := x(tag_width downto 1);
|
||||
result.idx := x(lg2(TLB_NUM_ENTRIES)+tag_width+1 downto tag_width+1);
|
||||
|
||||
return result;
|
||||
end to_dcache_entry;
|
||||
@@ -111,170 +123,314 @@ END COMPONENT;
|
||||
function to_tag_ram_data(x : dcache_entry_t) return tag_ram_data_t is
|
||||
variable result : tag_ram_data_t;
|
||||
begin
|
||||
result(0) := x.valid;
|
||||
result(3 downto 1) := x.tv_p;
|
||||
result(tag_width+3 downto 4) := x.tag;
|
||||
result(0) := x.valid;
|
||||
result(tag_width downto 1) := x.tag;
|
||||
result(lg2(TLB_NUM_ENTRIES)+tag_width+1 downto tag_width+1) := x.idx;
|
||||
|
||||
return result;
|
||||
end to_tag_ram_data;
|
||||
|
||||
type cache_state_t is (init, ready, invalidate_init, invalidate, flush, mem_request, mem_access, mem_data, rd_cache);
|
||||
signal s, sn : cache_state_t;
|
||||
function to_word_index(x : word_t) return unsigned is
|
||||
variable result : unsigned(word_index_width-1 downto 0);
|
||||
begin
|
||||
result := x(word_index_width+1 downto 2);
|
||||
|
||||
return result;
|
||||
|
||||
end to_word_index;
|
||||
|
||||
signal cache_req : std_logic;
|
||||
signal cache_ack : std_logic;
|
||||
signal cache_busy : std_logic;
|
||||
signal cache_hit : std_logic;
|
||||
signal tag_match : std_logic;
|
||||
signal cache_hit_inv : std_logic;
|
||||
signal tag_match_inv : std_logic;
|
||||
|
||||
signal request_addr : unsigned(addr_width-1 downto 0);
|
||||
signal fill_addr : unsigned(addr_width-1 downto 0);
|
||||
|
||||
signal cache_index_inv : unsigned(cache_index_width-1 downto 0);
|
||||
signal tag_inv : unsigned(tag_width-1 downto 0);
|
||||
signal tag_reg_inv : unsigned(tag_width-1 downto 0);
|
||||
|
||||
signal cache_entry_in : dcache_entry_t;
|
||||
signal cache_entry_out : dcache_entry_t;
|
||||
signal cache_entry_out_inv : dcache_entry_t;
|
||||
signal cpu_data_ram_addr : unsigned(lg2(cache_size)-1 downto 0);
|
||||
signal cpu_data_ram_dout : word_t;
|
||||
signal cpu_data_reg : word_t;
|
||||
signal cpu_be_reg : unsigned(3 downto 0);
|
||||
signal cpu_we_reg : std_logic;
|
||||
signal ctrl_data_ram_addr : unsigned(lg2(cache_size)-1 downto 0);
|
||||
signal ctrl_data_ram_we : unsigned(3 downto 0);
|
||||
signal cpu_data_ram_we : unsigned(3 downto 0);
|
||||
signal cpu_we2 : std_logic;
|
||||
function to_cache_index(x : word_t) return unsigned is
|
||||
variable result : unsigned(cache_index_width-1 downto 0);
|
||||
begin
|
||||
result := x(cache_index_width+word_index_width+1 downto word_index_width+2);
|
||||
|
||||
return result;
|
||||
|
||||
end to_cache_index;
|
||||
|
||||
signal tag_ram_addr_rd : unsigned(cache_index_width-1 downto 0);
|
||||
signal tag_ram_dout : tag_ram_data_t;
|
||||
signal tag_ram_dout_inv : tag_ram_data_t;
|
||||
signal tag_ram_addr_wr : unsigned(cache_index_width-1 downto 0);
|
||||
signal tag_ram_din : tag_ram_data_t;
|
||||
signal tag_ram_we : std_logic;
|
||||
|
||||
signal fill_count : natural range 0 to 2**word_index_width-1;
|
||||
signal fill_count_en : std_logic;
|
||||
signal fill_count_rdy : std_logic;
|
||||
signal flush_load_en : std_logic;
|
||||
signal flush_addr_preset : unsigned(cache_index_width-1 downto 0);
|
||||
signal flush_count_preset : natural range 0 to 2**cache_index_width-1;
|
||||
signal flush_addr : unsigned(cache_index_width-1 downto 0);
|
||||
signal flush_count : natural range 0 to 2**cache_index_width-1;
|
||||
signal flush_count_en : std_logic;
|
||||
signal flush_count_rdy : std_logic;
|
||||
signal request_count : natural range 0 to 2**word_index_width-1;
|
||||
signal request_count_en : std_logic;
|
||||
signal request_count_rdy : std_logic;
|
||||
signal was_miss : std_logic;
|
||||
signal invalidate_all : std_logic;
|
||||
signal invalidate_ack : std_logic;
|
||||
signal invalidate_en : std_logic;
|
||||
signal invalidate_req : std_logic;
|
||||
signal cpu_hit_we : std_logic;
|
||||
signal instant_raw : std_logic;
|
||||
signal hit_cache_index : unsigned(cache_index_width-1 downto 0);
|
||||
function to_tag(x : word_t) return unsigned is
|
||||
variable result : unsigned(tag_width-1 downto 0);
|
||||
begin
|
||||
result := x(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2);
|
||||
|
||||
return result;
|
||||
|
||||
end to_tag;
|
||||
|
||||
signal DAT_I_r : word_t;
|
||||
signal ACK_I_r : std_logic;
|
||||
|
||||
alias cpu_word_index is cpu_addr(word_index_width+1 downto 2);
|
||||
alias cpu_cache_index is cpu_addr(cache_index_width+word_index_width+1 downto word_index_width+2);
|
||||
alias cpu_tag is cpu_addr(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2);
|
||||
|
||||
alias fill_word_index is fill_addr(word_index_width+1 downto 2);
|
||||
alias fill_cache_index is fill_addr(cache_index_width+word_index_width+1 downto word_index_width+2);
|
||||
alias fill_tag is fill_addr(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2);
|
||||
|
||||
alias req_word_index is request_addr(word_index_width+1 downto 2);
|
||||
alias req_cache_index is request_addr(cache_index_width+word_index_width+1 downto word_index_width+2);
|
||||
alias req_tag is request_addr(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2);
|
||||
type cache_busy_state_t is (init, ready, busy);
|
||||
signal cache_busy_state, cache_busy_state_next : cache_busy_state_t;
|
||||
|
||||
type cache_ctrl_state_t is (init, ready, invalidate, invalidate_post, flush, bus_request, mem_read, mem_read_single, mem_read_data, mem_read_data_single, rd_cache, upd_cache, wait_write_thru);
|
||||
signal cache_ctrl_state, cache_ctrl_state_next : cache_ctrl_state_t;
|
||||
|
||||
type debug_t is record
|
||||
ready : std_logic;
|
||||
req_strobe : std_logic;
|
||||
req_read : std_logic;
|
||||
req_write : std_logic;
|
||||
req_va : word_t;
|
||||
req_pa : word_t;
|
||||
dout_reg : word_t;
|
||||
din_reg : word_t;
|
||||
end record;
|
||||
|
||||
signal debug : debug_t;
|
||||
|
||||
signal req_strobe : std_logic;
|
||||
signal cache_req : std_logic;
|
||||
signal cache_req_rd : std_logic;
|
||||
signal cache_req_wr : std_logic;
|
||||
signal cache_rdy : std_logic;
|
||||
signal cache_hit : std_logic;
|
||||
signal read_rdy : std_logic;
|
||||
signal write_rdy : std_logic;
|
||||
signal request_va : word_t;
|
||||
signal request_pa : word_t;
|
||||
signal request_nc : std_logic;
|
||||
|
||||
signal tag_match : std_logic;
|
||||
signal cache_hit_inv : std_logic;
|
||||
signal tag_match_inv : std_logic;
|
||||
|
||||
signal mem_fetch_req : std_logic;
|
||||
signal mem_fetch_ack : std_logic;
|
||||
signal single_read_en : std_logic;
|
||||
signal single_read_set : std_logic;
|
||||
signal single_read_reg_vld : std_logic;
|
||||
|
||||
signal cache_index_inv : unsigned(cache_index_width-1 downto 0);
|
||||
signal tag_inv : unsigned(tag_width-1 downto 0);
|
||||
signal tag_reg_inv : unsigned(tag_width-1 downto 0);
|
||||
|
||||
signal cache_entry_in : dcache_entry_t;
|
||||
signal cache_entry_out : dcache_entry_t;
|
||||
signal cache_entry_out_inv : dcache_entry_t;
|
||||
signal data_ram_addr : unsigned(lg2(CACHE_SIZE)-1 downto 0);
|
||||
signal data_ram_dout : word_t;
|
||||
signal din_reg : word_t;
|
||||
signal be_reg : unsigned(3 downto 0);
|
||||
signal ctrl_data_ram_addr : unsigned(lg2(CACHE_SIZE)-1 downto 0);
|
||||
signal ctrl_data_ram_we : unsigned(3 downto 0);
|
||||
signal data_ram_we : unsigned(3 downto 0);
|
||||
signal single_read_reg : word_t;
|
||||
signal cache_dout : word_t;
|
||||
|
||||
signal tag_ram_addr_rd : unsigned(cache_index_width-1 downto 0);
|
||||
signal tag_ram_dout : tag_ram_data_t;
|
||||
signal tag_ram_dout_inv : tag_ram_data_t;
|
||||
signal tag_ram_addr_wr : unsigned(cache_index_width-1 downto 0);
|
||||
signal tag_ram_din : tag_ram_data_t;
|
||||
signal tag_ram_we : std_logic;
|
||||
|
||||
signal fill_count : natural range 0 to 2**word_index_width-1;
|
||||
signal fill_count_en : std_logic;
|
||||
signal fill_count_rdy : std_logic;
|
||||
signal flush_count : natural range 0 to 2**cache_index_width-1;
|
||||
signal flush_count_rst : std_logic;
|
||||
signal flush_count_en : std_logic;
|
||||
signal flush_count_rdy : std_logic;
|
||||
signal request_count : natural range 0 to 2**word_index_width-1;
|
||||
signal request_count_en : std_logic;
|
||||
signal request_count_rdy : std_logic;
|
||||
signal ram_read_en : std_logic;
|
||||
signal was_miss : std_logic;
|
||||
signal invalidate_all : std_logic;
|
||||
signal invalidate_ack : std_logic;
|
||||
signal invalidate_en : std_logic;
|
||||
signal invalidate_req : std_logic;
|
||||
signal write_hit : std_logic;
|
||||
signal instant_raw : std_logic;
|
||||
signal ram_write_en : std_logic;
|
||||
signal fill_word_index : unsigned(word_index_width-1 downto 0);
|
||||
signal req_word_index : unsigned(word_index_width-1 downto 0);
|
||||
signal hit_cache_index : unsigned(cache_index_width-1 downto 0);
|
||||
|
||||
signal write_fifo_din : unsigned(67 downto 0);
|
||||
signal write_fifo_dout : unsigned(67 downto 0);
|
||||
signal write_fifo_re : std_logic;
|
||||
signal write_fifo_we : std_logic;
|
||||
signal write_fifo_full : std_logic;
|
||||
signal write_fifo_empty : std_logic;
|
||||
signal write_data_avail : std_logic;
|
||||
signal read_write_buffer : std_logic;
|
||||
|
||||
alias write_fifo_addr_in is write_fifo_din(31 downto 0);
|
||||
alias write_fifo_data_in is write_fifo_din(63 downto 32);
|
||||
alias write_fifo_sel_in is write_fifo_din(67 downto 64);
|
||||
alias write_fifo_addr_out is write_fifo_dout(31 downto 0);
|
||||
alias write_fifo_data_out is write_fifo_dout(63 downto 32);
|
||||
alias write_fifo_sel_out is write_fifo_dout(67 downto 64);
|
||||
|
||||
signal write_through_en : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
cache_index_inv <= ctrl.inv_addr(cache_index_width+word_index_width+1 downto word_index_width+2);
|
||||
tag_inv <= ctrl.inv_addr(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2);
|
||||
-- Print info
|
||||
assert false report "addr_width = " & natural'image(addr_width) & "." severity note;
|
||||
assert false report "tag_width = " & natural'image(tag_width) & "." severity note;
|
||||
assert false report "word_index_width = " & natural'image(word_index_width) & "." severity note;
|
||||
assert false report "cache_index_width = " & natural'image(cache_index_width) & "." severity note;
|
||||
|
||||
cpu_hit_we <= cpu_we2 and cache_hit;
|
||||
cache_index_inv <= ctrl_in.inv_addr(cache_index_width+word_index_width+1 downto word_index_width+2);
|
||||
tag_inv <= ctrl_in.inv_addr(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2);
|
||||
|
||||
bus_din_rdy <= fill_count_en or single_read_en;
|
||||
bus_cmd_out.addr <= write_fifo_addr_out when read_write_buffer = '1' else to_tag(request_pa) & to_cache_index(request_pa) & req_word_index & "00";
|
||||
bus_cmd_out.rw <= read_write_buffer;
|
||||
bus_cmd_out.sel <= write_fifo_sel_out when read_write_buffer = '1' else (others => '1');
|
||||
bus_dout <= write_fifo_data_out;
|
||||
bus_dout_vld <= read_write_buffer and write_data_avail;
|
||||
|
||||
-- tlb_query_out.vld <= cache_req;
|
||||
-- tlb_query_out.vaddr <= request_va;
|
||||
-- tlb_query_out.write <= cache_req_wr;
|
||||
-- tlb_query_out.vld <= req_strobe;
|
||||
-- tlb_query_out.vaddr <= query_in.addr;
|
||||
-- tlb_query_out.idx <= cache_entry_out.idx;
|
||||
-- tlb_query_out.write <= query_in.we;
|
||||
|
||||
data_in_register:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
ACK_I_r <= ACK_I;
|
||||
if ACK_I = '1' then
|
||||
DAT_I_r <= DAT_I;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
request_pa <= request_va;
|
||||
|
||||
write_hit <= cache_req_wr and cache_hit; -- and not tlb_query_in.exc;
|
||||
|
||||
fill_address_register:
|
||||
process(CLK_I)
|
||||
debug.req_strobe <= req_strobe;
|
||||
debug.req_read <= cache_req_rd;
|
||||
debug.req_write <= cache_req_wr;
|
||||
debug.req_va <= request_va;
|
||||
debug.req_pa <= request_pa;
|
||||
debug.din_reg <= din_reg;
|
||||
debug.dout_reg <= cache_dout;
|
||||
debug.ready <= cache_rdy;
|
||||
|
||||
-------------------------------------------------
|
||||
-- ctrl
|
||||
-------------------------------------------------
|
||||
req_strobe <= cache_rdy and query_in.en;
|
||||
|
||||
request_register:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if fill_count_en = '1' then
|
||||
if ACK_I_r = '1' then
|
||||
fill_word_index <= fill_word_index + 1;
|
||||
end if;
|
||||
elsif cache_busy = '0' then
|
||||
fill_addr <= cpu_addr(addr_width-1 downto 2) & "00";
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
cache_req_rd <= '0';
|
||||
cache_req_wr <= '0';
|
||||
elsif cache_rdy = '1' then
|
||||
cache_req_rd <= query_in.en and not query_in.we;
|
||||
cache_req_wr <= query_in.en and query_in.we;
|
||||
cache_req <= query_in.en;
|
||||
if query_in.we = '1' then
|
||||
hit_cache_index <= to_cache_index(query_in.addr);
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
request_address_register:
|
||||
process(CLK_I)
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if request_count_en = '1'then
|
||||
if SRDY_I = '1' then
|
||||
req_word_index <= req_word_index + 1;
|
||||
end if;
|
||||
elsif cache_busy = '0' then
|
||||
request_addr <= cpu_addr(addr_width-1 downto 2) & "00";
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
cpu_request_register:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if RST_I = '1' then
|
||||
cpu_we_reg <= '0';
|
||||
cache_req <= '0';
|
||||
elsif cpu_en = '1' then
|
||||
if cache_busy = '0' then
|
||||
cpu_we2 <= cpu_we;
|
||||
cache_req <= '1';
|
||||
cpu_data_reg <= cpu_din;
|
||||
cpu_be_reg <= cpu_be;
|
||||
cpu_we_reg <= cpu_we;
|
||||
if cpu_we = '1' then
|
||||
hit_cache_index <= cpu_cache_index;
|
||||
end if;
|
||||
end if;
|
||||
elsif cache_ack = '1' then
|
||||
cache_req <= '0';
|
||||
cpu_we2 <= '0';
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
request_va <= (others => '0');
|
||||
request_nc <= '0';
|
||||
elsif req_strobe = '1' then
|
||||
din_reg <= query_in.data;
|
||||
be_reg <= query_in.be;
|
||||
request_va <= query_in.addr;
|
||||
request_nc <= query_in.nc;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
instant_raw_logic:
|
||||
process(CLK_I)
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if rising_edge(clk) then
|
||||
instant_raw <= '0';
|
||||
if cpu_word_index = fill_word_index and cpu_cache_index = hit_cache_index then
|
||||
instant_raw <= cpu_hit_we and cpu_en and not cpu_we;
|
||||
if to_word_index(query_in.addr) = fill_word_index and to_cache_index(query_in.addr) = hit_cache_index then
|
||||
instant_raw <= write_hit and query_in.en and not query_in.we;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-------------------------------------------------
|
||||
-- Instantiate synchronous FIFO
|
||||
inst_write_fifo: entity work.fifo_sync
|
||||
GENERIC MAP
|
||||
(
|
||||
addr_width => lg2(WRITE_FIFO_SIZE),
|
||||
data_width => 68,
|
||||
do_last_read_update => true
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
rst => rst,
|
||||
clk => clk,
|
||||
we => write_fifo_we,
|
||||
re => write_fifo_re,
|
||||
fifo_full => write_fifo_full,
|
||||
fifo_empty => write_fifo_empty,
|
||||
fifo_afull => open,
|
||||
fifo_aempty => open,
|
||||
data_w => write_fifo_din,
|
||||
data_r => write_fifo_dout
|
||||
);
|
||||
|
||||
write_fifo_data_in <= din_reg;
|
||||
write_fifo_addr_in <= request_pa;
|
||||
write_fifo_sel_in <= be_reg;
|
||||
write_fifo_re <= read_write_buffer and bus_dout_rdy and bus_cmd_rdy;
|
||||
write_fifo_we <= write_through_en;
|
||||
write_data_avail <= not write_fifo_empty;
|
||||
|
||||
fill_address_register:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if req_strobe = '1' then
|
||||
fill_word_index <= to_word_index(query_in.addr);
|
||||
elsif bus_din_vld = '1' and fill_count_en = '1' then
|
||||
fill_word_index <= fill_word_index + 1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
bus_request_address_register:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if req_strobe = '1' then
|
||||
req_word_index <= to_word_index(query_in.addr);
|
||||
elsif request_count_en = '1' and bus_cmd_rdy = '1' then
|
||||
req_word_index <= req_word_index + 1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
single_read_register:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
single_read_en <= '0';
|
||||
single_read_reg_vld <= '0';
|
||||
elsif single_read_en = '0' then
|
||||
if single_read_set = '1' then
|
||||
single_read_en <= '1';
|
||||
end if;
|
||||
elsif single_read_reg_vld = '1' then
|
||||
if query_in.en = '1' then
|
||||
single_read_en <= '0';
|
||||
single_read_reg_vld <= '0';
|
||||
end if;
|
||||
elsif bus_din_vld = '1' and single_read_en = '1' then
|
||||
single_read_reg <= bus_din;
|
||||
single_read_reg_vld <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
inst_tag_ram : dpram_2w2r2c_ra
|
||||
GENERIC MAP
|
||||
(
|
||||
@@ -283,10 +439,10 @@ inst_tag_ram : dpram_2w2r2c_ra
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
clk_a => CLK_I,
|
||||
clk_b => CLK_I,
|
||||
clk_a => clk,
|
||||
clk_b => clk,
|
||||
re_a => '1',
|
||||
re_b => '1',
|
||||
re_b => ram_read_en,
|
||||
we_a => tag_ram_we,
|
||||
we_b => '0',
|
||||
addr_a => tag_ram_addr_wr,
|
||||
@@ -304,35 +460,35 @@ gen_data_ram:
|
||||
inst_data_ram : dpram_2w2r2c_ra
|
||||
GENERIC MAP
|
||||
(
|
||||
addr_width => lg2(cache_size),
|
||||
addr_width => lg2(CACHE_SIZE),
|
||||
data_width => word_t'length/4
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
clk_a => CLK_I,
|
||||
clk_b => CLK_I,
|
||||
clk_a => clk,
|
||||
clk_b => clk,
|
||||
re_a => '1',
|
||||
re_b => '1',
|
||||
we_a => cpu_data_ram_we(i),
|
||||
re_b => ram_read_en,
|
||||
we_a => data_ram_we(i),
|
||||
we_b => ctrl_data_ram_we(i),
|
||||
addr_a => ctrl_data_ram_addr,
|
||||
addr_b => cpu_data_ram_addr,
|
||||
din_a => cpu_data_reg(8*(i+1)-1 downto 8*i),
|
||||
din_b => DAT_I_r(8*(i+1)-1 downto 8*i),
|
||||
addr_b => data_ram_addr,
|
||||
din_a => din_reg(8*(i+1)-1 downto 8*i),
|
||||
din_b => bus_din(8*(i+1)-1 downto 8*i),
|
||||
dout_a => open,
|
||||
dout_b => cpu_data_ram_dout(8*(i+1)-1 downto 8*i)
|
||||
dout_b => data_ram_dout(8*(i+1)-1 downto 8*i)
|
||||
);
|
||||
end generate;
|
||||
|
||||
|
||||
|
||||
cache_invalidate_request:
|
||||
process(CLK_I)
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if RST_I = '1' or ctrl.inv_all = '1' or ctrl.inv_at = '1' then
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' or ctrl_in.inv_all = '1' or ctrl_in.inv_at = '1' then
|
||||
invalidate_req <= '1';
|
||||
invalidate_all <= ctrl.inv_all or RST_I;
|
||||
invalidate_all <= ctrl_in.inv_all or rst;
|
||||
tag_reg_inv <= tag_inv;
|
||||
elsif invalidate_ack = '1' then
|
||||
invalidate_req <= '0';
|
||||
@@ -342,102 +498,144 @@ cache_invalidate_request:
|
||||
end process;
|
||||
|
||||
cache_state_next:
|
||||
process(CLK_I)
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if RST_I = '1' then
|
||||
s <= init;
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
cache_ctrl_state <= init;
|
||||
cache_busy_state <= init;
|
||||
else
|
||||
s <= sn;
|
||||
cache_ctrl_state <= cache_ctrl_state_next;
|
||||
cache_busy_state <= cache_busy_state_next;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
MRDY_O <= fill_count_en;
|
||||
ADDR_O <= request_addr;
|
||||
|
||||
cpu_busy <= cache_busy;
|
||||
cpu_dout <= cpu_data_ram_dout;
|
||||
|
||||
tag_match <= '1' when fill_tag = cache_entry_out.tag else '0';
|
||||
cache_hit <= tag_match and cache_entry_out.valid;
|
||||
tag_match_inv <= '1' when tag_reg_inv = cache_entry_out_inv.tag else '0';
|
||||
cache_hit_inv <= tag_match_inv and cache_entry_out_inv.valid;
|
||||
tag_ram_din <= to_tag_ram_data(cache_entry_in);
|
||||
tag_ram_addr_wr <= flush_addr when invalidate_en = '1' else fill_cache_index;
|
||||
tag_ram_addr_rd <= cpu_cache_index when (was_miss = '0' and instant_raw = '0') else fill_cache_index;
|
||||
cache_rdy <= read_rdy and not instant_raw and write_rdy;
|
||||
write_rdy <= not (write_fifo_full and cache_req_wr);
|
||||
query_out.rdy <= cache_rdy;
|
||||
rdy <= cache_rdy;
|
||||
|
||||
cache_entry_out <= to_dcache_entry(tag_ram_dout);
|
||||
cache_entry_out_inv <= to_dcache_entry(tag_ram_dout_inv);
|
||||
cache_dout <= single_read_reg when single_read_en = '1' else to_mips_01(data_ram_dout);
|
||||
query_out.data <= cache_dout;
|
||||
|
||||
-- tag_match <= '1' when to_tag(request_pa) = cache_entry_out.tag else '0';
|
||||
tag_match <= '1' when ((to_tag(request_pa) xor cache_entry_out.tag) = (tag_width-1 downto 0 => '0')) else '0';
|
||||
cache_hit <= tag_match and cache_entry_out.valid;
|
||||
|
||||
tag_match_inv <= '1' when tag_reg_inv = cache_entry_out_inv.tag else '0';
|
||||
cache_hit_inv <= tag_match_inv and cache_entry_out_inv.valid;
|
||||
|
||||
tag_ram_din <= to_tag_ram_data(cache_entry_in);
|
||||
tag_ram_addr_wr <= to_unsigned(flush_count, cache_index_width) when invalidate_en = '1' else to_cache_index(request_va);
|
||||
tag_ram_addr_rd <= to_cache_index(query_in.addr) when (was_miss = '0' and instant_raw = '0') else to_cache_index(request_va);
|
||||
|
||||
cache_entry_out <= to_dcache_entry(to_mips_01(tag_ram_dout));
|
||||
cache_entry_out_inv <= to_dcache_entry(to_mips_01(tag_ram_dout_inv));
|
||||
|
||||
ram_read_en <= query_in.en or was_miss or fill_count_en;
|
||||
data_ram_addr <= (to_cache_index(query_in.addr) & to_word_index(query_in.addr)) when (was_miss = '0' and instant_raw = '0' and fill_count_en = '0') else (to_cache_index(request_va) & fill_word_index);
|
||||
ctrl_data_ram_addr <= to_cache_index(request_va) & fill_word_index;
|
||||
ctrl_data_ram_we <= (others => ram_write_en and bus_din_vld);
|
||||
data_ram_we <= be_reg when (write_hit = '1') else (others => '0');
|
||||
|
||||
write_through_en <= cache_rdy and cache_req_wr; -- and tlb_query_in.hit and not tlb_query_in.flags.D;
|
||||
|
||||
cpu_data_ram_addr <= (cpu_cache_index & cpu_word_index) when (was_miss = '0' and instant_raw = '0' and fill_count_en = '0') else (fill_cache_index & fill_word_index);
|
||||
ctrl_data_ram_addr <= fill_cache_index & fill_word_index;
|
||||
ctrl_data_ram_we <= (others => fill_count_en and ACK_I_r);
|
||||
cpu_data_ram_we <= cpu_be_reg when (cpu_hit_we = '1') else (others => '0');
|
||||
|
||||
cache_state:
|
||||
process(s, cache_req, instant_raw, cache_hit, cache_hit_inv, cache_index_inv, flush_count_rdy, fill_count_rdy, request_count_rdy, fill_tag, SRDY_I, cpu_we_reg, invalidate_req, invalidate_all)
|
||||
cache_busy_state_fsm:
|
||||
process(cache_busy_state, request_nc, cache_req_rd, cache_hit, mem_fetch_ack, single_read_en, single_read_reg_vld)
|
||||
begin
|
||||
|
||||
read_rdy <= '0';
|
||||
mem_fetch_req <= '0';
|
||||
single_read_set <= '0';
|
||||
cache_busy_state_next <= cache_busy_state;
|
||||
|
||||
case cache_busy_state is
|
||||
|
||||
when init =>
|
||||
cache_busy_state_next <= ready;
|
||||
|
||||
when ready =>
|
||||
if single_read_en = '1' then
|
||||
read_rdy <= single_read_reg_vld;
|
||||
else
|
||||
read_rdy <= '1';
|
||||
if cache_req_rd = '1' then
|
||||
-- if tlb_query_in.exc = '0' then
|
||||
if request_nc = '1' or cache_hit = '0' then
|
||||
-- mem_fetch_req <= '1';
|
||||
read_rdy <= '0';
|
||||
cache_busy_state_next <= busy;
|
||||
end if;
|
||||
-- end if;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
when busy =>
|
||||
mem_fetch_req <= '1';
|
||||
if mem_fetch_ack = '1' then
|
||||
single_read_set <= request_nc;
|
||||
cache_busy_state_next <= ready;
|
||||
end if;
|
||||
|
||||
when others =>
|
||||
cache_busy_state_next <= ready;
|
||||
|
||||
end case;
|
||||
|
||||
end process;
|
||||
|
||||
cache_ctrl_state_fsm:
|
||||
process(cache_ctrl_state, mem_fetch_req, request_nc, flush_count_rdy, fill_count_rdy, request_count_rdy, request_pa, bus_cmd_rdy, bus_din_vld, invalidate_req, invalidate_all, write_through_en, write_data_avail)
|
||||
begin
|
||||
cache_busy <= cache_req;
|
||||
cache_ack <= '0';
|
||||
tag_ram_we <= '0';
|
||||
flush_count_en <= '0';
|
||||
flush_count_rst <= '0';
|
||||
invalidate_en <= '0';
|
||||
request_count_en <= '0';
|
||||
fill_count_en <= '0';
|
||||
CYC_O <= '0';
|
||||
STB_O <= '0';
|
||||
ram_write_en <= '0';
|
||||
bus_cmd_cycle_en <= '0';
|
||||
bus_cmd_we <= '0';
|
||||
was_miss <= '0';
|
||||
|
||||
invalidate_en <= '0';
|
||||
invalidate_ack <= '0';
|
||||
|
||||
flush_load_en <= '0';
|
||||
flush_count_en <= '0';
|
||||
flush_addr_preset <= (others=>'0'); -- all
|
||||
flush_count_preset <= 2**cache_index_width-1;
|
||||
|
||||
cache_entry_in.tv_p <= (others => '0');
|
||||
cache_entry_in.tag <= fill_tag;
|
||||
cache_entry_in.valid <= '0';
|
||||
sn <= s;
|
||||
mem_fetch_ack <= '0';
|
||||
read_write_buffer <= '0';
|
||||
|
||||
case s is
|
||||
cache_entry_in.tag <= to_tag(request_pa);
|
||||
cache_entry_in.valid <= '0';
|
||||
cache_ctrl_state_next <= cache_ctrl_state;
|
||||
|
||||
case cache_ctrl_state is
|
||||
|
||||
when init =>
|
||||
sn <= ready;
|
||||
cache_ctrl_state_next <= ready;
|
||||
|
||||
when ready =>
|
||||
if invalidate_req = '1' then
|
||||
sn <= invalidate_init;
|
||||
invalidate_en <= '1';
|
||||
flush_load_en <= '1';
|
||||
if invalidate_all = '1' then
|
||||
flush_addr_preset <= (others=>'0'); -- all
|
||||
flush_count_preset <= 2**cache_index_width-1;
|
||||
else
|
||||
flush_addr_preset <= cache_index_inv; -- at
|
||||
flush_count_preset <= 0;
|
||||
end if;
|
||||
else
|
||||
if cache_req = '1' then
|
||||
if cache_hit = '0' and cpu_we_reg = '0' then
|
||||
sn <= mem_request;
|
||||
CYC_O <= '1';
|
||||
else
|
||||
cache_busy <= instant_raw;
|
||||
cache_ack <= not instant_raw;
|
||||
end if;
|
||||
end if;
|
||||
cache_ctrl_state_next <= invalidate;
|
||||
invalidate_en <= '1';
|
||||
elsif mem_fetch_req = '1' or write_data_avail = '1' then
|
||||
cache_ctrl_state_next <= bus_request;
|
||||
-- bus_cmd_cycle_en <= '1';
|
||||
elsif write_through_en = '1' then
|
||||
cache_ctrl_state_next <= wait_write_thru;
|
||||
-- bus_cmd_cycle_en <= '1';
|
||||
end if;
|
||||
|
||||
when invalidate_init =>
|
||||
invalidate_en <= '1';
|
||||
sn <= invalidate;
|
||||
|
||||
|
||||
when invalidate =>
|
||||
sn <= rd_cache;
|
||||
invalidate_en <= '1';
|
||||
invalidate_ack <= '1';
|
||||
if cache_hit_inv = '1' or invalidate_all = '1' then
|
||||
sn <= flush;
|
||||
end if;
|
||||
cache_ctrl_state_next <= rd_cache;
|
||||
invalidate_en <= '1';
|
||||
invalidate_ack <= '1';
|
||||
if invalidate_all = '1' then
|
||||
cache_ctrl_state_next <= flush;
|
||||
flush_count_rst <= '1';
|
||||
elsif cache_hit_inv = '1' then
|
||||
tag_ram_we <= '1';
|
||||
cache_entry_in.valid <= '0';
|
||||
cache_entry_in.tag <= (others => '0');
|
||||
cache_ctrl_state_next <= invalidate_post;
|
||||
end if;
|
||||
|
||||
when flush =>
|
||||
flush_count_en <= '1';
|
||||
@@ -447,68 +645,106 @@ cache_state:
|
||||
cache_entry_in.tag <= (others => '0');
|
||||
if flush_count_rdy = '1' then
|
||||
tag_ram_we <= '0';
|
||||
sn <= rd_cache;
|
||||
cache_ctrl_state_next <= invalidate_post;
|
||||
end if;
|
||||
when mem_request =>
|
||||
CYC_O <= '1';
|
||||
if SRDY_I = '1' then
|
||||
sn <= mem_access;
|
||||
end if;
|
||||
when mem_access =>
|
||||
fill_count_en <= '1';
|
||||
|
||||
when invalidate_post =>
|
||||
was_miss <= '1';
|
||||
cache_ctrl_state_next <= ready;
|
||||
|
||||
when wait_write_thru =>
|
||||
cache_ctrl_state_next <= bus_request;
|
||||
bus_cmd_cycle_en <= '1';
|
||||
|
||||
when bus_request =>
|
||||
bus_cmd_cycle_en <= '1';
|
||||
if bus_cmd_rdy = '1' then
|
||||
if write_data_avail = '1' then
|
||||
read_write_buffer <= '1';
|
||||
bus_cmd_we <= '1';
|
||||
elsif mem_fetch_req = '1' then
|
||||
if request_nc = '1' then
|
||||
cache_ctrl_state_next <= mem_read_single;
|
||||
else
|
||||
cache_ctrl_state_next <= mem_read;
|
||||
end if;
|
||||
else
|
||||
cache_ctrl_state_next <= ready;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
when mem_read =>
|
||||
bus_cmd_cycle_en <= '1';
|
||||
bus_cmd_we <= '1';
|
||||
request_count_en <= '1';
|
||||
CYC_O <= '1';
|
||||
STB_O <= '1';
|
||||
ram_write_en <= '1';
|
||||
fill_count_en <= '1';
|
||||
if request_count_rdy = '1' then
|
||||
STB_O <= '0';
|
||||
sn <= mem_data;
|
||||
bus_cmd_we <= '0';
|
||||
cache_ctrl_state_next <= mem_read_data;
|
||||
end if;
|
||||
when mem_data =>
|
||||
CYC_O <= '1';
|
||||
fill_count_en <= '1';
|
||||
|
||||
when mem_read_single =>
|
||||
mem_fetch_ack <= '1';
|
||||
bus_cmd_cycle_en <= '1';
|
||||
bus_cmd_we <= '1';
|
||||
cache_ctrl_state_next <= mem_read_data_single;
|
||||
|
||||
when mem_read_data =>
|
||||
bus_cmd_cycle_en <= '1';
|
||||
fill_count_en <= '1';
|
||||
ram_write_en <= '1';
|
||||
if fill_count_rdy = '1' then
|
||||
tag_ram_we <= '1';
|
||||
cache_entry_in.valid <= '1';
|
||||
sn <= rd_cache;
|
||||
cache_ctrl_state_next <= rd_cache;
|
||||
end if;
|
||||
when rd_cache =>
|
||||
was_miss <= '1';
|
||||
sn <= ready;
|
||||
|
||||
when mem_read_data_single =>
|
||||
bus_cmd_cycle_en <= '1';
|
||||
if bus_din_vld = '1' then
|
||||
cache_ctrl_state_next <= ready;
|
||||
end if;
|
||||
|
||||
when rd_cache =>
|
||||
mem_fetch_ack <= '1';
|
||||
was_miss <= '1';
|
||||
cache_ctrl_state_next <= ready;
|
||||
|
||||
when others =>
|
||||
sn <= ready;
|
||||
cache_ctrl_state_next <= ready;
|
||||
end case;
|
||||
|
||||
end process;
|
||||
|
||||
flush_counter:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if flush_load_en = '1' then
|
||||
flush_count_rdy <= '0';
|
||||
flush_count <= flush_count_preset;
|
||||
flush_addr <= flush_addr_preset;
|
||||
elsif flush_count_en = '1' then
|
||||
if flush_count /= 0 then
|
||||
flush_count <= flush_count - 1;
|
||||
flush_addr <= flush_addr + 1;
|
||||
else
|
||||
flush_count_rdy <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
flush_counter:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if ctrl_in.inv_at = '1' then
|
||||
flush_count <= to_integer(cache_index_inv);
|
||||
elsif flush_count_rst = '1' then
|
||||
flush_count_rdy <= '0';
|
||||
flush_count <= 2**cache_index_width-1;
|
||||
elsif flush_count_en = '1' then
|
||||
if flush_count /= 0 then
|
||||
flush_count <= flush_count - 1;
|
||||
else
|
||||
flush_count_rdy <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
request_counter:
|
||||
process(CLK_I)
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if rising_edge(clk) then
|
||||
if request_count_en = '0' then
|
||||
request_count_rdy <= '0';
|
||||
request_count <= 2**word_index_width-1;
|
||||
else
|
||||
if SRDY_I = '1' then
|
||||
if bus_cmd_rdy = '1' then
|
||||
if request_count /= 0 then
|
||||
request_count <= request_count - 1;
|
||||
else
|
||||
@@ -520,14 +756,14 @@ request_counter:
|
||||
end process;
|
||||
|
||||
fill_counter:
|
||||
process(CLK_I)
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if rising_edge(clk) then
|
||||
if fill_count_en = '0' then
|
||||
fill_count_rdy <= '0';
|
||||
fill_count <= 2**word_index_width-1;
|
||||
else
|
||||
if ACK_I_r = '1' then
|
||||
if bus_din_vld = '1' then
|
||||
if fill_count /= 0 then
|
||||
fill_count <= fill_count - 1;
|
||||
else
|
||||
|
||||
@@ -0,0 +1,276 @@
|
||||
--------------------------------------------------------------------------
|
||||
-- Project: JIPS, a portable 32-bit RISC CPU written in VHDL
|
||||
-- This file: Types, constants and functions for JIPS
|
||||
--
|
||||
-- Copyright (C) 2008 J. Ahrensfeld
|
||||
--
|
||||
-- This program is free software: you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation, either version 3 of the License, or
|
||||
-- (at your option) any later version.
|
||||
--
|
||||
-- This program 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 General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
--
|
||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||
--
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.NUMERIC_STD.ALL;
|
||||
use IEEE.MATH_REAL.ALL;
|
||||
|
||||
library work;
|
||||
use work.mips_util_pkg.all;
|
||||
use work.mips_types.all;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
package mips_func_pkg is
|
||||
|
||||
function store_shift(x : word_t; va, shift_off : unsigned(1 downto 0); bypass : std_logic) return word_t;
|
||||
function store_be(va : unsigned(1 downto 0); be_src, word2_en, word4_en, align_left, bypass : std_logic) return unsigned;
|
||||
function load_shift(x : word_t; va, shift_off : unsigned(1 downto 0); bypass : std_logic) return word_t;
|
||||
function load_be(va : unsigned(1 downto 0); align_left, bypass : std_logic) return unsigned;
|
||||
function load_sign_ext(x : word_t; bypass, signed, word2_en, word4_en : std_logic) return word_t;
|
||||
function events_clr return event_t;
|
||||
function event_is_active(e : event_t) return std_logic;
|
||||
function "or" (a, b : event_t) return event_t;
|
||||
|
||||
end mips_func_pkg;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
package body mips_func_pkg is
|
||||
|
||||
function store_shift(x : word_t; va, shift_off : unsigned(1 downto 0); bypass : std_logic) return word_t is
|
||||
variable stage1 : word_t;
|
||||
variable result : word_t;
|
||||
variable sa : unsigned(1 downto 0);
|
||||
begin
|
||||
|
||||
if bypass = '1' then
|
||||
sa := "00";
|
||||
else
|
||||
sa := va + shift_off;
|
||||
end if;
|
||||
|
||||
stage1 := x;
|
||||
if sa(0) = '1' then
|
||||
stage1 := x(23 downto 0) & x(31 downto 24);
|
||||
end if;
|
||||
result := stage1;
|
||||
if sa(1) = '1' then
|
||||
result := stage1(15 downto 0) & stage1(31 downto 16);
|
||||
end if;
|
||||
|
||||
return result;
|
||||
end store_shift;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
function store_be(va : unsigned(1 downto 0); be_src, word2_en, word4_en, align_left, bypass : std_logic) return unsigned is
|
||||
variable result : unsigned(3 downto 0);
|
||||
begin
|
||||
result := (3 downto 0 => be_src);
|
||||
if bypass = '0' then
|
||||
if word2_en = '1' then
|
||||
case va is
|
||||
when "00" =>
|
||||
result := "00" & be_src & be_src;
|
||||
when "10" =>
|
||||
result := be_src & be_src & "00";
|
||||
when others => null;
|
||||
end case;
|
||||
elsif word4_en = '1' then
|
||||
case va is
|
||||
when "00" =>
|
||||
result := "000" & be_src;
|
||||
when "01" =>
|
||||
result := "00" & be_src & '0';
|
||||
when "10" =>
|
||||
result := '0' & be_src & "00";
|
||||
when "11" =>
|
||||
result := be_src & "000";
|
||||
when others => null;
|
||||
end case;
|
||||
elsif align_left = '1' then
|
||||
case va is
|
||||
when "00" =>
|
||||
result := be_src & be_src & be_src & be_src;
|
||||
when "01" =>
|
||||
result := be_src & be_src & be_src & '0';
|
||||
when "10" =>
|
||||
result := be_src & be_src & "00";
|
||||
when "11" =>
|
||||
result := be_src & "000";
|
||||
when others => null;
|
||||
end case;
|
||||
else
|
||||
case va is
|
||||
when "00" =>
|
||||
result := "000" & be_src;
|
||||
when "01" =>
|
||||
result := "00" & be_src & be_src;
|
||||
when "10" =>
|
||||
result := '0' & be_src & be_src & be_src;
|
||||
when "11" =>
|
||||
result := be_src & be_src & be_src & be_src;
|
||||
when others => null;
|
||||
end case;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
return result;
|
||||
|
||||
end store_be;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
function load_shift(x : word_t; va, shift_off : unsigned(1 downto 0); bypass : std_logic) return word_t is
|
||||
variable stage1 : word_t;
|
||||
variable result : word_t;
|
||||
variable sa : unsigned(1 downto 0);
|
||||
|
||||
begin
|
||||
if bypass = '1' then
|
||||
sa := "00";
|
||||
else
|
||||
sa := va + shift_off;
|
||||
end if;
|
||||
|
||||
stage1 := x;
|
||||
if sa(0) = '1' then
|
||||
stage1 := x(7 downto 0) & x(31 downto 8);
|
||||
end if;
|
||||
result := stage1;
|
||||
if sa(1) = '1' then
|
||||
result := stage1(15 downto 0) & stage1(31 downto 16);
|
||||
end if;
|
||||
|
||||
return result;
|
||||
end load_shift;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
function load_be(va : unsigned(1 downto 0); align_left, bypass : std_logic) return unsigned is
|
||||
variable result : unsigned(3 downto 0);
|
||||
begin
|
||||
result := (3 downto 0 => '1');
|
||||
if bypass = '0' then
|
||||
if align_left = '1' then
|
||||
case va is
|
||||
when "00" =>
|
||||
result := "1000";
|
||||
when "01" =>
|
||||
result := "1100";
|
||||
when "10" =>
|
||||
result := "1110";
|
||||
when "11" =>
|
||||
result := "1111";
|
||||
when others => null;
|
||||
end case;
|
||||
else
|
||||
case va is
|
||||
when "00" =>
|
||||
result := "1111";
|
||||
when "01" =>
|
||||
result := "0111";
|
||||
when "10" =>
|
||||
result := "0011";
|
||||
when "11" =>
|
||||
result := "0001";
|
||||
when others => null;
|
||||
end case;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
return result;
|
||||
|
||||
end load_be;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
function load_sign_ext(x : word_t; bypass, signed, word2_en, word4_en : std_logic) return word_t is
|
||||
variable result : word_t;
|
||||
variable sign : std_logic;
|
||||
|
||||
begin
|
||||
if bypass = '1' then
|
||||
result := x;
|
||||
elsif word2_en = '1' then
|
||||
sign := signed and x(15);
|
||||
result := (31 downto 16 => sign) & x(15 downto 0);
|
||||
else
|
||||
sign := signed and x(7);
|
||||
result := (31 downto 8 => sign) & x(7 downto 0);
|
||||
end if;
|
||||
|
||||
return result;
|
||||
end load_sign_ext;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
function events_clr return event_t is
|
||||
variable result : event_t;
|
||||
begin
|
||||
result.NMI := '0';
|
||||
result.Int := '0';
|
||||
result.data_load_err := '0';
|
||||
result.data_store_err := '0';
|
||||
result.inst_load_err := '0';
|
||||
result.inst_priv_addr := '0';
|
||||
result.alu_ovf := '0';
|
||||
result.alu_uvf := '0';
|
||||
result.syscall := '0';
|
||||
result.break := '0';
|
||||
result.illegal := '0';
|
||||
|
||||
return result;
|
||||
|
||||
end events_clr;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
function event_is_active(e : event_t) return std_logic is
|
||||
variable result : std_logic;
|
||||
begin
|
||||
result := '0';
|
||||
|
||||
result := result or e.NMI;
|
||||
result := result or e.Int;
|
||||
result := result or e.data_load_err;
|
||||
result := result or e.data_store_err;
|
||||
result := result or e.inst_load_err;
|
||||
result := result or e.inst_priv_addr;
|
||||
result := result or e.alu_ovf;
|
||||
result := result or e.alu_uvf;
|
||||
result := result or e.syscall;
|
||||
result := result or e.break;
|
||||
result := result or e.illegal;
|
||||
|
||||
return result;
|
||||
|
||||
end event_is_active;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
function "or" (a, b : event_t) return event_t is
|
||||
variable result : event_t;
|
||||
begin
|
||||
result.NMI := a.NMI or b.NMI;
|
||||
result.Int := a.Int or b.Int;
|
||||
result.data_load_err := a.data_load_err or b.data_load_err;
|
||||
result.data_store_err := a.data_store_err or b.data_store_err;
|
||||
result.inst_load_err := a.inst_load_err or b.inst_load_err;
|
||||
result.inst_priv_addr := a.inst_priv_addr or b.inst_priv_addr;
|
||||
result.alu_ovf := a.alu_ovf or b.alu_ovf;
|
||||
result.alu_uvf := a.alu_uvf or b.alu_uvf;
|
||||
result.syscall := a.syscall or b.syscall;
|
||||
result.break := a.break or b.break;
|
||||
result.illegal := a.illegal or b.illegal;
|
||||
|
||||
return result;
|
||||
|
||||
end "or";
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
end mips_func_pkg;
|
||||
|
||||
@@ -26,30 +26,40 @@ USE IEEE.STD_LOGIC_1164.ALL;
|
||||
USE IEEE.NUMERIC_STD.ALL;
|
||||
|
||||
library work;
|
||||
use work.mips_util_pkg.all;
|
||||
use work.mips_types.all;
|
||||
use work.busmaster_types.all;
|
||||
|
||||
ENTITY icache IS
|
||||
Generic
|
||||
(
|
||||
cache_size : natural := 2048; -- words
|
||||
line_size : natural := 8 -- words
|
||||
CACHE_SIZE : natural := 1024; -- words
|
||||
LINE_SIZE : natural := 8 -- words
|
||||
);
|
||||
Port
|
||||
(
|
||||
RST_I : in STD_LOGIC;
|
||||
CLK_I : in STD_LOGIC;
|
||||
ACK_I : in STD_LOGIC;
|
||||
SRDY_I : in STD_LOGIC;
|
||||
MRDY_O : out STD_LOGIC;
|
||||
ADDR_O : out word_t;
|
||||
DAT_I : in word_t;
|
||||
STB_O : out STD_LOGIC;
|
||||
CYC_O : out STD_LOGIC;
|
||||
ctrl : in cache_ctrl_t;
|
||||
cpu_en : in STD_LOGIC;
|
||||
cpu_addr : in word_t;
|
||||
cpu_dout : out word_t;
|
||||
cpu_busy : out STD_LOGIC
|
||||
rst : in STD_LOGIC;
|
||||
clk : in STD_LOGIC;
|
||||
rdy : out STD_LOGIC;
|
||||
|
||||
-- CPU control/data
|
||||
query_in : in icache_query_in_t;
|
||||
query_out : out icache_query_out_t;
|
||||
|
||||
-- Cache control
|
||||
ctrl_in : in cache_ctrl_t;
|
||||
|
||||
-- busmaster data
|
||||
bus_din : in word_t;
|
||||
bus_din_rdy : out std_logic;
|
||||
bus_din_vld : in std_logic;
|
||||
|
||||
-- busmaster command
|
||||
bus_cmd_rdy : in std_logic;
|
||||
bus_cmd_we : out std_logic;
|
||||
bus_cmd_cycle_en : out std_logic;
|
||||
bus_cmd_out : out bm_cmd_t;
|
||||
bus_cyc_complete : in std_logic
|
||||
);
|
||||
END icache;
|
||||
|
||||
@@ -65,7 +75,7 @@ COMPONENT dpram_1w1r2c_ra
|
||||
clk_a : in STD_LOGIC;
|
||||
clk_b : in STD_LOGIC;
|
||||
we_a : in STD_LOGIC;
|
||||
re_b : in STD_LOGIC;
|
||||
re_b : in STD_LOGIC;
|
||||
addr_a : in unsigned (addr_width-1 downto 0);
|
||||
addr_b : in unsigned (addr_width-1 downto 0);
|
||||
din_a : in unsigned (data_width-1 downto 0);
|
||||
@@ -97,27 +107,26 @@ COMPONENT dpram_2w2r2c_ra is
|
||||
END COMPONENT;
|
||||
|
||||
constant addr_width : natural := 32;
|
||||
constant word_index_width : natural := lg2(line_size);
|
||||
constant cache_index_width : natural := lg2(cache_size) - word_index_width;
|
||||
constant tag_width : natural := addr_width - word_index_width - cache_index_width - 2;
|
||||
constant tag_parity_width : natural := 3;
|
||||
constant tag_ram_data_width : natural := 1 + tag_parity_width + tag_width;
|
||||
constant word_index_width : natural := lg2(LINE_SIZE);
|
||||
constant cache_index_width : natural := lg2(CACHE_SIZE) - word_index_width;
|
||||
constant tag_width : natural := addr_width - lg2(CACHE_SIZE) - 2;
|
||||
constant tag_ram_data_width : natural := 1 + tag_width + lg2(TLB_NUM_ENTRIES);
|
||||
constant tag_ram_addr_width : natural := cache_index_width;
|
||||
|
||||
subtype tag_ram_data_t is unsigned (tag_ram_data_width-1 downto 0);
|
||||
|
||||
type icache_entry_t is record
|
||||
valid : std_logic;
|
||||
tv_p : unsigned(tag_parity_width-1 downto 0);
|
||||
tag : unsigned(tag_width-1 downto 0);
|
||||
valid : std_logic;
|
||||
tag : unsigned(tag_width-1 downto 0);
|
||||
tlb_idx : unsigned(lg2(TLB_NUM_ENTRIES)-1 downto 0);
|
||||
end record;
|
||||
|
||||
function to_icache_entry(x : tag_ram_data_t) return icache_entry_t is
|
||||
variable result : icache_entry_t;
|
||||
begin
|
||||
result.valid := x(0);
|
||||
result.tv_p := x(3 downto 1);
|
||||
result.tag := x(tag_width+3 downto 4);
|
||||
result.tag := x(tag_width downto 1);
|
||||
result.tlb_idx := x(lg2(TLB_NUM_ENTRIES)+tag_width downto tag_width+1);
|
||||
|
||||
return result;
|
||||
end to_icache_entry;
|
||||
@@ -125,150 +134,222 @@ END COMPONENT;
|
||||
function to_tag_ram_data(x : icache_entry_t) return tag_ram_data_t is
|
||||
variable result : tag_ram_data_t;
|
||||
begin
|
||||
result(0) := x.valid;
|
||||
result(3 downto 1) := x.tv_p;
|
||||
result(tag_width+3 downto 4) := x.tag;
|
||||
result(0) := x.valid;
|
||||
result(tag_width downto 1) := x.tag;
|
||||
result(lg2(TLB_NUM_ENTRIES)+tag_width downto tag_width+1) := x.tlb_idx;
|
||||
|
||||
return result;
|
||||
end to_tag_ram_data;
|
||||
|
||||
type cache_state_t is (init, ready, invalidate_init, invalidate, flush, mem_request, mem_access, mem_data, rd_cache, upd_cache);
|
||||
signal s, sn : cache_state_t;
|
||||
function to_word_index(x : word_t) return unsigned is
|
||||
variable result : unsigned(word_index_width-1 downto 0);
|
||||
begin
|
||||
result := x(word_index_width+1 downto 2);
|
||||
|
||||
return result;
|
||||
|
||||
end to_word_index;
|
||||
|
||||
signal cache_req : std_logic;
|
||||
signal cache_ack : std_logic;
|
||||
signal cache_busy : std_logic;
|
||||
signal cache_hit : std_logic;
|
||||
signal tag_match : std_logic;
|
||||
signal cache_hit_inv : std_logic;
|
||||
signal tag_match_inv : std_logic;
|
||||
signal request_addr : unsigned(addr_width-1 downto 0);
|
||||
signal fill_addr : unsigned(addr_width-1 downto 0);
|
||||
|
||||
signal cache_index_inv : unsigned(cache_index_width-1 downto 0);
|
||||
signal tag_inv : unsigned(tag_width-1 downto 0);
|
||||
signal tag_reg_inv : unsigned(tag_width-1 downto 0);
|
||||
|
||||
signal cache_entry_in : icache_entry_t;
|
||||
signal cache_entry_out : icache_entry_t;
|
||||
signal cache_entry_out_inv : icache_entry_t;
|
||||
signal data_ram_addr_rd : unsigned(lg2(cache_size)-1 downto 0);
|
||||
signal data_ram_data_rd : word_t;
|
||||
signal data_ram_addr_wr : unsigned(lg2(cache_size)-1 downto 0);
|
||||
signal data_ram_data_wr : word_t;
|
||||
signal data_ram_we : std_logic;
|
||||
signal data_ram_re : std_logic;
|
||||
|
||||
signal tag_ram_addr_rd : unsigned(cache_index_width-1 downto 0);
|
||||
signal tag_ram_data_rd : tag_ram_data_t;
|
||||
signal tag_ram_data_rd_inv : tag_ram_data_t;
|
||||
signal tag_ram_addr_wr : unsigned(cache_index_width-1 downto 0);
|
||||
signal tag_ram_data_wr : tag_ram_data_t;
|
||||
signal tag_ram_we : std_logic;
|
||||
-- signal tag_ram_re : std_logic;
|
||||
function to_cache_index(x : word_t) return unsigned is
|
||||
variable result : unsigned(cache_index_width-1 downto 0);
|
||||
begin
|
||||
result := x(cache_index_width+word_index_width+1 downto word_index_width+2);
|
||||
|
||||
return result;
|
||||
|
||||
end to_cache_index;
|
||||
|
||||
function to_tag(x : word_t) return unsigned is
|
||||
variable result : unsigned(tag_width-1 downto 0);
|
||||
begin
|
||||
result := x(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2);
|
||||
|
||||
return result;
|
||||
|
||||
end to_tag;
|
||||
|
||||
type cache_busy_state_t is (init, ready, busy);
|
||||
signal cache_busy_state, cache_busy_state_next : cache_busy_state_t;
|
||||
|
||||
type cache_ctrl_state_t is (init, ready, invalidate, invalidate_post, flush, bus_request, mem_read, mem_read_single, mem_read_data, mem_read_data_single, rd_cache, upd_cache);
|
||||
signal cache_ctrl_state, cache_ctrl_state_next : cache_ctrl_state_t;
|
||||
|
||||
signal fill_count : natural range 0 to 2**word_index_width-1;
|
||||
signal fill_count_en : std_logic;
|
||||
signal fill_count_rdy : std_logic;
|
||||
signal flush_load_en : std_logic;
|
||||
signal flush_addr_preset : unsigned(cache_index_width-1 downto 0);
|
||||
signal flush_count_preset : natural range 0 to 2**cache_index_width-1;
|
||||
signal flush_addr : unsigned(cache_index_width-1 downto 0);
|
||||
signal flush_count : natural range 0 to 2**cache_index_width-1;
|
||||
signal flush_count_en : std_logic;
|
||||
signal flush_count_rdy : std_logic;
|
||||
signal request_count : natural range 0 to 2**word_index_width-1;
|
||||
signal request_count_en : std_logic;
|
||||
signal request_count_rdy : std_logic;
|
||||
signal was_miss : std_logic;
|
||||
signal invalidate_all : std_logic;
|
||||
signal invalidate_ack : std_logic;
|
||||
signal invalidate_en : std_logic;
|
||||
signal invalidate_req : std_logic;
|
||||
type debug_t is record
|
||||
ready : std_logic;
|
||||
req_strobe : std_logic;
|
||||
req_read : std_logic;
|
||||
req_va : word_t;
|
||||
req_pa : word_t;
|
||||
dout_reg : word_t;
|
||||
end record;
|
||||
|
||||
signal DAT_I_r : word_t;
|
||||
signal ACK_I_r : std_logic;
|
||||
signal debug : debug_t;
|
||||
|
||||
signal req_strobe : std_logic;
|
||||
signal cache_req_rd : std_logic;
|
||||
signal read_rdy : std_logic;
|
||||
signal cache_rdy : std_logic;
|
||||
signal cache_hit : std_logic;
|
||||
signal request_va : word_t;
|
||||
signal request_pa : word_t;
|
||||
signal request_nc : std_logic;
|
||||
|
||||
signal tag_match : std_logic;
|
||||
signal cache_hit_inv : std_logic;
|
||||
signal tag_match_inv : std_logic;
|
||||
|
||||
alias cpu_word_index is cpu_addr(word_index_width+1 downto 2);
|
||||
alias cpu_cache_index is cpu_addr(cache_index_width+word_index_width+1 downto word_index_width+2);
|
||||
alias cpu_tag is cpu_addr(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2);
|
||||
signal mem_fetch_req : std_logic;
|
||||
signal mem_fetch_ack : std_logic;
|
||||
signal single_read_en : std_logic;
|
||||
signal single_read_set : std_logic;
|
||||
signal single_read_reg_vld : std_logic;
|
||||
|
||||
alias fill_word_index is fill_addr(word_index_width+1 downto 2);
|
||||
alias fill_cache_index is fill_addr(cache_index_width+word_index_width+1 downto word_index_width+2);
|
||||
alias fill_tag is fill_addr(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2);
|
||||
signal cache_index_inv : unsigned(cache_index_width-1 downto 0);
|
||||
signal tag_inv : unsigned(tag_width-1 downto 0);
|
||||
signal tag_reg_inv : unsigned(tag_width-1 downto 0);
|
||||
|
||||
signal cache_entry_in : icache_entry_t;
|
||||
signal cache_entry_out : icache_entry_t;
|
||||
signal cache_entry_out_inv : icache_entry_t;
|
||||
signal data_ram_addr_rd : unsigned(lg2(CACHE_SIZE)-1 downto 0);
|
||||
signal data_ram_data_rd : word_t;
|
||||
signal data_ram_addr_wr : unsigned(lg2(CACHE_SIZE)-1 downto 0);
|
||||
signal data_ram_data_wr : word_t;
|
||||
signal data_ram_we : std_logic;
|
||||
signal single_read_reg : word_t;
|
||||
signal cache_dout : word_t;
|
||||
|
||||
alias req_word_index is request_addr(word_index_width+1 downto 2);
|
||||
alias req_cache_index is request_addr(cache_index_width+word_index_width+1 downto word_index_width+2);
|
||||
alias req_tag is request_addr(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2);
|
||||
signal tag_ram_addr_rd : unsigned(cache_index_width-1 downto 0);
|
||||
signal tag_ram_data_rd : tag_ram_data_t;
|
||||
signal tag_ram_data_rd_inv : tag_ram_data_t;
|
||||
signal tag_ram_addr_wr : unsigned(cache_index_width-1 downto 0);
|
||||
signal tag_ram_data_wr : tag_ram_data_t;
|
||||
signal tag_ram_we : std_logic;
|
||||
|
||||
signal fill_count : natural range 0 to 2**word_index_width-1;
|
||||
signal fill_count_en : std_logic;
|
||||
signal fill_count_rdy : std_logic;
|
||||
signal flush_count : natural range 0 to 2**cache_index_width-1;
|
||||
signal flush_count_rst : std_logic;
|
||||
signal flush_count_en : std_logic;
|
||||
signal flush_count_rdy : std_logic;
|
||||
signal request_count : natural range 0 to 2**word_index_width-1;
|
||||
signal request_count_en : std_logic;
|
||||
signal request_count_rdy : std_logic;
|
||||
signal ram_read_en : std_logic;
|
||||
signal ram_write_en : std_logic;
|
||||
signal was_miss : std_logic;
|
||||
signal invalidate_all : std_logic;
|
||||
signal invalidate_ack : std_logic;
|
||||
signal invalidate_en : std_logic;
|
||||
signal invalidate_req : std_logic;
|
||||
|
||||
signal fill_word_index : unsigned(word_index_width-1 downto 0);
|
||||
signal req_word_index : unsigned(word_index_width-1 downto 0);
|
||||
|
||||
begin
|
||||
|
||||
cache_index_inv <= ctrl.inv_addr(cache_index_width+word_index_width+1 downto word_index_width+2);
|
||||
tag_inv <= ctrl.inv_addr(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2);
|
||||
-- Print info
|
||||
assert false report "addr_width = " & natural'image(addr_width) & "." severity note;
|
||||
assert false report "tag_width = " & natural'image(tag_width) & "." severity note;
|
||||
assert false report "word_index_width = " & natural'image(word_index_width) & "." severity note;
|
||||
assert false report "cache_index_width = " & natural'image(cache_index_width) & "." severity note;
|
||||
|
||||
-- tlb_query_out.vld <= cache_req_rd;
|
||||
-- tlb_query_out.vaddr <= request_va;
|
||||
-- tlb_query_out.write <= '0';
|
||||
-- tlb_query_out.vld <= req_strobe;
|
||||
-- tlb_query_out.vaddr <= query_in.addr;
|
||||
-- tlb_query_out.write <= '0';
|
||||
|
||||
data_in_register:
|
||||
process(CLK_I)
|
||||
cache_index_inv <= ctrl_in.inv_addr(cache_index_width+word_index_width+1 downto word_index_width+2);
|
||||
tag_inv <= ctrl_in.inv_addr(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2);
|
||||
|
||||
request_pa <= request_va;
|
||||
|
||||
debug.req_strobe <= req_strobe;
|
||||
debug.req_read <= cache_req_rd;
|
||||
debug.req_va <= request_va;
|
||||
debug.req_pa <= request_pa;
|
||||
debug.dout_reg <= cache_dout;
|
||||
debug.ready <= cache_rdy;
|
||||
|
||||
-------------------------------------------------
|
||||
-- ctrl
|
||||
-------------------------------------------------
|
||||
req_strobe <= cache_rdy and query_in.en;
|
||||
|
||||
ctrl_request_register:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
ACK_I_r <= ACK_I;
|
||||
if ACK_I = '1' then
|
||||
DAT_I_r <= DAT_I;
|
||||
if rising_edge(clk) then
|
||||
if cache_rdy = '1' then
|
||||
cache_req_rd <= query_in.en;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
fill_address_register:
|
||||
process(CLK_I)
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if fill_count_en = '1' then
|
||||
if ACK_I_r = '1' then
|
||||
fill_word_index <= fill_word_index + 1;
|
||||
end if;
|
||||
elsif cache_busy = '0' then
|
||||
fill_addr <= cpu_addr(addr_width-1 downto 2) & "00";
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
request_va <= (others => '0');
|
||||
request_nc <= '0';
|
||||
elsif req_strobe = '1' then
|
||||
request_va <= query_in.addr;
|
||||
request_nc <= query_in.nc;
|
||||
fill_word_index <= to_word_index(query_in.addr);
|
||||
elsif bus_din_vld = '1' and fill_count_en = '1' then
|
||||
fill_word_index <= fill_word_index + 1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
request_address_register:
|
||||
process(CLK_I)
|
||||
bus_request_address_register:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if request_count_en = '1'then
|
||||
if SRDY_I = '1' then
|
||||
req_word_index <= req_word_index + 1;
|
||||
end if;
|
||||
elsif cache_busy = '0' then
|
||||
request_addr <= cpu_addr(addr_width-1 downto 2) & "00";
|
||||
end if;
|
||||
if rising_edge(clk) then
|
||||
if req_strobe = '1' then
|
||||
req_word_index <= to_word_index(query_in.addr);
|
||||
elsif request_count_en = '1' and bus_cmd_rdy = '1' then
|
||||
req_word_index <= req_word_index + 1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
cpu_request_register:
|
||||
process(CLK_I)
|
||||
single_read_register:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if RST_I = '1' then
|
||||
cache_req <= '0';
|
||||
elsif cpu_en = '1' then
|
||||
if cache_busy = '0' then
|
||||
cache_req <= '1';
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
single_read_en <= '0';
|
||||
single_read_reg_vld <= '0';
|
||||
elsif single_read_en = '0' then
|
||||
if single_read_set = '1' then
|
||||
single_read_en <= '1';
|
||||
end if;
|
||||
elsif single_read_reg_vld = '1' then
|
||||
if query_in.en = '1' then
|
||||
single_read_en <= '0';
|
||||
single_read_reg_vld <= '0';
|
||||
end if;
|
||||
elsif cache_ack = '1' then
|
||||
cache_req <= '0';
|
||||
elsif bus_din_vld = '1' and single_read_en = '1' then
|
||||
single_read_reg <= bus_din;
|
||||
single_read_reg_vld <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
cache_invalidate_request:
|
||||
process(CLK_I)
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if RST_I = '1' or ctrl.inv_all = '1' or ctrl.inv_at = '1' then
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' or ctrl_in.inv_all = '1' or ctrl_in.inv_at = '1' then
|
||||
invalidate_req <= '1';
|
||||
invalidate_all <= ctrl.inv_all or RST_I;
|
||||
invalidate_all <= ctrl_in.inv_all or rst;
|
||||
tag_reg_inv <= tag_inv;
|
||||
elsif invalidate_ack = '1' then
|
||||
invalidate_req <= '0';
|
||||
@@ -285,12 +366,12 @@ inst_tag_ram : dpram_2w2r2c_ra
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
clk_a => CLK_I,
|
||||
clk_b => CLK_I,
|
||||
clk_a => clk,
|
||||
clk_b => clk,
|
||||
re_a => '1',
|
||||
re_b => '1',
|
||||
we_a => tag_ram_we,
|
||||
we_b => '0',
|
||||
re_b => ram_read_en,
|
||||
we_a => tag_ram_we,
|
||||
we_b => '0',
|
||||
addr_a => tag_ram_addr_wr,
|
||||
addr_b => tag_ram_addr_rd,
|
||||
din_a => tag_ram_data_wr,
|
||||
@@ -302,15 +383,15 @@ inst_tag_ram : dpram_2w2r2c_ra
|
||||
inst_data_ram : dpram_1w1r2c_ra
|
||||
GENERIC MAP
|
||||
(
|
||||
addr_width => lg2(cache_size),
|
||||
addr_width => lg2(CACHE_SIZE),
|
||||
data_width => word_t'length
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
clk_a => CLK_I,
|
||||
clk_b => CLK_I,
|
||||
re_b => data_ram_re,
|
||||
clk_a => clk,
|
||||
clk_b => clk,
|
||||
we_a => data_ram_we,
|
||||
re_b => ram_read_en,
|
||||
addr_a => data_ram_addr_wr,
|
||||
addr_b => data_ram_addr_rd,
|
||||
din_a => data_ram_data_wr,
|
||||
@@ -318,172 +399,236 @@ inst_data_ram : dpram_1w1r2c_ra
|
||||
);
|
||||
|
||||
cache_state_next:
|
||||
process(CLK_I)
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if RST_I = '1' then
|
||||
s <= init;
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
cache_ctrl_state <= init;
|
||||
cache_busy_state <= init;
|
||||
else
|
||||
s <= sn;
|
||||
cache_ctrl_state <= cache_ctrl_state_next;
|
||||
cache_busy_state <= cache_busy_state_next;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
MRDY_O <= fill_count_en;
|
||||
ADDR_O <= fill_tag & fill_cache_index & req_word_index & "00";
|
||||
bus_din_rdy <= fill_count_en or single_read_en;
|
||||
bus_cmd_out.addr <= to_tag(request_pa) & to_cache_index(request_pa) & req_word_index & "00";
|
||||
bus_cmd_out.rw <= '0';
|
||||
bus_cmd_out.sel <= (others => '1');
|
||||
|
||||
cache_rdy <= read_rdy;
|
||||
query_out.rdy <= cache_rdy;
|
||||
rdy <= cache_rdy;
|
||||
|
||||
cpu_busy <= cache_busy;
|
||||
cpu_dout <= data_ram_data_rd;
|
||||
|
||||
cache_entry_out <= to_icache_entry(tag_ram_data_rd);
|
||||
tag_match <= '1' when fill_tag = cache_entry_out.tag else '0';
|
||||
cache_hit <= tag_match and cache_entry_out.valid;
|
||||
cache_dout <= single_read_reg when single_read_en = '1' else data_ram_data_rd;
|
||||
query_out.data <= cache_dout;
|
||||
|
||||
cache_entry_out_inv <= to_icache_entry(tag_ram_data_rd_inv);
|
||||
tag_match_inv <= '1' when tag_reg_inv = cache_entry_out_inv.tag else '0';
|
||||
cache_hit_inv <= tag_match_inv and cache_entry_out_inv.valid;
|
||||
cache_entry_out <= to_icache_entry(to_mips_01(tag_ram_data_rd));
|
||||
tag_match <= '1' when ((to_tag(request_pa) xor cache_entry_out.tag) = (tag_width-1 downto 0 => '0')) else '0';
|
||||
cache_hit <= tag_match and cache_entry_out.valid;
|
||||
|
||||
tag_ram_data_wr <= to_tag_ram_data(cache_entry_in);
|
||||
tag_ram_addr_wr <= flush_addr when invalidate_en = '1' else fill_cache_index;
|
||||
tag_ram_addr_rd <= cpu_cache_index when was_miss = '0' else fill_cache_index;
|
||||
data_ram_addr_rd <= (cpu_cache_index & cpu_word_index) when was_miss = '0' else (fill_cache_index & fill_word_index);
|
||||
data_ram_addr_wr <= fill_cache_index & fill_word_index;
|
||||
data_ram_data_wr <= DAT_I_r;
|
||||
data_ram_we <= fill_count_en and ACK_I_r;
|
||||
data_ram_re <= (cpu_en or was_miss) and not data_ram_we;
|
||||
-- tag_ram_re <= (cpu_en or was_miss) and not data_ram_we;
|
||||
cache_entry_out_inv <= to_icache_entry(to_mips_01(tag_ram_data_rd_inv));
|
||||
tag_match_inv <= '1' when tag_reg_inv = cache_entry_out_inv.tag else '0';
|
||||
cache_hit_inv <= tag_match_inv and cache_entry_out_inv.valid;
|
||||
|
||||
cache_state:
|
||||
process(s, cache_req, cache_hit, cache_hit_inv, cache_index_inv, flush_count_rdy, fill_count_rdy, request_count_rdy, fill_tag, SRDY_I, invalidate_req, invalidate_all)
|
||||
ram_read_en <= query_in.en or was_miss;
|
||||
tag_ram_data_wr <= to_tag_ram_data(cache_entry_in);
|
||||
tag_ram_addr_wr <= to_unsigned(flush_count, cache_index_width) when invalidate_en = '1' else to_cache_index(request_va);
|
||||
tag_ram_addr_rd <= to_cache_index(query_in.addr) when was_miss = '0' else to_cache_index(request_va);
|
||||
data_ram_addr_rd <= (to_cache_index(query_in.addr) & to_word_index(query_in.addr)) when was_miss = '0' else (to_cache_index(request_va) & fill_word_index);
|
||||
data_ram_addr_wr <= to_cache_index(request_va) & fill_word_index;
|
||||
data_ram_data_wr <= bus_din;
|
||||
data_ram_we <= ram_write_en and bus_din_vld;
|
||||
|
||||
cache_busy_state_fsm:
|
||||
process(cache_busy_state, request_nc, cache_req_rd, cache_hit, mem_fetch_ack, single_read_en, single_read_reg_vld)
|
||||
begin
|
||||
|
||||
read_rdy <= '0';
|
||||
mem_fetch_req <= '0';
|
||||
single_read_set <= '0';
|
||||
cache_busy_state_next <= cache_busy_state;
|
||||
|
||||
case cache_busy_state is
|
||||
|
||||
when init =>
|
||||
cache_busy_state_next <= ready;
|
||||
|
||||
when ready =>
|
||||
if single_read_en = '1' then
|
||||
read_rdy <= single_read_reg_vld;
|
||||
else
|
||||
read_rdy <= '1';
|
||||
if cache_req_rd = '1' then
|
||||
-- if tlb_query_in.exc = '0' then
|
||||
if request_nc = '1' or cache_hit = '0' then
|
||||
-- mem_fetch_req <= '1';
|
||||
read_rdy <= '0';
|
||||
single_read_set <= request_nc;
|
||||
cache_busy_state_next <= busy;
|
||||
end if;
|
||||
-- end if;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
when busy =>
|
||||
mem_fetch_req <= '1';
|
||||
if mem_fetch_ack = '1' then
|
||||
cache_busy_state_next <= ready;
|
||||
end if;
|
||||
|
||||
when others =>
|
||||
cache_busy_state_next <= ready;
|
||||
|
||||
end case;
|
||||
|
||||
end process;
|
||||
|
||||
cache_ctrl_state_fsm:
|
||||
process(cache_ctrl_state, mem_fetch_req, request_nc, bus_din_vld, cache_hit_inv, flush_count_rdy, fill_count_rdy, request_count_rdy, request_pa, bus_cmd_rdy, invalidate_req, invalidate_all)
|
||||
begin
|
||||
cache_busy <= cache_req;
|
||||
cache_ack <= '0';
|
||||
tag_ram_we <= '0';
|
||||
flush_count_en <= '0';
|
||||
flush_count_rst <= '0';
|
||||
invalidate_en <= '0';
|
||||
request_count_en <= '0';
|
||||
fill_count_en <= '0';
|
||||
CYC_O <= '0';
|
||||
STB_O <= '0';
|
||||
ram_write_en <= '0';
|
||||
bus_cmd_cycle_en <= '0';
|
||||
bus_cmd_we <= '0';
|
||||
was_miss <= '0';
|
||||
|
||||
invalidate_en <= '0';
|
||||
invalidate_ack <= '0';
|
||||
|
||||
flush_load_en <= '0';
|
||||
flush_count_en <= '0';
|
||||
flush_addr_preset <= (others=>'0'); -- all
|
||||
flush_count_preset <= 2**cache_index_width-1;
|
||||
mem_fetch_ack <= '0';
|
||||
|
||||
cache_entry_in.tv_p <= (others => '0');
|
||||
cache_entry_in.tag <= fill_tag;
|
||||
cache_entry_in.tag <= to_tag(request_pa);
|
||||
cache_entry_in.valid <= '0';
|
||||
sn <= s;
|
||||
cache_ctrl_state_next <= cache_ctrl_state;
|
||||
|
||||
case s is
|
||||
case cache_ctrl_state is
|
||||
|
||||
when init =>
|
||||
sn <= ready;
|
||||
cache_ctrl_state_next <= ready;
|
||||
|
||||
when ready =>
|
||||
if invalidate_req = '1' then
|
||||
sn <= invalidate_init;
|
||||
cache_ctrl_state_next <= invalidate;
|
||||
invalidate_en <= '1';
|
||||
flush_load_en <= '1';
|
||||
if invalidate_all = '1' then
|
||||
flush_addr_preset <= (others=>'0'); -- all
|
||||
flush_count_preset <= 2**cache_index_width-1;
|
||||
else
|
||||
flush_addr_preset <= cache_index_inv; -- at
|
||||
flush_count_preset <= 0;
|
||||
end if;
|
||||
elsif cache_req = '1' then
|
||||
if cache_hit = '0' then
|
||||
sn <= mem_request;
|
||||
CYC_O <= '1';
|
||||
else
|
||||
cache_busy <= '0';
|
||||
cache_ack <= '1';
|
||||
elsif mem_fetch_req = '1' then
|
||||
cache_ctrl_state_next <= bus_request;
|
||||
bus_cmd_cycle_en <= '1';
|
||||
end if;
|
||||
|
||||
when invalidate =>
|
||||
cache_ctrl_state_next <= rd_cache;
|
||||
invalidate_en <= '1';
|
||||
invalidate_ack <= '1';
|
||||
if invalidate_all = '1' then
|
||||
cache_ctrl_state_next <= flush;
|
||||
flush_count_rst <= '1';
|
||||
elsif cache_hit_inv = '1' then
|
||||
tag_ram_we <= '1';
|
||||
cache_entry_in.valid <= '0';
|
||||
cache_entry_in.tag <= (others => '0');
|
||||
cache_ctrl_state_next <= invalidate_post;
|
||||
end if;
|
||||
|
||||
when flush =>
|
||||
flush_count_en <= '1';
|
||||
invalidate_en <= '1';
|
||||
tag_ram_we <= '1';
|
||||
cache_entry_in.valid <= '0';
|
||||
cache_entry_in.tag <= (others => '0');
|
||||
if flush_count_rdy = '1' then
|
||||
tag_ram_we <= '0';
|
||||
cache_ctrl_state_next <= invalidate_post;
|
||||
end if;
|
||||
|
||||
when invalidate_post =>
|
||||
was_miss <= '1';
|
||||
cache_ctrl_state_next <= ready;
|
||||
|
||||
when bus_request =>
|
||||
bus_cmd_cycle_en <= '1';
|
||||
if bus_cmd_rdy = '1' then
|
||||
cache_ctrl_state_next <= mem_read;
|
||||
if request_nc = '1' then
|
||||
cache_ctrl_state_next <= mem_read_single;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
when invalidate_init =>
|
||||
invalidate_en <= '1';
|
||||
sn <= invalidate;
|
||||
|
||||
when invalidate =>
|
||||
sn <= rd_cache;
|
||||
invalidate_en <= '1';
|
||||
invalidate_ack <= '1';
|
||||
if cache_hit_inv = '1' or invalidate_all = '1' then
|
||||
sn <= flush;
|
||||
end if;
|
||||
|
||||
when flush =>
|
||||
flush_count_en <= '1';
|
||||
invalidate_en <= '1';
|
||||
tag_ram_we <= '1';
|
||||
cache_entry_in.valid <= '0';
|
||||
cache_entry_in.tag <= (others => '0');
|
||||
if flush_count_rdy = '1' then
|
||||
tag_ram_we <= '0';
|
||||
sn <= rd_cache;
|
||||
end if;
|
||||
when mem_request =>
|
||||
CYC_O <= '1';
|
||||
if SRDY_I = '1' then
|
||||
sn <= mem_access;
|
||||
end if;
|
||||
when mem_access =>
|
||||
end if;
|
||||
|
||||
when mem_read =>
|
||||
bus_cmd_cycle_en <= '1';
|
||||
bus_cmd_we <= '1';
|
||||
request_count_en <= '1';
|
||||
ram_write_en <= '1';
|
||||
fill_count_en <= '1';
|
||||
CYC_O <= '1';
|
||||
STB_O <= '1';
|
||||
if request_count_rdy = '1' then
|
||||
STB_O <= '0';
|
||||
sn <= mem_data;
|
||||
bus_cmd_we <= '0';
|
||||
cache_ctrl_state_next <= mem_read_data;
|
||||
end if;
|
||||
when mem_data =>
|
||||
CYC_O <= '1';
|
||||
fill_count_en <= '1';
|
||||
|
||||
when mem_read_single =>
|
||||
mem_fetch_ack <= '1';
|
||||
bus_cmd_cycle_en <= '1';
|
||||
bus_cmd_we <= '1';
|
||||
cache_ctrl_state_next <= mem_read_data_single;
|
||||
|
||||
when mem_read_data =>
|
||||
bus_cmd_cycle_en <= '1';
|
||||
fill_count_en <= '1';
|
||||
ram_write_en <= '1';
|
||||
if fill_count_rdy = '1' then
|
||||
tag_ram_we <= '1';
|
||||
cache_entry_in.valid <= '1';
|
||||
sn <= rd_cache;
|
||||
cache_ctrl_state_next <= rd_cache;
|
||||
end if;
|
||||
|
||||
when mem_read_data_single =>
|
||||
bus_cmd_cycle_en <= '1';
|
||||
if bus_din_vld = '1' then
|
||||
cache_ctrl_state_next <= ready;
|
||||
end if;
|
||||
|
||||
when rd_cache =>
|
||||
mem_fetch_ack <= '1';
|
||||
was_miss <= '1';
|
||||
sn <= ready;
|
||||
cache_ctrl_state_next <= ready;
|
||||
|
||||
when others =>
|
||||
sn <= ready;
|
||||
cache_ctrl_state_next <= ready;
|
||||
end case;
|
||||
|
||||
end process;
|
||||
|
||||
flush_counter:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if flush_load_en = '1' then
|
||||
flush_count_rdy <= '0';
|
||||
flush_count <= flush_count_preset;
|
||||
flush_addr <= flush_addr_preset;
|
||||
elsif flush_count_en = '1' then
|
||||
if flush_count /= 0 then
|
||||
flush_count <= flush_count - 1;
|
||||
flush_addr <= flush_addr + 1;
|
||||
else
|
||||
flush_count_rdy <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
flush_counter:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if ctrl_in.inv_at = '1' then
|
||||
flush_count <= to_integer(cache_index_inv);
|
||||
elsif flush_count_rst = '1' then
|
||||
flush_count_rdy <= '0';
|
||||
flush_count <= 2**cache_index_width-1;
|
||||
elsif flush_count_en = '1' then
|
||||
if flush_count /= 0 then
|
||||
flush_count <= flush_count - 1;
|
||||
else
|
||||
flush_count_rdy <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
request_counter:
|
||||
process(CLK_I)
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if rising_edge(clk) then
|
||||
if request_count_en = '0' then
|
||||
request_count_rdy <= '0';
|
||||
request_count <= 2**word_index_width-1;
|
||||
else
|
||||
if SRDY_I = '1' then
|
||||
if bus_cmd_rdy = '1' then
|
||||
if request_count /= 0 then
|
||||
request_count <= request_count - 1;
|
||||
else
|
||||
@@ -495,14 +640,14 @@ request_counter:
|
||||
end process;
|
||||
|
||||
fill_counter:
|
||||
process(CLK_I)
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if rising_edge(clk) then
|
||||
if fill_count_en = '0' then
|
||||
fill_count_rdy <= '0';
|
||||
fill_count <= 2**word_index_width-1;
|
||||
else
|
||||
if ACK_I_r = '1' then
|
||||
if bus_din_vld = '1' then
|
||||
if fill_count /= 0 then
|
||||
fill_count <= fill_count - 1;
|
||||
else
|
||||
|
||||
@@ -27,30 +27,30 @@ use IEEE.numeric_std.ALL;
|
||||
library work;
|
||||
use work.mips_types.all;
|
||||
use work.mips_instr.all;
|
||||
use work.mips_util_pkg.all;
|
||||
|
||||
entity pipeline is
|
||||
Port
|
||||
(
|
||||
rst : in STD_LOGIC;
|
||||
clk : in STD_LOGIC;
|
||||
ce : in STD_LOGIC;
|
||||
imem_rdy : in STD_LOGIC;
|
||||
imem_en : out STD_LOGIC;
|
||||
imem_addr : out word_t;
|
||||
imem_data : in word_t;
|
||||
dmem_rdy : in STD_LOGIC;
|
||||
dmem_en : out STD_LOGIC;
|
||||
dmem_we : out STD_LOGIC;
|
||||
dmem_be : out unsigned(3 downto 0);
|
||||
dmem_addr : out word_t;
|
||||
dmem_din : in word_t;
|
||||
dmem_dout : out word_t;
|
||||
cop_ir : out word_t;
|
||||
cop_ir_en : out STD_LOGIC;
|
||||
cop_din : in word_t;
|
||||
cop_dout : out word_t;
|
||||
c0_ctrl_out : out cop0_ctrl_in_t;
|
||||
c0_ctrl_in : in cop0_ctrl_out_t
|
||||
rst : in STD_LOGIC;
|
||||
clk : in STD_LOGIC;
|
||||
ce : in STD_LOGIC;
|
||||
imem_err : in STD_LOGIC;
|
||||
dmem_err : in STD_LOGIC;
|
||||
cop_ir : out word_t;
|
||||
cop_ir_en : out STD_LOGIC;
|
||||
cop_din : in word_t;
|
||||
cop_dout : out word_t;
|
||||
ctrl_out : out pipe_ctrl_out_t;
|
||||
ctrl_in : in pipe_ctrl_in_t;
|
||||
dtlb_qry_out : out tlb_query_in_t;
|
||||
dtlb_qry_in : in tlb_query_out_t;
|
||||
dcache_qry_out : out dcache_query_in_t;
|
||||
dcache_qry_in : in dcache_query_out_t;
|
||||
itlb_qry_out : out tlb_query_in_t;
|
||||
itlb_qry_in : in tlb_query_out_t;
|
||||
icache_qry_out : out icache_query_in_t;
|
||||
icache_qry_in : in icache_query_out_t
|
||||
|
||||
);
|
||||
end pipeline;
|
||||
@@ -146,87 +146,78 @@ architecture Behavioral of pipeline is
|
||||
signal EX_stage : EX_t;
|
||||
signal MEM_stage : MEM_t;
|
||||
signal WB_stage : WB_t;
|
||||
signal clk_2, clk_1 : STD_LOGIC;
|
||||
signal hdu : hdu_t;
|
||||
signal sdu : sdu_t;
|
||||
signal reg_a : word_t;
|
||||
signal reg_b : word_t;
|
||||
signal branch_taken : STD_LOGIC;
|
||||
signal branch_ce : STD_LOGIC;
|
||||
signal cpu_run : STD_LOGIC;
|
||||
signal alu_result : word_t;
|
||||
signal mul_result : word_t;
|
||||
signal mul_busy : STD_LOGIC;
|
||||
signal EX_events_instr : event_t;
|
||||
signal EX_events_alu : event_t;
|
||||
signal EX_events_mem : event_t;
|
||||
signal EX_events_DTLB : event_t;
|
||||
signal EX_events : event_t;
|
||||
signal MEM_events : event_t;
|
||||
signal bcu_op_a : word_t;
|
||||
signal bcu_op_b : word_t;
|
||||
signal bcu_flags : bcu_flags_t;
|
||||
signal vaddr : word_t;
|
||||
signal dmem_src : word_t;
|
||||
|
||||
signal pc : pc_t;
|
||||
signal pc_branch : word_t;
|
||||
signal pc_curr : word_t;
|
||||
signal pc_last : word_t;
|
||||
signal pc_nxt : word_t;
|
||||
signal pc_branch_take : STD_LOGIC;
|
||||
signal ID_ctrl_branch : STD_LOGIC;
|
||||
signal EX_ctrl_branch : STD_LOGIC;
|
||||
signal MEM_ctrl_branch : STD_LOGIC;
|
||||
signal sdu_ID_stall : STD_LOGIC;
|
||||
signal sdu_ID_nop : STD_LOGIC;
|
||||
signal c0_ctrl_in_exc_pending : STD_LOGIC;
|
||||
signal c0_ctrl_in_exc_inject : STD_LOGIC;
|
||||
signal stage_rst : unsigned(3 downto 0);
|
||||
signal pipe_rst : STD_LOGIC;
|
||||
|
||||
signal pc : pc_t;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
begin
|
||||
|
||||
clk_1 <= clk;
|
||||
clk_2 <= not clk;
|
||||
cpu_run <= ce;
|
||||
|
||||
-- Stall Detection Unit ---------------------------------------------------
|
||||
sdu.ID_nop <= sdu.imem_dep or c0_ctrl_in.exc_pending or ID_stage.exc or EX_stage.exc or MEM_stage.exc;
|
||||
sdu.ID_nop <= sdu.imem_dep or ctrl_in.exc_pending or ID_stage.exc or EX_stage.exc or MEM_stage.exc; -- or pc.branch_not_taken;
|
||||
sdu.EX_nop <= sdu.mul_dep or ID_stage.nop or ID_stage.exc;
|
||||
sdu.MEM_nop <= EX_stage.nop or EX_stage.exc;
|
||||
sdu.WB_nop <= sdu.dmem_dep or MEM_stage.nop;
|
||||
sdu.WB_nop <= sdu.dmem_dep or MEM_stage.exc or WB_stage.exc or ctrl_in.exc_pending;
|
||||
|
||||
sdu.stall_all <= sdu.dmem_dep;
|
||||
sdu.ID_stall <= sdu.stall_all or sdu.imem_dep or sdu.mul_dep or c0_ctrl_in.exc_exit;
|
||||
sdu.ID_stall <= sdu.stall_all or sdu.imem_dep or sdu.mul_dep or ctrl_in.exc_exit;
|
||||
sdu.EX_stall <= sdu.stall_all;
|
||||
sdu.MEM_stall <= sdu.stall_all;
|
||||
sdu.WB_stall <= sdu.stall_all;
|
||||
sdu.WB_stall <= '0';
|
||||
|
||||
sdu.mul_dep <= ID_stage.ctrl.mul_access and (EX_stage.ctrl.mul_start or mul_busy);
|
||||
sdu.imem_dep <= not imem_rdy;
|
||||
sdu.dmem_dep <= not dmem_rdy and MEM_stage.ctrl.dmem_en;
|
||||
sdu.imem_dep <= not icache_qry_in.rdy;
|
||||
sdu.dmem_dep <= not dcache_qry_in.rdy and MEM_stage.ctrl.dmem_en;
|
||||
---------------------------------------------------------------------------
|
||||
imem_en <= ce and not (sdu.mul_dep or sdu.dmem_dep or c0_ctrl_in.exc_commit);
|
||||
pc_branch <= pc.pc_branch;
|
||||
pc_curr <= pc.curr;
|
||||
pc_last <= pc.last;
|
||||
pc_nxt <= pc.nxt;
|
||||
pc_branch_take <= pc.branch_take;
|
||||
ID_ctrl_branch <= ID_stage.ctrl.branch;
|
||||
EX_ctrl_branch <= EX_stage.ctrl.branch;
|
||||
MEM_ctrl_branch <= MEM_stage.ctrl.branch;
|
||||
sdu_ID_stall <= sdu.ID_stall;
|
||||
sdu_ID_nop <= sdu.ID_nop;
|
||||
c0_ctrl_in_exc_pending <= c0_ctrl_in.exc_pending;
|
||||
c0_ctrl_in_exc_inject <= c0_ctrl_in.exc_inject;
|
||||
itlb_qry_out.vld <= (not sdu.ID_stall or ctrl_in.exc_inject);
|
||||
itlb_qry_out.write <= '0';
|
||||
itlb_qry_out.vaddr <= pc.nxt;
|
||||
|
||||
icache_qry_out.addr <= itlb_qry_in.paddr;
|
||||
icache_qry_out.en <= cpu_run and not (sdu.mul_dep or sdu.dmem_dep or ctrl_in.exc_commit);
|
||||
icache_qry_out.nc <= itlb_qry_in.flags.N;
|
||||
|
||||
dtlb_qry_out.vld <= ID_stage.ctrl.dmem_en and not sdu.dmem_dep;
|
||||
dtlb_qry_out.write <= ID_stage.ctrl.dmem_we;
|
||||
dtlb_qry_out.vaddr <= ID_stage.va;
|
||||
|
||||
dcache_qry_out.be <= store_be(EX_stage.pa_off, EX_stage.ctrl.dmem_en, EX_stage.ctrl.word2_en, EX_stage.ctrl.word4_en, EX_stage.ctrl.align_left, EX_stage.ctrl.shift_byp);
|
||||
dcache_qry_out.en <= EX_stage.dmem_en;
|
||||
dcache_qry_out.we <= EX_stage.ctrl.dmem_we;
|
||||
dcache_qry_out.data <= store_shift(EX_stage.reg_b, EX_stage.pa_off, EX_stage.ctrl.shift_offset, EX_stage.ctrl.shift_byp);
|
||||
dcache_qry_out.addr <= dtlb_qry_in.paddr;
|
||||
dcache_qry_out.nc <= dtlb_qry_in.flags.N;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
-- Coprocessor assignments
|
||||
--------------------------------------------------------------------------
|
||||
c0_ctrl_out.bd_wb <= WB_stage.bd;
|
||||
c0_ctrl_out.epc_mem <= MEM_stage.pcn;
|
||||
c0_ctrl_out.epc_wb <= MEM_stage.epc;
|
||||
c0_ctrl_out.imem_addr <= EX_stage.epc;
|
||||
c0_ctrl_out.dmem_addr <= MEM_stage.va;
|
||||
c0_ctrl_out.sdu <= sdu;
|
||||
c0_ctrl_out.events <= WB_stage.events;
|
||||
c0_ctrl_out.exc_req <= MEM_stage.exc;
|
||||
c0_ctrl_out.exc_ack <= WB_stage.exc;
|
||||
ctrl_out.sdu <= sdu;
|
||||
ctrl_out.exc_req <= WB_stage.exc and not WB_stage.exc_last;
|
||||
ctrl_out.exc_ack <= '1';
|
||||
cop_ir <= ID_stage.IR;
|
||||
cop_ir_en <= ID_stage.ctrl.cop_instr_en;
|
||||
cop_dout <= dmem_din when MEM_stage.ctrl.dmem_en = '1' else MEM_stage.ex_result;
|
||||
cop_dout <= EX_stage.reg_b;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
-- Muldiv
|
||||
@@ -250,90 +241,191 @@ inst_muldiv: muldiv
|
||||
--------------------------------------------------------------------------
|
||||
-- IF stage
|
||||
--------------------------------------------------------------------------
|
||||
imem_addr <= pc.curr;
|
||||
|
||||
proc_stage_pc_next:
|
||||
process(clk)
|
||||
pipe_rst <= stage_rst(0);
|
||||
|
||||
proc_stage_reset:
|
||||
process(clk_1)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if c0_ctrl_in.exc_inject = '1' then
|
||||
pc.nxt <= c0_ctrl_in.exc_vec;
|
||||
elsif sdu.ID_stall = '0' then
|
||||
pc.last <= pc.curr;
|
||||
if ID_stage.ctrl.jump = '1' then
|
||||
pc.nxt <= ID_stage.jimm32;
|
||||
elsif ID_stage.ctrl.jump_long = '1' then
|
||||
pc.nxt <= ID_stage.reg_a;
|
||||
else
|
||||
pc.nxt <= pc.curr + 4;
|
||||
end if;
|
||||
end if;
|
||||
if rising_edge(clk_1) then
|
||||
if rst = '1' then
|
||||
stage_rst <= (others => '1');
|
||||
else
|
||||
stage_rst <= stage_rst(stage_rst'left-1 downto 0) & '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
proc_stage_branch:
|
||||
process(EX_stage, bcu_flags)
|
||||
--------------------------------------------------------------------------
|
||||
-- pc
|
||||
--------------------------------------------------------------------------
|
||||
inst_bcu_alt_ID: bcu
|
||||
GENERIC MAP
|
||||
(
|
||||
data_width => word_t'length
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
op1_in => ID_stage.reg_a,
|
||||
op2_in => ID_stage.reg_b,
|
||||
flags => ID_stage.bcu_flags
|
||||
);
|
||||
|
||||
inst_bcu_alt_EX: bcu
|
||||
GENERIC MAP
|
||||
(
|
||||
data_width => word_t'length
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
op1_in => EX_stage.reg_a,
|
||||
op2_in => EX_stage.reg_b,
|
||||
flags => EX_stage.bcu_flags
|
||||
);
|
||||
|
||||
|
||||
proc_stage_branch_alt:
|
||||
process(ID_stage)
|
||||
begin
|
||||
pc.branch_take <= '0';
|
||||
if EX_stage.ctrl.branch = '1' then
|
||||
if ID_stage.ctrl.branch = '1' then
|
||||
|
||||
case EX_stage.ctrl.bc_src is
|
||||
case ID_stage.ctrl.bc_src is
|
||||
|
||||
when bc_eq_ne =>
|
||||
pc.branch_take <= EX_stage.ctrl.bc_not xor bcu_flags.eq;
|
||||
pc.branch_take <= ID_stage.ctrl.bc_not xor ID_stage.bcu_flags.eq;
|
||||
|
||||
when bc_lez_gtz =>
|
||||
pc.branch_take <= EX_stage.ctrl.bc_not xor (bcu_flags.eq or bcu_flags.ltz);
|
||||
pc.branch_take <= ID_stage.ctrl.bc_not xor (ID_stage.bcu_flags.eq or ID_stage.bcu_flags.ltz);
|
||||
|
||||
when bc_ltz_gez =>
|
||||
pc.branch_take <= EX_stage.ctrl.bc_not xor bcu_flags.ltz;
|
||||
pc.branch_take <= ID_stage.ctrl.bc_not xor ID_stage.bcu_flags.ltz;
|
||||
|
||||
when others => null;
|
||||
end case;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
proc_stage_branch_taken:
|
||||
process(clk)
|
||||
proc_stage_branch_not:
|
||||
process(EX_stage)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if branch_taken = '0' then
|
||||
if sdu.ID_stall = '1' or c0_ctrl_in.exc_inject = '1' then
|
||||
if pc.branch_take = '1' then
|
||||
branch_taken <= '1';
|
||||
end if;
|
||||
end if;
|
||||
elsif sdu.ID_stall = '0' then
|
||||
branch_taken <= '0';
|
||||
EX_stage.branch_not_taken <= '0';
|
||||
|
||||
case EX_stage.ctrl.bc_src is
|
||||
|
||||
when bc_eq_ne =>
|
||||
EX_stage.branch_not_taken <= EX_stage.ctrl.branch and not(EX_stage.ctrl.bc_not xor EX_stage.bcu_flags.eq);
|
||||
|
||||
when bc_lez_gtz =>
|
||||
EX_stage.branch_not_taken <= EX_stage.ctrl.branch and not(EX_stage.ctrl.bc_not xor (EX_stage.bcu_flags.eq or EX_stage.bcu_flags.ltz));
|
||||
|
||||
when bc_ltz_gez =>
|
||||
EX_stage.branch_not_taken <= EX_stage.ctrl.branch and not(EX_stage.ctrl.bc_not xor EX_stage.bcu_flags.ltz);
|
||||
|
||||
when others => null;
|
||||
end case;
|
||||
end process;
|
||||
|
||||
-- proc_stage_pc_next_alt:
|
||||
process(ctrl_in, sdu, pc, ID_stage, EX_stage)
|
||||
begin
|
||||
-- pc.nxt <= ctrl_in.exc_vec;
|
||||
-- if ctrl_in.exc_inject = '0' then
|
||||
pc.nxt <= pc.plus4;
|
||||
if ID_stage.ctrl.jump = '1' then
|
||||
pc.nxt <= ID_stage.jimm32;
|
||||
elsif ID_stage.ctrl.jump_long = '1' then
|
||||
pc.nxt <= ID_stage.reg_a;
|
||||
elsif pc.branch_take = '1' then
|
||||
pc.nxt <= pc.pc_branch;
|
||||
end if;
|
||||
-- end if;
|
||||
end process;
|
||||
|
||||
-- always branch in ID and revert in EX
|
||||
-- proc_stage_pc_next_alt:
|
||||
-- process(ctrl_in, sdu, ID_stage, EX_stage, pc)
|
||||
-- begin
|
||||
-- if EX_stage.branch_not_taken = '1' then
|
||||
-- pc.nxt <= pc.pc_branch_revert;
|
||||
-- else
|
||||
-- pc.nxt <= pc.plus4;
|
||||
-- if ID_stage.ctrl.jump = '1' then
|
||||
-- pc.nxt <= ID_stage.jimm32;
|
||||
-- elsif ID_stage.ctrl.jump_long = '1' then
|
||||
-- pc.nxt <= ID_stage.reg_a;
|
||||
-- elsif ID_stage.ctrl.branch = '1' then -- always take branch
|
||||
-- pc.nxt <= pc.pc_branch;
|
||||
-- end if;
|
||||
-- end if;
|
||||
-- end process;
|
||||
|
||||
proc_stage_pc_plus_4_alt:
|
||||
process(clk_2)
|
||||
begin
|
||||
if rising_edge(clk_2) then
|
||||
if rst = '1' then
|
||||
pc.plus4 <= ctrl_in.exc_vec;
|
||||
elsif cpu_run = '1' then
|
||||
if ctrl_in.exc_inject = '1' then
|
||||
pc.plus4 <= ctrl_in.exc_vec;
|
||||
else
|
||||
pc.plus4 <= pc.curr + 4;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
proc_stage_pc_branch:
|
||||
process(clk)
|
||||
proc_stage_pc_branch_alt:
|
||||
process(clk_2)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if sdu.ID_stall = '0' and ID_stage.ctrl.branch = '1' then
|
||||
if rising_edge(clk_2) then
|
||||
if cpu_run = '1' then
|
||||
pc.pc_branch <= pc.curr + ID_stage.bimm18;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
proc_stage_pc:
|
||||
process(pc, branch_taken)
|
||||
proc_stage_pc_curr_alt:
|
||||
process(clk_1)
|
||||
begin
|
||||
if pc.branch_take = '1' or branch_taken = '1' then
|
||||
pc.curr <= pc.pc_branch;
|
||||
else
|
||||
pc.curr <= pc.nxt;
|
||||
if rising_edge(clk_1) then
|
||||
if rst = '1' then
|
||||
pc.curr <= ctrl_in.exc_vec;
|
||||
pc.last <= ctrl_in.exc_vec;
|
||||
elsif cpu_run = '1' and (sdu.ID_stall = '0' or ctrl_in.exc_inject = '1') then
|
||||
pc.last <= pc.curr;
|
||||
pc.curr <= pc.nxt;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
proc_stage_pc_revert_alt:
|
||||
process(clk_1)
|
||||
begin
|
||||
if rising_edge(clk_1) then
|
||||
if cpu_run = '1' and (sdu.ID_stall = '0' or ctrl_in.exc_inject = '1') then
|
||||
if ID_stage.ctrl.branch = '1' then
|
||||
pc.pc_branch_revert <= pc.plus4;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
proc_stage_branch_not_taken_alt:
|
||||
process(clk_1)
|
||||
begin
|
||||
if rising_edge(clk_1) then
|
||||
if cpu_run = '1' and (sdu.ID_stall = '0' or ctrl_in.exc_inject = '1') then
|
||||
pc.branch_not_taken <= EX_stage.branch_not_taken;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
-- ID stage
|
||||
--------------------------------------------------------------------------
|
||||
ID_stage.IR <= to_01(imem_data);
|
||||
ID_stage.IR <= to_01(icache_qry_in.data);
|
||||
ID_stage.pcn <= pc.curr;
|
||||
ID_stage.op <= decode_op(ID_stage.IR);
|
||||
ID_stage.jimm32 <= extract_jimm32(ID_stage.IR, ID_stage.pcn);
|
||||
@@ -346,13 +438,25 @@ proc_stage_pc:
|
||||
ID_stage.epc <= pc.last;
|
||||
ID_stage.exc <= event_is_active(ID_stage.events); -- Todo: works
|
||||
ID_stage.nop <= sdu.ID_nop;
|
||||
ID_stage.va <= ID_stage.reg_a + extract_simm32(ID_stage.IR);
|
||||
|
||||
ID_stage_tlb_query_results:
|
||||
process(clk_1)
|
||||
begin
|
||||
if rising_edge(clk_1) then
|
||||
ID_stage.itlb_qry <= itlb_qry_in;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
proc_ID_except:
|
||||
process(ID_stage, c0_ctrl_in, pc)
|
||||
process(ID_stage, ctrl_in, pc)
|
||||
begin
|
||||
ID_stage.events <= events_clr;
|
||||
ID_stage.events.inst_load_err <= not c0_ctrl_in.exc_pending and (pc.nxt(1) or pc.nxt(0));
|
||||
ID_stage.events.inst_priv_addr <= not c0_ctrl_in.exc_pending and (pc.nxt(word_t'left) and c0_ctrl_in.user_mode);
|
||||
ID_stage.events.inst_load_err <= not ctrl_in.exc_pending and (ID_stage.pcn(1) or ID_stage.pcn(0));
|
||||
ID_stage.events.inst_priv_addr <= not ctrl_in.exc_pending and (ID_stage.pcn(word_t'left) and ctrl_in.user_mode);
|
||||
ID_stage.events.ITLB_LOAD <= not ctrl_in.exc_pending and ID_stage.itlb_qry.vld and ID_stage.itlb_qry.miss and not ID_stage.itlb_qry.write;
|
||||
ID_stage.events.ITLB_STORE <= not ctrl_in.exc_pending and ID_stage.itlb_qry.vld and ID_stage.itlb_qry.miss and ID_stage.itlb_qry.write;
|
||||
ID_stage.events.ITLB_MOD <= not ctrl_in.exc_pending and ID_stage.itlb_qry.vld and ID_stage.itlb_qry.dirty;
|
||||
end process;
|
||||
|
||||
proc_stage_hdu:
|
||||
@@ -366,19 +470,19 @@ proc_stage_hdu:
|
||||
|
||||
reg_ptr_a := ID_stage.reg_a_rptr;
|
||||
reg_ptr_b := ID_stage.reg_b_rptr;
|
||||
raw_a_EX := reg_ptr_a = EX_stage.reg_wptr and EX_stage.wreg_we = '1';
|
||||
raw_a_MEM := reg_ptr_a = MEM_stage.reg_wptr and MEM_stage.wreg_we = '1';
|
||||
raw_a_WB := reg_ptr_a = WB_stage.reg_wptr and WB_stage.wreg_we = '1';
|
||||
raw_b_EX := reg_ptr_b = EX_stage.reg_wptr and EX_stage.wreg_we = '1';
|
||||
raw_b_MEM := reg_ptr_b = MEM_stage.reg_wptr and MEM_stage.wreg_we = '1';
|
||||
raw_b_WB := reg_ptr_b = WB_stage.reg_wptr and WB_stage.wreg_we = '1';
|
||||
raw_a_EX := reg_ptr_a = EX_stage.reg_wptr and EX_stage.reg_we = '1';
|
||||
raw_a_MEM := reg_ptr_a = MEM_stage.reg_wptr and MEM_stage.reg_we = '1';
|
||||
raw_a_WB := reg_ptr_a = WB_stage.reg_wptr and WB_stage.reg_we = '1';
|
||||
raw_b_EX := reg_ptr_b = EX_stage.reg_wptr and EX_stage.reg_we = '1';
|
||||
raw_b_MEM := reg_ptr_b = MEM_stage.reg_wptr and MEM_stage.reg_we = '1';
|
||||
raw_b_WB := reg_ptr_b = WB_stage.reg_wptr and WB_stage.reg_we = '1';
|
||||
|
||||
hdu.alu_fwd_a_ex <= raw_a_EX;
|
||||
hdu.alu_fwd_a_mem <= raw_a_MEM;
|
||||
hdu.alu_fwd_a_wb <= raw_a_WB;
|
||||
hdu.alu_fwd_b_ex <= raw_b_EX;
|
||||
hdu.alu_fwd_b_mem <= raw_b_MEM;
|
||||
hdu.alu_fwd_b_wb <= raw_b_WB;
|
||||
hdu.alu_fwd_a_ex <= raw_a_EX after 1 ns;
|
||||
hdu.alu_fwd_a_mem <= raw_a_MEM after 1 ns;
|
||||
hdu.alu_fwd_a_wb <= raw_a_WB after 1 ns;
|
||||
hdu.alu_fwd_b_ex <= raw_b_EX after 1 ns;
|
||||
hdu.alu_fwd_b_mem <= raw_b_MEM after 1 ns;
|
||||
hdu.alu_fwd_b_wb <= raw_b_WB after 1 ns;
|
||||
|
||||
end process;
|
||||
|
||||
@@ -390,18 +494,12 @@ proc_stage_fwd_a:
|
||||
if hdu.alu_fwd_a_ex then
|
||||
data := EX_stage.result;
|
||||
elsif hdu.alu_fwd_a_mem then
|
||||
data := MEM_stage.data;
|
||||
data := MEM_stage.result;
|
||||
elsif hdu.alu_fwd_a_wb then
|
||||
data := WB_stage.data;
|
||||
data := WB_stage.result;
|
||||
end if;
|
||||
|
||||
for i in 0 to 31 loop
|
||||
if data(i) = '1' then
|
||||
ID_stage.reg_a(i) <= '1';
|
||||
else
|
||||
ID_stage.reg_a(i) <= '0';
|
||||
end if;
|
||||
end loop;
|
||||
ID_stage.reg_a <= to_mips_01(data) after 1 ns;
|
||||
|
||||
end process;
|
||||
|
||||
@@ -413,18 +511,12 @@ proc_stage_fwd_b:
|
||||
if hdu.alu_fwd_b_ex then
|
||||
data := EX_stage.result;
|
||||
elsif hdu.alu_fwd_b_mem then
|
||||
data := MEM_stage.data;
|
||||
data := MEM_stage.result;
|
||||
elsif hdu.alu_fwd_b_wb then
|
||||
data := WB_stage.data;
|
||||
data := WB_stage.result;
|
||||
end if;
|
||||
|
||||
for i in 0 to 31 loop
|
||||
if data(i) = '1' then
|
||||
ID_stage.reg_b(i) <= '1';
|
||||
else
|
||||
ID_stage.reg_b(i) <= '0';
|
||||
end if;
|
||||
end loop;
|
||||
ID_stage.reg_b <= to_mips_01(data) after 1 ns;
|
||||
|
||||
end process;
|
||||
|
||||
@@ -449,7 +541,7 @@ proc_imm_mux:
|
||||
|
||||
end case;
|
||||
|
||||
ID_stage.imm <= data;
|
||||
ID_stage.imm <= data after 1 ns;
|
||||
|
||||
end process;
|
||||
|
||||
@@ -462,11 +554,11 @@ inst_reg_dual: reg_dual
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
clk_w => clk,
|
||||
we => WB_stage.wreg_we,
|
||||
clk_w => clk_1,
|
||||
we => WB_stage.reg_we,
|
||||
en => '1',
|
||||
wptr => WB_stage.reg_wptr,
|
||||
din => WB_stage.data,
|
||||
din => WB_stage.result,
|
||||
rptr_a => ID_stage.reg_a_rptr,
|
||||
rptr_b => ID_stage.reg_b_rptr,
|
||||
dout_a => reg_a,
|
||||
@@ -479,13 +571,13 @@ inst_reg_dual: reg_dual
|
||||
EX_stage.reg_a_rptr <= extract_rs(EX_stage.IR);
|
||||
EX_stage.reg_b_rptr <= extract_rt(EX_stage.IR);
|
||||
EX_stage.result <= alu_result when EX_stage.ctrl.mul_access = '0' else mul_result;
|
||||
EX_stage.dtlb_qry <= dtlb_qry_in;
|
||||
|
||||
proc_stage_ID_EX_1:
|
||||
process(clk)
|
||||
process(clk_1)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
EX_stage.nop <= '1';
|
||||
if rising_edge(clk_1) then
|
||||
if stage_rst(1) = '1' then
|
||||
EX_stage.op <= op_nop;
|
||||
EX_stage.IR <= (others => '0');
|
||||
EX_stage.ctrl <= ctrl_lines_default;
|
||||
@@ -493,22 +585,20 @@ proc_stage_ID_EX_1:
|
||||
EX_stage.epc <= (others => '0');
|
||||
EX_stage.pcn <= (others => '0');
|
||||
EX_stage.events_in <= events_clr;
|
||||
EX_stage.reg_a <= (others => '0');
|
||||
EX_stage.reg_b <= (others => '0');
|
||||
elsif sdu.EX_stall = '0' then
|
||||
EX_stage.va <= vaddr;
|
||||
EX_stage.nop <= sdu.EX_nop;
|
||||
EX_stage.op <= ID_stage.op;
|
||||
EX_stage.IR <= ID_stage.IR;
|
||||
EX_stage.va <= ID_stage.va;
|
||||
|
||||
EX_stage.reg_a <= ID_stage.reg_a;
|
||||
EX_stage.reg_b <= ID_stage.reg_b;
|
||||
EX_stage.events_in <= ID_stage.events;
|
||||
EX_stage.op <= ID_stage.op;
|
||||
EX_stage.ctrl <= ID_stage.ctrl;
|
||||
EX_stage.reg_write <= ID_stage.reg_write;
|
||||
EX_stage.IR <= ID_stage.IR;
|
||||
EX_stage.pcn <= ID_stage.pcn;
|
||||
EX_stage.epc <= ID_stage.epc;
|
||||
if sdu.EX_nop = '1' then
|
||||
EX_stage.op <= op_nop;
|
||||
EX_stage.IR <= (others => '0');
|
||||
EX_stage.ctrl <= ctrl_lines_default;
|
||||
EX_stage.reg_write <= '0';
|
||||
@@ -526,6 +616,15 @@ proc_stage_EX_instr_except:
|
||||
EX_events_instr.syscall <= EX_stage.ctrl.exc_syscall;
|
||||
end process;
|
||||
|
||||
proc_stage_EX_DTLB_except:
|
||||
process(EX_stage)
|
||||
begin
|
||||
EX_events_DTLB <= events_clr;
|
||||
EX_events_DTLB.DTLB_LOAD <= EX_stage.dtlb_qry.vld and EX_stage.dtlb_qry.miss and not EX_stage.dtlb_qry.write;
|
||||
EX_events_DTLB.DTLB_STORE <= EX_stage.dtlb_qry.vld and EX_stage.dtlb_qry.miss and EX_stage.dtlb_qry.write;
|
||||
EX_events_DTLB.DTLB_MOD <= EX_stage.dtlb_qry.vld and EX_stage.dtlb_qry.dirty;
|
||||
end process;
|
||||
|
||||
proc_stage_EX_alu_except:
|
||||
process(EX_stage)
|
||||
begin
|
||||
@@ -540,30 +639,28 @@ proc_stage_EX_alu_except:
|
||||
end if;
|
||||
end process;
|
||||
|
||||
vaddr <= ID_stage.reg_a + extract_simm32(ID_stage.IR);
|
||||
|
||||
proc_stage_EX_mem_except:
|
||||
process(clk)
|
||||
process(clk_1)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
dmem_en <= '0';
|
||||
if rising_edge(clk_1) then
|
||||
if pipe_rst = '1' then
|
||||
EX_stage.dmem_en <= '0';
|
||||
elsif sdu.EX_stall = '0' then
|
||||
EX_events_mem <= events_clr;
|
||||
dmem_en <= '0';
|
||||
EX_stage.dmem_en <= '0';
|
||||
if ID_stage.ctrl.dmem_en = '1' then
|
||||
dmem_en <= '1';
|
||||
EX_stage.dmem_en <= '1';
|
||||
if ID_stage.ctrl.except_en = '1' then
|
||||
if ID_stage.ctrl.word2_en = '1' then
|
||||
if vaddr(0) = '1' then
|
||||
if ID_stage.va(0) = '1' then
|
||||
EX_events_mem.data_load_err <= not ID_stage.ctrl.dmem_we;
|
||||
EX_events_mem.data_store_err <= ID_stage.ctrl.dmem_we;
|
||||
dmem_en <= '0';
|
||||
EX_stage.dmem_en <= '0';
|
||||
end if;
|
||||
elsif vaddr(1 downto 0) /= "00" then
|
||||
elsif ID_stage.va(1 downto 0) /= "00" then
|
||||
EX_events_mem.data_load_err <= not ID_stage.ctrl.dmem_we;
|
||||
EX_events_mem.data_store_err <= ID_stage.ctrl.dmem_we;
|
||||
dmem_en <= '0';
|
||||
EX_stage.dmem_en <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
@@ -572,28 +669,23 @@ proc_stage_EX_mem_except:
|
||||
end process;
|
||||
|
||||
proc_stage_DMEM_ADDR:
|
||||
process(clk)
|
||||
process(clk_1)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rising_edge(clk_1) then
|
||||
if sdu.EX_stall = '0' then
|
||||
if c0_ctrl_in.EB = '1' then
|
||||
if ctrl_in.EB = '1' then
|
||||
if ID_stage.ctrl.word2_en = '0' then
|
||||
EX_stage.pa_off <= not vaddr(1 downto 0);
|
||||
EX_stage.pa_off <= not ID_stage.va(1 downto 0);
|
||||
else
|
||||
EX_stage.pa_off <= not vaddr(1) & vaddr(0);
|
||||
EX_stage.pa_off <= not ID_stage.va(1) & ID_stage.va(0);
|
||||
end if;
|
||||
else
|
||||
EX_stage.pa_off <= vaddr(1 downto 0);
|
||||
EX_stage.pa_off <= ID_stage.va(1 downto 0);
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
dmem_src <= cop_din when EX_stage.ctrl.cop_instr_en = '1' else EX_stage.reg_b;
|
||||
dmem_be <= store_be(EX_stage.pa_off, EX_stage.ctrl.dmem_en, EX_stage.ctrl.word2_en, EX_stage.ctrl.word4_en, EX_stage.ctrl.align_left, EX_stage.ctrl.shift_byp);
|
||||
dmem_we <= EX_stage.ctrl.dmem_we;
|
||||
dmem_dout <= store_shift(dmem_src, EX_stage.pa_off, EX_stage.ctrl.shift_offset, EX_stage.ctrl.shift_byp);
|
||||
dmem_addr <= EX_stage.va;
|
||||
EX_stage.events <= EX_events_instr or EX_events_mem or EX_events_alu or EX_stage.events_in;
|
||||
EX_stage.events <= EX_events_DTLB or EX_events_instr or EX_events_mem or EX_events_alu or EX_stage.events_in;
|
||||
EX_stage.exc <= event_is_active(EX_stage.events);
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
@@ -611,19 +703,19 @@ proc_wptr_mux:
|
||||
reg_wptr := extract_rt(EX_stage.IR);
|
||||
end case;
|
||||
|
||||
EX_stage.wreg_we <= EX_stage.reg_write;
|
||||
EX_stage.reg_we <= EX_stage.reg_write after 1 ns;
|
||||
if reg_wptr = "00000" then
|
||||
EX_stage.wreg_we <= '0';
|
||||
EX_stage.reg_we <= '0' after 1 ns;
|
||||
end if;
|
||||
|
||||
EX_stage.reg_wptr <= reg_wptr;
|
||||
EX_stage.reg_wptr <= reg_wptr after 1 ns;
|
||||
case EX_stage.ctrl.wptr_srcsel is
|
||||
when wptr_src_imm =>
|
||||
EX_stage.reg_wptr <= reg_wptr;
|
||||
EX_stage.reg_wptr <= reg_wptr after 1 ns;
|
||||
|
||||
when wptr_src_const =>
|
||||
EX_stage.reg_wptr <= to_unsigned(31, reg_ptr_t'length);
|
||||
EX_stage.wreg_we <= '1';
|
||||
EX_stage.reg_wptr <= to_unsigned(31, reg_ptr_t'length) after 1 ns;
|
||||
EX_stage.reg_we <= '1' after 1 ns;
|
||||
|
||||
when others => null;
|
||||
end case;
|
||||
@@ -631,76 +723,62 @@ proc_wptr_mux:
|
||||
end process;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
proc_stage_bcu_op:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if sdu.EX_stall = '0' then
|
||||
bcu_op_a <= ID_stage.reg_a;
|
||||
bcu_op_b <= ID_stage.reg_b;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
EX_stage.alu_op1 <= EX_stage.reg_a;
|
||||
|
||||
alu_op2_mux:
|
||||
process(clk)
|
||||
process(clk_1)
|
||||
variable data : word_t;
|
||||
begin
|
||||
|
||||
if rising_edge(clk) then
|
||||
if sdu.EX_stall = '0' then
|
||||
if rising_edge(clk_1) and sdu.EX_stall = '0' then
|
||||
data := ID_stage.reg_b;
|
||||
|
||||
case ID_stage.ctrl.alu.op2_src is
|
||||
|
||||
when alu_src_reg =>
|
||||
data := ID_stage.reg_b;
|
||||
|
||||
case ID_stage.ctrl.alu.op2_src is
|
||||
when alu_src_imm =>
|
||||
data := ID_stage.imm;
|
||||
|
||||
when alu_src_reg =>
|
||||
data := ID_stage.reg_b;
|
||||
when others => null;
|
||||
|
||||
when alu_src_imm =>
|
||||
data := ID_stage.imm;
|
||||
end case;
|
||||
|
||||
when others => null;
|
||||
|
||||
end case;
|
||||
|
||||
EX_stage.alu_op2 <= data;
|
||||
end if;
|
||||
EX_stage.alu_op2 <= data;
|
||||
end if;
|
||||
|
||||
end process;
|
||||
|
||||
shifter_sa_mux:
|
||||
process(clk)
|
||||
process(clk_1)
|
||||
variable data : shamt_t;
|
||||
variable data_inv : shamt_t;
|
||||
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if sdu.EX_stall = '0' then
|
||||
data := ID_stage.reg_a(4 downto 0);
|
||||
case ID_stage.ctrl.shamt2_srcsel is
|
||||
if rising_edge(clk_1) and sdu.EX_stall = '0' then
|
||||
data := ID_stage.reg_a(4 downto 0);
|
||||
case ID_stage.ctrl.shamt2_srcsel is
|
||||
|
||||
when sa_src_reg =>
|
||||
data := ID_stage.reg_a(4 downto 0);
|
||||
when sa_src_reg =>
|
||||
data := ID_stage.reg_a(4 downto 0);
|
||||
|
||||
when sa_src_imm =>
|
||||
data := ID_stage.shamt;
|
||||
when sa_src_imm =>
|
||||
data := ID_stage.shamt;
|
||||
|
||||
when others => null;
|
||||
when others => null;
|
||||
|
||||
end case;
|
||||
data_inv := not data + 1;
|
||||
if ID_stage.ctrl.alu.shift_right = '0' then
|
||||
EX_stage.shift_ctrl.shamt_rnd <= data_inv;
|
||||
else
|
||||
EX_stage.shift_ctrl.shamt_rnd <= data;
|
||||
end if;
|
||||
EX_stage.shift_ctrl.shamt_nrm <= data;
|
||||
EX_stage.shift_ctrl.shift_right <= ID_stage.ctrl.alu.shift_right;
|
||||
EX_stage.shift_ctrl.shift_arith <= ID_stage.ctrl.alu.shift_arith;
|
||||
end case;
|
||||
data_inv := not data + 1;
|
||||
if ID_stage.ctrl.alu.shift_right = '0' then
|
||||
EX_stage.shift_ctrl.shamt_rnd <= data_inv after 1 ns;
|
||||
else
|
||||
EX_stage.shift_ctrl.shamt_rnd <= data after 1 ns;
|
||||
end if;
|
||||
EX_stage.shift_ctrl.shamt_nrm <= data after 1 ns;
|
||||
EX_stage.shift_ctrl.shift_right <= ID_stage.ctrl.alu.shift_right;
|
||||
EX_stage.shift_ctrl.shift_arith <= ID_stage.ctrl.alu.shift_arith;
|
||||
end if;
|
||||
|
||||
end process;
|
||||
@@ -733,43 +811,31 @@ inst_alu: alu
|
||||
flags => EX_stage.alu_flags
|
||||
);
|
||||
|
||||
inst_bcu: bcu
|
||||
GENERIC MAP
|
||||
(
|
||||
data_width => word_t'length
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
op1_in => bcu_op_a,
|
||||
op2_in => bcu_op_b,
|
||||
flags => bcu_flags
|
||||
);
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
-- MEM stage
|
||||
--------------------------------------------------------------------------
|
||||
proc_stage_MEM_n:
|
||||
process(clk)
|
||||
process(clk_1)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
MEM_stage.nop <= '1';
|
||||
MEM_stage.op <= op_nop;
|
||||
MEM_stage.va <= (others => '0');
|
||||
MEM_stage.pcn <= (others => '0');
|
||||
MEM_stage.ex_result <= (others => '0');
|
||||
MEM_stage.epc <= (others => '0');
|
||||
MEM_stage.wreg_we <= '0';
|
||||
MEM_stage.reg_wptr <= (others => '0');
|
||||
MEM_stage.ctrl <= ctrl_lines_default;
|
||||
MEM_stage.pa_off <= (others => '0');
|
||||
if rising_edge(clk_1) then
|
||||
if stage_rst(2) = '1' then
|
||||
MEM_stage.op <= op_nop;
|
||||
MEM_stage.reg_we <= '0';
|
||||
MEM_stage.ctrl <= ctrl_lines_default;
|
||||
MEM_stage.pa_off <= (others => '0');
|
||||
MEM_stage.events_in <= events_clr;
|
||||
elsif sdu.MEM_stall = '0' then
|
||||
MEM_stage.nop <= sdu.MEM_nop;
|
||||
MEM_stage.events_in <= EX_stage.events;
|
||||
MEM_stage.reg_a <= EX_stage.reg_a;
|
||||
MEM_stage.reg_b <= EX_stage.reg_b;
|
||||
MEM_stage.result_in <= EX_stage.result;
|
||||
MEM_stage.op <= EX_stage.op;
|
||||
MEM_stage.wreg_we <= EX_stage.wreg_we;
|
||||
MEM_stage.epc <= EX_stage.epc;
|
||||
MEM_stage.pcn <= EX_stage.pcn;
|
||||
MEM_stage.events_in <= EX_stage.events;
|
||||
MEM_stage.reg_we <= EX_stage.reg_we;
|
||||
MEM_stage.ctrl <= EX_stage.ctrl;
|
||||
MEM_stage.branch_not_taken <= EX_stage.branch_not_taken;
|
||||
if EX_stage.ctrl.dmem_en = '1' then
|
||||
MEM_stage.va <= EX_stage.va;
|
||||
end if;
|
||||
@@ -777,44 +843,40 @@ proc_stage_MEM_n:
|
||||
MEM_stage.reg_wptr <= EX_stage.reg_wptr;
|
||||
if MEM_stage.reg_wptr = EX_stage.reg_wptr then
|
||||
if (EX_stage.ctrl.dmem_en and MEM_stage.ctrl.dmem_en) = '1' then
|
||||
MEM_stage.ex_result <= MEM_stage.data;
|
||||
MEM_stage.result_in <= MEM_stage.result;
|
||||
end if;
|
||||
else
|
||||
MEM_stage.ex_result <= EX_stage.reg_b;
|
||||
MEM_stage.result_in <= EX_stage.reg_b;
|
||||
end if;
|
||||
if EX_stage.ctrl.cop_instr_en = '1' then
|
||||
if EX_stage.ctrl.cop_read = '1' then
|
||||
MEM_stage.ex_result <= cop_din;
|
||||
MEM_stage.result_in <= cop_din;
|
||||
end if;
|
||||
elsif EX_stage.ctrl.dmem_en = '0' then
|
||||
MEM_stage.ex_result <= EX_stage.result;
|
||||
MEM_stage.result_in <= EX_stage.result;
|
||||
end if;
|
||||
if sdu.MEM_nop = '1' then
|
||||
MEM_stage.op <= op_nop;
|
||||
MEM_stage.wreg_we <= '0';
|
||||
MEM_stage.reg_we <= '0';
|
||||
MEM_stage.ctrl <= ctrl_lines_default;
|
||||
else
|
||||
MEM_stage.pcn <= EX_stage.pcn;
|
||||
MEM_stage.epc <= EX_stage.epc;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
proc_stage_MEM_mux:
|
||||
process(MEM_stage, dmem_din)
|
||||
process(MEM_stage, dcache_qry_in.data)
|
||||
variable temp1 : word_t;
|
||||
variable temp2 : word_t;
|
||||
variable data : word_t;
|
||||
variable be : unsigned(3 downto 0);
|
||||
begin
|
||||
data := MEM_stage.ex_result;
|
||||
temp1 := load_shift(dmem_din, MEM_stage.pa_off, MEM_stage.ctrl.shift_offset, MEM_stage.ctrl.shift_byp);
|
||||
temp2 := load_sign_ext(temp1, MEM_stage.ctrl.sign_ext_byp, MEM_stage.ctrl.load_signed, MEM_stage.ctrl.word2_en, MEM_stage.ctrl.word4_en);
|
||||
be := load_be(MEM_stage.pa_off, MEM_stage.ctrl.align_left, MEM_stage.ctrl.byte_en_byp);
|
||||
data := MEM_stage.result_in;
|
||||
if MEM_stage.ctrl.reg_link = '1' then
|
||||
data := MEM_stage.epc + 8;
|
||||
elsif MEM_stage.ctrl.dmem_en = '1' then
|
||||
temp1 := load_shift(dcache_qry_in.data, MEM_stage.pa_off, MEM_stage.ctrl.shift_offset, MEM_stage.ctrl.shift_byp);
|
||||
temp2 := load_sign_ext(temp1, MEM_stage.ctrl.sign_ext_byp, MEM_stage.ctrl.load_signed, MEM_stage.ctrl.word2_en, MEM_stage.ctrl.word4_en);
|
||||
be := load_be(MEM_stage.pa_off, MEM_stage.ctrl.align_left, MEM_stage.ctrl.byte_en_byp);
|
||||
if be(0) = '1' then
|
||||
data(7 downto 0) := temp2(7 downto 0);
|
||||
end if;
|
||||
@@ -828,16 +890,16 @@ proc_stage_MEM_mux:
|
||||
data(31 downto 24) := temp2(31 downto 24);
|
||||
end if;
|
||||
end if;
|
||||
MEM_stage.data <= data;
|
||||
MEM_stage.result <= data after 1 ns;
|
||||
|
||||
end process;
|
||||
|
||||
proc_stage_MEM_except:
|
||||
process(MEM_stage, c0_ctrl_in)
|
||||
process(MEM_stage, ctrl_in)
|
||||
begin
|
||||
MEM_stage.events <= MEM_stage.events_in;
|
||||
MEM_stage.events.Int <= c0_ctrl_in.int;
|
||||
MEM_stage.events.NMI <= c0_ctrl_in.NMI;
|
||||
MEM_stage.events.Int <= ctrl_in.int;
|
||||
MEM_stage.events.NMI <= ctrl_in.NMI;
|
||||
end process;
|
||||
|
||||
MEM_stage.exc <= event_is_active(MEM_stage.events);
|
||||
@@ -846,34 +908,50 @@ proc_stage_MEM_except:
|
||||
-- WB stage
|
||||
--------------------------------------------------------------------------
|
||||
proc_stage_WB_p:
|
||||
process(clk)
|
||||
process(clk_1)
|
||||
variable branch_delay : std_logic;
|
||||
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
WB_stage.nop <= '1';
|
||||
if rising_edge(clk_1) then
|
||||
if stage_rst(3) = '1' then
|
||||
WB_stage.op <= op_nop;
|
||||
WB_stage.wreg_we <= '1';
|
||||
WB_stage.reg_we <= '1';
|
||||
WB_stage.reg_wptr <= (others => '0');
|
||||
WB_stage.data <= (others => '0');
|
||||
WB_stage.events <= events_clr;
|
||||
WB_stage.bd <= '0';
|
||||
WB_stage.epc <= (others => '0');
|
||||
WB_stage.events <= events_clr;
|
||||
WB_stage.exc <= '0';
|
||||
elsif sdu.WB_stall = '0' then
|
||||
WB_stage.nop <= sdu.WB_nop;
|
||||
WB_stage.reg_a <= MEM_stage.reg_a;
|
||||
WB_stage.reg_b <= MEM_stage.reg_b;
|
||||
WB_stage.result <= MEM_stage.result;
|
||||
WB_stage.op <= MEM_stage.op;
|
||||
WB_stage.wreg_we <= MEM_stage.wreg_we;
|
||||
WB_stage.reg_wptr <= MEM_stage.reg_wptr;
|
||||
WB_stage.data <= MEM_stage.data;
|
||||
WB_stage.epc <= MEM_stage.epc;
|
||||
branch_delay := MEM_stage.ctrl.branch or MEM_stage.ctrl.jump or MEM_stage.ctrl.jump_long; -- Todo: works
|
||||
WB_stage.bd <= branch_delay;
|
||||
WB_stage.exc_last <= WB_stage.exc;
|
||||
WB_stage.exc <= MEM_stage.exc;
|
||||
if MEM_stage.exc = '1' then
|
||||
WB_stage.events <= MEM_stage.events;
|
||||
WB_stage.reg_we <= MEM_stage.reg_we;
|
||||
WB_stage.reg_wptr <= MEM_stage.reg_wptr;
|
||||
WB_stage.events <= MEM_stage.events;
|
||||
if sdu.stall_all = '0' then
|
||||
if MEM_stage.exc = '1' and WB_stage.exc = '0' then
|
||||
ctrl_out.dmem_addr <= MEM_stage.va;
|
||||
ctrl_out.imem_addr <= MEM_stage.epc;
|
||||
ctrl_out.epc_wb <= MEM_stage.epc;
|
||||
ctrl_out.bd_wb <= WB_stage.bd;
|
||||
ctrl_out.events <= MEM_stage.events;
|
||||
if WB_stage.bd = '1' then
|
||||
ctrl_out.epc_wb <= WB_stage.epc;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
if sdu.WB_nop = '1' then
|
||||
WB_stage.op <= op_nop;
|
||||
WB_stage.wreg_we <= '0';
|
||||
else
|
||||
WB_stage.bd <= MEM_stage.ctrl.branch or MEM_stage.ctrl.jump or MEM_stage.ctrl.jump_long; -- Todo: works
|
||||
WB_stage.reg_we <= '0';
|
||||
end if;
|
||||
if WB_stage.exc = '0' then
|
||||
WB_stage.va <= MEM_stage.va;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
@@ -30,37 +30,37 @@ use work.mips_types.all;
|
||||
entity shifter is
|
||||
Generic
|
||||
(
|
||||
data_width : integer := 8
|
||||
DATA_WIDTH : integer := 8
|
||||
);
|
||||
Port
|
||||
(
|
||||
shift_ctrl : in shift_ctrl_t;
|
||||
din : in unsigned (data_width-1 downto 0);
|
||||
dout : out unsigned (data_width-1 downto 0)
|
||||
din : in unsigned (DATA_WIDTH-1 downto 0);
|
||||
dout : out unsigned (DATA_WIDTH-1 downto 0)
|
||||
);
|
||||
end shifter;
|
||||
|
||||
architecture Behavioral of shifter is
|
||||
|
||||
subtype word_t is unsigned(data_width-1 downto 0);
|
||||
subtype word_t is unsigned(DATA_WIDTH-1 downto 0);
|
||||
type word_array_t is array (0 to 5) of word_t;
|
||||
|
||||
signal rot_data : word_array_t;
|
||||
signal sa_rnd : unsigned (4 downto 0);
|
||||
signal fill : std_logic;
|
||||
|
||||
type fill_mask_rom_t is array (0 to 2*data_width-1) of unsigned(data_width-1 downto 0);
|
||||
type fill_mask_rom_t is array (0 to 2*DATA_WIDTH-1) of unsigned(DATA_WIDTH-1 downto 0);
|
||||
--------------------------------------------------------------------------
|
||||
function gen_fill_mask_rom(data_width_arg : natural) return fill_mask_rom_t is
|
||||
function gen_fill_mask_rom(width : natural) return fill_mask_rom_t is
|
||||
variable result : fill_mask_rom_t;
|
||||
begin
|
||||
result(0) := (data_width_arg-1 downto 0 => '0');
|
||||
for i in 1 to data_width_arg-1 loop
|
||||
result(i) := (data_width_arg-1-i downto 0 => '0') & (i-1 downto 0 => '1');
|
||||
result(0) := (width-1 downto 0 => '0');
|
||||
for i in 1 to width-1 loop
|
||||
result(i) := (width-1-i downto 0 => '0') & (i-1 downto 0 => '1');
|
||||
end loop;
|
||||
result(data_width_arg) := (data_width_arg-1 downto 0 => '0');
|
||||
for i in 1 to data_width_arg-1 loop
|
||||
result(data_width_arg+i) := (i-1 downto 0 => '1') & (data_width_arg-1-i downto 0 => '0');
|
||||
result(width) := (width-1 downto 0 => '0');
|
||||
for i in 1 to width-1 loop
|
||||
result(width+i) := (i-1 downto 0 => '1') & (width-1-i downto 0 => '0');
|
||||
end loop;
|
||||
return result;
|
||||
|
||||
@@ -79,10 +79,10 @@ function rot_stage(x : unsigned; en : std_logic; stage_num : natural) return uns
|
||||
|
||||
end rot_stage;
|
||||
|
||||
constant fill_mask_rom : fill_mask_rom_t := gen_fill_mask_rom(data_width);
|
||||
signal fill_mask : unsigned(data_width-1 downto 0);
|
||||
constant fill_mask_rom : fill_mask_rom_t := gen_fill_mask_rom(DATA_WIDTH);
|
||||
signal fill_mask : unsigned(DATA_WIDTH-1 downto 0);
|
||||
signal fill_mask_addr : unsigned(5 downto 0);
|
||||
signal dout_filled : unsigned (data_width-1 downto 0);
|
||||
signal dout_filled : unsigned (DATA_WIDTH-1 downto 0);
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
begin
|
||||
@@ -96,7 +96,7 @@ gen_rotate_right:
|
||||
end generate;
|
||||
|
||||
sa_rnd <= shift_ctrl.shamt_rnd;
|
||||
fill <= shift_ctrl.shift_arith and din(data_width-1);
|
||||
fill <= shift_ctrl.shift_arith and din(DATA_WIDTH-1);
|
||||
fill_mask_addr <= shift_ctrl.shift_right & shift_ctrl.shamt_nrm;
|
||||
fill_mask <= fill_mask_rom(to_integer(fill_mask_addr));
|
||||
|
||||
@@ -110,7 +110,7 @@ proc_fill_neu:
|
||||
end if;
|
||||
end process;
|
||||
|
||||
dout <= dout_filled;
|
||||
dout <= dout_filled after 5 ns;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
end Behavioral;
|
||||
|
||||
@@ -0,0 +1,340 @@
|
||||
--------------------------------------------------------------------------
|
||||
-- Project: JIPS, a portable 32-bit RISC CPU written in VHDL
|
||||
-- This file: JIPS top file
|
||||
--
|
||||
-- Copyright (C) 2008 J. Ahrensfeld
|
||||
--
|
||||
-- This program is free software: you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation, either version 3 of the License, or
|
||||
-- (at your option) any later version.
|
||||
--
|
||||
-- This program 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 General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
--
|
||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||
--
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
LIBRARY IEEE;
|
||||
USE IEEE.STD_LOGIC_1164.ALL;
|
||||
USE IEEE.NUMERIC_STD.ALL;
|
||||
|
||||
library work;
|
||||
use work.mips_types.all;
|
||||
use work.mips_util_pkg.all;
|
||||
|
||||
ENTITY tlb IS
|
||||
Generic
|
||||
(
|
||||
NUM_ENTRIES : natural := 8;
|
||||
CACHE_KSEG1 : boolean := false;
|
||||
TRANSLATE_KSEG0_1 : boolean := true;
|
||||
USE_TLB : boolean := false
|
||||
);
|
||||
Port
|
||||
(
|
||||
rst : in STD_LOGIC;
|
||||
clk : in STD_LOGIC;
|
||||
ce : in STD_LOGIC;
|
||||
|
||||
rdy : out STD_LOGIC;
|
||||
|
||||
ctrl_in : in tlb_ctrl_in_t;
|
||||
ctrl_out : out tlb_ctrl_out_t;
|
||||
|
||||
query_in : in tlb_query_in_t;
|
||||
query_out : out tlb_query_out_t
|
||||
|
||||
);
|
||||
END tlb;
|
||||
|
||||
ARCHITECTURE behavior OF tlb IS
|
||||
|
||||
signal clk_rd : STD_LOGIC;
|
||||
signal blk_hit : unsigned(NUM_ENTRIES-1 downto 0);
|
||||
signal blk_entry_lo : tlb_entry_lo_t;
|
||||
|
||||
constant C_ENTRY_LO_DEFAULT : tlb_entry_lo_t :=
|
||||
(
|
||||
N => '0', D => '0', V => '1', G => '0', PFN => (others => '0')
|
||||
);
|
||||
|
||||
signal kseg1_force_cached : STD_LOGIC;
|
||||
signal kseg_0_1_pfn : unsigned (31 downto lg2(TLB_PAGE_SIZE));
|
||||
signal hit_umc : STD_LOGIC;
|
||||
signal hit_umuc : STD_LOGIC;
|
||||
signal entry_lo_res : tlb_entry_lo_t;
|
||||
signal qry_res : tlb_query_out_t;
|
||||
|
||||
signal pa : word_t;
|
||||
signal hit : STD_LOGIC;
|
||||
signal vld_r : STD_LOGIC;
|
||||
|
||||
signal cam_rdy : STD_LOGIC;
|
||||
signal cam_hit_vld : STD_LOGIC;
|
||||
|
||||
signal vaddr_reg : word_t;
|
||||
signal write_reg : STD_LOGIC;
|
||||
|
||||
subtype reg_lo_t is unsigned(23 downto 0);
|
||||
subtype reg_hi_t is unsigned(25 downto 0);
|
||||
|
||||
signal reg_ctrl_entry_lo_din : reg_lo_t;
|
||||
signal reg_ctrl_entry_lo_dout : reg_lo_t;
|
||||
signal reg_qry_entry_lo_dout : reg_lo_t;
|
||||
signal reg_qry_entry_lo_addr : unsigned(lg2(NUM_ENTRIES)-1 downto 0);
|
||||
signal reg_ctrl_entry_lo_addr : unsigned(lg2(NUM_ENTRIES)-1 downto 0);
|
||||
|
||||
signal reg_ctrl_entry_hi_din : reg_hi_t;
|
||||
signal reg_ctrl_entry_hi_dout : reg_hi_t;
|
||||
|
||||
function to_entry_lo(x : reg_lo_t) return tlb_entry_lo_t is
|
||||
variable result : tlb_entry_lo_t;
|
||||
begin
|
||||
result.PFN := x(23 downto 4);
|
||||
result.N := x(3);
|
||||
result.D := x(2);
|
||||
result.V := x(1);
|
||||
result.G := x(0);
|
||||
|
||||
return result;
|
||||
|
||||
end to_entry_lo;
|
||||
|
||||
function to_entry_hi(x : reg_hi_t) return tlb_entry_hi_t is
|
||||
variable result : tlb_entry_hi_t;
|
||||
begin
|
||||
result.VPN := x(25 downto 6);
|
||||
result.ASID := x(5 downto 0);
|
||||
|
||||
return result;
|
||||
|
||||
end to_entry_hi;
|
||||
|
||||
function to_reg_lo(x : tlb_entry_lo_t) return reg_lo_t is
|
||||
variable result : reg_lo_t;
|
||||
begin
|
||||
result(23 downto 4) := x.PFN;
|
||||
result(3) := x.N;
|
||||
result(2) := x.D;
|
||||
result(1) := x.V;
|
||||
result(0) := x.G;
|
||||
|
||||
return result;
|
||||
|
||||
end to_reg_lo;
|
||||
|
||||
function to_reg_hi(x : tlb_entry_hi_t) return reg_hi_t is
|
||||
variable result : reg_hi_t;
|
||||
begin
|
||||
result(25 downto 6) := x.VPN;
|
||||
result(5 downto 0) := x.ASID;
|
||||
|
||||
return result;
|
||||
|
||||
end to_reg_hi;
|
||||
|
||||
signal hit_idx : integer;
|
||||
function decode(x : unsigned; N : integer) return integer is
|
||||
variable result : integer;
|
||||
begin
|
||||
result := 0;
|
||||
for i in 0 to N-1 loop
|
||||
if x(i) = '1' then
|
||||
result := i;
|
||||
end if;
|
||||
end loop;
|
||||
|
||||
return result;
|
||||
|
||||
end decode;
|
||||
|
||||
function decode2(x : unsigned; N : integer) return unsigned is
|
||||
variable result : unsigned (lg2(N)-1 downto 0);
|
||||
begin
|
||||
result := (others => '0');
|
||||
for i in 0 to N-1 loop
|
||||
result := result or ((lg2(N)-1 downto 0 => x(i)) and to_unsigned(i, lg2(N)));
|
||||
end loop;
|
||||
|
||||
return result;
|
||||
|
||||
end decode2;
|
||||
|
||||
begin
|
||||
kseg1_force_cached <= '1' when CACHE_KSEG1 else '0';
|
||||
kseg_0_1_pfn <= "000" & vaddr_reg(28 downto lg2(TLB_PAGE_SIZE)) when TRANSLATE_KSEG0_1 else vaddr_reg(31 downto lg2(TLB_PAGE_SIZE));
|
||||
|
||||
clk_rd <= clk;
|
||||
rdy <= cam_rdy;
|
||||
|
||||
qry_res.vld <= vld_r;
|
||||
qry_res.miss <= not hit;
|
||||
qry_res.dirty <= hit and qry_res.flags.D and write_reg;
|
||||
qry_res.write <= write_reg;
|
||||
qry_res.flags.N <= entry_lo_res.N;
|
||||
qry_res.flags.D <= entry_lo_res.D;
|
||||
qry_res.flags.V <= entry_lo_res.V;
|
||||
qry_res.paddr <= pa;
|
||||
|
||||
query_out <= qry_res;
|
||||
|
||||
pa <= entry_lo_res.PFN & vaddr_reg(lg2(TLB_PAGE_SIZE)-1 downto 0);
|
||||
|
||||
hit_idx <= decode(blk_hit, NUM_ENTRIES);
|
||||
|
||||
blk_entry_lo <= to_entry_lo(to_mips_01(reg_qry_entry_lo_dout));
|
||||
-- reg_qry_entry_lo_addr <= to_unsigned(hit_idx, lg2(NUM_ENTRIES));
|
||||
reg_qry_entry_lo_addr <= decode2(blk_hit, NUM_ENTRIES);
|
||||
reg_ctrl_entry_lo_din <= to_reg_lo(ctrl_in.entry_lo);
|
||||
|
||||
ctrl_out.entry_hi <= to_entry_hi(to_mips_01(reg_ctrl_entry_hi_dout));
|
||||
reg_ctrl_entry_hi_din <= to_reg_hi(ctrl_in.entry_hi);
|
||||
|
||||
registered_ctrl_out:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if query_in.vld = '1' then
|
||||
vaddr_reg <= query_in.vaddr;
|
||||
write_reg <= query_in.write;
|
||||
end if;
|
||||
vld_r <= query_in.vld;
|
||||
if ce = '1' then
|
||||
if ctrl_in.entry_re = '1' then
|
||||
|
||||
ctrl_out.entry_lo <= to_entry_lo(to_mips_01(reg_ctrl_entry_lo_dout));
|
||||
ctrl_out.entry_vld <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
inst_reg_entry_lo: entity work.reg_dual
|
||||
GENERIC MAP
|
||||
(
|
||||
addr_width => lg2(NUM_ENTRIES),
|
||||
data_width => reg_lo_t'length
|
||||
)
|
||||
PORT MAP (
|
||||
clk_w => clk,
|
||||
we => ctrl_in.entry_we,
|
||||
en => '1',
|
||||
wptr => ctrl_in.entry_wr_idx(lg2(NUM_ENTRIES)-1 downto 0),
|
||||
din => reg_ctrl_entry_lo_din,
|
||||
rptr_a => ctrl_in.entry_rd_idx(lg2(NUM_ENTRIES)-1 downto 0),
|
||||
rptr_b => reg_qry_entry_lo_addr,
|
||||
dout_a => reg_ctrl_entry_lo_dout,
|
||||
dout_b => reg_qry_entry_lo_dout
|
||||
);
|
||||
|
||||
inst_reg_entry_hi: entity work.dpram_1w1r2c_ra
|
||||
GENERIC MAP
|
||||
(
|
||||
addr_width => lg2(NUM_ENTRIES),
|
||||
data_width => reg_hi_t'length
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
clk_a => clk,
|
||||
clk_b => clk,
|
||||
we_a => ctrl_in.entry_we,
|
||||
re_b => ctrl_in.entry_re,
|
||||
addr_a => ctrl_in.entry_wr_idx(lg2(NUM_ENTRIES)-1 downto 0),
|
||||
addr_b => ctrl_in.entry_rd_idx(lg2(NUM_ENTRIES)-1 downto 0),
|
||||
din_a => reg_ctrl_entry_hi_din,
|
||||
dout_b => reg_ctrl_entry_hi_dout
|
||||
);
|
||||
|
||||
inst_cam_va: entity work.cam
|
||||
GENERIC MAP
|
||||
(
|
||||
NUM_ENTRIES => NUM_ENTRIES,
|
||||
DATA_WIDTH => 20,
|
||||
CAM_RAM_MAX_WIDTH => 15
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
rst => rst,
|
||||
clk => clk,
|
||||
clk_rd => clk_rd,
|
||||
rdy => cam_rdy,
|
||||
|
||||
re => query_in.vld,
|
||||
we => ctrl_in.entry_we,
|
||||
vld => '1',
|
||||
addr => ctrl_in.entry_wr_idx,
|
||||
tag_wr => ctrl_in.entry_hi.VPN,
|
||||
|
||||
tag_rd => query_in.vaddr(31 downto lg2(TLB_PAGE_SIZE)),
|
||||
hit => blk_hit(NUM_ENTRIES-1 downto 0),
|
||||
hit_vld => cam_hit_vld
|
||||
|
||||
);
|
||||
|
||||
hit_umc <= '1' when vaddr_reg(31 downto 29) = "100" else '0';
|
||||
hit_umuc <= '1' when vaddr_reg(31 downto 29) = "101" else '0';
|
||||
|
||||
tlb_entry_lo_result_translate:
|
||||
if USE_TLB = true generate
|
||||
tlb_entry_lo_result:
|
||||
process(blk_entry_lo, hit_umc, hit_umuc, kseg_0_1_pfn, kseg1_force_cached)
|
||||
begin
|
||||
entry_lo_res <= blk_entry_lo;
|
||||
if hit_umc = '1' or hit_umuc = '1' then
|
||||
entry_lo_res.N <= hit_umuc and not kseg1_force_cached;
|
||||
entry_lo_res <= C_ENTRY_LO_DEFAULT;
|
||||
entry_lo_res.PFN <= kseg_0_1_pfn;
|
||||
end if;
|
||||
|
||||
end process;
|
||||
end generate;
|
||||
|
||||
tlb_entry_lo_result_notranslate:
|
||||
if USE_TLB = false generate
|
||||
tlb_entry_lo_result:
|
||||
process(blk_entry_lo, vaddr_reg, hit_umc, hit_umuc, kseg_0_1_pfn, kseg1_force_cached)
|
||||
begin
|
||||
entry_lo_res <= C_ENTRY_LO_DEFAULT;
|
||||
entry_lo_res.PFN <= vaddr_reg(31 downto lg2(TLB_PAGE_SIZE));
|
||||
if hit_umc = '1' or hit_umuc = '1' then
|
||||
entry_lo_res.N <= hit_umuc and not kseg1_force_cached;
|
||||
entry_lo_res <= C_ENTRY_LO_DEFAULT;
|
||||
entry_lo_res.PFN <= kseg_0_1_pfn;
|
||||
end if;
|
||||
end process;
|
||||
end generate;
|
||||
|
||||
tlb_hit_combine_translate:
|
||||
if USE_TLB = true generate
|
||||
tlb_hit_combine:
|
||||
process(blk_entry_lo, hit_umc, hit_umuc)
|
||||
variable t_v : std_logic;
|
||||
begin
|
||||
t_v := blk_entry_lo.V;
|
||||
t_v := t_v or hit_umc or hit_umuc;
|
||||
hit <= t_v;
|
||||
|
||||
end process;
|
||||
end generate;
|
||||
|
||||
tlb_hit_combine_notranslate:
|
||||
if USE_TLB = false generate
|
||||
tlb_hit_combine:
|
||||
process(blk_entry_lo, hit_umc, hit_umuc)
|
||||
variable t_v : std_logic;
|
||||
begin
|
||||
t_v := hit_umc or hit_umuc;
|
||||
hit <= t_v;
|
||||
|
||||
end process;
|
||||
end generate;
|
||||
|
||||
------------------------------------------------------------------
|
||||
end behavior;
|
||||
+168
-109
@@ -31,14 +31,16 @@ use work.mips_types.all;
|
||||
entity mips_top is
|
||||
Generic
|
||||
(
|
||||
icache_size : natural := 1024; -- words
|
||||
icache_line : natural := 8; -- words
|
||||
dcache_size : natural := 1024; -- words
|
||||
dcache_line : natural := 8 -- words
|
||||
icache_size : natural := 1024; -- words
|
||||
icache_line : natural := 8; -- words
|
||||
dcache_size : natural := 1024; -- words
|
||||
dcache_line : natural := 8; -- words
|
||||
WITH_TLB : boolean := true;
|
||||
TRANSLATE_KSEG0_1 : boolean := true
|
||||
);
|
||||
Port
|
||||
(
|
||||
debug : out unsigned(1 downto 0);
|
||||
debug : out chip_debug_t;
|
||||
eb : in STD_LOGIC;
|
||||
nmi : in STD_LOGIC;
|
||||
cpu_clk : in STD_LOGIC;
|
||||
@@ -67,42 +69,32 @@ architecture rtl of mips_top is
|
||||
COMPONENT pipeline is
|
||||
Port
|
||||
(
|
||||
rst : in STD_LOGIC;
|
||||
clk : in STD_LOGIC;
|
||||
ce : in STD_LOGIC;
|
||||
imem_rdy : in STD_LOGIC;
|
||||
imem_en : out STD_LOGIC;
|
||||
imem_addr : out word_t;
|
||||
imem_data : in word_t;
|
||||
dmem_rdy : in STD_LOGIC;
|
||||
dmem_en : out STD_LOGIC;
|
||||
dmem_we : out STD_LOGIC;
|
||||
dmem_be : out unsigned(3 downto 0);
|
||||
dmem_addr : out word_t;
|
||||
dmem_din : in word_t;
|
||||
dmem_dout : out word_t;
|
||||
cop_ir : out word_t;
|
||||
cop_ir_en : out STD_LOGIC;
|
||||
cop_din : in word_t;
|
||||
cop_dout : out word_t;
|
||||
c0_ctrl_out : out cop0_ctrl_in_t;
|
||||
c0_ctrl_in : in cop0_ctrl_out_t
|
||||
rst : in STD_LOGIC;
|
||||
clk : in STD_LOGIC;
|
||||
ce : in STD_LOGIC;
|
||||
imem_err : in STD_LOGIC;
|
||||
dmem_err : in STD_LOGIC;
|
||||
cop_ir : out word_t;
|
||||
cop_ir_en : out STD_LOGIC;
|
||||
cop_din : in word_t;
|
||||
cop_dout : out word_t;
|
||||
ctrl_out : out pipe_ctrl_out_t;
|
||||
ctrl_in : in pipe_ctrl_in_t;
|
||||
dtlb_qry_out : out tlb_query_in_t;
|
||||
dtlb_qry_in : in tlb_query_out_t;
|
||||
dcache_qry_out : out dcache_query_in_t;
|
||||
dcache_qry_in : in dcache_query_out_t;
|
||||
itlb_qry_out : out tlb_query_in_t;
|
||||
itlb_qry_in : in tlb_query_out_t;
|
||||
icache_qry_out : out icache_query_in_t;
|
||||
icache_qry_in : in icache_query_out_t
|
||||
);
|
||||
END COMPONENT;
|
||||
|
||||
signal imem_err : std_logic;
|
||||
signal imem_rdy : std_logic;
|
||||
signal imem_en : std_logic;
|
||||
signal imem_addr : word_t;
|
||||
signal imem_din : word_t;
|
||||
signal dmem_err : std_logic;
|
||||
signal dmem_rdy : std_logic;
|
||||
signal dmem_en : std_logic;
|
||||
signal dmem_we : std_logic;
|
||||
signal dmem_addr : word_t;
|
||||
signal dmem_dout : word_t;
|
||||
signal dmem_din : word_t;
|
||||
signal dmem_be : unsigned(3 downto 0);
|
||||
|
||||
signal biu_busy : STD_LOGIC;
|
||||
signal biu_rst : STD_LOGIC;
|
||||
signal cpu_rst : STD_LOGIC;
|
||||
signal cpu_run : STD_LOGIC;
|
||||
@@ -111,8 +103,14 @@ architecture rtl of mips_top is
|
||||
signal pipe_cop_ir_en : STD_LOGIC;
|
||||
signal pipe_cop_din : word_t;
|
||||
signal pipe_cop_dout : word_t;
|
||||
signal pipe_c0_ctrl_out : cop0_ctrl_in_t;
|
||||
signal pipe_c0_ctrl_in : cop0_ctrl_out_t;
|
||||
signal pipe_ctrl_in : pipe_ctrl_in_t;
|
||||
signal pipe_ctrl_out : pipe_ctrl_out_t;
|
||||
|
||||
signal cop0_ctrl_in : cop0_ctrl_in_t;
|
||||
signal cop0_ctrl_out : cop0_ctrl_out_t;
|
||||
|
||||
signal biu_ctrl_in : biu_ctrl_in_t;
|
||||
signal biu_ctrl_out : biu_ctrl_out_t;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
-- Coprocessor
|
||||
@@ -147,53 +145,48 @@ architecture rtl of mips_top is
|
||||
COMPONENT biu
|
||||
GENERIC
|
||||
(
|
||||
icache_size : natural;
|
||||
icache_line : natural;
|
||||
dcache_size : natural;
|
||||
dcache_line : natural
|
||||
icache_size : natural;
|
||||
icache_line : natural;
|
||||
dcache_size : natural;
|
||||
dcache_line : natural;
|
||||
WRITE_FIFO_SIZE : natural;
|
||||
WITH_TLB : boolean;
|
||||
TRANSLATE_KSEG0_1 : boolean
|
||||
);
|
||||
PORT
|
||||
(
|
||||
clk : in STD_LOGIC;
|
||||
busy : out STD_LOGIC;
|
||||
|
||||
imem_err : out STD_LOGIC;
|
||||
dmem_err : out STD_LOGIC;
|
||||
|
||||
RST_I : in STD_LOGIC;
|
||||
CLK_I : in STD_LOGIC;
|
||||
ACK_I : in STD_LOGIC;
|
||||
SRDY_I : in STD_LOGIC;
|
||||
ADDR_O : out unsigned(31 downto 0);
|
||||
DAT_I : in unsigned(31 downto 0);
|
||||
DAT_O : out unsigned(31 downto 0);
|
||||
MDAT_I : in unsigned(31 downto 0);
|
||||
MDAT_O : out unsigned(31 downto 0);
|
||||
WE_O : out STD_LOGIC;
|
||||
SEL_O : out unsigned(3 downto 0);
|
||||
CYC_O : out STD_LOGIC;
|
||||
STB_O : out STD_LOGIC;
|
||||
MRDY_O : out STD_LOGIC;
|
||||
cop0_ctrl_in : in cop0_ctrl_out_t;
|
||||
cpu_clk : in STD_LOGIC;
|
||||
cpu_imem_err : out STD_LOGIC;
|
||||
cpu_imem_rdy : out STD_LOGIC;
|
||||
cpu_imem_en : in STD_LOGIC;
|
||||
cpu_imem_addr : in word_t;
|
||||
cpu_imem_din : out word_t;
|
||||
cpu_dmem_err : out STD_LOGIC;
|
||||
cpu_dmem_rdy : out STD_LOGIC;
|
||||
cpu_dmem_en : in STD_LOGIC;
|
||||
cpu_dmem_we : in STD_LOGIC;
|
||||
cpu_dmem_be : in unsigned(3 downto 0);
|
||||
cpu_dmem_dout : in word_t;
|
||||
cpu_dmem_din : out word_t;
|
||||
cpu_dmem_addr : in word_t
|
||||
|
||||
ctrl_in : in biu_ctrl_in_t;
|
||||
ctrl_out : out biu_ctrl_out_t
|
||||
|
||||
);
|
||||
END COMPONENT;
|
||||
|
||||
begin
|
||||
|
||||
-------------------------------------------------------------------
|
||||
debug(0) <= imem_err;
|
||||
debug(1) <= dmem_err;
|
||||
|
||||
process(CLK_I)
|
||||
process(cpu_clk)
|
||||
variable reset_delay : unsigned (31 downto 0);
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if rising_edge(cpu_clk) then
|
||||
if RST_I = '1' then
|
||||
reset_delay := (others => '0');
|
||||
biu_rst <= '1';
|
||||
@@ -207,7 +200,7 @@ begin
|
||||
if reset_delay(31) = '1' then
|
||||
cpu_rst <= '0';
|
||||
end if;
|
||||
if reset_delay(16) = '1' then
|
||||
if reset_delay(16) = '1' and biu_busy = '0' then
|
||||
cpu_run <= '1';
|
||||
end if;
|
||||
end if;
|
||||
@@ -217,28 +210,29 @@ begin
|
||||
inst_pipeline: pipeline
|
||||
PORT MAP
|
||||
(
|
||||
rst => cpu_rst,
|
||||
clk => cpu_clk,
|
||||
ce => cpu_run,
|
||||
imem_rdy => imem_rdy,
|
||||
imem_en => imem_en,
|
||||
imem_addr => imem_addr,
|
||||
imem_data => imem_din,
|
||||
dmem_rdy => dmem_rdy,
|
||||
dmem_en => dmem_en,
|
||||
dmem_we => dmem_we,
|
||||
dmem_be => dmem_be,
|
||||
dmem_addr => dmem_addr,
|
||||
dmem_din => dmem_din,
|
||||
dmem_dout => dmem_dout,
|
||||
cop_ir => pipe_cop_ir,
|
||||
cop_ir_en => pipe_cop_ir_en,
|
||||
cop_din => pipe_cop_din,
|
||||
cop_dout => pipe_cop_dout,
|
||||
c0_ctrl_out => pipe_c0_ctrl_out,
|
||||
c0_ctrl_in => pipe_c0_ctrl_in
|
||||
rst => cpu_rst,
|
||||
clk => cpu_clk,
|
||||
ce => cpu_run,
|
||||
imem_err => imem_err,
|
||||
dmem_err => dmem_err,
|
||||
cop_ir => pipe_cop_ir,
|
||||
cop_ir_en => pipe_cop_ir_en,
|
||||
cop_din => pipe_cop_din,
|
||||
cop_dout => pipe_cop_dout,
|
||||
ctrl_out => pipe_ctrl_out,
|
||||
ctrl_in => pipe_ctrl_in,
|
||||
dtlb_qry_out => biu_ctrl_in.dtlb_qry,
|
||||
dtlb_qry_in => biu_ctrl_out.dtlb_qry,
|
||||
dcache_qry_out => biu_ctrl_in.dcache_qry,
|
||||
dcache_qry_in => biu_ctrl_out.dcache_qry,
|
||||
itlb_qry_out => biu_ctrl_in.itlb_qry,
|
||||
itlb_qry_in => biu_ctrl_out.itlb_qry,
|
||||
icache_qry_out => biu_ctrl_in.icache_qry,
|
||||
icache_qry_in => biu_ctrl_out.icache_qry
|
||||
);
|
||||
|
||||
pipe_ctrl_in <= cop0_ctrl_out.pipe;
|
||||
|
||||
inst_cop: cop
|
||||
GENERIC MAP
|
||||
(
|
||||
@@ -256,49 +250,114 @@ inst_cop: cop
|
||||
int => INT,
|
||||
ir_en => pipe_cop_ir_en,
|
||||
ir => pipe_cop_ir,
|
||||
ctrl_in => pipe_c0_ctrl_out,
|
||||
ctrl_out => pipe_c0_ctrl_in,
|
||||
ctrl_in => cop0_ctrl_in,
|
||||
ctrl_out => cop0_ctrl_out,
|
||||
dout => pipe_cop_din,
|
||||
din => pipe_cop_dout
|
||||
);
|
||||
|
||||
|
||||
cop0_ctrl_in.pipe <= pipe_ctrl_out;
|
||||
cop0_ctrl_in.itlb_ctrl <= biu_ctrl_out.itlb_ctrl;
|
||||
cop0_ctrl_in.dtlb_ctrl <= biu_ctrl_out.dtlb_ctrl;
|
||||
|
||||
inst_biu: biu
|
||||
GENERIC MAP
|
||||
(
|
||||
icache_size => icache_size, -- words
|
||||
icache_line => icache_line, -- words
|
||||
dcache_size => dcache_size, -- words
|
||||
dcache_line => dcache_line -- words
|
||||
icache_size => icache_size, -- words
|
||||
icache_line => icache_line, -- words
|
||||
dcache_size => dcache_size, -- words
|
||||
dcache_line => dcache_line, -- words
|
||||
WRITE_FIFO_SIZE => 4,
|
||||
WITH_TLB => WITH_TLB,
|
||||
TRANSLATE_KSEG0_1 => TRANSLATE_KSEG0_1
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
|
||||
clk => cpu_clk,
|
||||
busy => biu_busy,
|
||||
|
||||
imem_err => imem_err,
|
||||
dmem_err => dmem_err,
|
||||
|
||||
RST_I => biu_rst,
|
||||
CLK_I => CLK_I,
|
||||
ACK_I => ACK_I,
|
||||
SRDY_I => SRDY_I,
|
||||
ADDR_O => ADDR_O,
|
||||
DAT_I => DAT_I,
|
||||
DAT_O => DAT_O,
|
||||
MDAT_I => DAT_I,
|
||||
MDAT_O => DAT_O,
|
||||
WE_O => WE_O,
|
||||
SEL_O => SEL_O,
|
||||
CYC_O => CYC_O,
|
||||
STB_O => STB_O,
|
||||
MRDY_O => MRDY_O,
|
||||
cop0_ctrl_in => pipe_c0_ctrl_in,
|
||||
cpu_clk => cpu_clk,
|
||||
cpu_imem_err => imem_err,
|
||||
cpu_imem_rdy => imem_rdy,
|
||||
cpu_imem_en => imem_en,
|
||||
cpu_imem_addr => imem_addr,
|
||||
cpu_imem_din => imem_din,
|
||||
cpu_dmem_err => dmem_err,
|
||||
cpu_dmem_rdy => dmem_rdy,
|
||||
cpu_dmem_en => dmem_en,
|
||||
cpu_dmem_we => dmem_we,
|
||||
cpu_dmem_be => dmem_be,
|
||||
cpu_dmem_addr => dmem_addr,
|
||||
cpu_dmem_din => dmem_din,
|
||||
cpu_dmem_dout => dmem_dout
|
||||
|
||||
ctrl_in => biu_ctrl_in,
|
||||
ctrl_out => biu_ctrl_out
|
||||
|
||||
);
|
||||
|
||||
biu_ctrl_in.icache <= cop0_ctrl_out.icache;
|
||||
biu_ctrl_in.dcache <= cop0_ctrl_out.dcache;
|
||||
biu_ctrl_in.itlb_ctrl <= cop0_ctrl_out.itlb_ctrl;
|
||||
biu_ctrl_in.dtlb_ctrl <= cop0_ctrl_out.dtlb_ctrl;
|
||||
-- biu_ctrl_in.itlb_qry <= pipe_ctrl_out.itlb_qry;
|
||||
-- biu_ctrl_in.dtlb_qry <= pipe_ctrl_out.dtlb_qry;
|
||||
|
||||
-------------------------------------------
|
||||
-- debug
|
||||
-------------------------------------------
|
||||
debug.imem_err <= imem_err;
|
||||
debug.dmem_err <= dmem_err;
|
||||
|
||||
debug_imem_din_register:
|
||||
process(cpu_clk)
|
||||
variable en_r: std_logic;
|
||||
variable addr_r: word_t;
|
||||
begin
|
||||
if rising_edge(cpu_clk) then
|
||||
debug.imem_din_vld <= '0';
|
||||
if biu_ctrl_out.icache_qry.rdy = '1' then
|
||||
if en_r = '1' then
|
||||
debug.imem_addr_reg <= addr_r;
|
||||
debug.imem_din_reg <= biu_ctrl_out.icache_qry.data;
|
||||
debug.imem_din_vld <= '1';
|
||||
end if;
|
||||
if biu_ctrl_in.icache_qry.en = '1' then
|
||||
addr_r := biu_ctrl_in.icache_qry.addr;
|
||||
end if;
|
||||
en_r := biu_ctrl_in.icache_qry.en;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
debug_dmem_din_register:
|
||||
process(cpu_clk)
|
||||
variable en_r: std_logic;
|
||||
variable we_r: std_logic;
|
||||
variable addr_r: word_t;
|
||||
variable dout_r: word_t;
|
||||
begin
|
||||
if rising_edge(cpu_clk) then
|
||||
debug.dmem_din_vld <= '0';
|
||||
debug.dmem_dout_vld <= '0';
|
||||
if biu_ctrl_out.dcache_qry.rdy = '1' then
|
||||
if en_r = '1' then
|
||||
debug.dmem_addr_reg <= addr_r;
|
||||
debug.dmem_din_reg <= biu_ctrl_out.dcache_qry.data;
|
||||
debug.dmem_din_vld <= not we_r;
|
||||
debug.dmem_dout_reg <= dout_r;
|
||||
debug.dmem_dout_vld <= we_r;
|
||||
end if;
|
||||
if biu_ctrl_in.dcache_qry.en = '1' then
|
||||
dout_r := biu_ctrl_in.dcache_qry.data;
|
||||
addr_r := biu_ctrl_in.dcache_qry.addr;
|
||||
end if;
|
||||
en_r := biu_ctrl_in.dcache_qry.en;
|
||||
we_r := biu_ctrl_in.dcache_qry.we;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end rtl;
|
||||
|
||||
@@ -26,12 +26,18 @@ use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.NUMERIC_STD.ALL;
|
||||
use IEEE.MATH_REAL.ALL;
|
||||
|
||||
library work;
|
||||
use work.mips_util_pkg.all;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
package mips_types is
|
||||
|
||||
-- Revision of the CPU
|
||||
constant REVISION : integer := 13;
|
||||
constant WORD_WIDTH : integer := 32;
|
||||
constant REVISION : integer := 14;
|
||||
constant WORD_WIDTH : integer := 32;
|
||||
constant TLB_PAGE_SIZE : positive := 4096;
|
||||
constant TLB_NUM_ASIDS : positive := 64;
|
||||
constant TLB_NUM_ENTRIES : positive := 32;
|
||||
|
||||
--Types
|
||||
subtype instr_name_t is string(1 to 12);
|
||||
@@ -45,9 +51,17 @@ package mips_types is
|
||||
|
||||
type chip_debug_t is record
|
||||
imem_err : std_logic;
|
||||
imem_addr_reg : word_t;
|
||||
imem_din_reg : word_t;
|
||||
imem_din_vld : std_logic;
|
||||
dmem_err : std_logic;
|
||||
dmem_addr_reg : word_t;
|
||||
dmem_din_reg : word_t;
|
||||
dmem_din_vld : std_logic;
|
||||
dmem_dout_reg : word_t;
|
||||
dmem_dout_vld : std_logic;
|
||||
end record;
|
||||
|
||||
|
||||
type op_t is
|
||||
(
|
||||
op_illegal,
|
||||
@@ -159,11 +173,14 @@ package mips_types is
|
||||
type wptr_src_t is (wptr_src_imm, wptr_src_const);
|
||||
|
||||
type pc_t is record
|
||||
curr : word_t;
|
||||
last : word_t;
|
||||
nxt : word_t;
|
||||
pc_branch : word_t;
|
||||
branch_take : std_logic;
|
||||
curr : word_t;
|
||||
last : word_t;
|
||||
nxt : word_t;
|
||||
pc_branch : word_t;
|
||||
pc_branch_revert : word_t;
|
||||
branch_take : std_logic;
|
||||
branch_not_taken : std_logic;
|
||||
plus4 : word_t;
|
||||
end record;
|
||||
|
||||
type alu_outsel_t is
|
||||
@@ -227,6 +244,12 @@ package mips_types is
|
||||
syscall : STD_LOGIC;
|
||||
break : STD_LOGIC;
|
||||
illegal : STD_LOGIC;
|
||||
ITLB_MOD : STD_LOGIC;
|
||||
ITLB_LOAD : STD_LOGIC;
|
||||
ITLB_STORE : STD_LOGIC;
|
||||
DTLB_MOD : STD_LOGIC;
|
||||
DTLB_LOAD : STD_LOGIC;
|
||||
DTLB_STORE : STD_LOGIC;
|
||||
end record;
|
||||
|
||||
type exc_flags_t is record
|
||||
@@ -239,6 +262,12 @@ package mips_types is
|
||||
Sys : STD_LOGIC;
|
||||
Bp : STD_LOGIC;
|
||||
RI : STD_LOGIC;
|
||||
ITLB_MOD : STD_LOGIC;
|
||||
ITLB_LOAD : STD_LOGIC;
|
||||
ITLB_STORE : STD_LOGIC;
|
||||
DTLB_MOD : STD_LOGIC;
|
||||
DTLB_LOAD : STD_LOGIC;
|
||||
DTLB_STORE : STD_LOGIC;
|
||||
IBE : STD_LOGIC;
|
||||
DBE : STD_LOGIC;
|
||||
end record;
|
||||
@@ -249,25 +278,108 @@ package mips_types is
|
||||
cause : word_t;
|
||||
end record;
|
||||
|
||||
type icache_query_in_t is record
|
||||
en : std_logic;
|
||||
nc : std_logic;
|
||||
addr : word_t;
|
||||
end record;
|
||||
|
||||
type icache_query_out_t is record
|
||||
rdy : std_logic;
|
||||
data : word_t;
|
||||
end record;
|
||||
|
||||
type dcache_query_in_t is record
|
||||
en : std_logic;
|
||||
we : std_logic;
|
||||
be : unsigned(3 downto 0);
|
||||
nc : std_logic;
|
||||
addr : word_t;
|
||||
data : word_t;
|
||||
end record;
|
||||
|
||||
type dcache_query_out_t is record
|
||||
rdy : std_logic;
|
||||
data : word_t;
|
||||
end record;
|
||||
|
||||
type cache_ctrl_t is record
|
||||
inv_addr : word_t;
|
||||
inv_at : STD_LOGIC;
|
||||
inv_all : STD_LOGIC;
|
||||
end record;
|
||||
|
||||
type cop0_ctrl_in_t is record
|
||||
sdu : sdu_t;
|
||||
events : event_t;
|
||||
bd_wb : STD_LOGIC;
|
||||
epc_mem : word_t;
|
||||
epc_wb : word_t;
|
||||
imem_addr : word_t;
|
||||
dmem_addr : word_t;
|
||||
exc_req : STD_LOGIC;
|
||||
exc_ack : STD_LOGIC;
|
||||
type tlb_flags_t is record
|
||||
N : std_logic;
|
||||
D : std_logic;
|
||||
V : std_logic;
|
||||
end record;
|
||||
|
||||
type cop0_ctrl_out_t is record
|
||||
type tlb_entry_lo_t is record
|
||||
PFN : unsigned (31 downto lg2(TLB_PAGE_SIZE));
|
||||
G : std_logic;
|
||||
N : std_logic;
|
||||
D : std_logic;
|
||||
V : std_logic;
|
||||
end record;
|
||||
|
||||
type tlb_entry_hi_t is record
|
||||
VPN : unsigned (31 downto lg2(TLB_PAGE_SIZE));
|
||||
ASID : unsigned (lg2(TLB_NUM_ASIDS)-1 downto 0);
|
||||
end record;
|
||||
|
||||
type tlb_query_in_t is record
|
||||
vld : std_logic;
|
||||
write : std_logic;
|
||||
vaddr : word_t;
|
||||
end record;
|
||||
|
||||
type tlb_query_out_t is record
|
||||
vld : std_logic;
|
||||
paddr : word_t;
|
||||
miss : STD_LOGIC;
|
||||
dirty : std_logic;
|
||||
write : std_logic;
|
||||
flags : tlb_flags_t;
|
||||
end record;
|
||||
|
||||
type tlb_ctrl_in_t is record
|
||||
entry_we : STD_LOGIC;
|
||||
entry_re : STD_LOGIC;
|
||||
entry_rd_idx : unsigned (lg2(TLB_NUM_ENTRIES)-1 downto 0);
|
||||
entry_wr_idx : unsigned (lg2(TLB_NUM_ENTRIES)-1 downto 0);
|
||||
entry_lo : tlb_entry_lo_t;
|
||||
entry_hi : tlb_entry_hi_t;
|
||||
end record;
|
||||
|
||||
type tlb_ctrl_out_t is record
|
||||
entry_vld : std_logic;
|
||||
entry_lo : tlb_entry_lo_t;
|
||||
entry_hi : tlb_entry_hi_t;
|
||||
entry_prb_idx : unsigned (lg2(TLB_NUM_ENTRIES)-1 downto 0);
|
||||
end record;
|
||||
|
||||
type biu_ctrl_in_t is record
|
||||
itlb_ctrl : tlb_ctrl_in_t;
|
||||
dtlb_ctrl : tlb_ctrl_in_t;
|
||||
icache : cache_ctrl_t;
|
||||
dcache : cache_ctrl_t;
|
||||
itlb_qry : tlb_query_in_t;
|
||||
dtlb_qry : tlb_query_in_t;
|
||||
icache_qry : icache_query_in_t;
|
||||
dcache_qry : dcache_query_in_t;
|
||||
end record;
|
||||
|
||||
type biu_ctrl_out_t is record
|
||||
itlb_ctrl : tlb_ctrl_out_t;
|
||||
dtlb_ctrl : tlb_ctrl_out_t;
|
||||
itlb_qry : tlb_query_out_t;
|
||||
dtlb_qry : tlb_query_out_t;
|
||||
icache_qry : icache_query_out_t;
|
||||
dcache_qry : dcache_query_out_t;
|
||||
end record;
|
||||
|
||||
type pipe_ctrl_in_t is record
|
||||
EB : STD_LOGIC;
|
||||
exc_inject : STD_LOGIC;
|
||||
exc_commit : STD_LOGIC;
|
||||
@@ -277,6 +389,29 @@ package mips_types is
|
||||
NMI : STD_LOGIC;
|
||||
int : STD_LOGIC;
|
||||
exc_vec : word_t;
|
||||
end record;
|
||||
|
||||
type pipe_ctrl_out_t is record
|
||||
sdu : sdu_t;
|
||||
events : event_t;
|
||||
bd_wb : STD_LOGIC;
|
||||
epc_wb : word_t;
|
||||
imem_addr : word_t;
|
||||
dmem_addr : word_t;
|
||||
exc_req : STD_LOGIC;
|
||||
exc_ack : STD_LOGIC;
|
||||
end record;
|
||||
|
||||
type cop0_ctrl_in_t is record
|
||||
pipe : pipe_ctrl_out_t;
|
||||
itlb_ctrl : tlb_ctrl_out_t;
|
||||
dtlb_ctrl : tlb_ctrl_out_t;
|
||||
end record;
|
||||
|
||||
type cop0_ctrl_out_t is record
|
||||
pipe : pipe_ctrl_in_t;
|
||||
itlb_ctrl : tlb_ctrl_in_t;
|
||||
dtlb_ctrl : tlb_ctrl_in_t;
|
||||
icache : cache_ctrl_t;
|
||||
dcache : cache_ctrl_t;
|
||||
end record;
|
||||
@@ -337,76 +472,93 @@ package mips_types is
|
||||
type ID_t is record
|
||||
nop : STD_LOGIC;
|
||||
exc : std_logic;
|
||||
IR : word_t;
|
||||
op : op_t;
|
||||
pcn : word_t;
|
||||
IR : word_t;
|
||||
epc : word_t;
|
||||
pcn : word_t;
|
||||
jimm32 : word_t;
|
||||
bimm18 : word_t;
|
||||
imm : word_t;
|
||||
shamt : shamt_t;
|
||||
ctrl : ctrl_lines_t;
|
||||
va : word_t;
|
||||
reg_write : STD_LOGIC;
|
||||
reg_a_rptr : reg_ptr_t;
|
||||
reg_b_rptr : reg_ptr_t;
|
||||
reg_a : word_t;
|
||||
reg_b : word_t;
|
||||
events : event_t;
|
||||
bcu_flags : bcu_flags_t;
|
||||
itlb_qry : tlb_query_out_t;
|
||||
end record;
|
||||
|
||||
type EX_t is record
|
||||
nop : STD_LOGIC;
|
||||
exc : std_logic;
|
||||
IR : word_t;
|
||||
op : op_t;
|
||||
pcn : word_t;
|
||||
IR : word_t;
|
||||
epc : word_t;
|
||||
pcn : word_t;
|
||||
reg_a : word_t;
|
||||
reg_b : word_t;
|
||||
result : word_t;
|
||||
ctrl : ctrl_lines_t;
|
||||
shift_ctrl : shift_ctrl_t;
|
||||
alu_op1 : word_t;
|
||||
alu_op2 : word_t;
|
||||
alu_op2_s : word_t;
|
||||
alu_flags : alu_flags_t;
|
||||
result : word_t;
|
||||
reg_write : STD_LOGIC;
|
||||
wreg_we : STD_LOGIC;
|
||||
reg_we : STD_LOGIC;
|
||||
reg_wptr : reg_ptr_t;
|
||||
reg_a_rptr : reg_ptr_t;
|
||||
reg_b_rptr : reg_ptr_t;
|
||||
va : word_t;
|
||||
dmem_en : STD_LOGIC;
|
||||
pa_off : unsigned(1 downto 0);
|
||||
events_in : event_t;
|
||||
events : event_t;
|
||||
bcu_flags : bcu_flags_t;
|
||||
branch_not_taken : std_logic;
|
||||
dtlb_qry : tlb_query_out_t;
|
||||
end record;
|
||||
|
||||
type MEM_t is record
|
||||
nop : STD_LOGIC;
|
||||
exc : std_logic;
|
||||
op : op_t;
|
||||
pcn : word_t;
|
||||
epc : word_t;
|
||||
pcn : word_t;
|
||||
reg_a : word_t;
|
||||
reg_b : word_t;
|
||||
result : word_t;
|
||||
result_in : word_t;
|
||||
ctrl : ctrl_lines_t;
|
||||
ex_result : word_t;
|
||||
reg_wptr : reg_ptr_t;
|
||||
wreg_we : STD_LOGIC;
|
||||
data : word_t;
|
||||
reg_we : STD_LOGIC;
|
||||
va : word_t;
|
||||
pa_off : unsigned(1 downto 0);
|
||||
events_in : event_t;
|
||||
events : event_t;
|
||||
bcu_flags : bcu_flags_t;
|
||||
branch_not_taken : std_logic;
|
||||
end record;
|
||||
|
||||
type WB_t is record
|
||||
nop : STD_LOGIC;
|
||||
epc : word_t;
|
||||
reg_a : word_t;
|
||||
reg_b : word_t;
|
||||
result : word_t;
|
||||
bd : STD_LOGIC;
|
||||
exc : std_logic;
|
||||
exc_last : std_logic;
|
||||
events : event_t;
|
||||
op : op_t;
|
||||
reg_wptr : reg_ptr_t;
|
||||
wreg_we : STD_LOGIC;
|
||||
data : word_t;
|
||||
bd : STD_LOGIC;
|
||||
reg_we : STD_LOGIC;
|
||||
va : word_t;
|
||||
bcu_flags : bcu_flags_t;
|
||||
end record;
|
||||
|
||||
|
||||
@@ -422,9 +574,7 @@ package mips_types is
|
||||
function events_clr return event_t;
|
||||
function event_is_active(e : event_t) return std_logic;
|
||||
function "or" (a, b : event_t) return event_t;
|
||||
|
||||
function lg2(x : natural) return natural;
|
||||
function po2(x : natural) return natural;
|
||||
function "or" (a, b : tlb_flags_t) return tlb_flags_t;
|
||||
|
||||
end mips_types;
|
||||
|
||||
@@ -608,6 +758,12 @@ package body mips_types is
|
||||
result.syscall := '0';
|
||||
result.break := '0';
|
||||
result.illegal := '0';
|
||||
result.ITLB_MOD := '0';
|
||||
result.ITLB_LOAD := '0';
|
||||
result.ITLB_STORE := '0';
|
||||
result.DTLB_MOD := '0';
|
||||
result.DTLB_LOAD := '0';
|
||||
result.DTLB_STORE := '0';
|
||||
|
||||
return result;
|
||||
|
||||
@@ -630,6 +786,12 @@ package body mips_types is
|
||||
result := result or e.syscall;
|
||||
result := result or e.break;
|
||||
result := result or e.illegal;
|
||||
result := result or e.ITLB_MOD;
|
||||
result := result or e.ITLB_LOAD;
|
||||
result := result or e.ITLB_STORE;
|
||||
result := result or e.DTLB_MOD;
|
||||
result := result or e.DTLB_LOAD;
|
||||
result := result or e.DTLB_STORE;
|
||||
|
||||
return result;
|
||||
|
||||
@@ -650,23 +812,28 @@ package body mips_types is
|
||||
result.syscall := a.syscall or b.syscall;
|
||||
result.break := a.break or b.break;
|
||||
result.illegal := a.illegal or b.illegal;
|
||||
result.ITLB_MOD := a.ITLB_MOD or b.ITLB_MOD;
|
||||
result.ITLB_LOAD := a.ITLB_LOAD or b.ITLB_LOAD;
|
||||
result.ITLB_STORE := a.ITLB_STORE or b.ITLB_STORE;
|
||||
result.DTLB_MOD := a.DTLB_MOD or b.DTLB_MOD;
|
||||
result.DTLB_LOAD := a.DTLB_LOAD or b.DTLB_LOAD;
|
||||
result.DTLB_STORE := a.DTLB_STORE or b.DTLB_STORE;
|
||||
|
||||
return result;
|
||||
|
||||
end "or";
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
function lg2(x : natural) return natural is
|
||||
function "or" (a, b : tlb_flags_t) return tlb_flags_t is
|
||||
variable result : tlb_flags_t;
|
||||
begin
|
||||
return natural(ceil(log2(real(x))));
|
||||
end lg2;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
function po2(x : natural) return natural is
|
||||
begin
|
||||
|
||||
return 2**lg2(x);
|
||||
end po2;
|
||||
result.N := a.N or b.N;
|
||||
result.D := a.D or b.D;
|
||||
result.V := a.V or b.V;
|
||||
|
||||
return result;
|
||||
|
||||
end "or";
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
end mips_types;
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
--------------------------------------------------------------------------
|
||||
-- Project: JIPS, a portable 32-bit RISC CPU written in VHDL
|
||||
-- This file: Types, constants and functions for JIPS
|
||||
--
|
||||
-- Copyright (C) 2008 J. Ahrensfeld
|
||||
--
|
||||
-- This program is free software: you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation, either version 3 of the License, or
|
||||
-- (at your option) any later version.
|
||||
--
|
||||
-- This program 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 General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
--
|
||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||
--
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.NUMERIC_STD.ALL;
|
||||
use IEEE.MATH_REAL.ALL;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
package mips_util_pkg is
|
||||
|
||||
|
||||
function to_mips_01(x : unsigned) return unsigned;
|
||||
function lg2(x : natural) return natural;
|
||||
function po2(x : natural) return natural;
|
||||
|
||||
end mips_util_pkg;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
package body mips_util_pkg is
|
||||
|
||||
function to_mips_01(x : unsigned) return unsigned is
|
||||
variable result : unsigned (x'left downto x'right);
|
||||
begin
|
||||
for i in x'left downto x'right loop
|
||||
if x(i) = '1' then
|
||||
result(i) := '1';
|
||||
else
|
||||
result(i) := '0';
|
||||
end if;
|
||||
end loop;
|
||||
return result;
|
||||
end to_mips_01;
|
||||
|
||||
function lg2(x : natural) return natural is
|
||||
begin
|
||||
return natural(ceil(log2(real(x))));
|
||||
end lg2;
|
||||
|
||||
function po2(x : natural) return natural is
|
||||
begin
|
||||
|
||||
return 2**lg2(x);
|
||||
end po2;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
end mips_util_pkg;
|
||||
|
||||
@@ -0,0 +1,410 @@
|
||||
LIBRARY ieee;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
USE ieee.numeric_std.ALL;
|
||||
|
||||
library work;
|
||||
use work.mips_types.all;
|
||||
use work.mips_util_pkg.all;
|
||||
use work.busmaster_types.all;
|
||||
|
||||
ENTITY tb_biu IS
|
||||
END tb_biu;
|
||||
|
||||
ARCHITECTURE behavior OF tb_biu IS
|
||||
|
||||
constant DATA_WIDTH : integer := 32;
|
||||
constant CLK_PERIOD : time := 10 ns;
|
||||
|
||||
signal CLK : std_logic := '1';
|
||||
signal RST : std_logic := '1';
|
||||
signal INT_O : std_logic;
|
||||
signal CYC_O : std_logic;
|
||||
signal STB_O : std_logic;
|
||||
signal WE_O : std_logic;
|
||||
signal SEL_O : unsigned(3 downto 0) := (others => '1');
|
||||
signal ACK_I : std_logic := '0';
|
||||
signal MRDY_O : std_logic := '1';
|
||||
signal SRDY_I : std_logic := '0';
|
||||
signal ADDR_O : unsigned(31 downto 0) := (others => '-');
|
||||
signal MDAT_I : unsigned(31 downto 0) := (others => '-');
|
||||
signal MDAT_O : unsigned(31 downto 0) := (others => '-');
|
||||
|
||||
signal index_in : unsigned(lg2(TLB_NUM_ENTRIES)-1 downto 0) := (others => '0');
|
||||
signal entry_we : STD_LOGIC := '0';
|
||||
signal entry_lo_in : tlb_entry_lo_t;
|
||||
signal entry_hi_in : tlb_entry_hi_t;
|
||||
|
||||
signal index_out : unsigned(lg2(TLB_NUM_ENTRIES)-1 downto 0) := (others => '0');
|
||||
signal entry_re : STD_LOGIC := '0';
|
||||
signal entry_lo_out : tlb_entry_lo_t;
|
||||
signal entry_hi_out : tlb_entry_hi_t;
|
||||
|
||||
-- CPU control/data
|
||||
signal cpu_imem_err : STD_LOGIC := '0';
|
||||
signal cpu_imem_en : STD_LOGIC := '0';
|
||||
signal cpu_imem_addr : word_t := (others => '-');
|
||||
signal cpu_imem_dout : word_t;
|
||||
signal cpu_imem_rdy : STD_LOGIC;
|
||||
|
||||
signal cpu_dmem_err : STD_LOGIC := '0';
|
||||
signal cpu_dmem_en : STD_LOGIC := '0';
|
||||
signal cpu_dmem_we : STD_LOGIC := '0';
|
||||
signal cpu_dmem_addr : word_t := (others => '-');
|
||||
signal cpu_dmem_be : unsigned(3 downto 0) := (others => '1');
|
||||
signal cpu_dmem_din : word_t := X"BFC0_BABE";
|
||||
signal cpu_dmem_dout : word_t;
|
||||
signal cpu_dmem_rdy : STD_LOGIC;
|
||||
|
||||
-- BIU control
|
||||
signal ctrl_in : biu_ctrl_in_t;
|
||||
signal ctrl_out : biu_ctrl_out_t;
|
||||
|
||||
type op_descr_t is (op_idle, op_entry_i_write, op_entry_d_write, op_cpu_i_read, op_cpu_d_read, op_cpu_d_write);
|
||||
signal op_descr : op_descr_t := op_idle;
|
||||
|
||||
signal cpu_imem_din_reg : word_t;
|
||||
signal cpu_imem_din_vld : STD_LOGIC;
|
||||
signal cpu_dmem_din_reg : word_t;
|
||||
signal cpu_dmem_din_vld : STD_LOGIC;
|
||||
|
||||
BEGIN
|
||||
|
||||
inst_biu: entity work.biu
|
||||
GENERIC MAP
|
||||
(
|
||||
ICACHE_SIZE => 1024, -- words
|
||||
ICACHE_LINE => 8, -- words
|
||||
DCACHE_SIZE => 1024, -- words
|
||||
DCACHE_LINE => 8, -- words
|
||||
WRITE_FIFO_SIZE => 4, -- words
|
||||
WITH_TLB => true
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
clk => CLK,
|
||||
|
||||
imem_err => cpu_imem_err,
|
||||
imem_rdy => cpu_imem_rdy,
|
||||
imem_en => cpu_imem_en,
|
||||
imem_addr => cpu_imem_addr,
|
||||
imem_dout => cpu_imem_dout,
|
||||
dmem_err => cpu_dmem_err,
|
||||
dmem_rdy => cpu_dmem_rdy,
|
||||
dmem_en => cpu_dmem_en,
|
||||
dmem_we => cpu_dmem_we,
|
||||
dmem_be => cpu_dmem_be,
|
||||
dmem_dout => cpu_dmem_dout,
|
||||
dmem_din => cpu_dmem_din,
|
||||
dmem_addr => cpu_dmem_addr,
|
||||
|
||||
RST_I => RST,
|
||||
CLK_I => CLK,
|
||||
ACK_I => ACK_I,
|
||||
SRDY_I => SRDY_I,
|
||||
ADDR_O => ADDR_O,
|
||||
MDAT_I => MDAT_I,
|
||||
MDAT_O => MDAT_O,
|
||||
WE_O => WE_O,
|
||||
SEL_O => SEL_O,
|
||||
CYC_O => CYC_O,
|
||||
STB_O => STB_O,
|
||||
MRDY_O => MRDY_O,
|
||||
|
||||
ctrl_in => ctrl_in,
|
||||
ctrl_out => ctrl_out
|
||||
|
||||
);
|
||||
|
||||
|
||||
inst_rom_wb: entity work.rom_wb
|
||||
-- GENERIC MAP
|
||||
-- (
|
||||
-- NUM_WORDS => 256
|
||||
-- )
|
||||
PORT MAP
|
||||
(
|
||||
CLK_I => CLK,
|
||||
RST_I => RST,
|
||||
CYC_I => CYC_O,
|
||||
STB_I => STB_O,
|
||||
-- SEL_I => SEL_O,
|
||||
WE_I => WE_O,
|
||||
ACK_O => ACK_I,
|
||||
SRDY_O => SRDY_I,
|
||||
MRDY_I => MRDY_O,
|
||||
ADDR_I => ADDR_O,
|
||||
-- DAT_I => MDAT_O,
|
||||
DAT_O => MDAT_I
|
||||
);
|
||||
|
||||
|
||||
CLK_GEN: process
|
||||
begin
|
||||
wait for CLK_PERIOD/2;
|
||||
CLK <= not CLK;
|
||||
end process;
|
||||
|
||||
cpu_imem_din_register:
|
||||
process(clk)
|
||||
variable en2: std_logic;
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
cpu_imem_din_vld <= '0';
|
||||
if en2 = '1' and cpu_imem_rdy = '1' then
|
||||
cpu_imem_din_reg <= cpu_imem_dout;
|
||||
cpu_imem_din_vld <= '1';
|
||||
end if;
|
||||
en2 := cpu_imem_en;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
cpu_dmem_din_register:
|
||||
process(clk)
|
||||
variable en2: std_logic;
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
cpu_dmem_din_vld <= '0';
|
||||
if en2 = '1' and cpu_dmem_rdy = '1' then
|
||||
cpu_dmem_din_reg <= cpu_dmem_dout;
|
||||
cpu_dmem_din_vld <= '1';
|
||||
end if;
|
||||
en2 := cpu_dmem_en;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
|
||||
ctrl_in.icache.inv_addr <= X"BEEF_BABE";
|
||||
ctrl_in.icache.inv_at <= '0';
|
||||
ctrl_in.icache.inv_all <= '0';
|
||||
|
||||
ctrl_in.dcache.inv_addr <= X"BEEF_BABE";
|
||||
ctrl_in.dcache.inv_at <= '0';
|
||||
ctrl_in.dcache.inv_all <= '0';
|
||||
|
||||
STIMULUS: process
|
||||
|
||||
variable result : unsigned(31 downto 0);
|
||||
|
||||
procedure cmd_entry_i_write(index : integer; asid, vpn, pfn : unsigned; g, n, d, v : std_logic) is
|
||||
begin
|
||||
|
||||
op_descr <= op_entry_i_write;
|
||||
|
||||
ctrl_in.itlb.entry_wr_idx <= to_unsigned(index, lg2(TLB_NUM_ENTRIES));
|
||||
|
||||
ctrl_in.itlb.entry_hi.vpn <= vpn;
|
||||
ctrl_in.itlb.entry_hi.asid <= asid;
|
||||
|
||||
ctrl_in.itlb.entry_lo.pfn <= pfn;
|
||||
ctrl_in.itlb.entry_lo.n <= n;
|
||||
ctrl_in.itlb.entry_lo.d <= d;
|
||||
ctrl_in.itlb.entry_lo.v <= v;
|
||||
ctrl_in.itlb.entry_lo.g <= g;
|
||||
|
||||
ctrl_in.itlb.entry_we <= '1';
|
||||
wait until rising_edge(CLK);
|
||||
ctrl_in.itlb.entry_we <= '0';
|
||||
|
||||
end procedure cmd_entry_i_write;
|
||||
|
||||
procedure cmd_entry_d_write(index : integer; asid, vpn, pfn : unsigned; g, n, d, v : std_logic) is
|
||||
begin
|
||||
|
||||
op_descr <= op_entry_d_write;
|
||||
ctrl_in.dtlb.entry_wr_idx <= to_unsigned(index, lg2(TLB_NUM_ENTRIES));
|
||||
|
||||
ctrl_in.dtlb.entry_hi.vpn <= vpn;
|
||||
ctrl_in.dtlb.entry_hi.asid <= asid;
|
||||
|
||||
ctrl_in.dtlb.entry_lo.pfn <= pfn;
|
||||
ctrl_in.dtlb.entry_lo.n <= n;
|
||||
ctrl_in.dtlb.entry_lo.d <= d;
|
||||
ctrl_in.dtlb.entry_lo.v <= v;
|
||||
ctrl_in.dtlb.entry_lo.g <= g;
|
||||
|
||||
ctrl_in.dtlb.entry_we <= '1';
|
||||
wait until rising_edge(CLK);
|
||||
ctrl_in.dtlb.entry_we <= '0';
|
||||
|
||||
end procedure cmd_entry_d_write;
|
||||
|
||||
procedure cpu_i_read(addr : unsigned) is
|
||||
begin
|
||||
|
||||
op_descr <= op_cpu_i_read;
|
||||
cpu_imem_addr <= addr;
|
||||
cpu_imem_en <= '1';
|
||||
wait until rising_edge(CLK) and cpu_imem_rdy = '1';
|
||||
cpu_imem_en <= '0';
|
||||
|
||||
end procedure cpu_i_read;
|
||||
|
||||
procedure cpu_d_read(addr : unsigned) is
|
||||
begin
|
||||
|
||||
op_descr <= op_cpu_d_read;
|
||||
cpu_dmem_addr <= addr;
|
||||
cpu_dmem_en <= '1';
|
||||
wait until rising_edge(CLK) and cpu_dmem_rdy = '1';
|
||||
cpu_dmem_en <= '0';
|
||||
|
||||
end procedure cpu_d_read;
|
||||
|
||||
procedure cpu_d_write(addr, data : unsigned) is
|
||||
begin
|
||||
|
||||
op_descr <= op_cpu_d_write;
|
||||
cpu_dmem_we <= '1';
|
||||
cpu_dmem_addr <= addr;
|
||||
cpu_dmem_din <= data;
|
||||
cpu_dmem_en <= '1';
|
||||
wait until rising_edge(CLK) and cpu_dmem_rdy = '1';
|
||||
cpu_dmem_en <= '0';
|
||||
|
||||
end procedure cpu_d_write;
|
||||
|
||||
begin
|
||||
|
||||
wait for 6*CLK_PERIOD;
|
||||
RST <= '0';
|
||||
wait for 60*CLK_PERIOD;
|
||||
wait until rising_edge(CLK) and cpu_imem_rdy = '1' and cpu_dmem_rdy = '1';
|
||||
|
||||
cmd_entry_i_write(0, "110000", X"0000_0", X"00DE_C", '0', '0', '0', '1');
|
||||
cmd_entry_i_write(1, "110000", X"0000_1", X"11DE_C", '0', '0', '0', '1');
|
||||
cmd_entry_i_write(2, "110000", X"0000_2", X"22DE_C", '0', '0', '0', '1');
|
||||
cmd_entry_i_write(3, "110000", X"0000_3", X"33DE_C", '0', '0', '0', '1');
|
||||
cmd_entry_i_write(4, "110000", X"0000_4", X"44DE_C", '0', '0', '0', '1');
|
||||
cmd_entry_i_write(5, "110000", X"0000_5", X"55DE_C", '0', '0', '0', '1');
|
||||
cmd_entry_i_write(6, "110000", X"0000_6", X"66DE_C", '0', '0', '0', '1');
|
||||
cmd_entry_i_write(7, "110000", X"0000_7", X"77DE_C", '0', '0', '0', '1');
|
||||
|
||||
cmd_entry_d_write(0, "110000", X"0000_0", X"00DE_C", '0', '0', '0', '1');
|
||||
cmd_entry_d_write(1, "110000", X"0000_1", X"11DE_C", '0', '0', '0', '1');
|
||||
cmd_entry_d_write(2, "110000", X"0000_2", X"22DE_C", '0', '0', '0', '1');
|
||||
cmd_entry_d_write(3, "110000", X"0000_3", X"33DE_C", '0', '0', '0', '1');
|
||||
cmd_entry_d_write(4, "110000", X"0000_4", X"44DE_C", '0', '0', '0', '1');
|
||||
cmd_entry_d_write(5, "110000", X"0000_5", X"55DE_C", '0', '0', '0', '1');
|
||||
cmd_entry_d_write(6, "110000", X"0000_6", X"66DE_C", '0', '0', '0', '1');
|
||||
cmd_entry_d_write(7, "110000", X"0000_7", X"77DE_C", '0', '0', '0', '1');
|
||||
|
||||
cpu_i_read(X"BFC0_0200");
|
||||
cpu_i_read(X"BFC0_0180");
|
||||
cpu_d_read(X"BFC0_0200");
|
||||
|
||||
cpu_i_read(X"8000_0204");
|
||||
cpu_i_read(X"8000_0300");
|
||||
cpu_i_read(X"8000_0304");
|
||||
cpu_i_read(X"8000_0308");
|
||||
|
||||
cpu_i_read(X"9000_0208");
|
||||
cpu_i_read(X"9000_030C");
|
||||
cpu_i_read(X"9100_0310");
|
||||
cpu_i_read(X"9200_0314");
|
||||
|
||||
cpu_i_read(X"A000_020C");
|
||||
cpu_i_read(X"A000_0318");
|
||||
cpu_i_read(X"A100_031C");
|
||||
cpu_i_read(X"A200_0320");
|
||||
|
||||
cpu_i_read(X"B000_0210");
|
||||
cpu_i_read(X"B000_0324");
|
||||
cpu_i_read(X"B000_0328");
|
||||
cpu_i_read(X"B000_032C");
|
||||
|
||||
cpu_i_read(X"0000_0400");
|
||||
cpu_i_read(X"0000_1420");
|
||||
cpu_i_read(X"0000_2440");
|
||||
cpu_i_read(X"0000_3460");
|
||||
cpu_i_read(X"0000_4480");
|
||||
cpu_i_read(X"0000_54A0");
|
||||
cpu_i_read(X"0000_64C0");
|
||||
cpu_i_read(X"0000_74E0");
|
||||
cpu_i_read(X"0000_8500");
|
||||
cpu_i_read(X"0000_9520");
|
||||
|
||||
cpu_i_read(X"0000_0400");
|
||||
cpu_i_read(X"0000_1420");
|
||||
cpu_i_read(X"0000_2440");
|
||||
cpu_i_read(X"0000_3460");
|
||||
cpu_i_read(X"0000_4480");
|
||||
cpu_i_read(X"0000_54A0");
|
||||
cpu_i_read(X"0000_64C0");
|
||||
cpu_i_read(X"0000_74E0");
|
||||
|
||||
|
||||
cpu_i_read(X"0000_0400");
|
||||
|
||||
cpu_i_read(X"0000_0410");
|
||||
cpu_i_read(X"0000_0404");
|
||||
cpu_i_read(X"0000_0408");
|
||||
cpu_i_read(X"0000_0404");
|
||||
cpu_i_read(X"0000_0434");
|
||||
cpu_i_read(X"0000_0400");
|
||||
|
||||
|
||||
---------------------------------------------
|
||||
cpu_d_read(X"BFC0_0200");
|
||||
cpu_d_read(X"BFC0_0180");
|
||||
|
||||
cpu_d_read(X"8000_0204");
|
||||
cpu_d_read(X"8000_0300");
|
||||
cpu_d_read(X"8000_0304");
|
||||
cpu_d_read(X"8000_0308");
|
||||
|
||||
cpu_d_read(X"9000_0208");
|
||||
cpu_d_read(X"9000_030C");
|
||||
cpu_d_read(X"9100_0310");
|
||||
cpu_d_read(X"9200_0314");
|
||||
|
||||
cpu_d_read(X"A000_020C");
|
||||
cpu_d_read(X"A000_0318");
|
||||
cpu_d_read(X"A100_031C");
|
||||
cpu_d_read(X"A200_0320");
|
||||
|
||||
cpu_d_read(X"B000_0210");
|
||||
cpu_d_read(X"B000_0324");
|
||||
cpu_d_read(X"B000_0328");
|
||||
cpu_d_read(X"B000_032C");
|
||||
|
||||
cpu_d_read(X"0000_0400");
|
||||
cpu_d_read(X"0000_1420");
|
||||
cpu_d_read(X"0000_2440");
|
||||
cpu_d_read(X"0000_3460");
|
||||
cpu_d_read(X"0000_4480");
|
||||
cpu_d_read(X"0000_54A0");
|
||||
cpu_d_read(X"0000_64C0");
|
||||
cpu_d_read(X"0000_74E0");
|
||||
cpu_d_read(X"0000_8500");
|
||||
cpu_d_read(X"0000_9520");
|
||||
|
||||
cpu_d_read(X"0000_0400");
|
||||
cpu_d_read(X"0000_1420");
|
||||
cpu_d_read(X"0000_2440");
|
||||
cpu_d_read(X"0000_3460");
|
||||
cpu_d_read(X"0000_4480");
|
||||
cpu_d_read(X"0000_54A0");
|
||||
cpu_d_read(X"0000_64C0");
|
||||
cpu_d_read(X"0000_74E0");
|
||||
cpu_d_write(X"0000_0400", X"AAAA_AAAA");
|
||||
|
||||
cpu_d_read(X"0000_0400");
|
||||
|
||||
cpu_d_read(X"0000_0410");
|
||||
cpu_d_read(X"0000_0404");
|
||||
cpu_d_read(X"0000_0408");
|
||||
cpu_d_write(X"0000_0404", X"5555_5555");
|
||||
cpu_d_read(X"0000_0404");
|
||||
cpu_d_write(X"0000_0404", X"6666_6666");
|
||||
cpu_d_read(X"0000_0434");
|
||||
cpu_d_write(X"0000_0400", X"1111_1111");
|
||||
cpu_d_write(X"0000_0404", X"2222_2222");
|
||||
cpu_d_write(X"0000_0408", X"3333_3333");
|
||||
cpu_d_write(X"0000_040C", X"4444_4444");
|
||||
cpu_d_read(X"0000_0400");
|
||||
|
||||
wait;
|
||||
|
||||
end process;
|
||||
|
||||
END;
|
||||
@@ -0,0 +1,265 @@
|
||||
LIBRARY ieee;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
USE ieee.numeric_std.ALL;
|
||||
|
||||
library work;
|
||||
use work.mips_types.all;
|
||||
use work.mips_util_pkg.all;
|
||||
|
||||
ENTITY tb_cam IS
|
||||
END tb_cam;
|
||||
|
||||
ARCHITECTURE behavior OF tb_cam IS
|
||||
|
||||
constant CLK_PERIOD : time := 10 ns;
|
||||
constant DATA_WIDTH : integer := 20;
|
||||
constant CAM_NUM_ENTRIES : integer := 32;
|
||||
|
||||
signal CLK_O : std_logic := '1';
|
||||
signal RST_O : std_logic := '1';
|
||||
signal cam_we : std_logic := '0';
|
||||
signal cam_re : std_logic := '0';
|
||||
signal cam_vld : std_logic := '0';
|
||||
signal cam_rdy : std_logic := '-';
|
||||
|
||||
signal cam_addr : unsigned(lg2(CAM_NUM_ENTRIES)-1 downto 0) := (others => '0');
|
||||
signal cam_rtag : unsigned(DATA_WIDTH-1 downto 0) := (others => '0');
|
||||
signal cam_wtag : unsigned(DATA_WIDTH-1 downto 0) := (others => '0');
|
||||
|
||||
signal cam_hit : unsigned (CAM_NUM_ENTRIES-1 downto 0);
|
||||
signal cam_hit_vld : std_logic := '-';
|
||||
|
||||
|
||||
BEGIN
|
||||
|
||||
inst_cam: entity work.cam
|
||||
GENERIC MAP
|
||||
(
|
||||
NUM_ENTRIES => CAM_NUM_ENTRIES,
|
||||
DATA_WIDTH => DATA_WIDTH,
|
||||
CAM_RAM_MAX_WIDTH => 15
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
rst => RST_O,
|
||||
clk => CLK_O,
|
||||
clk_rd => CLK_O,
|
||||
|
||||
rdy => cam_rdy,
|
||||
|
||||
re => cam_re,
|
||||
we => cam_we,
|
||||
vld => cam_vld,
|
||||
addr => cam_addr,
|
||||
tag_rd => cam_rtag,
|
||||
tag_wr => cam_wtag,
|
||||
|
||||
hit_vld => cam_hit_vld,
|
||||
hit => cam_hit
|
||||
|
||||
);
|
||||
|
||||
CLK_GEN: process
|
||||
begin
|
||||
wait for CLK_PERIOD/2;
|
||||
CLK_O <= not CLK_O;
|
||||
end process;
|
||||
|
||||
|
||||
STIMULUS: process
|
||||
|
||||
variable tag : unsigned(DATA_WIDTH-1 downto 0) := (others => '0');
|
||||
|
||||
procedure cam_entry_write(index : integer; data : unsigned; valid : std_logic) is
|
||||
begin
|
||||
|
||||
cam_wtag <= data;
|
||||
cam_addr <= to_unsigned(index, lg2(CAM_NUM_ENTRIES));
|
||||
cam_vld <= valid;
|
||||
cam_we <= '1';
|
||||
wait until rising_edge(CLK_O) and cam_rdy = '1';
|
||||
cam_we <= '0';
|
||||
|
||||
end procedure cam_entry_write;
|
||||
|
||||
procedure cam_lookup(data : unsigned) is
|
||||
begin
|
||||
|
||||
cam_rtag <= data;
|
||||
cam_re <= '1';
|
||||
wait until rising_edge(CLK_O) and cam_rdy = '1';
|
||||
cam_re <= '0';
|
||||
|
||||
end procedure cam_lookup;
|
||||
|
||||
|
||||
begin
|
||||
|
||||
wait for 6*CLK_PERIOD;
|
||||
RST_O <= '0';
|
||||
wait for 60*CLK_PERIOD;
|
||||
wait until rising_edge(CLK_O) and cam_rdy = '1';
|
||||
|
||||
-----------------------
|
||||
tag := X"CAF0_0";
|
||||
for i in 0 to CAM_NUM_ENTRIES-1 loop
|
||||
cam_entry_write(i, tag, '1');
|
||||
tag := tag + X"0100_0";
|
||||
end loop;
|
||||
wait for 60*CLK_PERIOD;
|
||||
wait until rising_edge(CLK_O) and cam_rdy = '1';
|
||||
tag := X"CAF0_0";
|
||||
for i in 0 to CAM_NUM_ENTRIES-1 loop
|
||||
cam_lookup(tag);
|
||||
tag := tag + X"0100_0";
|
||||
end loop;
|
||||
|
||||
wait for 60*CLK_PERIOD;
|
||||
wait until rising_edge(CLK_O) and cam_rdy = '1';
|
||||
|
||||
RST_O <= '1';
|
||||
wait for 6*CLK_PERIOD;
|
||||
wait until rising_edge(CLK_O);
|
||||
RST_O <= '0';
|
||||
wait until rising_edge(CLK_O) and cam_rdy = '1';
|
||||
-----------------------
|
||||
tag := X"CAF0_0";
|
||||
for i in 0 to CAM_NUM_ENTRIES-1 loop
|
||||
cam_entry_write(i, tag, '1');
|
||||
tag := tag + X"0010_0";
|
||||
end loop;
|
||||
wait for 60*CLK_PERIOD;
|
||||
wait until rising_edge(CLK_O) and cam_rdy = '1';
|
||||
tag := X"CAF0_0";
|
||||
for i in 0 to CAM_NUM_ENTRIES-1 loop
|
||||
cam_lookup(tag);
|
||||
tag := tag + X"0010_0";
|
||||
end loop;
|
||||
|
||||
wait for 60*CLK_PERIOD;
|
||||
wait until rising_edge(CLK_O) and cam_rdy = '1';
|
||||
|
||||
RST_O <= '1';
|
||||
wait for 6*CLK_PERIOD;
|
||||
wait until rising_edge(CLK_O);
|
||||
RST_O <= '0';
|
||||
wait until rising_edge(CLK_O) and cam_rdy = '1';
|
||||
-----------------------
|
||||
tag := X"CAF0_0";
|
||||
for i in 0 to CAM_NUM_ENTRIES-1 loop
|
||||
cam_entry_write(i, tag, '1');
|
||||
tag := tag + X"0001_0";
|
||||
end loop;
|
||||
wait for 60*CLK_PERIOD;
|
||||
wait until rising_edge(CLK_O) and cam_rdy = '1';
|
||||
tag := X"CAF0_0";
|
||||
for i in 0 to CAM_NUM_ENTRIES-1 loop
|
||||
cam_lookup(tag);
|
||||
tag := tag + X"0001_0";
|
||||
end loop;
|
||||
|
||||
wait for 60*CLK_PERIOD;
|
||||
wait until rising_edge(CLK_O) and cam_rdy = '1';
|
||||
|
||||
RST_O <= '1';
|
||||
wait for 6*CLK_PERIOD;
|
||||
wait until rising_edge(CLK_O);
|
||||
RST_O <= '0';
|
||||
wait until rising_edge(CLK_O) and cam_rdy = '1';
|
||||
-----------------------
|
||||
tag := X"CAF0_0";
|
||||
for i in 0 to CAM_NUM_ENTRIES-1 loop
|
||||
cam_entry_write(i, tag, '1');
|
||||
tag := tag + X"0000_1";
|
||||
end loop;
|
||||
wait for 60*CLK_PERIOD;
|
||||
wait until rising_edge(CLK_O) and cam_rdy = '1';
|
||||
tag := X"CAF0_0";
|
||||
for i in 0 to CAM_NUM_ENTRIES-1 loop
|
||||
cam_lookup(tag);
|
||||
tag := tag + X"0000_1";
|
||||
end loop;
|
||||
|
||||
wait for 60*CLK_PERIOD;
|
||||
wait until rising_edge(CLK_O) and cam_rdy = '1';
|
||||
|
||||
RST_O <= '1';
|
||||
wait for 6*CLK_PERIOD;
|
||||
wait until rising_edge(CLK_O);
|
||||
RST_O <= '0';
|
||||
wait until rising_edge(CLK_O) and cam_rdy = '1';
|
||||
-----------------------
|
||||
tag := X"CAF0_0";
|
||||
for i in 0 to CAM_NUM_ENTRIES-1 loop
|
||||
cam_entry_write(i, tag, '1');
|
||||
tag := tag + X"0102_3";
|
||||
end loop;
|
||||
|
||||
wait for 60*CLK_PERIOD;
|
||||
wait until rising_edge(CLK_O) and cam_rdy = '1';
|
||||
tag := X"CAF0_0";
|
||||
for i in 0 to CAM_NUM_ENTRIES-1 loop
|
||||
cam_lookup(tag);
|
||||
tag := tag + X"0102_3";
|
||||
end loop;
|
||||
|
||||
wait for 60*CLK_PERIOD;
|
||||
wait until rising_edge(CLK_O) and cam_rdy = '1';
|
||||
|
||||
RST_O <= '1';
|
||||
wait for 6*CLK_PERIOD;
|
||||
wait until rising_edge(CLK_O);
|
||||
RST_O <= '0';
|
||||
wait until rising_edge(CLK_O) and cam_rdy = '1';
|
||||
-----------------------
|
||||
-- overwrite
|
||||
cam_entry_write(2, X"BEEF_2", '1');
|
||||
wait for 8*CLK_PERIOD;
|
||||
wait until rising_edge(CLK_O) and cam_rdy = '1';
|
||||
|
||||
-- overwrite entry
|
||||
cam_entry_write(2, X"CAFE_2", '1');
|
||||
-- new entry
|
||||
cam_entry_write(3, X"CAFE_3", '1');
|
||||
cam_entry_write(4, X"CAFE_4", '1');
|
||||
|
||||
wait for 8*CLK_PERIOD;
|
||||
wait until rising_edge(CLK_O) and cam_rdy = '1';
|
||||
cam_entry_write(1, X"CAFE_1", '0');
|
||||
cam_entry_write(2, X"CAFE_2", '0');
|
||||
cam_entry_write(3, X"CAFE_3", '0');
|
||||
cam_entry_write(4, X"CAFE_4", '0');
|
||||
|
||||
wait for 8*CLK_PERIOD;
|
||||
wait until rising_edge(CLK_O) and cam_rdy = '1';
|
||||
cam_lookup(X"BEEF_2");
|
||||
cam_lookup(X"CAFE_1");
|
||||
cam_lookup(X"CAFE_2");
|
||||
cam_lookup(X"CAFE_3");
|
||||
cam_lookup(X"CAFE_4");
|
||||
|
||||
wait for 8*CLK_PERIOD;
|
||||
wait until rising_edge(CLK_O) and cam_rdy = '1';
|
||||
cam_entry_write(1, X"CAFE_1", '1');
|
||||
cam_entry_write(2, X"CAFE_2", '1');
|
||||
cam_entry_write(3, X"CAFE_3", '1');
|
||||
cam_entry_write(4, X"CAFE_4", '1');
|
||||
|
||||
wait for 8*CLK_PERIOD;
|
||||
wait until rising_edge(CLK_O) and cam_rdy = '1';
|
||||
cam_lookup(X"CAFE_1");
|
||||
cam_lookup(X"CAFE_2");
|
||||
cam_lookup(X"CAFE_3");
|
||||
cam_lookup(X"CAFE_4");
|
||||
|
||||
wait for 8*CLK_PERIOD;
|
||||
wait until rising_edge(CLK_O) and cam_rdy = '1';
|
||||
cam_entry_write(7, X"CAFE_7", '0');
|
||||
|
||||
wait for 8*CLK_PERIOD;
|
||||
wait until rising_edge(CLK_O) and cam_rdy = '1';
|
||||
wait;
|
||||
|
||||
end process;
|
||||
|
||||
END;
|
||||
@@ -0,0 +1,211 @@
|
||||
LIBRARY ieee;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
USE ieee.numeric_std.ALL;
|
||||
|
||||
library work;
|
||||
use work.mips_types.all;
|
||||
use work.mips_util_pkg.all;
|
||||
|
||||
ENTITY tb_tlb IS
|
||||
END tb_tlb;
|
||||
|
||||
ARCHITECTURE behavior OF tb_tlb IS
|
||||
|
||||
constant DATA_WIDTH : integer := 32;
|
||||
constant CLK_PERIOD : time := 10 ns;
|
||||
|
||||
signal CLK_O : std_logic := '1';
|
||||
signal RST_O : std_logic := '1';
|
||||
signal ce : std_logic := '1';
|
||||
|
||||
signal tlb_rdy : std_logic;
|
||||
|
||||
signal tlb_ctrl_in : tlb_ctrl_in_t;
|
||||
signal tlb_ctrl_out : tlb_ctrl_out_t;
|
||||
signal tlb_query_in : tlb_query_in_t;
|
||||
signal tlb_query_out : tlb_query_out_t;
|
||||
|
||||
|
||||
BEGIN
|
||||
|
||||
inst_uut : entity work.tlb
|
||||
GENERIC MAP
|
||||
(
|
||||
NUM_ENTRIES => TLB_NUM_ENTRIES,
|
||||
CACHE_KSEG1 => false,
|
||||
USE_TLB => true
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
-- System signals
|
||||
rst => RST_O,
|
||||
clk => CLK_O,
|
||||
ce => ce,
|
||||
|
||||
rdy => tlb_rdy,
|
||||
|
||||
ctrl_in => tlb_ctrl_in,
|
||||
ctrl_out => tlb_ctrl_out,
|
||||
|
||||
query_in => tlb_query_in,
|
||||
query_out => tlb_query_out
|
||||
|
||||
);
|
||||
|
||||
CLK_GEN: process
|
||||
begin
|
||||
wait for CLK_PERIOD/2;
|
||||
CLK_O <= not CLK_O;
|
||||
end process;
|
||||
|
||||
STIMULUS: process
|
||||
|
||||
variable result : unsigned(31 downto 0);
|
||||
|
||||
procedure cmd_entry_write(index : integer; asid, vpn, pfn : unsigned; g, n, d, v : std_logic) is
|
||||
begin
|
||||
|
||||
tlb_ctrl_in.entry_wr_idx <= to_unsigned(index, lg2(TLB_NUM_ENTRIES));
|
||||
|
||||
tlb_ctrl_in.entry_hi.vpn <= vpn;
|
||||
tlb_ctrl_in.entry_hi.asid <= asid;
|
||||
|
||||
tlb_ctrl_in.entry_lo.pfn <= pfn;
|
||||
tlb_ctrl_in.entry_lo.g <= g;
|
||||
tlb_ctrl_in.entry_lo.n <= n;
|
||||
tlb_ctrl_in.entry_lo.d <= d;
|
||||
tlb_ctrl_in.entry_lo.v <= v;
|
||||
|
||||
tlb_ctrl_in.entry_we <= '1';
|
||||
wait until rising_edge(CLK_O) and tlb_rdy = '1';
|
||||
tlb_ctrl_in.entry_we <= '0';
|
||||
|
||||
end procedure cmd_entry_write;
|
||||
|
||||
procedure cmd_read_single(addr : unsigned) is
|
||||
begin
|
||||
|
||||
end procedure cmd_read_single;
|
||||
|
||||
begin
|
||||
|
||||
tlb_ctrl_in.entry_we <= '0';
|
||||
tlb_ctrl_in.entry_re <= '0';
|
||||
tlb_query_in.vld <= '0';
|
||||
tlb_query_in.write <= '0';
|
||||
tlb_query_in.vaddr <= X"BFC0_CAFE";
|
||||
|
||||
wait for 6*CLK_PERIOD;
|
||||
RST_O <= '0';
|
||||
wait for 60*CLK_PERIOD;
|
||||
wait until rising_edge(CLK_O) and tlb_rdy = '1';
|
||||
|
||||
wait until rising_edge(CLK_O);
|
||||
tlb_query_in.vld <= '1';
|
||||
wait until rising_edge(CLK_O);
|
||||
tlb_query_in.vld <= '0';
|
||||
wait until rising_edge(CLK_O);
|
||||
tlb_query_in.vld <= '1';
|
||||
tlb_query_in.vaddr <= X"9FC0_CAFE";
|
||||
wait until rising_edge(CLK_O);
|
||||
tlb_query_in.vld <= '0';
|
||||
|
||||
cmd_entry_write(0, "110000", X"0000_0", X"00DE_F", '0', '0', '0', '1');
|
||||
cmd_entry_write(1, "110000", X"0000_1", X"01DE_F", '0', '0', '0', '1');
|
||||
cmd_entry_write(2, "110000", X"0000_2", X"02DE_F", '0', '0', '0', '0');
|
||||
cmd_entry_write(3, "110000", X"0000_3", X"43DE_F", '0', '0', '0', '1');
|
||||
cmd_entry_write(4, "100000", X"0000_4", X"44DE_F", '0', '0', '0', '1');
|
||||
cmd_entry_write(5, "110000", X"0000_5", X"65DE_F", '0', '0', '0', '1');
|
||||
cmd_entry_write(6, "100000", X"0000_6", X"66DE_F", '1', '0', '0', '1');
|
||||
cmd_entry_write(7, "110000", X"0000_7", X"67DE_F", '0', '0', '0', '1');
|
||||
|
||||
wait until rising_edge(CLK_O);
|
||||
tlb_query_in.vld <= '1';
|
||||
|
||||
tlb_query_in.vaddr <= X"8000_BABE";
|
||||
wait until rising_edge(CLK_O);
|
||||
tlb_query_in.vaddr <= X"8000_1234";
|
||||
wait until rising_edge(CLK_O);
|
||||
tlb_query_in.vaddr <= X"8100_1234";
|
||||
wait until rising_edge(CLK_O);
|
||||
tlb_query_in.vaddr <= X"8200_1234";
|
||||
|
||||
wait until rising_edge(CLK_O);
|
||||
tlb_query_in.vaddr <= X"9000_BABE";
|
||||
wait until rising_edge(CLK_O);
|
||||
tlb_query_in.vaddr <= X"9000_1234";
|
||||
wait until rising_edge(CLK_O);
|
||||
tlb_query_in.vaddr <= X"9100_1234";
|
||||
wait until rising_edge(CLK_O);
|
||||
tlb_query_in.vaddr <= X"9200_1234";
|
||||
|
||||
wait until rising_edge(CLK_O);
|
||||
tlb_query_in.vaddr <= X"A000_BABE";
|
||||
wait until rising_edge(CLK_O);
|
||||
tlb_query_in.vaddr <= X"A000_1234";
|
||||
wait until rising_edge(CLK_O);
|
||||
tlb_query_in.vaddr <= X"A100_1234";
|
||||
wait until rising_edge(CLK_O);
|
||||
tlb_query_in.vaddr <= X"A200_1234";
|
||||
|
||||
wait until rising_edge(CLK_O);
|
||||
tlb_query_in.vaddr <= X"B000_BABE";
|
||||
wait until rising_edge(CLK_O);
|
||||
tlb_query_in.vaddr <= X"B000_1234";
|
||||
wait until rising_edge(CLK_O);
|
||||
tlb_query_in.vaddr <= X"B100_1234";
|
||||
wait until rising_edge(CLK_O);
|
||||
tlb_query_in.vaddr <= X"B200_1234";
|
||||
|
||||
|
||||
wait until rising_edge(CLK_O);
|
||||
tlb_query_in.vaddr <= X"0000_0CAF";
|
||||
wait until rising_edge(CLK_O);
|
||||
tlb_query_in.vaddr <= tlb_query_in.vaddr + X"1000";
|
||||
wait until rising_edge(CLK_O);
|
||||
tlb_query_in.vaddr <= tlb_query_in.vaddr + X"1000";
|
||||
wait until rising_edge(CLK_O);
|
||||
tlb_query_in.vaddr <= tlb_query_in.vaddr + X"1000";
|
||||
wait until rising_edge(CLK_O);
|
||||
tlb_query_in.vaddr <= tlb_query_in.vaddr + X"1000";
|
||||
wait until rising_edge(CLK_O);
|
||||
tlb_query_in.vaddr <= tlb_query_in.vaddr + X"1000";
|
||||
wait until rising_edge(CLK_O);
|
||||
tlb_query_in.vaddr <= tlb_query_in.vaddr + X"1000";
|
||||
wait until rising_edge(CLK_O);
|
||||
tlb_query_in.vaddr <= tlb_query_in.vaddr + X"1000";
|
||||
wait until rising_edge(CLK_O);
|
||||
tlb_query_in.vaddr <= tlb_query_in.vaddr + X"1000";
|
||||
wait until rising_edge(CLK_O);
|
||||
tlb_query_in.vaddr <= tlb_query_in.vaddr + X"1000";
|
||||
|
||||
wait until rising_edge(CLK_O);
|
||||
tlb_query_in.vld <= '0';
|
||||
|
||||
cmd_entry_write(0, "110000", X"0000_0", X"40DE_F", '0', '0', '1', '1');
|
||||
|
||||
wait until rising_edge(CLK_O);
|
||||
tlb_query_in.vld <= '1';
|
||||
tlb_query_in.vaddr <= X"0000_0CAF";
|
||||
wait until rising_edge(CLK_O);
|
||||
tlb_query_in.vld <= '0';
|
||||
|
||||
wait until rising_edge(CLK_O);
|
||||
tlb_query_in.vld <= '1';
|
||||
tlb_query_in.write <= '1';
|
||||
tlb_query_in.vaddr <= X"0008_0CAF";
|
||||
wait until rising_edge(CLK_O);
|
||||
tlb_query_in.vld <= '0';
|
||||
|
||||
wait until rising_edge(CLK_O);
|
||||
tlb_query_in.vld <= '1';
|
||||
tlb_query_in.write <= '1';
|
||||
tlb_query_in.vaddr <= X"0000_0CAF";
|
||||
wait until rising_edge(CLK_O);
|
||||
tlb_query_in.vld <= '0';
|
||||
|
||||
wait;
|
||||
|
||||
end process;
|
||||
|
||||
END;
|
||||
@@ -25,6 +25,7 @@
|
||||
LIBRARY ieee;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
USE ieee.numeric_std.ALL;
|
||||
USE std.textio.ALL;
|
||||
|
||||
library work;
|
||||
use work.mips_types.all;
|
||||
@@ -39,10 +40,12 @@ ARCHITECTURE behavior OF tb_mips_top IS
|
||||
|
||||
constant SYS_FREQ : real := 100.0;
|
||||
constant CLK_PERIOD : time := 10 ns;
|
||||
constant SRAM_ADDR_WIDTH : integer := 18; -- bits
|
||||
constant FLASH_ADDR_WIDTH : integer := 18; -- bits
|
||||
|
||||
signal debug : unsigned(1 downto 0);
|
||||
constant SRAM_ADDR_WIDTH : integer := 17; -- bits
|
||||
constant FLASH_ADDR_WIDTH : integer := 17; -- bits
|
||||
constant WITH_TLB : boolean := false;
|
||||
constant KSEG_01_TRANSLATED : boolean := false;
|
||||
signal debug : chip_debug_t;
|
||||
signal tb_fin : STD_LOGIC := '0';
|
||||
|
||||
-- Master
|
||||
signal nmi : STD_LOGIC := '0';
|
||||
@@ -115,7 +118,43 @@ ARCHITECTURE behavior OF tb_mips_top IS
|
||||
type word_array_t is array (natural range <>) of unsigned(31 downto 0);
|
||||
signal sram_data : word_array_t(0 to 2**SRAM_ADDR_WIDTH-1);
|
||||
signal flash_data : word_array_t(0 to 2**FLASH_ADDR_WIDTH-1);
|
||||
|
||||
subtype nibble_t is unsigned (3 downto 0);
|
||||
|
||||
function to_character(x : nibble_t) return character is
|
||||
type cnv_tbl_t is array (0 to 15) of character;
|
||||
variable cnv_tbl : cnv_tbl_t := "0123456789ABCDEF";
|
||||
variable result : character;
|
||||
begin
|
||||
for i in nibble_t'low to nibble_t'high loop
|
||||
result := '0';
|
||||
if x(i) /= '0' and x(i) /= '1' then
|
||||
result := 'X';
|
||||
end if;
|
||||
end loop;
|
||||
|
||||
if result = '0' then
|
||||
result := cnv_tbl(to_integer(x));
|
||||
end if;
|
||||
|
||||
return result;
|
||||
end to_character;
|
||||
|
||||
|
||||
function to_string(x : word_t ) return string is
|
||||
variable result : string (1 to 8);
|
||||
variable j : integer := 32;
|
||||
variable nibble : nibble_t;
|
||||
begin
|
||||
for i in 1 to 8 loop
|
||||
nibble := x(j-1 downto j-4);
|
||||
j := j - 4;
|
||||
result(i) := to_character(nibble);
|
||||
end loop;
|
||||
return result;
|
||||
|
||||
end to_string;
|
||||
|
||||
BEGIN
|
||||
|
||||
------------------------------------------------------------------
|
||||
@@ -128,6 +167,46 @@ CLK_GEN: process
|
||||
------------------------------------------------------------------
|
||||
-- Memory mux
|
||||
------------------------------------------------------------------
|
||||
-- rom_u : Virtual = 0xBFC00000, Physical = 0x1FC00000
|
||||
-- rom_c : Virtual = 0x9FC00000, Physical = 0x1FC00000
|
||||
|
||||
-- ram_u : Virtual = 0xA0000000, Physical = 0x00000000
|
||||
-- ram_c : Virtual = 0x80000000, Physical = 0x00000000
|
||||
-- flash_u : Virtual = 0xA4000000, Physical = 0x04000000
|
||||
-- flash_c : Virtual = 0x88000000, Physical = 0x08000000
|
||||
-- io_u : Virtual = 0xA8000000, Physical = 0x0C000000
|
||||
-- io_c : Virtual = 0x88000000, Physical = 0x0C000000
|
||||
|
||||
gen_mem_mux_translate:
|
||||
if KSEG_01_TRANSLATED = true generate
|
||||
mem_mux:
|
||||
process(ADDR_O)
|
||||
begin
|
||||
mem_area <= mem_dead;
|
||||
flash_page_mode_en <= '0';
|
||||
if ADDR_O(31 downto 28) = X"0" then
|
||||
if ADDR_O(27 downto 26) = "00" then
|
||||
mem_area <= mem_sram;
|
||||
elsif ADDR_O(27 downto 26) = "01" then
|
||||
mem_area <= mem_flash;
|
||||
elsif ADDR_O(27 downto 26) = "10" then
|
||||
mem_area <= mem_flash;
|
||||
flash_page_mode_en <= '1';
|
||||
elsif ADDR_O(27 downto 26) = "11" then
|
||||
if ADDR_O(18 downto 16) = "000" then
|
||||
mem_area <= mem_gpio;
|
||||
elsif ADDR_O(18 downto 16) = "001" then
|
||||
mem_area <= mem_uart;
|
||||
end if;
|
||||
end if;
|
||||
elsif (ADDR_O(31 downto 28) = X"1" and ADDR_O(15) = '0') then
|
||||
mem_area <= mem_rom;
|
||||
end if;
|
||||
end process;
|
||||
end generate;
|
||||
|
||||
gen_mem_mux_non_translate:
|
||||
if KSEG_01_TRANSLATED = false generate
|
||||
mem_mux:
|
||||
process(ADDR_O)
|
||||
begin
|
||||
@@ -152,6 +231,7 @@ mem_mux:
|
||||
mem_area <= mem_sram;
|
||||
end if;
|
||||
end process;
|
||||
end generate;
|
||||
|
||||
signal_mux:
|
||||
process(mem_area, CYC_O)
|
||||
@@ -199,8 +279,10 @@ signal_mux:
|
||||
uut: entity work.mips_top
|
||||
GENERIC MAP
|
||||
(
|
||||
icache_size => 1024, -- words
|
||||
dcache_size => 1024 -- words
|
||||
icache_size => 256, -- words
|
||||
dcache_size => 256, -- words
|
||||
WITH_TLB => WITH_TLB,
|
||||
TRANSLATE_KSEG0_1 => KSEG_01_TRANSLATED
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
@@ -224,7 +306,6 @@ uut: entity work.mips_top
|
||||
);
|
||||
INT(1) <= int_uart;
|
||||
INT(5) <= int_timer;
|
||||
INT(2) <= '1';
|
||||
|
||||
inst_rom : entity work.rom_wb
|
||||
PORT MAP
|
||||
@@ -391,12 +472,17 @@ SRAM_WRITE:
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
|
||||
------------------------------------------------------------------
|
||||
FLASH_READ:
|
||||
process(rst, flash_cs_n, flash_oe_n, flash_a)
|
||||
type file_t is file of integer;
|
||||
file load_flash : file_t open read_mode is "hello.elf.flash.bin";
|
||||
-- file load_flash : file_t open read_mode is "test_tlb_sim.elf.flash.bin";
|
||||
-- file load_flash : file_t open read_mode is "test_exception_sim.elf.flash.bin";
|
||||
-- file load_flash : file_t open read_mode is "test_timer.elf.flash.bin";
|
||||
-- file load_flash : file_t open read_mode is "test_dcache_sim.elf.flash.bin";
|
||||
-- file load_flash : file_t open read_mode is "dhry.flash.bin";
|
||||
variable instr : integer;
|
||||
variable index : natural;
|
||||
variable temp : signed(31 downto 0);
|
||||
@@ -432,6 +518,62 @@ FLASH_READ:
|
||||
end if;
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
icache_trace_write:
|
||||
process(clk)
|
||||
type file_t is file of string;
|
||||
file f : file_t open write_mode is "icache_trace.dat";
|
||||
variable file_opened : std_logic;
|
||||
variable saddr : string(1 to 8);
|
||||
variable sdata : string(1 to 8);
|
||||
begin
|
||||
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
file_opened := '1';
|
||||
elsif file_opened = '1' then
|
||||
if debug.imem_din_vld = '1' then
|
||||
saddr := to_string(debug.imem_addr_reg);
|
||||
sdata := to_string(debug.imem_din_reg);
|
||||
write(f, saddr & " : " & sdata & CR);
|
||||
end if;
|
||||
else
|
||||
file_close(f);
|
||||
file_opened := '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
dcache_trace_write:
|
||||
process(clk)
|
||||
type file_t is file of string;
|
||||
file f : file_t open write_mode is "dcache_trace.dat";
|
||||
variable file_opened : std_logic;
|
||||
variable saddr : string(1 to 8);
|
||||
variable sdata : string(1 to 8);
|
||||
begin
|
||||
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
file_opened := '1';
|
||||
elsif file_opened = '1' then
|
||||
if debug.dmem_din_vld = '1' then
|
||||
saddr := to_string(debug.dmem_addr_reg);
|
||||
sdata := to_string(debug.dmem_din_reg);
|
||||
write(f, saddr & " : " & sdata & " R" & CR);
|
||||
elsif debug.dmem_dout_vld = '1' then
|
||||
saddr := to_string(debug.dmem_addr_reg);
|
||||
sdata := to_string(debug.dmem_dout_reg);
|
||||
write(f, saddr & " : " & sdata & " W" & CR);
|
||||
end if;
|
||||
else
|
||||
file_close(f);
|
||||
file_opened := '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
STIMULUS: process
|
||||
|
||||
@@ -441,10 +583,13 @@ STIMULUS: process
|
||||
wait for 3*CLK_PERIOD;
|
||||
wait until rising_edge(clk);
|
||||
rst <= '0';
|
||||
nmi <= '0';
|
||||
|
||||
wait for 1200000*CLK_PERIOD;
|
||||
|
||||
wait until rising_edge(clk);
|
||||
wait for 1500 us;
|
||||
tb_fin <= '1';
|
||||
wait until rising_edge(clk);
|
||||
tb_fin <= '0';
|
||||
|
||||
wait;
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
PRJ := mips_top
|
||||
PRJDIR := ./project
|
||||
|
||||
PRJ := mips_top
|
||||
PREQ := $(PRJDIR)/$(PRJ).prj $(PRJDIR)/$(PRJ).xst $(PRJDIR)/$(PRJ).lso
|
||||
DIRS := ./xst/tmp
|
||||
DEVICE := "xc4vsx35-ff668-10"
|
||||
|
||||
include $(VHDL_HOME)/make/ise.mk
|
||||
include $(VHDL_MAKE_HOME)/ise.mk
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
set -xsthdpdir "./xst"
|
||||
set -tmpdir "./xst/tmp"
|
||||
set -xsthdpdir xst
|
||||
set -tmpdir xst/tmp
|
||||
run
|
||||
-ifn ./project/mips_top.prj
|
||||
-ifn project/mips_top.prj
|
||||
-ifmt mixed
|
||||
-ofn mips_top
|
||||
-ofmt NGC
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
.gitignore
|
||||
build/
|
||||
.gitignore
|
||||
build/
|
||||
@@ -1,5 +1,5 @@
|
||||
# -----------------------------------------------------------
|
||||
include $(VHDL_HOME)/make/defs.mk
|
||||
include $(VHDL_HOME)/defs.mk
|
||||
# -----------------------------------------------------------
|
||||
PKG_NAME := FIFO_ASYNC
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# -----------------------------------------------------------
|
||||
include $(VHDL_HOME)/make/defs.mk
|
||||
include $(VHDL_HOME)/defs.mk
|
||||
# -----------------------------------------------------------
|
||||
PKG_NAME := FIFO_SYNC
|
||||
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
[*]
|
||||
[*] GTKWave Analyzer v3.3.104 (w)1999-2020 BSI
|
||||
[*] Tue Mar 23 08:22:19 2021
|
||||
[*] Thu Jun 30 17:26:51 2022
|
||||
[*]
|
||||
[dumpfile] "/home/jens/work/vhdl/trunk/lib/FIFO/ghdl/build/tb_fifo_async/tb_fifo_async.vcd"
|
||||
[dumpfile_mtime] "Tue Mar 23 08:21:16 2021"
|
||||
[dumpfile_size] 79616
|
||||
[savefile] "/home/jens/work/vhdl/trunk/lib/FIFO/ghdl/build/tb_fifo_async/tb_fifo_async.gtkw"
|
||||
[dumpfile] "/home/jens/work/projects/vhdl/lib/FIFO/ghdl/build/tb_fifo_async/tb_fifo_async.fst"
|
||||
[dumpfile_mtime] "Thu Jun 30 17:25:34 2022"
|
||||
[dumpfile_size] 2432
|
||||
[savefile] "/home/jens/work/projects/vhdl/lib/FIFO/ghdl/tb_fifo_async.gtkw"
|
||||
[timestart] 0
|
||||
[size] 1000 600
|
||||
[pos] 413 163
|
||||
[pos] 2275 292
|
||||
*-30.757229 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
|
||||
[sst_width] 233
|
||||
[signals_width] 166
|
||||
[sst_expanded] 1
|
||||
[sst_vpaned_height] 144
|
||||
@29
|
||||
tb_fifo_async.rst
|
||||
rst
|
||||
@28
|
||||
tb_fifo_async.clk_w
|
||||
tb_fifo_async.fifo_almost_full
|
||||
tb_fifo_async.fifo_full
|
||||
clk_w
|
||||
fifo_almost_full
|
||||
fifo_full
|
||||
@22
|
||||
tb_fifo_async.din[7:0]
|
||||
din[7:0]
|
||||
@28
|
||||
tb_fifo_async.we
|
||||
tb_fifo_async.clk_r
|
||||
tb_fifo_async.fifo_almost_empty
|
||||
tb_fifo_async.fifo_empty
|
||||
we
|
||||
clk_r
|
||||
fifo_almost_empty
|
||||
fifo_empty
|
||||
@22
|
||||
tb_fifo_async.dout[7:0]
|
||||
dout[7:0]
|
||||
@28
|
||||
tb_fifo_async.re
|
||||
re
|
||||
[pattern_trace] 1
|
||||
[pattern_trace] 0
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
include $(VHDL_HOME)/make/defs.mk
|
||||
include $(VHDL_HOME)/defs.mk
|
||||
include fifo_async.inc
|
||||
|
||||
ROOT_PATH := ../../..
|
||||
@@ -12,5 +12,5 @@ TARGET := tb_fifo_async
|
||||
ENTITY := tb_fifo_async
|
||||
RUN_TIME := 5us
|
||||
|
||||
include $(VHDL_HOME)/make/ghdl.mk
|
||||
include $(VHDL_MAKE_HOME)/ghdl.mk
|
||||
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
[*]
|
||||
[*] GTKWave Analyzer v3.3.104 (w)1999-2020 BSI
|
||||
[*] Tue Mar 23 08:21:05 2021
|
||||
[*] Thu Jun 30 17:29:48 2022
|
||||
[*]
|
||||
[dumpfile] "/home/jens/work/vhdl/trunk/lib/FIFO/ghdl/build/tb_fifo_sync/tb_fifo_sync.vcd"
|
||||
[dumpfile_mtime] "Tue Mar 23 08:20:21 2021"
|
||||
[dumpfile_size] 38508
|
||||
[savefile] "/home/jens/work/vhdl/trunk/lib/FIFO/ghdl/build/tb_fifo_sync/tb_fifo_sync.gtkw"
|
||||
[dumpfile] "/home/jens/work/projects/vhdl/lib/FIFO/ghdl/build/tb_fifo_sync/tb_fifo_sync.fst"
|
||||
[dumpfile_mtime] "Thu Jun 30 17:29:20 2022"
|
||||
[dumpfile_size] 1617
|
||||
[savefile] "/home/jens/work/projects/vhdl/lib/FIFO/ghdl/tb_fifo_sync.gtkw"
|
||||
[timestart] 0
|
||||
[size] 1000 600
|
||||
[pos] -1 -1
|
||||
[pos] 395 8
|
||||
*-30.891594 2114000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
|
||||
[sst_width] 233
|
||||
[signals_width] 215
|
||||
[sst_expanded] 1
|
||||
[sst_vpaned_height] 144
|
||||
@28
|
||||
tb_fifo_sync.clk
|
||||
tb_fifo_sync.rst
|
||||
clk
|
||||
rst
|
||||
@29
|
||||
tb_fifo_sync.we
|
||||
we
|
||||
@22
|
||||
tb_fifo_sync.din[7:0]
|
||||
din[7:0]
|
||||
@28
|
||||
tb_fifo_sync.re
|
||||
re
|
||||
@22
|
||||
tb_fifo_sync.dout[7:0]
|
||||
dout[7:0]
|
||||
@28
|
||||
tb_fifo_sync.fifo_almost_empty
|
||||
tb_fifo_sync.fifo_almost_full
|
||||
tb_fifo_sync.fifo_empty
|
||||
tb_fifo_sync.fifo_full
|
||||
fifo_almost_empty
|
||||
fifo_almost_full
|
||||
fifo_empty
|
||||
fifo_full
|
||||
[pattern_trace] 1
|
||||
[pattern_trace] 0
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
include $(VHDL_HOME)/make/defs.mk
|
||||
include $(VHDL_HOME)/defs.mk
|
||||
include fifo_sync.inc
|
||||
|
||||
ROOT_PATH := ../../..
|
||||
@@ -12,5 +12,5 @@ TARGET := tb_fifo_sync
|
||||
ENTITY := tb_fifo_sync
|
||||
RUN_TIME := 5us
|
||||
|
||||
include $(VHDL_HOME)/make/ghdl.mk
|
||||
include $(VHDL_MAKE_HOME)/ghdl.mk
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
[*]
|
||||
[*] GTKWave Analyzer v3.3.104 (w)1999-2020 BSI
|
||||
[*] Tue Mar 23 08:23:15 2021
|
||||
[*] Thu Jun 30 17:30:57 2022
|
||||
[*]
|
||||
[dumpfile] "/home/jens/work/vhdl/trunk/lib/FIFO/ghdl/build/tb_gray_counter/tb_gray_counter.vcd"
|
||||
[dumpfile_mtime] "Tue Mar 23 08:22:40 2021"
|
||||
[dumpfile_size] 12229
|
||||
[savefile] "/home/jens/work/vhdl/trunk/lib/FIFO/ghdl/build/tb_gray_counter/tb_gray_counter.gtkw"
|
||||
[dumpfile] "/home/jens/work/projects/vhdl/lib/FIFO/ghdl/build/tb_gray_counter/tb_gray_counter.fst"
|
||||
[dumpfile_mtime] "Thu Jun 30 17:30:50 2022"
|
||||
[dumpfile_size] 565
|
||||
[savefile] "/home/jens/work/projects/vhdl/lib/FIFO/ghdl/tb_gray_counter.gtkw"
|
||||
[timestart] 0
|
||||
[size] 1000 600
|
||||
[pos] -1 -1
|
||||
@@ -15,13 +15,13 @@
|
||||
[sst_expanded] 1
|
||||
[sst_vpaned_height] 144
|
||||
@28
|
||||
tb_gray_counter.rst
|
||||
tb_gray_counter.clk
|
||||
tb_gray_counter.ce
|
||||
tb_gray_counter.bcnt[2:0]
|
||||
tb_gray_counter.bnxt[2:0]
|
||||
tb_gray_counter.gcnt[2:0]
|
||||
rst
|
||||
clk
|
||||
ce
|
||||
bcnt[2:0]
|
||||
bnxt[2:0]
|
||||
gcnt[2:0]
|
||||
@29
|
||||
tb_gray_counter.gnxt[2:0]
|
||||
gnxt[2:0]
|
||||
[pattern_trace] 1
|
||||
[pattern_trace] 0
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
include $(VHDL_HOME)/make/defs.mk
|
||||
include $(VHDL_HOME)/defs.mk
|
||||
|
||||
SRCS += $(LIB_PATH)/FIFO/src/fifo_ctrl_pkg.vhd
|
||||
SRCS += $(LIB_PATH)/FIFO/src/gray_counter.vhd
|
||||
@@ -9,5 +9,5 @@ TARGET := tb_gray_counter
|
||||
ENTITY := tb_gray_counter
|
||||
RUN_TIME := 1us
|
||||
|
||||
include $(VHDL_HOME)/make/ghdl.mk
|
||||
include $(VHDL_MAKE_HOME)/ghdl.mk
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
[*]
|
||||
[*] GTKWave Analyzer v3.3.104 (w)1999-2020 BSI
|
||||
[*] Thu Jun 30 17:32:24 2022
|
||||
[*]
|
||||
[dumpfile] "/home/jens/work/projects/vhdl/lib/FIFO/ghdl/build/tb_reg_stage/tb_reg_stage.fst"
|
||||
[dumpfile_mtime] "Thu Jun 30 17:31:56 2022"
|
||||
[dumpfile_size] 672
|
||||
[savefile] "/home/jens/work/projects/vhdl/lib/FIFO/ghdl/tb_reg_stage.gtkw"
|
||||
[timestart] 0
|
||||
[size] 1000 600
|
||||
[pos] -1 -1
|
||||
*-28.283821 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
|
||||
[sst_width] 233
|
||||
[signals_width] 102
|
||||
[sst_expanded] 1
|
||||
[sst_vpaned_height] 144
|
||||
@28
|
||||
clk
|
||||
rst
|
||||
@22
|
||||
din[7:0]
|
||||
dout[7:0]
|
||||
@29
|
||||
vld_dout
|
||||
[pattern_trace] 1
|
||||
[pattern_trace] 0
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
include $(VHDL_HOME)/make/defs.mk
|
||||
include $(VHDL_HOME)/defs.mk
|
||||
|
||||
SRCS += $(LIB_PATH)/FIFO/src/reg_stage.vhd
|
||||
SRCS += $(LIB_PATH)/FIFO/src/tb_reg_stage.vhd
|
||||
@@ -8,5 +8,5 @@ TARGET := tb_reg_stage
|
||||
ENTITY := tb_reg_stage
|
||||
RUN_TIME := 1us
|
||||
|
||||
include $(VHDL_HOME)/make/ghdl.mk
|
||||
include $(VHDL_MAKE_HOME)/ghdl.mk
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
.gitignore
|
||||
build/
|
||||
.gitignore
|
||||
build/
|
||||
@@ -0,0 +1,14 @@
|
||||
# -----------------------------------------------------------
|
||||
include $(VHDL_HOME)/defs.mk
|
||||
include $(LIB_PATH)/FIFO/ghdl/fifo_async.inc
|
||||
# -----------------------------------------------------------
|
||||
PKG_NAME := BUSMASTER_ASYNC
|
||||
|
||||
# -----------------------------------------------------------
|
||||
$(PKG_NAME)_SRCS := $(FIFO_ASYNC_SRCS)
|
||||
$(PKG_NAME)_SRCS += $(LIB_PATH)/misc/utils_pkg.vhd
|
||||
$(PKG_NAME)_SRCS += $(LIB_PATH)/JBUS/busmaster/src/busmaster_types.vhd
|
||||
$(PKG_NAME)_SRCS += $(LIB_PATH)/JBUS/busmaster/src/busmaster_async.vhd
|
||||
|
||||
# -----------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
# -----------------------------------------------------------
|
||||
include $(VHDL_HOME)/defs.mk
|
||||
include $(LIB_PATH)/FIFO/ghdl/fifo_sync.inc
|
||||
# -----------------------------------------------------------
|
||||
PKG_NAME := BUSMASTER_SYNC
|
||||
|
||||
# -----------------------------------------------------------
|
||||
$(PKG_NAME)_SRCS := $(FIFO_SYNC_SRCS)
|
||||
$(PKG_NAME)_SRCS += $(LIB_PATH)/misc/utils_pkg.vhd
|
||||
$(PKG_NAME)_SRCS += $(LIB_PATH)/JBUS/busmaster/src/busmaster_types.vhd
|
||||
$(PKG_NAME)_SRCS += $(LIB_PATH)/JBUS/busmaster/src/busmaster_sync.vhd
|
||||
|
||||
# -----------------------------------------------------------
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
include $(VHDL_HOME)/make/defs.mk
|
||||
include $(LIB_PATH)/FIFO/ghdl/fifo_async.inc
|
||||
include $(VHDL_HOME)/defs.mk
|
||||
include $(LIB_PATH)/JBUS/busmaster/ghdl/busmaster_async.inc
|
||||
|
||||
MOD_PATH := $(LIB_PATH)/JBUS/busmaster
|
||||
|
||||
SRCS += $(LIB_PATH)/misc/utils_pkg.vhd
|
||||
SRCS += $(FIFO_ASYNC_SRCS)
|
||||
SRCS += $(MOD_PATH)/src/busmaster_types.vhd
|
||||
SRCS += $(MOD_PATH)/src/busmaster_async.vhd
|
||||
SRCS += $(MOD_PATH)/src/tb_busmaster_async.vhd
|
||||
SRCS += $(BUSMASTER_ASYNC_SRCS)
|
||||
SRCS += $(LIB_PATH)/JBUS/busmaster/src/tb_busmaster_async.vhd
|
||||
|
||||
# Compile
|
||||
TARGET := tb_busmaster_async
|
||||
ENTITY := tb_busmaster_async
|
||||
RUN_TIME := 80us
|
||||
WAVE_FORMAT := vcd
|
||||
|
||||
include $(VHDL_HOME)/make/ghdl.mk
|
||||
include $(VHDL_MAKE_HOME)/ghdl.mk
|
||||
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
include $(VHDL_HOME)/make/defs.mk
|
||||
include $(LIB_PATH)/FIFO/ghdl/fifo_sync.inc
|
||||
include $(VHDL_HOME)/defs.mk
|
||||
include $(LIB_PATH)/JBUS/busmaster/ghdl/busmaster_sync.inc
|
||||
|
||||
MOD_PATH := $(LIB_PATH)/JBUS/busmaster
|
||||
|
||||
SRCS += $(LIB_PATH)/misc/utils_pkg.vhd
|
||||
SRCS += $(FIFO_SYNC_SRCS)
|
||||
SRCS += $(MOD_PATH)/src/busmaster_types.vhd
|
||||
SRCS += $(MOD_PATH)/src/busmaster_sync.vhd
|
||||
SRCS += $(MOD_PATH)/src/tb_busmaster_sync.vhd
|
||||
SRCS += $(BUSMASTER_SYNC_SRCS)
|
||||
SRCS += $(LIB_PATH)/JBUS/busmaster/src/tb_busmaster_sync.vhd
|
||||
|
||||
# Compile
|
||||
TARGET := tb_busmaster_sync
|
||||
ENTITY := tb_busmaster_sync
|
||||
RUN_TIME := 40us
|
||||
WAVE_FORMAT := vcd
|
||||
|
||||
include $(VHDL_HOME)/make/ghdl.mk
|
||||
include $(VHDL_MAKE_HOME)/ghdl.mk
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
.gitignore
|
||||
build/
|
||||
.gitignore
|
||||
build/
|
||||
@@ -1,4 +1,4 @@
|
||||
include $(VHDL_HOME)/make/defs.mk
|
||||
include $(VHDL_HOME)/defs.mk
|
||||
include $(LIB_PATH)/FIFO/ghdl/fifo_sync.inc
|
||||
|
||||
MOD_PATH := $(LIB_PATH)/JBUS
|
||||
@@ -14,6 +14,7 @@ SRCS += $(MOD_PATH)/dmac/src/tb_dmac.vhd
|
||||
TARGET := tb_dmac_sync
|
||||
ENTITY := tb_dmac
|
||||
RUN_TIME := 6us
|
||||
WAVE_FORMAT := vcd
|
||||
|
||||
include $(VHDL_HOME)/make/ghdl.mk
|
||||
include $(VHDL_MAKE_HOME)/ghdl.mk
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
.gitignore
|
||||
build/
|
||||
.gitignore
|
||||
build/
|
||||
@@ -1,4 +1,4 @@
|
||||
include $(VHDL_HOME)/make/defs.mk
|
||||
include $(VHDL_HOME)/defs.mk
|
||||
|
||||
MOD_PATH := $(LIB_PATH)/JBUS/memory
|
||||
|
||||
@@ -11,5 +11,6 @@ SRCS += $(MOD_PATH)/src/tb_ram_wb.vhd
|
||||
TARGET := tb_ram_wb
|
||||
ENTITY := tb_ram_wb
|
||||
RUN_TIME := 1500ns
|
||||
WAVE_FORMAT := vcd
|
||||
|
||||
include $(VHDL_HOME)/make/ghdl.mk
|
||||
include $(VHDL_MAKE_HOME)/ghdl.mk
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
include $(VHDL_HOME)/make/defs.mk
|
||||
include $(VHDL_HOME)/defs.mk
|
||||
|
||||
MOD_PATH := $(LIB_PATH)/JBUS/memory
|
||||
|
||||
@@ -10,6 +10,7 @@ SRCS += $(MOD_PATH)/src/tb_rom_wb.vhd
|
||||
TARGET := tb_rom_wb
|
||||
ENTITY := tb_rom_wb
|
||||
RUN_TIME := 1500ns
|
||||
WAVE_FORMAT := vcd
|
||||
|
||||
include $(VHDL_HOME)/make/ghdl.mk
|
||||
include $(VHDL_MAKE_HOME)/ghdl.mk
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
.gitignore
|
||||
build/
|
||||
.gitignore
|
||||
build/
|
||||
@@ -1,5 +1,5 @@
|
||||
# -----------------------------------------------------------
|
||||
include $(VHDL_HOME)/make/defs.mk
|
||||
include $(VHDL_HOME)/defs.mk
|
||||
# -----------------------------------------------------------
|
||||
include $(LIB_PATH)/FIFO/ghdl/fifo_sync.inc
|
||||
include $(LIB_PATH)/FIFO/ghdl/fifo_async.inc
|
||||
@@ -27,8 +27,9 @@ SRCS += $(MOD_PATH)/src/tb_ctrl_ddr_wb32.vhd
|
||||
TARGET := tb_ctrl_ddr_wb32
|
||||
ENTITY := tb_ctrl_ddr_wb32
|
||||
RUN_TIME := 200us
|
||||
WAVE_FORMAT := vcd
|
||||
|
||||
GHDL_OPTS := -P$(VHDL_HOME)/Common/sim/build/unisim/unisim -fsynopsys -fexplicit
|
||||
GHDL_OPTS := -P$(VHDL_HOME)/Common/sim/build/ghdl/unisim -fsynopsys -fexplicit
|
||||
|
||||
include $(VHDL_HOME)/make/ghdl.mk
|
||||
include $(VHDL_MAKE_HOME)/ghdl.mk
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# -----------------------------------------------------------
|
||||
include $(VHDL_HOME)/make/defs.mk
|
||||
include $(VHDL_HOME)/defs.mk
|
||||
# -----------------------------------------------------------
|
||||
include $(LIB_PATH)/FIFO/ghdl/fifo_sync.inc
|
||||
include $(LIB_PATH)/FIFO/ghdl/fifo_async.inc
|
||||
@@ -26,8 +26,9 @@ SRCS += $(MOD_PATH)/src/tb_ctrl_ddr_wb64.vhd
|
||||
TARGET := tb_ctrl_ddr_wb64
|
||||
ENTITY := tb_ctrl_ddr_wb64
|
||||
RUN_TIME := 200us
|
||||
WAVE_FORMAT := vcd
|
||||
|
||||
GHDL_OPTS := -P$(VHDL_HOME)/Common/sim/build/unisim/unisim -fsynopsys -fexplicit
|
||||
GHDL_OPTS := -P$(VHDL_HOME)/Common/sim/build/ghdl/unisim -fsynopsys -fexplicit
|
||||
|
||||
include $(VHDL_HOME)/make/ghdl.mk
|
||||
include $(VHDL_MAKE_HOME)/ghdl.mk
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
.gitignore
|
||||
build/
|
||||
.gitignore
|
||||
build/
|
||||
@@ -1,5 +1,5 @@
|
||||
# -----------------------------------------------------------
|
||||
include $(VHDL_HOME)/make/defs.mk
|
||||
include $(VHDL_HOME)/defs.mk
|
||||
# -----------------------------------------------------------
|
||||
include vga_frontend_jb32.inc
|
||||
|
||||
@@ -13,6 +13,6 @@ TARGET := tb_vga_frontend_jb32
|
||||
ENTITY := tb_vga_frontend_jb32
|
||||
RUN_TIME := 20ms
|
||||
|
||||
include $(VHDL_HOME)/make/ghdl.mk
|
||||
include $(VHDL_MAKE_HOME)/ghdl.mk
|
||||
# -----------------------------------------------------------
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# -----------------------------------------------------------
|
||||
include $(VHDL_HOME)/make/defs.mk
|
||||
include $(VHDL_HOME)/defs.mk
|
||||
# -----------------------------------------------------------
|
||||
include vga_frontend_jb64.inc
|
||||
|
||||
@@ -13,6 +13,6 @@ TARGET := tb_vga_frontend_jb64
|
||||
ENTITY := tb_vga_frontend_jb64
|
||||
RUN_TIME := 2ms
|
||||
|
||||
include $(VHDL_HOME)/make/ghdl.mk
|
||||
include $(VHDL_MAKE_HOME)/ghdl.mk
|
||||
# -----------------------------------------------------------
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# -----------------------------------------------------------
|
||||
include $(VHDL_HOME)/make/defs.mk
|
||||
include $(VHDL_HOME)/defs.mk
|
||||
|
||||
# -----------------------------------------------------------
|
||||
PKG_NAME := VGA_BACKEND
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# -----------------------------------------------------------
|
||||
include $(VHDL_HOME)/make/defs.mk
|
||||
include $(VHDL_HOME)/defs.mk
|
||||
include vga_backend.inc
|
||||
include $(LIB_PATH)/FIFO/ghdl/fifo_async.inc
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# -----------------------------------------------------------
|
||||
include $(VHDL_HOME)/make/defs.mk
|
||||
include $(VHDL_HOME)/defs.mk
|
||||
include $(LIB_PATH)/VGA_ctrl/ghdl/vga_backend.inc
|
||||
include $(LIB_PATH)/FIFO/ghdl/fifo_sync.inc
|
||||
include $(LIB_PATH)/FIFO/ghdl/fifo_async.inc
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
.gitignore
|
||||
build/
|
||||
.gitignore
|
||||
build/
|
||||
@@ -1,5 +1,5 @@
|
||||
# -----------------------------------------------------------
|
||||
include $(VHDL_HOME)/make/defs.mk
|
||||
include $(VHDL_HOME)/defs.mk
|
||||
# -----------------------------------------------------------
|
||||
include $(LIB_PATH)/emac/ghdl/emac_tx.inc
|
||||
include $(LIB_PATH)/emac/ghdl/emac_rx.inc
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user