Compare commits

..

1 Commits

Author SHA1 Message Date
Anton Blanchard 53ccf89d26 Use a record for cache parameters
The number of generics we pass down from the top level is getting a
bit unwieldy. Paul suggests using records to group them.

Signed-off-by: Anton Blanchard <anton@linux.ibm.com>
3 years ago

@ -5,19 +5,12 @@ on:
pull_request: pull_request:
schedule: schedule:
- cron: '0 0 * * 5' - cron: '0 0 * * 5'
workflow_dispatch:


jobs: jobs:


build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: container: ghdl/vunit:llvm
fail-fast: false
matrix:
backend:
- llvm
- gcc
container: ghdl/vunit:${{ matrix.backend }}
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- run: make GNATMAKE='gnatmake -j'$(nproc) - run: make GNATMAKE='gnatmake -j'$(nproc)
@ -40,6 +33,7 @@ jobs:
max-parallel: 3 max-parallel: 3
matrix: matrix:
task: [ task: [
"tests_unit",
"tests_console", "tests_console",
"{1..99}", "{1..99}",
"{100..199}", "{100..199}",
@ -58,24 +52,16 @@ jobs:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- run: bash -c "make -j$(nproc) ${{ matrix.task }}" - run: bash -c "make -j$(nproc) ${{ matrix.task }}"


VUnit:
needs: [build]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: docker://ghdl/vunit:llvm
with:
args: python3 ./run.py -p10

symbiflow: symbiflow:
strategy: strategy:
fail-fast: false fail-fast: false
max-parallel: 2 max-parallel: 2
matrix: matrix:
task: [ ECP5-EVN, ORANGE-CRAB, ORANGE-CRAB-0.21 ] task: [ ECP5-EVN, ORANGE-CRAB ]
runs-on: ubuntu-latest runs-on: ubuntu-latest
env: env:
DOCKER: 1 DOCKER: 1
SYNTH_ECP5_FLAGS: -noflatten
FPGA_TARGET: ${{matrix.task}} FPGA_TARGET: ${{matrix.task}}
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
@ -93,17 +79,3 @@ jobs:
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- run: make DOCKER=1 microwatt.v - run: make DOCKER=1 microwatt.v

verilator:
runs-on: ubuntu-latest
env:
DOCKER: 1
FPGA_TARGET: verilator
RAM_INIT_FILE: micropython/firmware.hex
MEMORY_SIZE: 524288
steps:
- uses: actions/checkout@v2
- run: |
sudo apt update
sudo apt install -y python3-pexpect
make -j$(nproc) test_micropython_verilator test_micropython_verilator_long

1
.gitignore vendored

@ -13,5 +13,4 @@ tests/*/*.hex
tests/*/*.elf tests/*/*.elf
TAGS TAGS
litedram/build/* litedram/build/*
liteeth/build/*
obj_dir/* obj_dir/*

@ -1,22 +1,12 @@
GHDL ?= ghdl GHDL ?= ghdl
GHDLFLAGS=--std=08 GHDLFLAGS=--std=08 -frelaxed
CFLAGS=-O3 -Wall CFLAGS=-O3 -Wall
# Need to investigate why yosys is hitting verilator warnings, and eventually turn on -Wall
VERILATOR_FLAGS=-O3 -Wno-fatal -Wno-CASEOVERLAP -Wno-UNOPTFLAT #--trace
# It takes forever to build with optimisation, so disable by default
#VERILATOR_CFLAGS=-O3


# some yosys builds have ghdl plugin built in, otherwise need "-m ghdl" GHDLSYNTH ?= ghdl.so
GHDLSYNTH ?= $(shell ($(YOSYS) -H | grep -q ghdl) || echo -m ghdl)
YOSYS ?= yosys YOSYS ?= yosys
NEXTPNR ?= nextpnr-ecp5 NEXTPNR ?= nextpnr-ecp5
ECPPACK ?= ecppack ECPPACK ?= ecppack
ECPPROG ?= ecpprog
OPENOCD ?= openocd OPENOCD ?= openocd
VUNITRUN ?= python3 ./run.py
VERILATOR ?= verilator
DFUUTIL ?= dfu-util
DFUSUFFIX ?= dfu-suffix


# We need a version of GHDL built with either the LLVM or gcc backend. # We need a version of GHDL built with either the LLVM or gcc backend.
# Fedora provides this, but other distros may not. Another option is to use # Fedora provides this, but other distros may not. Another option is to use
@ -39,41 +29,37 @@ PWD = $(shell pwd)
DOCKERARGS = run --rm -v $(PWD):/src:z -w /src DOCKERARGS = run --rm -v $(PWD):/src:z -w /src
GHDL = $(DOCKERBIN) $(DOCKERARGS) ghdl/ghdl:buster-llvm-7 ghdl GHDL = $(DOCKERBIN) $(DOCKERARGS) ghdl/ghdl:buster-llvm-7 ghdl
CC = $(DOCKERBIN) $(DOCKERARGS) ghdl/ghdl:buster-llvm-7 gcc CC = $(DOCKERBIN) $(DOCKERARGS) ghdl/ghdl:buster-llvm-7 gcc
GHDLSYNTH = -m ghdl GHDLSYNTH = ghdl
YOSYS = $(DOCKERBIN) $(DOCKERARGS) hdlc/ghdl:yosys yosys YOSYS = $(DOCKERBIN) $(DOCKERARGS) hdlc/ghdl:yosys yosys
NEXTPNR = $(DOCKERBIN) $(DOCKERARGS) hdlc/nextpnr:ecp5 nextpnr-ecp5 NEXTPNR = $(DOCKERBIN) $(DOCKERARGS) hdlc/nextpnr:ecp5 nextpnr-ecp5
ECPPACK = $(DOCKERBIN) $(DOCKERARGS) hdlc/prjtrellis ecppack ECPPACK = $(DOCKERBIN) $(DOCKERARGS) hdlc/prjtrellis ecppack
OPENOCD = $(DOCKERBIN) $(DOCKERARGS) --device /dev/bus/usb hdlc/prog openocd OPENOCD = $(DOCKERBIN) $(DOCKERARGS) --device /dev/bus/usb hdlc/prog openocd
VUNITRUN = $(DOCKERBIN) $(DOCKERARGS) ghdl/vunit:llvm python3 ./run.py
VERILATOR = $(DOCKERBIN) $(DOCKERARGS) verilator/verilator:latest
endif endif


VUNITARGS += -p10 all = core_tb icache_tb dcache_tb multiply_tb dmi_dtm_tb divider_tb \

rotator_tb countzero_tb wishbone_bram_tb soc_reset_tb
all = core_tb icache_tb dcache_tb dmi_dtm_tb \
wishbone_bram_tb soc_reset_tb


all: $(all) all: $(all)


core_files = decode_types.vhdl common.vhdl wishbone_types.vhdl fetch1.vhdl \ core_files = params.vhdl decode_types.vhdl common.vhdl wishbone_types.vhdl fetch1.vhdl \
utils.vhdl plru.vhdl cache_ram.vhdl icache.vhdl \ utils.vhdl plru.vhdl cache_ram.vhdl icache.vhdl \
decode1.vhdl helpers.vhdl insn_helpers.vhdl \ decode1.vhdl helpers.vhdl insn_helpers.vhdl \
control.vhdl decode2.vhdl register_file.vhdl \ control.vhdl decode2.vhdl register_file.vhdl \
cr_file.vhdl crhelpers.vhdl ppc_fx_insns.vhdl rotator.vhdl \ cr_file.vhdl crhelpers.vhdl ppc_fx_insns.vhdl rotator.vhdl \
logical.vhdl countbits.vhdl multiply.vhdl divider.vhdl execute1.vhdl \ logical.vhdl countzero.vhdl multiply.vhdl divider.vhdl execute1.vhdl \
loadstore1.vhdl mmu.vhdl dcache.vhdl writeback.vhdl core_debug.vhdl \ loadstore1.vhdl mmu.vhdl dcache.vhdl writeback.vhdl core_debug.vhdl \
core.vhdl fpu.vhdl pmu.vhdl core.vhdl fpu.vhdl


soc_files = wishbone_arbiter.vhdl wishbone_bram_wrapper.vhdl sync_fifo.vhdl \ soc_files = $(core_files) wishbone_arbiter.vhdl wishbone_bram_wrapper.vhdl sync_fifo.vhdl \
wishbone_debug_master.vhdl xics.vhdl syscon.vhdl gpio.vhdl soc.vhdl \ wishbone_debug_master.vhdl xics.vhdl syscon.vhdl soc.vhdl \
spi_rxtx.vhdl spi_flash_ctrl.vhdl spi_rxtx.vhdl spi_flash_ctrl.vhdl


uart_files = $(wildcard uart16550/*.v) uart_files = $(wildcard uart16550/*.v)


soc_sim_files = $(core_files) $(soc_files) sim_console.vhdl sim_pp_uart.vhdl sim_bram_helpers.vhdl \ soc_sim_files = $(soc_files) sim_console.vhdl sim_pp_uart.vhdl sim_bram_helpers.vhdl \
sim_bram.vhdl sim_jtag_socket.vhdl sim_jtag.vhdl dmi_dtm_xilinx.vhdl \ sim_bram.vhdl sim_jtag_socket.vhdl sim_jtag.vhdl dmi_dtm_xilinx.vhdl \
sim_16550_uart.vhdl \ sim_16550_uart.vhdl \
foreign_random.vhdl glibc_random.vhdl glibc_random_helpers.vhdl random.vhdl glibc_random.vhdl glibc_random_helpers.vhdl


soc_sim_c_files = sim_vhpi_c.c sim_bram_helpers_c.c sim_console_c.c \ soc_sim_c_files = sim_vhpi_c.c sim_bram_helpers_c.c sim_console_c.c \
sim_jtag_socket_c.c sim_jtag_socket_c.c
@ -90,6 +76,7 @@ $(unisim_lib): $(unisim_lib_files)
$(GHDL) -i --std=08 --work=unisim --workdir=$(unisim_dir) $^ $(GHDL) -i --std=08 --work=unisim --workdir=$(unisim_dir) $^
GHDLFLAGS += -P$(unisim_dir) GHDLFLAGS += -P$(unisim_dir)


core_tbs = multiply_tb divider_tb rotator_tb countzero_tb
soc_tbs = core_tb icache_tb dcache_tb dmi_dtm_tb wishbone_bram_tb soc_tbs = core_tb icache_tb dcache_tb dmi_dtm_tb wishbone_bram_tb
soc_flash_tbs = core_flash_tb soc_flash_tbs = core_flash_tb
soc_dram_tbs = dram_tb core_dram_tb soc_dram_tbs = dram_tb core_dram_tb
@ -115,6 +102,9 @@ $(soc_flash_tbs): %: $(soc_sim_files) $(soc_sim_obj_files) $(unisim_lib) $(fmf_l
$(soc_tbs): %: $(soc_sim_files) $(soc_sim_obj_files) $(unisim_lib) %.vhdl $(soc_tbs): %: $(soc_sim_files) $(soc_sim_obj_files) $(unisim_lib) %.vhdl
$(GHDL) -c $(GHDLFLAGS) $(soc_sim_link) $(soc_sim_files) $@.vhdl -e $@ $(GHDL) -c $(GHDLFLAGS) $(soc_sim_link) $(soc_sim_files) $@.vhdl -e $@


$(core_tbs): %: $(core_files) glibc_random.vhdl glibc_random_helpers.vhdl %.vhdl
$(GHDL) -c $(GHDLFLAGS) $(core_files) glibc_random.vhdl glibc_random_helpers.vhdl $@.vhdl -e $@

soc_reset_tb: fpga/soc_reset_tb.vhdl fpga/soc_reset.vhdl soc_reset_tb: fpga/soc_reset_tb.vhdl fpga/soc_reset.vhdl
$(GHDL) -c $(GHDLFLAGS) fpga/soc_reset_tb.vhdl fpga/soc_reset.vhdl -e $@ $(GHDL) -c $(GHDLFLAGS) fpga/soc_reset_tb.vhdl fpga/soc_reset.vhdl -e $@


@ -125,8 +115,10 @@ $(soc_dram_tbs):
$(error "Verilator is required to make this target !") $(error "Verilator is required to make this target !")
else else


VERILATOR_CFLAGS=-O3
VERILATOR_FLAGS=-O3
verilated_dram: litedram/generated/sim/litedram_core.v verilated_dram: litedram/generated/sim/litedram_core.v
verilator $(VERILATOR_FLAGS) -CFLAGS $(VERILATOR_CFLAGS) -Wno-fatal --cc $< verilator $(VERILATOR_FLAGS) -CFLAGS $(VERILATOR_CFLAGS) -Wno-fatal --cc $< --trace
make -C obj_dir -f ../litedram/extras/sim_dram_verilate.mk VERILATOR_ROOT=$(VERILATOR_ROOT) make -C obj_dir -f ../litedram/extras/sim_dram_verilate.mk VERILATOR_ROOT=$(VERILATOR_ROOT)


SIM_DRAM_CFLAGS = -I. -Iobj_dir -Ilitedram/generated/sim -I$(VERILATOR_ROOT)/include -I$(VERILATOR_ROOT)/include/vltstd SIM_DRAM_CFLAGS = -I. -Iobj_dir -Ilitedram/generated/sim -I$(VERILATOR_ROOT)/include -I$(VERILATOR_ROOT)/include/vltstd
@ -134,7 +126,7 @@ SIM_DRAM_CFLAGS += -DVM_COVERAGE=0 -DVM_SC=0 -DVM_TRACE=1 -DVL_PRINTF=printf -fa
sim_litedram_c.o: litedram/extras/sim_litedram_c.cpp verilated_dram sim_litedram_c.o: litedram/extras/sim_litedram_c.cpp verilated_dram
$(CC) $(CPPFLAGS) $(SIM_DRAM_CFLAGS) $(CFLAGS) -c $< -o $@ $(CC) $(CPPFLAGS) $(SIM_DRAM_CFLAGS) $(CFLAGS) -c $< -o $@


soc_dram_files = $(core_files) $(soc_files) litedram/extras/litedram-wrapper-l2.vhdl litedram/generated/sim/litedram-initmem.vhdl soc_dram_files = $(soc_files) litedram/extras/litedram-wrapper-l2.vhdl litedram/generated/sim/litedram-initmem.vhdl
soc_dram_sim_files = $(soc_sim_files) litedram/extras/sim_litedram.vhdl soc_dram_sim_files = $(soc_sim_files) litedram/extras/sim_litedram.vhdl
soc_dram_sim_obj_files = $(soc_sim_obj_files) sim_litedram_c.o soc_dram_sim_obj_files = $(soc_sim_obj_files) sim_litedram_c.o
dram_link_files=-Wl,obj_dir/Vlitedram_core__ALL.a -Wl,obj_dir/verilated.o -Wl,obj_dir/verilated_vcd_c.o -Wl,-lstdc++ dram_link_files=-Wl,obj_dir/Vlitedram_core__ALL.a -Wl,obj_dir/verilated.o -Wl,obj_dir/verilated_vcd_c.o -Wl,-lstdc++
@ -145,54 +137,25 @@ $(soc_dram_tbs): %: $(soc_dram_files) $(soc_dram_sim_files) $(soc_dram_sim_obj_f
endif endif


# Hello world # Hello world
MEMORY_SIZE ?=8192 MEMORY_SIZE=8192
RAM_INIT_FILE ?=hello_world/hello_world.hex RAM_INIT_FILE=hello_world/hello_world.hex


# Micropython # Micropython
#MEMORY_SIZE=393216 #MEMORY_SIZE=393216
#RAM_INIT_FILE=micropython/firmware.hex #RAM_INIT_FILE=micropython/firmware.hex


FPGA_TARGET ?= ORANGE-CRAB-0.21 FPGA_TARGET ?= ORANGE-CRAB

# FIXME: icache RAMs aren't being inferrenced as block RAMs on ECP5
# with yosys, so make it smaller for now as a workaround.
ICACHE_NUM_LINES=4

clkgen=fpga/clk_gen_ecp5.vhd
toplevel=fpga/top-generic.vhdl
dmi_dtm=dmi_dtm_dummy.vhdl
LITEDRAM_GHDL_ARG=


# OrangeCrab with ECP85 (original v0.0 with UM5G-85 chip) # OrangeCrab with ECP85
ifeq ($(FPGA_TARGET), ORANGE-CRAB) ifeq ($(FPGA_TARGET), ORANGE-CRAB)
RESET_LOW=true RESET_LOW=true
CLK_INPUT=48000000 CLK_INPUT=50000000
CLK_FREQUENCY=48000000 CLK_FREQUENCY=40000000
LPF=constraints/orange-crab.lpf LPF=constraints/orange-crab.lpf
PACKAGE=CSFBGA285 PACKAGE=CSFBGA285
NEXTPNR_FLAGS=--um5g-85k --freq 48 NEXTPNR_FLAGS=--um5g-85k --freq 40
OPENOCD_JTAG_CONFIG=openocd/olimex-arm-usb-tiny-h.cfg OPENOCD_JTAG_CONFIG=openocd/olimex-arm-usb-tiny-h.cfg
OPENOCD_DEVICE_CONFIG=openocd/LFE5UM5G-85F.cfg OPENOCD_DEVICE_CONFIG=openocd/LFE5UM5G-85F.cfg
ECP_FLASH_OFFSET=0x80000
endif

# OrangeCrab with ECP85 (v0.21)
ifeq ($(FPGA_TARGET), ORANGE-CRAB-0.21)
RESET_LOW=true
CLK_INPUT=48000000
CLK_FREQUENCY=48000000
LPF=constraints/orange-crab-0.2.lpf
PACKAGE=CSFBGA285
NEXTPNR_FLAGS=--85k --speed 8 --freq 48 --timing-allow-fail --ignore-loops
OPENOCD_JTAG_CONFIG=openocd/olimex-arm-usb-tiny-h.cfg
OPENOCD_DEVICE_CONFIG=openocd/LFE5U-85F.cfg
DFU_VENDOR=1209
DFU_PRODUCT=5af0
ECP_FLASH_OFFSET=0x80000
toplevel=fpga/top-orangecrab0.2.vhdl
litedram_target=orangecrab-85-0.2
soc_extra_v += litesdcard/generated/lattice/litesdcard_core.v
dmi_dtm=dmi_dtm_ecp5.vhdl
endif endif


# ECP5-EVN # ECP5-EVN
@ -207,17 +170,12 @@ OPENOCD_JTAG_CONFIG=openocd/ecp5-evn.cfg
OPENOCD_DEVICE_CONFIG=openocd/LFE5UM5G-85F.cfg OPENOCD_DEVICE_CONFIG=openocd/LFE5UM5G-85F.cfg
endif endif


ifneq ($(litedram_target),)
soc_extra_synth += litedram/extras/litedram-wrapper-l2.vhdl \
litedram/generated/$(litedram_target)/litedram-initmem.vhdl
soc_extra_v += litedram/generated/$(litedram_target)/litedram_core.v
LITEDRAM_GHDL_ARG=-gUSE_LITEDRAM=true
endif

GHDL_IMAGE_GENERICS=-gMEMORY_SIZE=$(MEMORY_SIZE) -gRAM_INIT_FILE=$(RAM_INIT_FILE) \ GHDL_IMAGE_GENERICS=-gMEMORY_SIZE=$(MEMORY_SIZE) -gRAM_INIT_FILE=$(RAM_INIT_FILE) \
-gRESET_LOW=$(RESET_LOW) -gCLK_INPUT=$(CLK_INPUT) -gCLK_FREQUENCY=$(CLK_FREQUENCY) -gICACHE_NUM_LINES=$(ICACHE_NUM_LINES) \ -gRESET_LOW=$(RESET_LOW) -gCLK_INPUT=$(CLK_INPUT) -gCLK_FREQUENCY=$(CLK_FREQUENCY)
$(LITEDRAM_GHDL_ARG)


clkgen=fpga/clk_gen_ecp5.vhd
toplevel=fpga/top-generic.vhdl
dmi_dtm=dmi_dtm_dummy.vhdl


ifeq ($(FPGA_TARGET), verilator) ifeq ($(FPGA_TARGET), verilator)
RESET_LOW=true RESET_LOW=true
@ -226,20 +184,22 @@ CLK_FREQUENCY=50000000
clkgen=fpga/clk_gen_bypass.vhd clkgen=fpga/clk_gen_bypass.vhd
endif endif


fpga_files = fpga/soc_reset.vhdl \ fpga_files = $(core_files) $(soc_files) fpga/soc_reset.vhdl \
fpga/pp_fifo.vhd fpga/pp_soc_uart.vhd fpga/main_bram.vhdl \ fpga/pp_fifo.vhd fpga/pp_soc_uart.vhd fpga/main_bram.vhdl \
nonrandom.vhdl nonrandom.vhdl


synth_files = $(core_files) $(soc_files) $(soc_extra_synth) $(fpga_files) $(clkgen) $(toplevel) $(dmi_dtm) synth_files = $(core_files) $(soc_files) $(fpga_files) $(clkgen) $(toplevel) $(dmi_dtm)


microwatt.json: $(synth_files) $(RAM_INIT_FILE) microwatt.json: $(synth_files) $(RAM_INIT_FILE)
$(YOSYS) $(GHDLSYNTH) -p "ghdl --std=08 --no-formal $(GHDL_IMAGE_GENERICS) $(synth_files) -e toplevel; read_verilog $(uart_files) $(soc_extra_v); synth_ecp5 -abc9 -nowidelut -json $@ $(SYNTH_ECP5_FLAGS)" $(YOSYS) -m $(GHDLSYNTH) -p "ghdl --std=08 --no-formal $(GHDL_IMAGE_GENERICS) $(GHDL_TARGET_GENERICS) $(synth_files) -e toplevel; synth_ecp5 -json $@ $(SYNTH_ECP5_FLAGS)" $(uart_files)


microwatt.v: $(synth_files) $(RAM_INIT_FILE) microwatt.v: $(synth_files) $(RAM_INIT_FILE)
$(YOSYS) $(GHDLSYNTH) -p "ghdl --std=08 --no-formal $(GHDL_IMAGE_GENERICS) $(synth_files) -e toplevel; write_verilog $@" $(YOSYS) -m $(GHDLSYNTH) -p "ghdl --std=08 --no-formal $(GHDL_IMAGE_GENERICS) $(GHDL_TARGET_GENERICS) $(synth_files) -e toplevel; write_verilog $@"


# Need to investigate why yosys is hitting verilator warnings, and eventually turn on -Wall
microwatt-verilator: microwatt.v verilator/microwatt-verilator.cpp verilator/uart-verilator.c microwatt-verilator: microwatt.v verilator/microwatt-verilator.cpp verilator/uart-verilator.c
$(VERILATOR) $(VERILATOR_FLAGS) -CFLAGS "$(VERILATOR_CFLAGS) -DCLK_FREQUENCY=$(CLK_FREQUENCY)" -Iuart16550 --assert --cc --exe --build $^ -o $@ -top-module toplevel verilator -O3 -CFLAGS "-DCLK_FREQUENCY=$(CLK_FREQUENCY)" --assert --cc microwatt.v --exe verilator/microwatt-verilator.cpp verilator/uart-verilator.c -o $@ -Iuart16550 -Wno-fatal -Wno-CASEOVERLAP -Wno-UNOPTFLAT #--trace
make -C obj_dir -f Vmicrowatt.mk
@cp -f obj_dir/microwatt-verilator microwatt-verilator @cp -f obj_dir/microwatt-verilator microwatt-verilator


microwatt_out.config: microwatt.json $(LPF) microwatt_out.config: microwatt.json $(LPF)
@ -247,36 +207,18 @@ microwatt_out.config: microwatt.json $(LPF)
mv -f $@.tmp $@ mv -f $@.tmp $@


microwatt.bit: microwatt_out.config microwatt.bit: microwatt_out.config
$(ECPPACK) --compress --freq 38.8 --svf microwatt.svf $< $@ $(ECPPACK) --svf microwatt.svf $< $@


microwatt.svf: microwatt.bit microwatt.svf: microwatt.bit


prog: microwatt.svf prog: microwatt.svf
$(OPENOCD) -f $(OPENOCD_JTAG_CONFIG) -f $(OPENOCD_DEVICE_CONFIG) -c "transport select jtag; init; svf $<; exit" $(OPENOCD) -f $(OPENOCD_JTAG_CONFIG) -f $(OPENOCD_DEVICE_CONFIG) -c "transport select jtag; init; svf $<; exit"


microwatt.dfu: microwatt.bit
cp $< $@.tmp
$(DFUSUFFIX) -v $(DFU_VENDOR) -p $(DFU_PRODUCT) -a $@.tmp
mv $@.tmp $@

dfuprog: microwatt.dfu
$(DFUUTIL) -a 0 -D $<

ecpprog: microwatt.bit
$(ECPPROG) -S $<

ecpflash: microwatt.bit
test -n "$(ECP_FLASH_OFFSET)" || (echo Error: No ECP_FLASH_OFFSET defined for target; exit 1)
$(ECPPROG) -o $(ECP_FLASH_OFFSET) $<

tests = $(sort $(patsubst tests/%.out,%,$(wildcard tests/*.out))) tests = $(sort $(patsubst tests/%.out,%,$(wildcard tests/*.out)))
tests_console = $(sort $(patsubst tests/%.console_out,%,$(wildcard tests/*.console_out))) tests_console = $(sort $(patsubst tests/%.console_out,%,$(wildcard tests/*.console_out)))


tests_console: $(tests_console) tests_console: $(tests_console)


check_vunit:
$(VUNITRUN) $(VUNITARGS)

check: $(tests) tests_console test_micropython test_micropython_long tests_unit check: $(tests) tests_console test_micropython test_micropython_long tests_unit


check_light: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 test_micropython test_micropython_long tests_console tests_unit check_light: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 test_micropython test_micropython_long tests_console tests_unit
@ -290,24 +232,22 @@ $(tests_console): core_tb
test_micropython: core_tb test_micropython: core_tb
@./scripts/test_micropython.py @./scripts/test_micropython.py


test_micropython_verilator: microwatt-verilator
@./scripts/test_micropython_verilator.py

test_micropython_long: core_tb test_micropython_long: core_tb
@./scripts/test_micropython_long.py @./scripts/test_micropython_long.py


test_micropython_verilator_long: microwatt-verilator tests_core_tb = $(patsubst %_tb,%_tb_test,$(core_tbs))
@./scripts/test_micropython_verilator_long.py

tests_soc_tb = $(patsubst %_tb,%_tb_test,$(soc_tbs)) tests_soc_tb = $(patsubst %_tb,%_tb_test,$(soc_tbs))


%_test: % %_test: %
./$< --assert-level=error > /dev/null ./$< --assert-level=error > /dev/null


tests_core: $(tests_core_tb)

tests_soc: $(tests_soc_tb) tests_soc: $(tests_soc_tb)


# FIXME SOC tests have bit rotted, so disable for now # FIXME SOC tests have bit rotted, so disable for now
#tests_unit: tests_soc #tests_unit: tests_core tests_soc
tests_unit: tests_core


TAGS: TAGS:
find . -name '*.vhdl' | xargs ./scripts/vhdltags find . -name '*.vhdl' | xargs ./scripts/vhdltags

@ -97,19 +97,15 @@ sudo dnf copr enable sharkcz/danny
sudo dnf install fusesoc sudo dnf install fusesoc
``` ```


- If this is your first time using fusesoc, initialize fusesoc. - Create a working directory and point FuseSoC at microwatt:
This is needed to be able to pull down fussoc library components referenced
by microwatt. Run


``` ```
fusesoc init mkdir microwatt-fusesoc
fusesoc fetch uart16550 cd microwatt-fusesoc
fusesoc library add microwatt /path/to/microwatt fusesoc library add microwatt /path/to/microwatt/
``` ```


- Build using FuseSoC. For hello world (Replace nexys_video with your FPGA board such as --target=arty_a7-100): - Build using FuseSoC. For hello world (Replace nexys_video with your FPGA board such as --target=arty_a7-100):
You may wish to ensure you have [installed Digilent Board files](https://reference.digilentinc.com/vivado/installing-vivado/start#installing_digilent_board_files)
or appropriate files for your board first.


``` ```
fusesoc run --target=nexys_video microwatt --memory_size=16384 --ram_init_file=/path/to/microwatt/fpga/hello_world.hex fusesoc run --target=nexys_video microwatt --memory_size=16384 --ram_init_file=/path/to/microwatt/fpga/hello_world.hex
@ -122,68 +118,6 @@ You should then be able to see output via the serial port of the board (/dev/tty
fusesoc run --target=nexys_video microwatt fusesoc run --target=nexys_video microwatt
``` ```


## Linux on Microwatt

Mainline Linux supports Microwatt as of v5.14. The Arty A7 is the best tested
platform, but it's also been tested on the OrangeCrab and ButterStick.

1. Use buildroot to create a userspace

A small change is required to glibc in order to support the VMX/AltiVec-less
Microwatt, as float128 support is mandiatory and for this in GCC requires
VSX/AltiVec. This change is included in Joel's buildroot fork, along with a
defconfig:
```
git clone -b microwatt https://github.com/shenki/buildroot
cd buildroot
make ppc64le_microwatt_defconfig
make
```

The output is `output/images/rootfs.cpio`.

2. Build the Linux kernel
```
git clone https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
cd linux
make ARCH=powerpc microwatt_defconfig
make ARCH=powerpc CROSS_COMPILE=powerpc64le-linux-gnu- \
CONFIG_INITRAMFS_SOURCE=/buildroot/output/images/rootfs.cpio -j`nproc`
```

The output is `arch/powerpc/boot/dtbImage.microwatt.elf`.

3. Build gateware using FuseSoC

First configure FuseSoC as above.
```
fusesoc run --build --target=arty_a7-100 microwatt --no_bram --memory_size=0
```

The output is `build/microwatt_0/arty_a7-100-vivado/microwatt_0.bit`.

4. Program the flash

This operation will overwrite the contents of your flash.

For the Arty A7 A100, set `FLASH_ADDRESS` to `0x400000` and pass `-f a100`.

For the Arty A7 A35, set `FLASH_ADDRESS` to `0x300000` and pass `-f a35`.
```
microwatt/openocd/flash-arty -f a100 build/microwatt_0/arty_a7-100-vivado/microwatt_0.bit
microwatt/openocd/flash-arty -f a100 dtbImage.microwatt.elf -t bin -a $FLASH_ADDRESS
```

5. Connect to the second USB TTY device exposed by the FPGA

```
minicom -D /dev/ttyUSB1
```

The gateware has firmware that will look at `FLASH_ADDRESS` and attempt to
parse an ELF there, loading it to the address specified in the ELF header
and jumping to it.

## Testing ## Testing


- A simple test suite containing random execution test cases and a couple of - A simple test suite containing random execution test cases and a couple of
@ -195,5 +129,8 @@ make -j$(nproc) check


## Issues ## Issues


- There are a few instructions still to be implemented: This is functional, but very simple. We still have quite a lot to do:
- Vector/VMX/VSX
- There are a few instructions still to be implemented
- Need to add caches and bypassing (in progress)
- Need to add supervisor state (in progress)

@ -5,21 +5,21 @@ use ieee.math_real.all;


entity cache_ram is entity cache_ram is
generic( generic(
ROW_BITS : integer := 16; ROW_BITS : integer := 16;
WIDTH : integer := 64; WIDTH : integer := 64;
TRACE : boolean := false; TRACE : boolean := false;
ADD_BUF : boolean := false ADD_BUF : boolean := false
); );


port( port(
clk : in std_logic; clk : in std_logic;
rd_en : in std_logic; rd_en : in std_logic;
rd_addr : in std_logic_vector(ROW_BITS - 1 downto 0); rd_addr : in std_logic_vector(ROW_BITS - 1 downto 0);
rd_data : out std_logic_vector(WIDTH - 1 downto 0); rd_data : out std_logic_vector(WIDTH - 1 downto 0);
wr_sel : in std_logic_vector(WIDTH/8 - 1 downto 0); wr_sel : in std_logic_vector(WIDTH/8 - 1 downto 0);
wr_addr : in std_logic_vector(ROW_BITS - 1 downto 0); wr_addr : in std_logic_vector(ROW_BITS - 1 downto 0);
wr_data : in std_logic_vector(WIDTH - 1 downto 0) wr_data : in std_logic_vector(WIDTH - 1 downto 0)
); );


end cache_ram; end cache_ram;


@ -35,13 +35,13 @@ architecture rtl of cache_ram is


begin begin
process(clk) process(clk)
variable lbit : integer range 0 to WIDTH - 1; variable lbit : integer range 0 to WIDTH - 1;
variable mbit : integer range 0 to WIDTH - 1; variable mbit : integer range 0 to WIDTH - 1;
variable widx : integer range 0 to SIZE - 1; variable widx : integer range 0 to SIZE - 1;
constant sel0 : std_logic_vector(WIDTH/8 - 1 downto 0) constant sel0 : std_logic_vector(WIDTH/8 - 1 downto 0)
:= (others => '0'); := (others => '0');
begin begin
if rising_edge(clk) then if rising_edge(clk) then
if TRACE then if TRACE then
if wr_sel /= sel0 then if wr_sel /= sel0 then
report "write a:" & to_hstring(wr_addr) & report "write a:" & to_hstring(wr_addr) &
@ -57,29 +57,29 @@ begin
ram(widx)(mbit downto lbit) <= wr_data(mbit downto lbit); ram(widx)(mbit downto lbit) <= wr_data(mbit downto lbit);
end if; end if;
end loop; end loop;
if rd_en = '1' then if rd_en = '1' then
rd_data0 <= ram(to_integer(unsigned(rd_addr))); rd_data0 <= ram(to_integer(unsigned(rd_addr)));
if TRACE then if TRACE then
report "read a:" & to_hstring(rd_addr) & report "read a:" & to_hstring(rd_addr) &
" dat:" & to_hstring(ram(to_integer(unsigned(rd_addr)))); " dat:" & to_hstring(ram(to_integer(unsigned(rd_addr))));
end if; end if;
end if; end if;
end if; end if;
end process; end process;


buf: if ADD_BUF generate buf: if ADD_BUF generate
begin begin
process(clk) process(clk)
begin begin
if rising_edge(clk) then if rising_edge(clk) then
rd_data <= rd_data0; rd_data <= rd_data0;
end if; end if;
end process; end process;
end generate; end generate;


nobuf: if not ADD_BUF generate nobuf: if not ADD_BUF generate
begin begin
rd_data <= rd_data0; rd_data <= rd_data0;
end generate; end generate;


end; end;

@ -21,7 +21,6 @@ package common is
constant MSR_FE1 : integer := (63 - 55); -- Floating Exception mode constant MSR_FE1 : integer := (63 - 55); -- Floating Exception mode
constant MSR_IR : integer := (63 - 58); -- Instruction Relocation constant MSR_IR : integer := (63 - 58); -- Instruction Relocation
constant MSR_DR : integer := (63 - 59); -- Data Relocation constant MSR_DR : integer := (63 - 59); -- Data Relocation
constant MSR_PMM : integer := (63 - 61); -- Performance Monitor Mark
constant MSR_RI : integer := (63 - 62); -- Recoverable Interrupt constant MSR_RI : integer := (63 - 62); -- Recoverable Interrupt
constant MSR_LE : integer := (63 - 63); -- Little Endian constant MSR_LE : integer := (63 - 63); -- Little Endian


@ -52,37 +51,9 @@ package common is
constant SPR_HSPRG0 : spr_num_t := 304; constant SPR_HSPRG0 : spr_num_t := 304;
constant SPR_HSPRG1 : spr_num_t := 305; constant SPR_HSPRG1 : spr_num_t := 305;
constant SPR_PID : spr_num_t := 48; constant SPR_PID : spr_num_t := 48;
constant SPR_PTCR : spr_num_t := 464; constant SPR_PRTBL : spr_num_t := 720;
constant SPR_PVR : spr_num_t := 287; constant SPR_PVR : spr_num_t := 287;


-- PMU registers
constant SPR_UPMC1 : spr_num_t := 771;
constant SPR_UPMC2 : spr_num_t := 772;
constant SPR_UPMC3 : spr_num_t := 773;
constant SPR_UPMC4 : spr_num_t := 774;
constant SPR_UPMC5 : spr_num_t := 775;
constant SPR_UPMC6 : spr_num_t := 776;
constant SPR_UMMCR0 : spr_num_t := 779;
constant SPR_UMMCR1 : spr_num_t := 782;
constant SPR_UMMCR2 : spr_num_t := 769;
constant SPR_UMMCRA : spr_num_t := 770;
constant SPR_USIER : spr_num_t := 768;
constant SPR_USIAR : spr_num_t := 780;
constant SPR_USDAR : spr_num_t := 781;
constant SPR_PMC1 : spr_num_t := 787;
constant SPR_PMC2 : spr_num_t := 788;
constant SPR_PMC3 : spr_num_t := 789;
constant SPR_PMC4 : spr_num_t := 790;
constant SPR_PMC5 : spr_num_t := 791;
constant SPR_PMC6 : spr_num_t := 792;
constant SPR_MMCR0 : spr_num_t := 795;
constant SPR_MMCR1 : spr_num_t := 798;
constant SPR_MMCR2 : spr_num_t := 785;
constant SPR_MMCRA : spr_num_t := 786;
constant SPR_SIER : spr_num_t := 784;
constant SPR_SIAR : spr_num_t := 796;
constant SPR_SDAR : spr_num_t := 797;

-- GPR indices in the register file (GPR only) -- GPR indices in the register file (GPR only)
subtype gpr_index_t is std_ulogic_vector(4 downto 0); subtype gpr_index_t is std_ulogic_vector(4 downto 0);


@ -156,12 +127,6 @@ package common is
constant FPSCR_NI : integer := 63 - 61; constant FPSCR_NI : integer := 63 - 61;
constant FPSCR_RN : integer := 63 - 63; constant FPSCR_RN : integer := 63 - 63;


-- Real addresses
-- REAL_ADDR_BITS is the number of real address bits that we store
constant REAL_ADDR_BITS : positive := 56;
subtype real_addr_t is std_ulogic_vector(REAL_ADDR_BITS - 1 downto 0);
function addr_to_real(addr: std_ulogic_vector(63 downto 0)) return real_addr_t;

-- Used for tracking instruction completion and pending register writes -- Used for tracking instruction completion and pending register writes
constant TAG_COUNT : positive := 4; constant TAG_COUNT : positive := 4;
constant TAG_NUMBER_BITS : natural := log2(TAG_COUNT); constant TAG_NUMBER_BITS : natural := log2(TAG_COUNT);
@ -200,8 +165,8 @@ package common is
priv_mode : std_ulogic; priv_mode : std_ulogic;
big_endian : std_ulogic; big_endian : std_ulogic;
stop_mark: std_ulogic; stop_mark: std_ulogic;
sequential: std_ulogic;
predicted : std_ulogic; predicted : std_ulogic;
pred_ntaken : std_ulogic;
nia: std_ulogic_vector(63 downto 0); nia: std_ulogic_vector(63 downto 0);
end record; end record;


@ -213,12 +178,6 @@ package common is
insn: std_ulogic_vector(31 downto 0); insn: std_ulogic_vector(31 downto 0);
big_endian: std_ulogic; big_endian: std_ulogic;
next_predicted: std_ulogic; next_predicted: std_ulogic;
next_pred_ntaken: std_ulogic;
end record;

type IcacheEventType is record
icache_miss : std_ulogic;
itlb_miss_resolved : std_ulogic;
end record; end record;


type Decode1ToDecode2Type is record type Decode1ToDecode2Type is record
@ -344,51 +303,6 @@ package common is
is_extended => '0', is_modulus => '0', is_extended => '0', is_modulus => '0',
neg_result => '0', others => (others => '0')); neg_result => '0', others => (others => '0'));


type PMUEventType is record
no_instr_avail : std_ulogic;
dispatch : std_ulogic;
ext_interrupt : std_ulogic;
instr_complete : std_ulogic;
fp_complete : std_ulogic;
ld_complete : std_ulogic;
st_complete : std_ulogic;
br_taken_complete : std_ulogic;
br_mispredict : std_ulogic;
ipref_discard : std_ulogic;
itlb_miss : std_ulogic;
itlb_miss_resolved : std_ulogic;
icache_miss : std_ulogic;
dc_miss_resolved : std_ulogic;
dc_load_miss : std_ulogic;
dc_ld_miss_resolved : std_ulogic;
dc_store_miss : std_ulogic;
dtlb_miss : std_ulogic;
dtlb_miss_resolved : std_ulogic;
ld_miss_nocache : std_ulogic;
ld_fill_nocache : std_ulogic;
end record;
constant PMUEventInit : PMUEventType := (others => '0');

type Execute1ToPMUType is record
mfspr : std_ulogic;
mtspr : std_ulogic;
spr_num : std_ulogic_vector(4 downto 0);
spr_val : std_ulogic_vector(63 downto 0);
tbbits : std_ulogic_vector(3 downto 0); -- event bits from timebase
pmm_msr : std_ulogic; -- PMM bit from MSR
pr_msr : std_ulogic; -- PR bit from MSR
run : std_ulogic;
nia : std_ulogic_vector(63 downto 0);
addr : std_ulogic_vector(63 downto 0);
addr_v : std_ulogic;
occur : PMUEventType;
end record;

type PMUToExecute1Type is record
spr_val : std_ulogic_vector(63 downto 0);
intr : std_ulogic;
end record;

type Decode2ToRegisterFileType is record type Decode2ToRegisterFileType is record
read1_enable : std_ulogic; read1_enable : std_ulogic;
read1_reg : gspr_index_t; read1_reg : gspr_index_t;
@ -455,7 +369,6 @@ package common is
type Loadstore1ToExecute1Type is record type Loadstore1ToExecute1Type is record
busy : std_ulogic; busy : std_ulogic;
in_progress : std_ulogic; in_progress : std_ulogic;
interrupt : std_ulogic;
end record; end record;


type Loadstore1ToDcacheType is record type Loadstore1ToDcacheType is record
@ -482,14 +395,6 @@ package common is
cache_paradox : std_ulogic; cache_paradox : std_ulogic;
end record; end record;


type DcacheEventType is record
load_miss : std_ulogic;
store_miss : std_ulogic;
dcache_refill : std_ulogic;
dtlb_miss : std_ulogic;
dtlb_miss_resolved : std_ulogic;
end record;

type Loadstore1ToMmuType is record type Loadstore1ToMmuType is record
valid : std_ulogic; valid : std_ulogic;
tlbie : std_ulogic; tlbie : std_ulogic;
@ -559,12 +464,6 @@ package common is
interrupt => '0', intr_vec => 0, interrupt => '0', intr_vec => 0,
srr0 => (others => '0'), srr1 => (others => '0')); srr0 => (others => '0'), srr1 => (others => '0'));


type Loadstore1EventType is record
load_complete : std_ulogic;
store_complete : std_ulogic;
itlb_miss : std_ulogic;
end record;

type Execute1ToWritebackType is record type Execute1ToWritebackType is record
valid: std_ulogic; valid: std_ulogic;
instr_tag : instr_tag_t; instr_tag : instr_tag_t;
@ -695,11 +594,6 @@ package common is
write_cr_mask => (others => '0'), write_cr_mask => (others => '0'),
write_cr_data => (others => '0')); write_cr_data => (others => '0'));


type WritebackEventType is record
instr_complete : std_ulogic;
fp_complete : std_ulogic;
end record;

end common; end common;


package body common is package body common is
@ -784,9 +678,4 @@ package body common is
begin begin
return tag1.valid = '1' and tag2.valid = '1' and tag1.tag = tag2.tag; return tag1.valid = '1' and tag2.valid = '1' and tag1.tag = tag2.tag;
end; end;

function addr_to_real(addr: std_ulogic_vector(63 downto 0)) return real_addr_t is
begin
return addr(real_addr_t'range);
end;
end common; end common;

@ -1,225 +0,0 @@
LOCATE COMP "ext_clk" SITE "A9";
IOBUF PORT "ext_clk" IO_TYPE=LVCMOS33;

// LOCATE COMP "ext_rst_n" SITE "J2"; // io_13
// IOBUF PORT "ext_rst_n" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;

// user_button as reset
LOCATE COMP "ext_rst_n" SITE "J17";
IOBUF PORT "ext_rst_n" IO_TYPE=SSTL135_I;

LOCATE COMP "usb_d_p" SITE "N1";
LOCATE COMP "usb_d_n" SITE "M2";
LOCATE COMP "usb_pullup" SITE "N2";

IOBUF PORT "usb_d_p" IO_TYPE=LVCMOS33;
IOBUF PORT "usb_d_n" IO_TYPE=LVCMOS33;
IOBUF PORT "usb_pullup" IO_TYPE=LVCMOS33;

LOCATE COMP "led0_g" SITE "M3";
LOCATE COMP "led0_r" SITE "K4";
LOCATE COMP "led0_b" SITE "J3";

IOBUF PORT "led0_g" IO_TYPE=LVCMOS33;
IOBUF PORT "led0_g" IO_TYPE=LVCMOS33;
IOBUF PORT "led0_b" IO_TYPE=LVCMOS33;

// discontinuous gpio numbers, match orangecrab litex platform
LOCATE COMP "pin_gpio_0" SITE "N17"; // tx
LOCATE COMP "pin_gpio_1" SITE "M18"; // rx
LOCATE COMP "pin_gpio_2" SITE "C10"; // sda
LOCATE COMP "pin_gpio_3" SITE "C9"; // scl
//
LOCATE COMP "pin_gpio_5" SITE "B10"; // io_5
LOCATE COMP "pin_gpio_6" SITE "B9"; // ...
//
LOCATE COMP "pin_gpio_9" SITE "C8"; //
LOCATE COMP "pin_gpio_10" SITE "B8"; //
LOCATE COMP "pin_gpio_11" SITE "A8"; //
LOCATE COMP "pin_gpio_12" SITE "H2"; //
LOCATE COMP "pin_gpio_13" SITE "J2"; // io_13
LOCATE COMP "pin_gpio_14" SITE "N15"; // miso
LOCATE COMP "pin_gpio_15" SITE "R17"; // sck
LOCATE COMP "pin_gpio_16" SITE "N16"; // mosi

LOCATE COMP "pin_io_a0" SITE "L4";
LOCATE COMP "pin_io_a1" SITE "N3";
LOCATE COMP "pin_io_a2" SITE "N4";
LOCATE COMP "pin_io_a3" SITE "H4";
LOCATE COMP "pin_io_a4" SITE "G4";
LOCATE COMP "pin_io_a5" SITE "T17";

IOBUF PORT "pin_gpio_0" IO_TYPE=LVCMOS33;
IOBUF PORT "pin_gpio_1" IO_TYPE=LVCMOS33;
IOBUF PORT "pin_gpio_2" IO_TYPE=LVCMOS33;
IOBUF PORT "pin_gpio_3" IO_TYPE=LVCMOS33;
IOBUF PORT "pin_gpio_5" IO_TYPE=LVCMOS33;
IOBUF PORT "pin_gpio_6" IO_TYPE=LVCMOS33;
IOBUF PORT "pin_gpio_9" IO_TYPE=LVCMOS33;
IOBUF PORT "pin_gpio_10" IO_TYPE=LVCMOS33;
IOBUF PORT "pin_gpio_11" IO_TYPE=LVCMOS33;
IOBUF PORT "pin_gpio_12" IO_TYPE=LVCMOS33;
IOBUF PORT "pin_gpio_13" IO_TYPE=LVCMOS33;
IOBUF PORT "pin_gpio_14" IO_TYPE=LVCMOS33;
IOBUF PORT "pin_gpio_15" IO_TYPE=LVCMOS33;
IOBUF PORT "pin_gpio_16" IO_TYPE=LVCMOS33;
IOBUF PORT "pin_io_a0" IO_TYPE=LVCMOS33;
IOBUF PORT "pin_io_a1" IO_TYPE=LVCMOS33;
IOBUF PORT "pin_io_a2" IO_TYPE=LVCMOS33;
IOBUF PORT "pin_io_a3" IO_TYPE=LVCMOS33;
IOBUF PORT "pin_io_a4" IO_TYPE=LVCMOS33;
IOBUF PORT "pin_io_a5" IO_TYPE=LVCMOS33;

LOCATE COMP "ddram_a[0]" SITE "C4";
LOCATE COMP "ddram_a[1]" SITE "D2";
LOCATE COMP "ddram_a[2]" SITE "D3";
LOCATE COMP "ddram_a[3]" SITE "A3";
LOCATE COMP "ddram_a[4]" SITE "A4";
LOCATE COMP "ddram_a[5]" SITE "D4";
LOCATE COMP "ddram_a[6]" SITE "C3";
LOCATE COMP "ddram_a[7]" SITE "B2";
LOCATE COMP "ddram_a[8]" SITE "B1";
LOCATE COMP "ddram_a[9]" SITE "D1";
LOCATE COMP "ddram_a[10]" SITE "A7";
LOCATE COMP "ddram_a[11]" SITE "C2";
LOCATE COMP "ddram_a[12]" SITE "B6";
LOCATE COMP "ddram_a[13]" SITE "C1";
LOCATE COMP "ddram_a[14]" SITE "A2";
LOCATE COMP "ddram_a[15]" SITE "C7";
IOBUF PORT "ddram_a[0]" IO_TYPE=SSTL135_I SLEWRATE=FAST;
IOBUF PORT "ddram_a[1]" IO_TYPE=SSTL135_I SLEWRATE=FAST;
IOBUF PORT "ddram_a[2]" IO_TYPE=SSTL135_I SLEWRATE=FAST;
IOBUF PORT "ddram_a[3]" IO_TYPE=SSTL135_I SLEWRATE=FAST;
IOBUF PORT "ddram_a[4]" IO_TYPE=SSTL135_I SLEWRATE=FAST;
IOBUF PORT "ddram_a[5]" IO_TYPE=SSTL135_I SLEWRATE=FAST;
IOBUF PORT "ddram_a[6]" IO_TYPE=SSTL135_I SLEWRATE=FAST;
IOBUF PORT "ddram_a[7]" IO_TYPE=SSTL135_I SLEWRATE=FAST;
IOBUF PORT "ddram_a[8]" IO_TYPE=SSTL135_I SLEWRATE=FAST;
IOBUF PORT "ddram_a[9]" IO_TYPE=SSTL135_I SLEWRATE=FAST;
IOBUF PORT "ddram_a[10]" IO_TYPE=SSTL135_I SLEWRATE=FAST;
IOBUF PORT "ddram_a[11]" IO_TYPE=SSTL135_I SLEWRATE=FAST;
IOBUF PORT "ddram_a[12]" IO_TYPE=SSTL135_I SLEWRATE=FAST;
IOBUF PORT "ddram_a[13]" IO_TYPE=SSTL135_I SLEWRATE=FAST;
IOBUF PORT "ddram_a[14]" IO_TYPE=SSTL135_I SLEWRATE=FAST;
IOBUF PORT "ddram_a[15]" IO_TYPE=SSTL135_I SLEWRATE=FAST;

LOCATE COMP "ddram_ba[0]" SITE "D6";
LOCATE COMP "ddram_ba[1]" SITE "B7";
LOCATE COMP "ddram_ba[2]" SITE "A6";
LOCATE COMP "ddram_cas_n" SITE "D13";
LOCATE COMP "ddram_cs_n" SITE "A12";
LOCATE COMP "ddram_dm[0]" SITE "D16";
LOCATE COMP "ddram_dm[1]" SITE "G16";
LOCATE COMP "ddram_ras_n" SITE "C12";
LOCATE COMP "ddram_we_n" SITE "B12";
IOBUF PORT "ddram_ba[0]" IO_TYPE=SSTL135_I SLEWRATE=FAST;
IOBUF PORT "ddram_ba[1]" IO_TYPE=SSTL135_I SLEWRATE=FAST;
IOBUF PORT "ddram_ba[2]" IO_TYPE=SSTL135_I SLEWRATE=FAST;
IOBUF PORT "ddram_cas_n" IO_TYPE=SSTL135_I SLEWRATE=FAST;
IOBUF PORT "ddram_cs_n" IO_TYPE=SSTL135_I SLEWRATE=FAST;
IOBUF PORT "ddram_dm[0]" IO_TYPE=SSTL135_I SLEWRATE=FAST;
IOBUF PORT "ddram_dm[1]" IO_TYPE=SSTL135_I SLEWRATE=FAST;
IOBUF PORT "ddram_ras_n" IO_TYPE=SSTL135_I SLEWRATE=FAST;
IOBUF PORT "ddram_we_n" IO_TYPE=SSTL135_I SLEWRATE=FAST;

// from litex platform, termination disabled to reduce heat
LOCATE COMP "ddram_dq[0]" SITE "C17";
LOCATE COMP "ddram_dq[1]" SITE "D15";
LOCATE COMP "ddram_dq[2]" SITE "B17";
LOCATE COMP "ddram_dq[3]" SITE "C16";
LOCATE COMP "ddram_dq[4]" SITE "A15";
LOCATE COMP "ddram_dq[5]" SITE "B13";
LOCATE COMP "ddram_dq[6]" SITE "A17";
LOCATE COMP "ddram_dq[7]" SITE "A13";
LOCATE COMP "ddram_dq[8]" SITE "F17";
LOCATE COMP "ddram_dq[9]" SITE "F16";
LOCATE COMP "ddram_dq[10]" SITE "G15";
LOCATE COMP "ddram_dq[11]" SITE "F15";
LOCATE COMP "ddram_dq[12]" SITE "J16";
LOCATE COMP "ddram_dq[13]" SITE "C18";
LOCATE COMP "ddram_dq[14]" SITE "H16";
LOCATE COMP "ddram_dq[15]" SITE "F18";
IOBUF PORT "ddram_dq[0]" IO_TYPE=SSTL135_I SLEWRATE=FAST TERMINATION=OFF;
IOBUF PORT "ddram_dq[1]" IO_TYPE=SSTL135_I SLEWRATE=FAST TERMINATION=OFF;
IOBUF PORT "ddram_dq[2]" IO_TYPE=SSTL135_I SLEWRATE=FAST TERMINATION=OFF;
IOBUF PORT "ddram_dq[3]" IO_TYPE=SSTL135_I SLEWRATE=FAST TERMINATION=OFF;
IOBUF PORT "ddram_dq[4]" IO_TYPE=SSTL135_I SLEWRATE=FAST TERMINATION=OFF;
IOBUF PORT "ddram_dq[5]" IO_TYPE=SSTL135_I SLEWRATE=FAST TERMINATION=OFF;
IOBUF PORT "ddram_dq[6]" IO_TYPE=SSTL135_I SLEWRATE=FAST TERMINATION=OFF;
IOBUF PORT "ddram_dq[7]" IO_TYPE=SSTL135_I SLEWRATE=FAST TERMINATION=OFF;
IOBUF PORT "ddram_dq[8]" IO_TYPE=SSTL135_I SLEWRATE=FAST TERMINATION=OFF;
IOBUF PORT "ddram_dq[9]" IO_TYPE=SSTL135_I SLEWRATE=FAST TERMINATION=OFF;
IOBUF PORT "ddram_dq[10]" IO_TYPE=SSTL135_I SLEWRATE=FAST TERMINATION=OFF;
IOBUF PORT "ddram_dq[11]" IO_TYPE=SSTL135_I SLEWRATE=FAST TERMINATION=OFF;
IOBUF PORT "ddram_dq[12]" IO_TYPE=SSTL135_I SLEWRATE=FAST TERMINATION=OFF;
IOBUF PORT "ddram_dq[13]" IO_TYPE=SSTL135_I SLEWRATE=FAST TERMINATION=OFF;
IOBUF PORT "ddram_dq[14]" IO_TYPE=SSTL135_I SLEWRATE=FAST TERMINATION=OFF;
IOBUF PORT "ddram_dq[15]" IO_TYPE=SSTL135_I SLEWRATE=FAST TERMINATION=OFF;

LOCATE COMP "ddram_dqs_n[0]" SITE "A16";
LOCATE COMP "ddram_dqs_n[1]" SITE "H17";
LOCATE COMP "ddram_dqs_p[0]" SITE "B15";
LOCATE COMP "ddram_dqs_p[1]" SITE "G18";
IOBUF PORT "ddram_dqs_n[0]" IO_TYPE=SSTL135D_I SLEWRATE=FAST DIFFRESISTOR=100 TERMINATION=OFF;
IOBUF PORT "ddram_dqs_n[1]" IO_TYPE=SSTL135D_I SLEWRATE=FAST DIFFRESISTOR=100 TERMINATION=OFF;
IOBUF PORT "ddram_dqs_p[0]" IO_TYPE=SSTL135D_I SLEWRATE=FAST DIFFRESISTOR=100 TERMINATION=OFF;
IOBUF PORT "ddram_dqs_p[1]" IO_TYPE=SSTL135D_I SLEWRATE=FAST DIFFRESISTOR=100 TERMINATION=OFF;

LOCATE COMP "ddram_clk_p" SITE "J18";
LOCATE COMP "ddram_clk_n" SITE "K18";
IOBUF PORT "ddram_clk_p" IO_TYPE=SSTL135D_I SLEWRATE=FAST;
IOBUF PORT "ddram_clk_n" IO_TYPE=SSTL135D_I SLEWRATE=FAST;

LOCATE COMP "ddram_cke" SITE "D18";
LOCATE COMP "ddram_odt" SITE "C13";
LOCATE COMP "ddram_reset_n" SITE "L18";
IOBUF PORT "ddram_cke" IO_TYPE=SSTL135_I SLEWRATE=FAST;
IOBUF PORT "ddram_odt" IO_TYPE=SSTL135_I SLEWRATE=FAST;
IOBUF PORT "ddram_reset_n" IO_TYPE=SSTL135_I SLEWRATE=FAST;

LOCATE COMP "ddram_vccio[0]" SITE "K16";
LOCATE COMP "ddram_vccio[1]" SITE "D17";
LOCATE COMP "ddram_vccio[2]" SITE "K15";
LOCATE COMP "ddram_vccio[3]" SITE "K17";
LOCATE COMP "ddram_vccio[4]" SITE "B18";
LOCATE COMP "ddram_vccio[5]" SITE "C6";
LOCATE COMP "ddram_gnd[0]" SITE "L15";
LOCATE COMP "ddram_gnd[1]" SITE "L16";
IOBUF PORT "ddram_vccio[0]" IO_TYPE=SSTL135_II SLEWRATE=FAST;
IOBUF PORT "ddram_vccio[1]" IO_TYPE=SSTL135_II SLEWRATE=FAST;
IOBUF PORT "ddram_vccio[2]" IO_TYPE=SSTL135_II SLEWRATE=FAST;
IOBUF PORT "ddram_vccio[3]" IO_TYPE=SSTL135_II SLEWRATE=FAST;
IOBUF PORT "ddram_vccio[4]" IO_TYPE=SSTL135_II SLEWRATE=FAST;
IOBUF PORT "ddram_vccio[5]" IO_TYPE=SSTL135_II SLEWRATE=FAST;
IOBUF PORT "ddram_gnd[0]" IO_TYPE=SSTL135_II SLEWRATE=FAST;
IOBUF PORT "ddram_gnd[1]" IO_TYPE=SSTL135_II SLEWRATE=FAST;

// We use USRMCLK instead for clk
// LOCATE COMP "spi_flash_clk" SITE "U16";
// IOBUF PORT "spi_flash_clk" IO_TYPE=LVCMOS33;
LOCATE COMP "spi_flash_cs_n" SITE "U17";
IOBUF PORT "spi_flash_cs_n" IO_TYPE=LVCMOS33;
LOCATE COMP "spi_flash_mosi" SITE "U18";
IOBUF PORT "spi_flash_mosi" IO_TYPE=LVCMOS33;
LOCATE COMP "spi_flash_miso" SITE "T18";
IOBUF PORT "spi_flash_miso" IO_TYPE=LVCMOS33;
LOCATE COMP "spi_flash_wp_n" SITE "R18";
IOBUF PORT "spi_flash_wp_n" IO_TYPE=LVCMOS33;
LOCATE COMP "spi_flash_hold_n" SITE "N18";
IOBUF PORT "spi_flash_hold_n" IO_TYPE=LVCMOS33;

LOCATE COMP "sdcard_data[0]" SITE "J1";
LOCATE COMP "sdcard_data[1]" SITE "K3";
LOCATE COMP "sdcard_data[2]" SITE "L3";
LOCATE COMP "sdcard_data[3]" SITE "M1";
LOCATE COMP "sdcard_cmd" SITE "K2";
LOCATE COMP "sdcard_clk" SITE "K1";
LOCATE COMP "sdcard_cd" SITE "L1";

IOBUF PORT "sdcard_data[0]" IO_TYPE=LVCMOS33 SLEWRATE=FAST PULLMODE=UP;
IOBUF PORT "sdcard_data[1]" IO_TYPE=LVCMOS33 SLEWRATE=FAST PULLMODE=UP;
IOBUF PORT "sdcard_data[2]" IO_TYPE=LVCMOS33 SLEWRATE=FAST PULLMODE=UP;
IOBUF PORT "sdcard_data[3]" IO_TYPE=LVCMOS33 SLEWRATE=FAST PULLMODE=UP;
IOBUF PORT "sdcard_cmd" IO_TYPE=LVCMOS33 SLEWRATE=FAST PULLMODE=UP;
IOBUF PORT "sdcard_clk" IO_TYPE=LVCMOS33 SLEWRATE=FAST;
IOBUF PORT "sdcard_cd" IO_TYPE=LVCMOS33;

@ -17,7 +17,7 @@ entity control is
valid_in : in std_ulogic; valid_in : in std_ulogic;
repeated : in std_ulogic; repeated : in std_ulogic;
flush_in : in std_ulogic; flush_in : in std_ulogic;
busy_in : in std_ulogic; busy_in : in std_ulogic;
deferred : in std_ulogic; deferred : in std_ulogic;
sgl_pipe_in : in std_ulogic; sgl_pipe_in : in std_ulogic;
stop_mark_in : in std_ulogic; stop_mark_in : in std_ulogic;
@ -64,8 +64,8 @@ architecture rtl of control is


signal r_int, rin_int : reg_internal_type := reg_internal_init; signal r_int, rin_int : reg_internal_type := reg_internal_init;


signal gpr_write_valid : std_ulogic; signal gpr_write_valid : std_ulogic := '0';
signal cr_write_valid : std_ulogic; signal cr_write_valid : std_ulogic := '0';


type tag_register is record type tag_register is record
wr_gpr : std_ulogic; wr_gpr : std_ulogic;
@ -245,8 +245,6 @@ begin
end if; end if;


if rst = '1' then if rst = '1' then
gpr_write_valid <= '0';
cr_write_valid <= '0';
v_int := reg_internal_init; v_int := reg_internal_init;
valid_tmp := '0'; valid_tmp := '0';
end if; end if;

@ -3,6 +3,7 @@ use ieee.std_logic_1164.all;
use ieee.numeric_std.all; use ieee.numeric_std.all;


library work; library work;
use work.params.all;
use work.common.all; use work.common.all;
use work.wishbone_types.all; use work.wishbone_types.all;


@ -13,16 +14,9 @@ entity core is
EX1_BYPASS : boolean := true; EX1_BYPASS : boolean := true;
HAS_FPU : boolean := true; HAS_FPU : boolean := true;
HAS_BTC : boolean := true; HAS_BTC : boolean := true;
HAS_SHORT_MULT : boolean := false;
ALT_RESET_ADDRESS : std_ulogic_vector(63 downto 0) := (others => '0'); ALT_RESET_ADDRESS : std_ulogic_vector(63 downto 0) := (others => '0');
LOG_LENGTH : natural := 512; LOG_LENGTH : natural := 512;
ICACHE_NUM_LINES : natural := 64; CACHE_PARAMS : CACHE_PARAMS_T := CACHE_PARAMS_DEFAULT
ICACHE_NUM_WAYS : natural := 2;
ICACHE_TLB_SIZE : natural := 64;
DCACHE_NUM_LINES : natural := 64;
DCACHE_NUM_WAYS : natural := 2;
DCACHE_TLB_SET_SIZE : natural := 64;
DCACHE_TLB_NUM_WAYS : natural := 2
); );
port ( port (
clk : in std_ulogic; clk : in std_ulogic;
@ -38,8 +32,6 @@ entity core is
wishbone_data_in : in wishbone_slave_out; wishbone_data_in : in wishbone_slave_out;
wishbone_data_out : out wishbone_master_out; wishbone_data_out : out wishbone_master_out;


wb_snoop_in : in wishbone_master_out;

dmi_addr : in std_ulogic_vector(3 downto 0); dmi_addr : in std_ulogic_vector(3 downto 0);
dmi_din : in std_ulogic_vector(63 downto 0); dmi_din : in std_ulogic_vector(63 downto 0);
dmi_dout : out std_ulogic_vector(63 downto 0); dmi_dout : out std_ulogic_vector(63 downto 0);
@ -117,20 +109,21 @@ architecture behave of core is
signal complete: instr_tag_t; signal complete: instr_tag_t;
signal terminate: std_ulogic; signal terminate: std_ulogic;
signal core_rst: std_ulogic; signal core_rst: std_ulogic;
signal icache_inv: std_ulogic;
signal do_interrupt: std_ulogic; signal do_interrupt: std_ulogic;


-- Delayed/Latched resets and alt_reset -- Delayed/Latched resets and alt_reset
signal rst_fetch1 : std_ulogic; signal rst_fetch1 : std_ulogic := '1';
signal rst_fetch2 : std_ulogic; signal rst_fetch2 : std_ulogic := '1';
signal rst_icache : std_ulogic; signal rst_icache : std_ulogic := '1';
signal rst_dcache : std_ulogic; signal rst_dcache : std_ulogic := '1';
signal rst_dec1 : std_ulogic; signal rst_dec1 : std_ulogic := '1';
signal rst_dec2 : std_ulogic; signal rst_dec2 : std_ulogic := '1';
signal rst_ex1 : std_ulogic; signal rst_ex1 : std_ulogic := '1';
signal rst_fpu : std_ulogic; signal rst_fpu : std_ulogic := '1';
signal rst_ls1 : std_ulogic; signal rst_ls1 : std_ulogic := '1';
signal rst_wback : std_ulogic; signal rst_wback : std_ulogic := '1';
signal rst_dbg : std_ulogic; signal rst_dbg : std_ulogic := '1';
signal alt_reset_d : std_ulogic; signal alt_reset_d : std_ulogic;


signal sim_cr_dump: std_ulogic; signal sim_cr_dump: std_ulogic;
@ -147,12 +140,6 @@ architecture behave of core is


signal msr : std_ulogic_vector(63 downto 0); signal msr : std_ulogic_vector(63 downto 0);


-- PMU event bus
signal icache_events : IcacheEventType;
signal loadstore_events : Loadstore1EventType;
signal dcache_events : DcacheEventType;
signal writeback_events : WritebackEventType;

-- Debug status -- Debug status
signal dbg_core_is_stopped: std_ulogic; signal dbg_core_is_stopped: std_ulogic;


@ -231,10 +218,10 @@ begin
icache_0: entity work.icache icache_0: entity work.icache
generic map( generic map(
SIM => SIM, SIM => SIM,
LINE_SIZE => 64, LINE_SIZE => CACHE_PARAMS.LINE_SIZE,
NUM_LINES => ICACHE_NUM_LINES, NUM_LINES => CACHE_PARAMS.ICACHE_NUM_LINES,
NUM_WAYS => ICACHE_NUM_WAYS, NUM_WAYS => CACHE_PARAMS.ICACHE_NUM_WAYS,
TLB_SIZE => ICACHE_TLB_SIZE, TLB_SIZE => CACHE_PARAMS.ICACHE_TLB_SIZE,
LOG_LENGTH => LOG_LENGTH LOG_LENGTH => LOG_LENGTH
) )
port map( port map(
@ -249,8 +236,6 @@ begin
stall_out => icache_stall_out, stall_out => icache_stall_out,
wishbone_out => wishbone_insn_out, wishbone_out => wishbone_insn_out,
wishbone_in => wishbone_insn_in, wishbone_in => wishbone_insn_in,
wb_snoop_in => wb_snoop_in,
events => icache_events,
log_out => log_data(96 downto 43) log_out => log_data(96 downto 43)
); );


@ -340,7 +325,6 @@ begin
generic map ( generic map (
EX1_BYPASS => EX1_BYPASS, EX1_BYPASS => EX1_BYPASS,
HAS_FPU => HAS_FPU, HAS_FPU => HAS_FPU,
HAS_SHORT_MULT => HAS_SHORT_MULT,
LOG_LENGTH => LOG_LENGTH LOG_LENGTH => LOG_LENGTH
) )
port map ( port map (
@ -360,10 +344,6 @@ begin
bypass_cr_data => execute1_cr_bypass, bypass_cr_data => execute1_cr_bypass,
icache_inval => ex1_icache_inval, icache_inval => ex1_icache_inval,
dbg_msr_out => msr, dbg_msr_out => msr,
wb_events => writeback_events,
ls_events => loadstore_events,
dc_events => dcache_events,
ic_events => icache_events,
terminate_out => terminate, terminate_out => terminate,
log_out => log_data(134 downto 120), log_out => log_data(134 downto 120),
log_rd_addr => log_rd_addr, log_rd_addr => log_rd_addr,
@ -405,7 +385,6 @@ begin
m_out => loadstore1_to_mmu, m_out => loadstore1_to_mmu,
m_in => mmu_to_loadstore1, m_in => mmu_to_loadstore1,
dc_stall => dcache_stall_out, dc_stall => dcache_stall_out,
events => loadstore_events,
log_out => log_data(149 downto 140) log_out => log_data(149 downto 140)
); );


@ -422,11 +401,11 @@ begin


dcache_0: entity work.dcache dcache_0: entity work.dcache
generic map( generic map(
LINE_SIZE => 64, LINE_SIZE => CACHE_PARAMS.LINE_SIZE,
NUM_LINES => DCACHE_NUM_LINES, NUM_LINES => CACHE_PARAMS.DCACHE_NUM_LINES,
NUM_WAYS => DCACHE_NUM_WAYS, NUM_WAYS => CACHE_PARAMS.DCACHE_NUM_WAYS,
TLB_SET_SIZE => DCACHE_TLB_SET_SIZE, TLB_SET_SIZE => CACHE_PARAMS.DCACHE_TLB_SET_SIZE,
TLB_NUM_WAYS => DCACHE_TLB_NUM_WAYS, TLB_NUM_WAYS => CACHE_PARAMS.DCACHE_TLB_NUM_WAYS,
LOG_LENGTH => LOG_LENGTH LOG_LENGTH => LOG_LENGTH
) )
port map ( port map (
@ -439,8 +418,6 @@ begin
stall_out => dcache_stall_out, stall_out => dcache_stall_out,
wishbone_in => wishbone_data_in, wishbone_in => wishbone_data_in,
wishbone_out => wishbone_data_out, wishbone_out => wishbone_data_out,
snoop_in => wb_snoop_in,
events => dcache_events,
log_out => log_data(170 downto 151) log_out => log_data(170 downto 151)
); );


@ -455,7 +432,6 @@ begin
w_out => writeback_to_register_file, w_out => writeback_to_register_file,
c_out => writeback_to_cr_file, c_out => writeback_to_cr_file,
f_out => writeback_to_fetch1, f_out => writeback_to_fetch1,
events => writeback_events,
interrupt_out => do_interrupt, interrupt_out => do_interrupt,
complete_out => complete complete_out => complete
); );

@ -12,25 +12,25 @@ entity core_debug is
LOG_LENGTH : natural := 512 LOG_LENGTH : natural := 512
); );
port ( port (
clk : in std_logic; clk : in std_logic;
rst : in std_logic; rst : in std_logic;


dmi_addr : in std_ulogic_vector(3 downto 0); dmi_addr : in std_ulogic_vector(3 downto 0);
dmi_din : in std_ulogic_vector(63 downto 0); dmi_din : in std_ulogic_vector(63 downto 0);
dmi_dout : out std_ulogic_vector(63 downto 0); dmi_dout : out std_ulogic_vector(63 downto 0);
dmi_req : in std_ulogic; dmi_req : in std_ulogic;
dmi_wr : in std_ulogic; dmi_wr : in std_ulogic;
dmi_ack : out std_ulogic; dmi_ack : out std_ulogic;


-- Debug actions -- Debug actions
core_stop : out std_ulogic; core_stop : out std_ulogic;
core_rst : out std_ulogic; core_rst : out std_ulogic;
icache_rst : out std_ulogic; icache_rst : out std_ulogic;


-- Core status inputs -- Core status inputs
terminate : in std_ulogic; terminate : in std_ulogic;
core_stopped : in std_ulogic; core_stopped : in std_ulogic;
nia : in std_ulogic_vector(63 downto 0); nia : in std_ulogic_vector(63 downto 0);
msr : in std_ulogic_vector(63 downto 0); msr : in std_ulogic_vector(63 downto 0);


-- GSPR register read port -- GSPR register read port
@ -45,8 +45,8 @@ entity core_debug is
log_read_data : out std_ulogic_vector(63 downto 0); log_read_data : out std_ulogic_vector(63 downto 0);
log_write_addr : out std_ulogic_vector(31 downto 0); log_write_addr : out std_ulogic_vector(31 downto 0);


-- Misc -- Misc
terminated_out : out std_ulogic terminated_out : out std_ulogic
); );
end core_debug; end core_debug;


@ -60,7 +60,7 @@ architecture behave of core_debug is
-- bit 2 : Icache reset -- bit 2 : Icache reset
-- bit 3 : Single step -- bit 3 : Single step
-- bit 4 : Core start -- bit 4 : Core start
constant DBG_CORE_CTRL : std_ulogic_vector(3 downto 0) := "0000"; constant DBG_CORE_CTRL : std_ulogic_vector(3 downto 0) := "0000";
constant DBG_CORE_CTRL_STOP : integer := 0; constant DBG_CORE_CTRL_STOP : integer := 0;
constant DBG_CORE_CTRL_RESET : integer := 1; constant DBG_CORE_CTRL_RESET : integer := 1;
constant DBG_CORE_CTRL_ICRESET : integer := 2; constant DBG_CORE_CTRL_ICRESET : integer := 2;
@ -71,13 +71,13 @@ architecture behave of core_debug is
-- bit 0 : Core stopping (wait til bit 1 set) -- bit 0 : Core stopping (wait til bit 1 set)
-- bit 1 : Core stopped -- bit 1 : Core stopped
-- bit 2 : Core terminated (clears with start or reset) -- bit 2 : Core terminated (clears with start or reset)
constant DBG_CORE_STAT : std_ulogic_vector(3 downto 0) := "0001"; constant DBG_CORE_STAT : std_ulogic_vector(3 downto 0) := "0001";
constant DBG_CORE_STAT_STOPPING : integer := 0; constant DBG_CORE_STAT_STOPPING : integer := 0;
constant DBG_CORE_STAT_STOPPED : integer := 1; constant DBG_CORE_STAT_STOPPED : integer := 1;
constant DBG_CORE_STAT_TERM : integer := 2; constant DBG_CORE_STAT_TERM : integer := 2;


-- NIA register (read only for now) -- NIA register (read only for now)
constant DBG_CORE_NIA : std_ulogic_vector(3 downto 0) := "0010"; constant DBG_CORE_NIA : std_ulogic_vector(3 downto 0) := "0010";


-- MSR (read only) -- MSR (read only)
constant DBG_CORE_MSR : std_ulogic_vector(3 downto 0) := "0011"; constant DBG_CORE_MSR : std_ulogic_vector(3 downto 0) := "0011";
@ -107,14 +107,14 @@ architecture behave of core_debug is
signal do_gspr_rd : std_ulogic; signal do_gspr_rd : std_ulogic;
signal gspr_index : gspr_index_t; signal gspr_index : gspr_index_t;


signal log_dmi_addr : std_ulogic_vector(31 downto 0) := (others => '0'); signal log_dmi_addr : std_ulogic_vector(31 downto 0) := (others => '0');
signal log_dmi_data : std_ulogic_vector(63 downto 0) := (others => '0'); signal log_dmi_data : std_ulogic_vector(63 downto 0) := (others => '0');
signal log_dmi_trigger : std_ulogic_vector(63 downto 0) := (others => '0'); signal log_dmi_trigger : std_ulogic_vector(63 downto 0) := (others => '0');
signal do_log_trigger : std_ulogic := '0'; signal do_log_trigger : std_ulogic := '0';
signal do_dmi_log_rd : std_ulogic; signal do_dmi_log_rd : std_ulogic;
signal dmi_read_log_data : std_ulogic; signal dmi_read_log_data : std_ulogic;
signal dmi_read_log_data_1 : std_ulogic; signal dmi_read_log_data_1 : std_ulogic;
signal log_trigger_delay : integer range 0 to 255 := 0; signal log_trigger_delay : integer range 0 to 255 := 0;


begin begin
-- Single cycle register accesses on DMI except for GSPR data -- Single cycle register accesses on DMI except for GSPR data
@ -125,37 +125,36 @@ begin


-- Status register read composition -- Status register read composition
stat_reg <= (2 => terminated, stat_reg <= (2 => terminated,
1 => core_stopped, 1 => core_stopped,
0 => stopping, 0 => stopping,
others => '0'); others => '0');


-- DMI read data mux -- DMI read data mux
with dmi_addr select dmi_dout <= with dmi_addr select dmi_dout <=
stat_reg when DBG_CORE_STAT, stat_reg when DBG_CORE_STAT,
nia when DBG_CORE_NIA, nia when DBG_CORE_NIA,
msr when DBG_CORE_MSR, msr when DBG_CORE_MSR,
dbg_gpr_data when DBG_CORE_GSPR_DATA, dbg_gpr_data when DBG_CORE_GSPR_DATA,
log_write_addr & log_dmi_addr when DBG_CORE_LOG_ADDR, log_write_addr & log_dmi_addr when DBG_CORE_LOG_ADDR,
log_dmi_data when DBG_CORE_LOG_DATA, log_dmi_data when DBG_CORE_LOG_DATA,
log_dmi_trigger when DBG_CORE_LOG_TRIGGER, log_dmi_trigger when DBG_CORE_LOG_TRIGGER,
(others => '0') when others; (others => '0') when others;


-- DMI writes -- DMI writes
reg_write: process(clk) reg_write: process(clk)
begin begin
if rising_edge(clk) then if rising_edge(clk) then
-- Reset the 1-cycle "do" signals -- Reset the 1-cycle "do" signals
do_step <= '0'; do_step <= '0';
do_reset <= '0'; do_reset <= '0';
do_icreset <= '0'; do_icreset <= '0';
do_dmi_log_rd <= '0'; do_dmi_log_rd <= '0';


if (rst) then if (rst) then
stopping <= '0'; stopping <= '0';
terminated <= '0'; terminated <= '0';
log_trigger_delay <= 0; log_trigger_delay <= 0;
gspr_index <= (others => '0'); else
else
if do_log_trigger = '1' or log_trigger_delay /= 0 then if do_log_trigger = '1' or log_trigger_delay /= 0 then
if log_trigger_delay = 255 then if log_trigger_delay = 255 then
log_dmi_trigger(1) <= '1'; log_dmi_trigger(1) <= '1';
@ -164,32 +163,32 @@ begin
log_trigger_delay <= log_trigger_delay + 1; log_trigger_delay <= log_trigger_delay + 1;
end if; end if;
end if; end if;
-- Edge detect on dmi_req for 1-shot pulses -- Edge detect on dmi_req for 1-shot pulses
dmi_req_1 <= dmi_req; dmi_req_1 <= dmi_req;
if dmi_req = '1' and dmi_req_1 = '0' then if dmi_req = '1' and dmi_req_1 = '0' then
if dmi_wr = '1' then if dmi_wr = '1' then
report("DMI write to " & to_hstring(dmi_addr)); report("DMI write to " & to_hstring(dmi_addr));


-- Control register actions -- Control register actions
if dmi_addr = DBG_CORE_CTRL then if dmi_addr = DBG_CORE_CTRL then
if dmi_din(DBG_CORE_CTRL_RESET) = '1' then if dmi_din(DBG_CORE_CTRL_RESET) = '1' then
do_reset <= '1'; do_reset <= '1';
terminated <= '0'; terminated <= '0';
end if; end if;
if dmi_din(DBG_CORE_CTRL_STOP) = '1' then if dmi_din(DBG_CORE_CTRL_STOP) = '1' then
stopping <= '1'; stopping <= '1';
end if; end if;
if dmi_din(DBG_CORE_CTRL_STEP) = '1' then if dmi_din(DBG_CORE_CTRL_STEP) = '1' then
do_step <= '1'; do_step <= '1';
terminated <= '0'; terminated <= '0';
end if; end if;
if dmi_din(DBG_CORE_CTRL_ICRESET) = '1' then if dmi_din(DBG_CORE_CTRL_ICRESET) = '1' then
do_icreset <= '1'; do_icreset <= '1';
end if; end if;
if dmi_din(DBG_CORE_CTRL_START) = '1' then if dmi_din(DBG_CORE_CTRL_START) = '1' then
stopping <= '0'; stopping <= '0';
terminated <= '0'; terminated <= '0';
end if; end if;
elsif dmi_addr = DBG_CORE_GSPR_INDEX then elsif dmi_addr = DBG_CORE_GSPR_INDEX then
gspr_index <= dmi_din(gspr_index_t'left downto 0); gspr_index <= dmi_din(gspr_index_t'left downto 0);
elsif dmi_addr = DBG_CORE_LOG_ADDR then elsif dmi_addr = DBG_CORE_LOG_ADDR then
@ -197,17 +196,17 @@ begin
do_dmi_log_rd <= '1'; do_dmi_log_rd <= '1';
elsif dmi_addr = DBG_CORE_LOG_TRIGGER then elsif dmi_addr = DBG_CORE_LOG_TRIGGER then
log_dmi_trigger <= dmi_din; log_dmi_trigger <= dmi_din;
end if; end if;
else else
report("DMI read from " & to_string(dmi_addr)); report("DMI read from " & to_string(dmi_addr));
end if; end if;


elsif dmi_read_log_data = '0' and dmi_read_log_data_1 = '1' then elsif dmi_read_log_data = '0' and dmi_read_log_data_1 = '1' then
-- Increment log_dmi_addr after the end of a read from DBG_CORE_LOG_DATA -- Increment log_dmi_addr after the end of a read from DBG_CORE_LOG_DATA
log_dmi_addr(LOG_INDEX_BITS + 1 downto 0) <= log_dmi_addr(LOG_INDEX_BITS + 1 downto 0) <=
std_ulogic_vector(unsigned(log_dmi_addr(LOG_INDEX_BITS+1 downto 0)) + 1); std_ulogic_vector(unsigned(log_dmi_addr(LOG_INDEX_BITS+1 downto 0)) + 1);
do_dmi_log_rd <= '1'; do_dmi_log_rd <= '1';
end if; end if;
dmi_read_log_data_1 <= dmi_read_log_data; dmi_read_log_data_1 <= dmi_read_log_data;
if dmi_req = '1' and dmi_addr = DBG_CORE_LOG_DATA then if dmi_req = '1' and dmi_addr = DBG_CORE_LOG_DATA then
dmi_read_log_data <= '1'; dmi_read_log_data <= '1';
@ -215,15 +214,15 @@ begin
dmi_read_log_data <= '0'; dmi_read_log_data <= '0';
end if; end if;


-- Set core stop on terminate. We'll be stopping some time *after* -- Set core stop on terminate. We'll be stopping some time *after*
-- the offending instruction, at least until we can do back flushes -- the offending instruction, at least until we can do back flushes
-- that preserve NIA which we can't just yet. -- that preserve NIA which we can't just yet.
if terminate = '1' then if terminate = '1' then
stopping <= '1'; stopping <= '1';
terminated <= '1'; terminated <= '1';
end if; end if;
end if; end if;
end if; end if;
end process; end process;


dbg_gpr_addr <= gspr_index; dbg_gpr_addr <= gspr_index;
@ -238,15 +237,15 @@ begin
maybe_log: if LOG_LENGTH > 0 generate maybe_log: if LOG_LENGTH > 0 generate
subtype log_ptr_t is unsigned(LOG_INDEX_BITS - 1 downto 0); subtype log_ptr_t is unsigned(LOG_INDEX_BITS - 1 downto 0);
type log_array_t is array(0 to LOG_LENGTH - 1) of std_ulogic_vector(255 downto 0); type log_array_t is array(0 to LOG_LENGTH - 1) of std_ulogic_vector(255 downto 0);
signal log_array : log_array_t; signal log_array : log_array_t;
signal log_rd_ptr : log_ptr_t; signal log_rd_ptr : log_ptr_t;
signal log_wr_ptr : log_ptr_t; signal log_wr_ptr : log_ptr_t;
signal log_toggle : std_ulogic; signal log_toggle : std_ulogic;
signal log_wr_enable : std_ulogic; signal log_wr_enable : std_ulogic;
signal log_rd_ptr_latched : log_ptr_t; signal log_rd_ptr_latched : log_ptr_t;
signal log_rd : std_ulogic_vector(255 downto 0); signal log_rd : std_ulogic_vector(255 downto 0);
signal log_dmi_reading : std_ulogic; signal log_dmi_reading : std_ulogic;
signal log_dmi_read_done : std_ulogic; signal log_dmi_read_done : std_ulogic;


function select_dword(data : std_ulogic_vector(255 downto 0); function select_dword(data : std_ulogic_vector(255 downto 0);
addr : std_ulogic_vector(31 downto 0)) return std_ulogic_vector is addr : std_ulogic_vector(31 downto 0)) return std_ulogic_vector is

@ -9,7 +9,7 @@ use work.utils.all;


entity core_dram_tb is entity core_dram_tb is
generic ( generic (
MEMORY_SIZE : natural := (384*1024); MEMORY_SIZE : natural := (384*1024);
MAIN_RAM_FILE : string := "main_ram.bin"; MAIN_RAM_FILE : string := "main_ram.bin";
DRAM_INIT_FILE : string := ""; DRAM_INIT_FILE : string := "";
DRAM_INIT_SIZE : natural := 16#c000# DRAM_INIT_SIZE : natural := 16#c000#
@ -57,25 +57,25 @@ architecture behave of core_dram_tb is
begin begin


soc0: entity work.soc soc0: entity work.soc
generic map( generic map(
SIM => true, SIM => true,
MEMORY_SIZE => MEMORY_SIZE, MEMORY_SIZE => MEMORY_SIZE,
RAM_INIT_FILE => MAIN_RAM_FILE, RAM_INIT_FILE => MAIN_RAM_FILE,
HAS_DRAM => true, HAS_DRAM => true,
DRAM_SIZE => 256 * 1024 * 1024, DRAM_SIZE => 256 * 1024 * 1024,
DRAM_INIT_SIZE => ROM_SIZE, DRAM_INIT_SIZE => ROM_SIZE,
CLK_FREQ => 100000000, CLK_FREQ => 100000000,
HAS_SPI_FLASH => true, HAS_SPI_FLASH => true,
SPI_FLASH_DLINES => 4, SPI_FLASH_DLINES => 4,
SPI_FLASH_OFFSET => 0 SPI_FLASH_OFFSET => 0
) )
port map( port map(
rst => soc_rst, rst => soc_rst,
system_clk => system_clk, system_clk => system_clk,
wb_dram_in => wb_dram_in, wb_dram_in => wb_dram_in,
wb_dram_out => wb_dram_out, wb_dram_out => wb_dram_out,
wb_ext_io_in => wb_ext_io_in, wb_ext_io_in => wb_ext_io_in,
wb_ext_io_out => wb_ext_io_out, wb_ext_io_out => wb_ext_io_out,
wb_ext_is_dram_csr => wb_ext_is_dram_csr, wb_ext_is_dram_csr => wb_ext_is_dram_csr,
wb_ext_is_dram_init => wb_ext_is_dram_init, wb_ext_is_dram_init => wb_ext_is_dram_init,
spi_flash_sck => spi_sck, spi_flash_sck => spi_sck,
@ -83,8 +83,8 @@ begin
spi_flash_sdat_o => spi_sdat_o, spi_flash_sdat_o => spi_sdat_o,
spi_flash_sdat_oe => spi_sdat_oe, spi_flash_sdat_oe => spi_sdat_oe,
spi_flash_sdat_i => spi_sdat_i, spi_flash_sdat_i => spi_sdat_i,
alt_reset => core_alt_reset alt_reset => core_alt_reset
); );


flash: entity work.s25fl128s flash: entity work.s25fl128s
generic map ( generic map (
@ -121,7 +121,6 @@ begin
DRAM_ABITS => 24, DRAM_ABITS => 24,
DRAM_ALINES => 1, DRAM_ALINES => 1,
DRAM_DLINES => 16, DRAM_DLINES => 16,
DRAM_CKLINES => 1,
DRAM_PORT_WIDTH => 128, DRAM_PORT_WIDTH => 128,
PAYLOAD_FILE => DRAM_INIT_FILE, PAYLOAD_FILE => DRAM_INIT_FILE,
PAYLOAD_SIZE => ROM_SIZE PAYLOAD_SIZE => ROM_SIZE
@ -143,18 +142,18 @@ begin


clk_process: process clk_process: process
begin begin
clk <= '0'; clk <= '0';
wait for clk_period/2; wait for clk_period/2;
clk <= '1'; clk <= '1';
wait for clk_period/2; wait for clk_period/2;
end process; end process;


rst_process: process rst_process: process
begin begin
rst <= '1'; rst <= '1';
wait for 10*clk_period; wait for 10*clk_period;
rst <= '0'; rst <= '0';
wait; wait;
end process; end process;


jtag: entity work.sim_jtag; jtag: entity work.sim_jtag;

@ -10,10 +10,10 @@ entity core_flash_tb is
end core_flash_tb; end core_flash_tb;


architecture behave of core_flash_tb is architecture behave of core_flash_tb is
signal clk, rst: std_logic; signal clk, rst: std_logic;


-- testbench signals -- testbench signals
constant clk_period : time := 10 ns; constant clk_period : time := 10 ns;


-- SPI -- SPI
signal spi_sck : std_ulogic; signal spi_sck : std_ulogic;
@ -28,24 +28,24 @@ architecture behave of core_flash_tb is
begin begin


soc0: entity work.soc soc0: entity work.soc
generic map( generic map(
SIM => true, SIM => true,
MEMORY_SIZE => (384*1024), MEMORY_SIZE => (384*1024),
RAM_INIT_FILE => "main_ram.bin", RAM_INIT_FILE => "main_ram.bin",
CLK_FREQ => 100000000, CLK_FREQ => 100000000,
HAS_SPI_FLASH => true, HAS_SPI_FLASH => true,
SPI_FLASH_DLINES => 4, SPI_FLASH_DLINES => 4,
SPI_FLASH_OFFSET => 0 SPI_FLASH_OFFSET => 0
) )
port map( port map(
rst => rst, rst => rst,
system_clk => clk, system_clk => clk,
spi_flash_sck => spi_sck, spi_flash_sck => spi_sck,
spi_flash_cs_n => spi_cs_n, spi_flash_cs_n => spi_cs_n,
spi_flash_sdat_o => spi_sdat_o, spi_flash_sdat_o => spi_sdat_o,
spi_flash_sdat_oe => spi_sdat_oe, spi_flash_sdat_oe => spi_sdat_oe,
spi_flash_sdat_i => spi_sdat_i spi_flash_sdat_i => spi_sdat_i
); );


flash: entity work.s25fl128s flash: entity work.s25fl128s
generic map ( generic map (
@ -78,18 +78,18 @@ begin
clk_process: process clk_process: process
begin begin
clk <= '0'; clk <= '0';
wait for clk_period/2; wait for clk_period/2;
clk <= '1'; clk <= '1';
wait for clk_period/2; wait for clk_period/2;
end process; end process;


rst_process: process rst_process: process
begin begin
rst <= '1'; rst <= '1';
wait for 10*clk_period; wait for 10*clk_period;
rst <= '0'; rst <= '0';
wait; wait;
end process; end process;


jtag: entity work.sim_jtag; jtag: entity work.sim_jtag;

@ -10,38 +10,38 @@ entity core_tb is
end core_tb; end core_tb;


architecture behave of core_tb is architecture behave of core_tb is
signal clk, rst: std_logic; signal clk, rst: std_logic;


-- testbench signals -- testbench signals
constant clk_period : time := 10 ns; constant clk_period : time := 10 ns;
begin begin


soc0: entity work.soc soc0: entity work.soc
generic map( generic map(
SIM => true, SIM => true,
MEMORY_SIZE => (384*1024), MEMORY_SIZE => (384*1024),
RAM_INIT_FILE => "main_ram.bin", RAM_INIT_FILE => "main_ram.bin",
CLK_FREQ => 100000000 CLK_FREQ => 100000000
) )
port map( port map(
rst => rst, rst => rst,
system_clk => clk system_clk => clk
); );


clk_process: process clk_process: process
begin begin
clk <= '0'; clk <= '0';
wait for clk_period/2; wait for clk_period/2;
clk <= '1'; clk <= '1';
wait for clk_period/2; wait for clk_period/2;
end process; end process;


rst_process: process rst_process: process
begin begin
rst <= '1'; rst <= '1';
wait for 10*clk_period; wait for 10*clk_period;
rst <= '0'; rst <= '0';
wait; wait;
end process; end process;


jtag: entity work.sim_jtag; jtag: entity work.sim_jtag;

@ -1,136 +0,0 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

library work;
use work.helpers.all;

entity bit_counter is
port (
clk : in std_logic;
rs : in std_ulogic_vector(63 downto 0);
count_right : in std_ulogic;
do_popcnt : in std_ulogic;
is_32bit : in std_ulogic;
datalen : in std_ulogic_vector(3 downto 0);
result : out std_ulogic_vector(63 downto 0)
);
end entity bit_counter;

architecture behaviour of bit_counter is
-- signals for count-leading/trailing-zeroes
signal inp : std_ulogic_vector(63 downto 0);
signal inp_r : std_ulogic_vector(63 downto 0);
signal sum : std_ulogic_vector(64 downto 0);
signal sum_r : std_ulogic_vector(64 downto 0);
signal onehot : std_ulogic_vector(63 downto 0);
signal edge : std_ulogic_vector(63 downto 0);
signal bitnum : std_ulogic_vector(5 downto 0);
signal cntz : std_ulogic_vector(63 downto 0);

-- signals for popcnt
signal dlen_r : std_ulogic_vector(3 downto 0);
signal pcnt_r : std_ulogic;
subtype twobit is unsigned(1 downto 0);
type twobit32 is array(0 to 31) of twobit;
signal pc2 : twobit32;
subtype threebit is unsigned(2 downto 0);
type threebit16 is array(0 to 15) of threebit;
signal pc4 : threebit16;
subtype fourbit is unsigned(3 downto 0);
type fourbit8 is array(0 to 7) of fourbit;
signal pc8 : fourbit8;
signal pc8_r : fourbit8;
subtype sixbit is unsigned(5 downto 0);
type sixbit2 is array(0 to 1) of sixbit;
signal pc32 : sixbit2;
signal popcnt : std_ulogic_vector(63 downto 0);

begin
countzero_r: process(clk)
begin
if rising_edge(clk) then
inp_r <= inp;
sum_r <= sum;
end if;
end process;

countzero: process(all)
variable bitnum_e, bitnum_o : std_ulogic_vector(5 downto 0);
begin
if is_32bit = '0' then
if count_right = '0' then
inp <= bit_reverse(rs);
else
inp <= rs;
end if;
else
inp(63 downto 32) <= x"FFFFFFFF";
if count_right = '0' then
inp(31 downto 0) <= bit_reverse(rs(31 downto 0));
else
inp(31 downto 0) <= rs(31 downto 0);
end if;
end if;

sum <= std_ulogic_vector(unsigned('0' & not inp) + 1);

-- The following occurs after a clock edge
edge <= sum_r(63 downto 0) or inp_r;
bitnum_e := edgelocation(edge, 6);
onehot <= sum_r(63 downto 0) and inp_r;
bitnum_o := bit_number(onehot);
bitnum(5 downto 2) <= bitnum_e(5 downto 2);
bitnum(1 downto 0) <= bitnum_o(1 downto 0);

cntz <= 57x"0" & sum_r(64) & bitnum;
end process;

popcnt_r: process(clk)
begin
if rising_edge(clk) then
for i in 0 to 7 loop
pc8_r(i) <= pc8(i);
end loop;
dlen_r <= datalen;
pcnt_r <= do_popcnt;
end if;
end process;

popcnt_a: process(all)
begin
for i in 0 to 31 loop
pc2(i) <= unsigned("0" & rs(i * 2 downto i * 2)) + unsigned("0" & rs(i * 2 + 1 downto i * 2 + 1));
end loop;
for i in 0 to 15 loop
pc4(i) <= ('0' & pc2(i * 2)) + ('0' & pc2(i * 2 + 1));
end loop;
for i in 0 to 7 loop
pc8(i) <= ('0' & pc4(i * 2)) + ('0' & pc4(i * 2 + 1));
end loop;

-- after a clock edge
for i in 0 to 1 loop
pc32(i) <= ("00" & pc8_r(i * 4)) + ("00" & pc8_r(i * 4 + 1)) +
("00" & pc8_r(i * 4 + 2)) + ("00" & pc8_r(i * 4 + 3));
end loop;
popcnt <= (others => '0');
if dlen_r(3 downto 2) = "00" then
-- popcntb
for i in 0 to 7 loop
popcnt(i * 8 + 3 downto i * 8) <= std_ulogic_vector(pc8_r(i));
end loop;
elsif dlen_r(3) = '0' then
-- popcntw
for i in 0 to 1 loop
popcnt(i * 32 + 5 downto i * 32) <= std_ulogic_vector(pc32(i));
end loop;
else
popcnt(6 downto 0) <= std_ulogic_vector(('0' & pc32(0)) + ('0' & pc32(1)));
end if;
end process;

result <= cntz when pcnt_r = '0' else popcnt;

end behaviour;

@ -1,118 +0,0 @@
library vunit_lib;
context vunit_lib.vunit_context;

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

library work;
use work.common.all;

library osvvm;
use osvvm.RandomPkg.all;

entity countbits_tb is
generic (runner_cfg : string := runner_cfg_default);
end countbits_tb;

architecture behave of countbits_tb is
constant clk_period: time := 10 ns;
signal rs: std_ulogic_vector(63 downto 0);
signal is_32bit, count_right: std_ulogic := '0';
signal res: std_ulogic_vector(63 downto 0);
signal clk: std_ulogic;

begin
bitcounter_0: entity work.bit_counter
port map (
clk => clk,
rs => rs,
result => res,
count_right => count_right,
is_32bit => is_32bit,
do_popcnt => '0',
datalen => "0000"
);

clk_process: process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;

stim_process: process
variable r: std_ulogic_vector(63 downto 0);
variable rnd : RandomPType;
begin
rnd.InitSeed(stim_process'path_name);

test_runner_setup(runner, runner_cfg);

while test_suite loop
if run("Test with input = 0") then
rs <= (others => '0');
is_32bit <= '0';
count_right <= '0';
wait for clk_period;
check_equal(res, 16#40#, result("for cntlzd"));
count_right <= '1';
wait for clk_period;
check_equal(res, 16#40#, result("for cnttzd"));
is_32bit <= '1';
count_right <= '0';
wait for clk_period;
check_equal(res, 16#20#, result("for cntlzw"));
count_right <= '1';
wait for clk_period;
check_equal(res, 16#20#, result("for cnttzw"));

elsif run("Test cntlzd/w") then
count_right <= '0';
for j in 0 to 100 loop
r := rnd.RandSlv(64);
r(63) := '1';
for i in 0 to 63 loop
rs <= r;
is_32bit <= '0';
wait for clk_period;
check_equal(res, i, result("for cntlzd " & to_hstring(rs)));
rs <= r(31 downto 0) & r(63 downto 32);
is_32bit <= '1';
wait for clk_period;
if i < 32 then
check_equal(res, i, result("for cntlzw " & to_hstring(rs)));
else
check_equal(res, 32, result("for cntlzw " & to_hstring(rs)));
end if;
r := '0' & r(63 downto 1);
end loop;
end loop;

elsif run("Test cnttzd/w") then
count_right <= '1';
for j in 0 to 100 loop
r := rnd.RandSlv(64);
r(0) := '1';
for i in 0 to 63 loop
rs <= r;
is_32bit <= '0';
wait for clk_period;
check_equal(res, i, result("for cnttzd " & to_hstring(rs)));
is_32bit <= '1';
wait for clk_period;
if i < 32 then
check_equal(res, i, result("for cnttzw " & to_hstring(rs)));
else
check_equal(res, 32, result("for cnttzw " & to_hstring(rs)));
end if;
r := r(62 downto 0) & '0';
end loop;
end loop;
end if;
end loop;

test_runner_cleanup(runner);
end process;
end behave;

@ -0,0 +1,60 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

library work;
use work.helpers.all;

entity zero_counter is
port (
clk : in std_logic;
rs : in std_ulogic_vector(63 downto 0);
count_right : in std_ulogic;
is_32bit : in std_ulogic;
result : out std_ulogic_vector(63 downto 0)
);
end entity zero_counter;

architecture behaviour of zero_counter is
signal inp : std_ulogic_vector(63 downto 0);
signal sum : std_ulogic_vector(64 downto 0);
signal msb_r : std_ulogic;
signal onehot : std_ulogic_vector(63 downto 0);
signal onehot_r : std_ulogic_vector(63 downto 0);
signal bitnum : std_ulogic_vector(5 downto 0);

begin
countzero_r: process(clk)
begin
if rising_edge(clk) then
msb_r <= sum(64);
onehot_r <= onehot;
end if;
end process;

countzero: process(all)
begin
if is_32bit = '0' then
if count_right = '0' then
inp <= bit_reverse(rs);
else
inp <= rs;
end if;
else
inp(63 downto 32) <= x"FFFFFFFF";
if count_right = '0' then
inp(31 downto 0) <= bit_reverse(rs(31 downto 0));
else
inp(31 downto 0) <= rs(31 downto 0);
end if;
end if;

sum <= std_ulogic_vector(unsigned('0' & not inp) + 1);
onehot <= sum(63 downto 0) and inp;

-- The following occurs after a clock edge
bitnum <= bit_number(onehot_r);

result <= x"00000000000000" & "0" & msb_r & bitnum;
end process;
end behaviour;

@ -0,0 +1,114 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

library work;
use work.common.all;
use work.glibc_random.all;

entity countzero_tb is
end countzero_tb;

architecture behave of countzero_tb is
constant clk_period: time := 10 ns;
signal rs: std_ulogic_vector(63 downto 0);
signal is_32bit, count_right: std_ulogic := '0';
signal result: std_ulogic_vector(63 downto 0);
signal randno: std_ulogic_vector(63 downto 0);
signal clk: std_ulogic;

begin
zerocounter_0: entity work.zero_counter
port map (
clk => clk,
rs => rs,
result => result,
count_right => count_right,
is_32bit => is_32bit
);

clk_process: process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;

stim_process: process
variable r: std_ulogic_vector(63 downto 0);
begin
-- test with input = 0
report "test zero input";
rs <= (others => '0');
is_32bit <= '0';
count_right <= '0';
wait for clk_period;
assert result = x"0000000000000040"
report "bad cntlzd 0 = " & to_hstring(result);
count_right <= '1';
wait for clk_period;
assert result = x"0000000000000040"
report "bad cnttzd 0 = " & to_hstring(result);
is_32bit <= '1';
count_right <= '0';
wait for clk_period;
assert result = x"0000000000000020"
report "bad cntlzw 0 = " & to_hstring(result);
count_right <= '1';
wait for clk_period;
assert result = x"0000000000000020"
report "bad cnttzw 0 = " & to_hstring(result);

report "test cntlzd/w";
count_right <= '0';
for j in 0 to 100 loop
r := pseudorand(64);
r(63) := '1';
for i in 0 to 63 loop
rs <= r;
is_32bit <= '0';
wait for clk_period;
assert to_integer(unsigned(result)) = i
report "bad cntlzd " & to_hstring(rs) & " -> " & to_hstring(result);
rs <= r(31 downto 0) & r(63 downto 32);
is_32bit <= '1';
wait for clk_period;
if i < 32 then
assert to_integer(unsigned(result)) = i
report "bad cntlzw " & to_hstring(rs) & " -> " & to_hstring(result);
else
assert to_integer(unsigned(result)) = 32
report "bad cntlzw " & to_hstring(rs) & " -> " & to_hstring(result);
end if;
r := '0' & r(63 downto 1);
end loop;
end loop;

report "test cnttzd/w";
count_right <= '1';
for j in 0 to 100 loop
r := pseudorand(64);
r(0) := '1';
for i in 0 to 63 loop
rs <= r;
is_32bit <= '0';
wait for clk_period;
assert to_integer(unsigned(result)) = i
report "bad cnttzd " & to_hstring(rs) & " -> " & to_hstring(result);
is_32bit <= '1';
wait for clk_period;
if i < 32 then
assert to_integer(unsigned(result)) = i
report "bad cnttzw " & to_hstring(rs) & " -> " & to_hstring(result);
else
assert to_integer(unsigned(result)) = 32
report "bad cnttzw " & to_hstring(rs) & " -> " & to_hstring(result);
end if;
r := r(62 downto 0) & '0';
end loop;
end loop;

std.env.finish;
end process;
end behave;

@ -48,11 +48,11 @@ begin


crs_updated <= cr_tmp; crs_updated <= cr_tmp;


if w_in.write_xerc_enable = '1' then if w_in.write_xerc_enable = '1' then
xerc_updated <= w_in.write_xerc_data; xerc_updated <= w_in.write_xerc_data;
else else
xerc_updated <= xerc; xerc_updated <= xerc;
end if; end if;


end process; end process;


@ -62,12 +62,12 @@ begin
if rising_edge(clk) then if rising_edge(clk) then
if w_in.write_cr_enable = '1' then if w_in.write_cr_enable = '1' then
report "Writing " & to_hstring(w_in.write_cr_data) & " to CR mask " & to_hstring(w_in.write_cr_mask); report "Writing " & to_hstring(w_in.write_cr_data) & " to CR mask " & to_hstring(w_in.write_cr_mask);
crs <= crs_updated; crs <= crs_updated;
end if; end if;
if w_in.write_xerc_enable = '1' then if w_in.write_xerc_enable = '1' then
report "Writing XERC"; report "Writing XERC";
xerc <= xerc_updated; xerc <= xerc_updated;
end if; end if;
end if; end if;
end process; end process;


@ -87,7 +87,7 @@ begin
begin begin
if sim_dump = '1' then if sim_dump = '1' then
report "CR 00000000" & to_hstring(crs); report "CR 00000000" & to_hstring(crs);
assert false report "end of test" severity failure; assert false report "end of test" severity failure;
end if; end if;
end process; end process;
end generate; end generate;

@ -39,15 +39,11 @@ entity dcache is
m_in : in MmuToDcacheType; m_in : in MmuToDcacheType;
m_out : out DcacheToMmuType; m_out : out DcacheToMmuType;


snoop_in : in wishbone_master_out := wishbone_master_out_init;

stall_out : out std_ulogic; stall_out : out std_ulogic;


wishbone_out : out wishbone_master_out; wishbone_out : out wishbone_master_out;
wishbone_in : in wishbone_slave_out; wishbone_in : in wishbone_slave_out;


events : out DcacheEventType;

log_out : out std_ulogic_vector(19 downto 0) log_out : out std_ulogic_vector(19 downto 0)
); );
end entity dcache; end entity dcache;
@ -67,6 +63,8 @@ architecture rtl of dcache is


-- Bit fields counts in the address -- Bit fields counts in the address


-- REAL_ADDR_BITS is the number of real address bits that we store
constant REAL_ADDR_BITS : positive := 56;
-- ROW_BITS is the number of bits to select a row -- ROW_BITS is the number of bits to select a row
constant ROW_BITS : natural := log2(BRAM_ROWS); constant ROW_BITS : natural := log2(BRAM_ROWS);
-- ROW_LINEBITS is the number of bits to select a row within a line -- ROW_LINEBITS is the number of bits to select a row within a line
@ -120,7 +118,7 @@ architecture rtl of dcache is
type cache_valids_t is array(index_t) of cache_way_valids_t; type cache_valids_t is array(index_t) of cache_way_valids_t;
type row_per_line_valid_t is array(0 to ROW_PER_LINE - 1) of std_ulogic; type row_per_line_valid_t is array(0 to ROW_PER_LINE - 1) of std_ulogic;


-- Storage. Hopefully implemented in LUTs -- Storage. Hopefully "cache_rows" is a BRAM, the rest is LUTs
signal cache_tags : cache_tags_array_t; signal cache_tags : cache_tags_array_t;
signal cache_tag_set : cache_tags_set_t; signal cache_tag_set : cache_tags_set_t;
signal cache_valids : cache_valids_t; signal cache_valids : cache_valids_t;
@ -287,7 +285,7 @@ architecture rtl of dcache is
op : op_t; op : op_t;
valid : std_ulogic; valid : std_ulogic;
dcbz : std_ulogic; dcbz : std_ulogic;
real_addr : real_addr_t; real_addr : std_ulogic_vector(REAL_ADDR_BITS - 1 downto 0);
data : std_ulogic_vector(63 downto 0); data : std_ulogic_vector(63 downto 0);
byte_sel : std_ulogic_vector(7 downto 0); byte_sel : std_ulogic_vector(7 downto 0);
hit_way : way_t; hit_way : way_t;
@ -315,13 +313,15 @@ architecture rtl of dcache is
tlb_hit_way : tlb_way_t; tlb_hit_way : tlb_way_t;
tlb_hit_index : tlb_index_t; tlb_hit_index : tlb_index_t;


-- data buffer for data forwarded from writes to reads -- 2-stage data buffer for data forwarded from writes to reads
forward_data : std_ulogic_vector(63 downto 0); forward_data1 : std_ulogic_vector(63 downto 0);
forward_tag : cache_tag_t; forward_data2 : std_ulogic_vector(63 downto 0);
forward_sel1 : std_ulogic_vector(7 downto 0);
forward_valid1 : std_ulogic;
forward_way1 : way_t;
forward_row1 : row_t;
use_forward1 : std_ulogic;
forward_sel : std_ulogic_vector(7 downto 0); forward_sel : std_ulogic_vector(7 downto 0);
forward_valid : std_ulogic;
forward_row : row_t;
data_out : std_ulogic_vector(63 downto 0);


-- Cache miss state (reload state machine) -- Cache miss state (reload state machine)
state : state_t; state : state_t;
@ -353,8 +353,6 @@ architecture rtl of dcache is


signal r1 : reg_stage_1_t; signal r1 : reg_stage_1_t;


signal ev : DcacheEventType;

-- Reservation information -- Reservation information
-- --
type reservation_t is record type reservation_t is record
@ -383,16 +381,12 @@ architecture rtl of dcache is
signal r0_valid : std_ulogic; signal r0_valid : std_ulogic;
signal r0_stall : std_ulogic; signal r0_stall : std_ulogic;


signal fwd_same_tag : std_ulogic; signal use_forward1_next : std_ulogic;
signal use_forward_st : std_ulogic; signal use_forward2_next : std_ulogic;
signal use_forward_rl : std_ulogic;
signal use_forward2 : std_ulogic;


-- Cache RAM interface -- Cache RAM interface
type cache_ram_out_t is array(way_t) of cache_row_t; type cache_ram_out_t is array(way_t) of cache_row_t;
signal cache_out : cache_ram_out_t; signal cache_out : cache_ram_out_t;
signal ram_wr_data : cache_row_t;
signal ram_wr_select : std_ulogic_vector(ROW_SIZE - 1 downto 0);


-- PLRU output interface -- PLRU output interface
type plru_out_t is array(index_t) of std_ulogic_vector(WAY_BITS-1 downto 0); type plru_out_t is array(index_t) of std_ulogic_vector(WAY_BITS-1 downto 0);
@ -410,23 +404,17 @@ architecture rtl of dcache is
signal tlb_hit : std_ulogic; signal tlb_hit : std_ulogic;
signal tlb_hit_way : tlb_way_t; signal tlb_hit_way : tlb_way_t;
signal pte : tlb_pte_t; signal pte : tlb_pte_t;
signal ra : real_addr_t; signal ra : std_ulogic_vector(REAL_ADDR_BITS - 1 downto 0);
signal valid_ra : std_ulogic; signal valid_ra : std_ulogic;
signal perm_attr : perm_attr_t; signal perm_attr : perm_attr_t;
signal rc_ok : std_ulogic; signal rc_ok : std_ulogic;
signal perm_ok : std_ulogic; signal perm_ok : std_ulogic;
signal access_ok : std_ulogic; signal access_ok : std_ulogic;
signal tlb_miss : std_ulogic;


-- TLB PLRU output interface -- TLB PLRU output interface
type tlb_plru_out_t is array(tlb_index_t) of std_ulogic_vector(TLB_WAY_BITS-1 downto 0); type tlb_plru_out_t is array(tlb_index_t) of std_ulogic_vector(TLB_WAY_BITS-1 downto 0);
signal tlb_plru_victim : tlb_plru_out_t; signal tlb_plru_victim : tlb_plru_out_t;


signal snoop_tag_set : cache_tags_set_t;
signal snoop_valid : std_ulogic;
signal snoop_wrtag : cache_tag_t;
signal snoop_index : index_t;

-- --
-- Helper functions to decode incoming requests -- Helper functions to decode incoming requests
-- --
@ -452,9 +440,9 @@ architecture rtl of dcache is
end; end;


-- Returns whether this is the last row of a line -- Returns whether this is the last row of a line
function is_last_row_wb_addr(addr: wishbone_addr_type; last: row_in_line_t) return boolean is function is_last_row_addr(addr: wishbone_addr_type; last: row_in_line_t) return boolean is
begin begin
return unsigned(addr(LINE_OFF_BITS - ROW_OFF_BITS - 1 downto 0)) = last; return unsigned(addr(LINE_OFF_BITS-1 downto ROW_OFF_BITS)) = last;
end; end;


-- Returns whether this is the last row of a line -- Returns whether this is the last row of a line
@ -464,15 +452,15 @@ architecture rtl of dcache is
end; end;


-- Return the address of the next row in the current cache line -- Return the address of the next row in the current cache line
function next_row_wb_addr(addr: wishbone_addr_type) return std_ulogic_vector is function next_row_addr(addr: wishbone_addr_type) return std_ulogic_vector is
variable row_idx : std_ulogic_vector(ROW_LINEBITS-1 downto 0); variable row_idx : std_ulogic_vector(ROW_LINEBITS-1 downto 0);
variable result : wishbone_addr_type; variable result : wishbone_addr_type;
begin begin
-- Is there no simpler way in VHDL to generate that 3 bits adder ? -- Is there no simpler way in VHDL to generate that 3 bits adder ?
row_idx := addr(ROW_LINEBITS - 1 downto 0); row_idx := addr(LINE_OFF_BITS-1 downto ROW_OFF_BITS);
row_idx := std_ulogic_vector(unsigned(row_idx) + 1); row_idx := std_ulogic_vector(unsigned(row_idx) + 1);
result := addr; result := addr;
result(ROW_LINEBITS - 1 downto 0) := row_idx; result(LINE_OFF_BITS-1 downto ROW_OFF_BITS) := row_idx;
return result; return result;
end; end;


@ -540,8 +528,7 @@ begin
assert LINE_SIZE mod ROW_SIZE = 0 report "LINE_SIZE not multiple of ROW_SIZE" severity FAILURE; assert LINE_SIZE mod ROW_SIZE = 0 report "LINE_SIZE not multiple of ROW_SIZE" severity FAILURE;
assert ispow2(LINE_SIZE) report "LINE_SIZE not power of 2" severity FAILURE; assert ispow2(LINE_SIZE) report "LINE_SIZE not power of 2" severity FAILURE;
assert ispow2(NUM_LINES) report "NUM_LINES not power of 2" severity FAILURE; assert ispow2(NUM_LINES) report "NUM_LINES not power of 2" severity FAILURE;
assert ispow2(ROW_PER_LINE) and ROW_PER_LINE > 1 assert ispow2(ROW_PER_LINE) report "ROW_PER_LINE not power of 2" severity FAILURE;
report "ROW_PER_LINE not power of 2 greater than 1" severity FAILURE;
assert (ROW_BITS = INDEX_BITS + ROW_LINEBITS) assert (ROW_BITS = INDEX_BITS + ROW_LINEBITS)
report "geometry bits don't add up" severity FAILURE; report "geometry bits don't add up" severity FAILURE;
assert (LINE_OFF_BITS = ROW_OFF_BITS + ROW_LINEBITS) assert (LINE_OFF_BITS = ROW_OFF_BITS + ROW_LINEBITS)
@ -576,7 +563,6 @@ begin
r.doall := m_in.doall; r.doall := m_in.doall;
r.tlbld := m_in.tlbld; r.tlbld := m_in.tlbld;
r.mmu_req := '1'; r.mmu_req := '1';
r.d_valid := '1';
else else
r.req := d_in; r.req := d_in;
r.req.data := (others => '0'); r.req.data := (others => '0');
@ -584,19 +570,21 @@ begin
r.doall := '0'; r.doall := '0';
r.tlbld := '0'; r.tlbld := '0';
r.mmu_req := '0'; r.mmu_req := '0';
r.d_valid := '0';
end if; end if;
r.d_valid := '0';
if rst = '1' then if rst = '1' then
r0_full <= '0'; r0_full <= '0';
elsif (r1.full = '0' and d_in.hold = '0') or r0_full = '0' then elsif (r1.full = '0' and d_in.hold = '0') or r0_full = '0' then
r0 <= r; r0 <= r;
r0_full <= r.req.valid; r0_full <= r.req.valid;
elsif r0.d_valid = '0' then end if;
-- Sample data the cycle after a request comes in from loadstore1. -- Sample data the cycle after a request comes in from loadstore1.
-- If this request is already moving into r1 then the data will get -- If another request has come in already then the data will get
-- put directly into req.data in the dcache_slow process below. -- put directly into req.data below.
if r0.req.valid = '1' and r.req.valid = '0' and r0.d_valid = '0' and
r0.mmu_req = '0' then
r0.req.data <= d_in.data; r0.req.data <= d_in.data;
r0.d_valid <= r0.req.valid; r0.d_valid <= '1';
end if; end if;
end if; end if;
end process; end process;
@ -609,8 +597,6 @@ begin
r0_valid <= r0_full and not r1.full and not d_in.hold; r0_valid <= r0_full and not r1.full and not d_in.hold;
stall_out <= r0_stall; stall_out <= r0_stall;


events <= ev;

-- TLB -- TLB
-- Operates in the second cycle on the request latched in r0.req. -- Operates in the second cycle on the request latched in r0.req.
-- TLB updates write the entry at the end of the second cycle. -- TLB updates write the entry at the end of the second cycle.
@ -695,7 +681,6 @@ begin
pte <= (others => '0'); pte <= (others => '0');
end if; end if;
valid_ra <= tlb_hit or not r0.req.virt_mode; valid_ra <= tlb_hit or not r0.req.virt_mode;
tlb_miss <= r0_valid and r0.req.virt_mode and not tlb_hit;
if r0.req.virt_mode = '1' then if r0.req.virt_mode = '1' then
ra <= pte(REAL_ADDR_BITS - 1 downto TLB_LG_PGSZ) & ra <= pte(REAL_ADDR_BITS - 1 downto TLB_LG_PGSZ) &
r0.req.addr(TLB_LG_PGSZ - 1 downto ROW_OFF_BITS) & r0.req.addr(TLB_LG_PGSZ - 1 downto ROW_OFF_BITS) &
@ -719,7 +704,6 @@ begin
if rising_edge(clk) then if rising_edge(clk) then
tlbie := r0_valid and r0.tlbie; tlbie := r0_valid and r0.tlbie;
tlbwe := r0_valid and r0.tlbld; tlbwe := r0_valid and r0.tlbld;
ev.dtlb_miss_resolved <= tlbwe;
if rst = '1' or (tlbie = '1' and r0.doall = '1') then if rst = '1' or (tlbie = '1' and r0.doall = '1') then
-- clear all valid bits at once -- clear all valid bits at once
for i in tlb_index_t loop for i in tlb_index_t loop
@ -799,23 +783,6 @@ begin
end if; end if;
end process; end process;


-- Cache tag RAM second read port, for snooping
cache_tag_read_2 : process(clk)
variable addr : real_addr_t;
begin
if rising_edge(clk) then
addr := addr_to_real(wb_to_addr(snoop_in.adr));
snoop_tag_set <= cache_tags(get_index(addr));
snoop_wrtag <= get_tag(addr);
snoop_index <= get_index(addr);
-- Don't snoop our own cycles
snoop_valid <= '0';
if not (r1.wb.cyc = '1' and wishbone_in.stall = '0') then
snoop_valid <= snoop_in.cyc and snoop_in.stb and snoop_in.we;
end if;
end if;
end process;

-- Cache request parsing and hit detection -- Cache request parsing and hit detection
dcache_request : process(all) dcache_request : process(all)
variable is_hit : std_ulogic; variable is_hit : std_ulogic;
@ -827,13 +794,11 @@ begin
variable s_hit : std_ulogic; variable s_hit : std_ulogic;
variable s_tag : cache_tag_t; variable s_tag : cache_tag_t;
variable s_pte : tlb_pte_t; variable s_pte : tlb_pte_t;
variable s_ra : real_addr_t; variable s_ra : std_ulogic_vector(REAL_ADDR_BITS - 1 downto 0);
variable hit_set : std_ulogic_vector(TLB_NUM_WAYS - 1 downto 0); variable hit_set : std_ulogic_vector(TLB_NUM_WAYS - 1 downto 0);
variable hit_way_set : hit_way_set_t; variable hit_way_set : hit_way_set_t;
variable rel_matches : std_ulogic_vector(TLB_NUM_WAYS - 1 downto 0); variable rel_matches : std_ulogic_vector(TLB_NUM_WAYS - 1 downto 0);
variable rel_match : std_ulogic; variable rel_match : std_ulogic;
variable fwd_matches : std_ulogic_vector(TLB_NUM_WAYS - 1 downto 0);
variable fwd_match : std_ulogic;
begin begin
-- Extract line, row and tag from request -- Extract line, row and tag from request
req_index <= get_index(r0.req.addr); req_index <= get_index(r0.req.addr);
@ -849,10 +814,8 @@ begin
hit_way := 0; hit_way := 0;
is_hit := '0'; is_hit := '0';
rel_match := '0'; rel_match := '0';
fwd_match := '0';
if r0.req.virt_mode = '1' then if r0.req.virt_mode = '1' then
rel_matches := (others => '0'); rel_matches := (others => '0');
fwd_matches := (others => '0');
for j in tlb_way_t loop for j in tlb_way_t loop
hit_way_set(j) := 0; hit_way_set(j) := 0;
s_hit := '0'; s_hit := '0';
@ -872,15 +835,11 @@ begin
if s_tag = r1.reload_tag then if s_tag = r1.reload_tag then
rel_matches(j) := '1'; rel_matches(j) := '1';
end if; end if;
if s_tag = r1.forward_tag then
fwd_matches(j) := '1';
end if;
end loop; end loop;
if tlb_hit = '1' then if tlb_hit = '1' then
is_hit := hit_set(tlb_hit_way); is_hit := hit_set(tlb_hit_way);
hit_way := hit_way_set(tlb_hit_way); hit_way := hit_way_set(tlb_hit_way);
rel_match := rel_matches(tlb_hit_way); rel_match := rel_matches(tlb_hit_way);
fwd_match := fwd_matches(tlb_hit_way);
end if; end if;
else else
s_tag := get_tag(r0.req.addr); s_tag := get_tag(r0.req.addr);
@ -894,52 +853,46 @@ begin
if s_tag = r1.reload_tag then if s_tag = r1.reload_tag then
rel_match := '1'; rel_match := '1';
end if; end if;
if s_tag = r1.forward_tag then
fwd_match := '1';
end if;
end if; end if;
req_same_tag <= rel_match; req_same_tag <= rel_match;
fwd_same_tag <= fwd_match;

-- Whether to use forwarded data for a load or not
use_forward_st <= '0';
use_forward_rl <= '0';
if r1.store_row = req_row and rel_match = '1' then
-- Use the forwarding path if this cycle is a write to this row
use_forward_st <= r1.write_bram;
if r1.state = RELOAD_WAIT_ACK and wishbone_in.ack = '1' then
use_forward_rl <= '1';
end if;
end if;
use_forward2 <= '0';
if r1.forward_row = req_row and fwd_match = '1' then
use_forward2 <= r1.forward_valid;
end if;

-- The way to replace on a miss
if r1.write_tag = '1' then
replace_way <= to_integer(unsigned(plru_victim(r1.store_index)));
else
replace_way <= r1.store_way;
end if;


-- See if the request matches the line currently being reloaded -- See if the request matches the line currently being reloaded
if r1.state = RELOAD_WAIT_ACK and req_index = r1.store_index and if r1.state = RELOAD_WAIT_ACK and req_index = r1.store_index and
rel_match = '1' then rel_match = '1' then
-- Ignore is_hit from above, because a load miss writes the new tag
-- but doesn't clear the valid bit on the line before refilling it.
-- For a store, consider this a hit even if the row isn't valid -- For a store, consider this a hit even if the row isn't valid
-- since it will be by the time we perform the store. -- since it will be by the time we perform the store.
-- For a load, check the appropriate row valid bit; but also, -- For a load, check the appropriate row valid bit.
-- if use_forward_rl is 1 then we can consider this a hit. is_hit := not r0.req.load or r1.rows_valid(req_row mod ROW_PER_LINE);
is_hit := not r0.req.load or r1.rows_valid(req_row mod ROW_PER_LINE) or
use_forward_rl;
hit_way := replace_way; hit_way := replace_way;
end if; end if;


-- Whether to use forwarded data for a load or not
use_forward1_next <= '0';
if get_row(r1.req.real_addr) = req_row and r1.req.hit_way = hit_way then
-- Only need to consider r1.write_bram here, since if we are
-- writing refill data here, then we don't have a cache hit this
-- cycle on the line being refilled. (There is the possibility
-- that the load following the load miss that started the refill
-- could be to the old contents of the victim line, since it is a
-- couple of cycles after the refill starts before we see the
-- updated cache tag. In that case we don't use the bypass.)
use_forward1_next <= r1.write_bram;
end if;
use_forward2_next <= '0';
if r1.forward_row1 = req_row and r1.forward_way1 = hit_way then
use_forward2_next <= r1.forward_valid1;
end if;

-- The way that matched on a hit -- The way that matched on a hit
req_hit_way <= hit_way; req_hit_way <= hit_way;


-- The way to replace on a miss
if r1.write_tag = '1' then
replace_way <= to_integer(unsigned(plru_victim(r1.store_index)));
else
replace_way <= r1.store_way;
end if;

-- work out whether we have permission for this access -- work out whether we have permission for this access
-- NB we don't yet implement AMR, thus no KUAP -- NB we don't yet implement AMR, thus no KUAP
rc_ok <= perm_attr.reference and (r0.req.load or perm_attr.changed); rc_ok <= perm_attr.reference and (r0.req.load or perm_attr.changed);
@ -1035,9 +988,28 @@ begin
-- Return data for loads & completion control logic -- Return data for loads & completion control logic
-- --
writeback_control: process(all) writeback_control: process(all)
variable data_out : std_ulogic_vector(63 downto 0);
variable data_fwd : std_ulogic_vector(63 downto 0);
variable j : integer;
begin begin
-- Use the bypass if are reading the row that was written 1 or 2 cycles
-- ago, including for the slow_valid = 1 case (i.e. completing a load
-- miss or a non-cacheable load).
if r1.use_forward1 = '1' then
data_fwd := r1.forward_data1;
else
data_fwd := r1.forward_data2;
end if;
data_out := cache_out(r1.hit_way);
for i in 0 to 7 loop
j := i * 8;
if r1.forward_sel(i) = '1' then
data_out(j + 7 downto j) := data_fwd(j + 7 downto j);
end if;
end loop;

d_out.valid <= r1.ls_valid; d_out.valid <= r1.ls_valid;
d_out.data <= r1.data_out; d_out.data <= data_out;
d_out.store_done <= not r1.stcx_fail; d_out.store_done <= not r1.stcx_fail;
d_out.error <= r1.ls_error; d_out.error <= r1.ls_error;
d_out.cache_paradox <= r1.cache_paradox; d_out.cache_paradox <= r1.cache_paradox;
@ -1045,7 +1017,7 @@ begin
-- Outputs to MMU -- Outputs to MMU
m_out.done <= r1.mmu_done; m_out.done <= r1.mmu_done;
m_out.err <= r1.mmu_error; m_out.err <= r1.mmu_error;
m_out.data <= r1.data_out; m_out.data <= data_out;


-- We have a valid load or store hit or we just completed a slow -- We have a valid load or store hit or we just completed a slow
-- op such as a load miss, a NC load or a store -- op such as a load miss, a NC load or a store
@ -1069,7 +1041,7 @@ begin
-- Request came from loadstore1... -- Request came from loadstore1...
-- Load hit case is the standard path -- Load hit case is the standard path
if r1.hit_load_valid = '1' then if r1.hit_load_valid = '1' then
report "completing load hit data=" & to_hstring(r1.data_out); report "completing load hit data=" & to_hstring(data_out);
end if; end if;


-- error cases complete without stalling -- error cases complete without stalling
@ -1079,7 +1051,7 @@ begin


-- Slow ops (load miss, NC, stores) -- Slow ops (load miss, NC, stores)
if r1.slow_valid = '1' then if r1.slow_valid = '1' then
report "completing store or load miss data=" & to_hstring(r1.data_out); report "completing store or load miss data=" & to_hstring(data_out);
end if; end if;


else else
@ -1101,13 +1073,6 @@ begin


end process; end process;


-- RAM write data and select multiplexers
ram_wr_data <= r1.req.data when r1.write_bram = '1' else
wishbone_in.dat when r1.dcbz = '0' else
(others => '0');
ram_wr_select <= r1.req.byte_sel when r1.write_bram = '1' else
(others => '1');

-- --
-- Generate a cache RAM for each way. This handles the normal -- Generate a cache RAM for each way. This handles the normal
-- reads, writes from reloads and the special store-hit update -- reads, writes from reloads and the special store-hit update
@ -1121,6 +1086,7 @@ begin
rams: for i in 0 to NUM_WAYS-1 generate rams: for i in 0 to NUM_WAYS-1 generate
signal do_read : std_ulogic; signal do_read : std_ulogic;
signal rd_addr : std_ulogic_vector(ROW_BITS-1 downto 0); signal rd_addr : std_ulogic_vector(ROW_BITS-1 downto 0);
signal do_write : std_ulogic;
signal wr_addr : std_ulogic_vector(ROW_BITS-1 downto 0); signal wr_addr : std_ulogic_vector(ROW_BITS-1 downto 0);
signal wr_data : std_ulogic_vector(wishbone_data_bits-1 downto 0); signal wr_data : std_ulogic_vector(wishbone_data_bits-1 downto 0);
signal wr_sel : std_ulogic_vector(ROW_SIZE-1 downto 0); signal wr_sel : std_ulogic_vector(ROW_SIZE-1 downto 0);
@ -1131,7 +1097,7 @@ begin
generic map ( generic map (
ROW_BITS => ROW_BITS, ROW_BITS => ROW_BITS,
WIDTH => wishbone_data_bits, WIDTH => wishbone_data_bits,
ADD_BUF => false ADD_BUF => true
) )
port map ( port map (
clk => clk, clk => clk,
@ -1140,7 +1106,7 @@ begin
rd_data => dout, rd_data => dout,
wr_sel => wr_sel_m, wr_sel => wr_sel_m,
wr_addr => wr_addr, wr_addr => wr_addr,
wr_data => ram_wr_data wr_data => wr_data
); );
process(all) process(all)
begin begin
@ -1156,13 +1122,37 @@ begin
-- For timing, the mux on wr_data/sel/addr is not dependent on anything -- For timing, the mux on wr_data/sel/addr is not dependent on anything
-- other than the current state. -- other than the current state.
-- --
wr_addr <= std_ulogic_vector(to_unsigned(r1.store_row, ROW_BITS));

wr_sel_m <= (others => '0'); wr_sel_m <= (others => '0');
if i = replace_way and
(r1.write_bram = '1' or do_write <= '0';
(r1.state = RELOAD_WAIT_ACK and wishbone_in.ack = '1')) then if r1.write_bram = '1' then
wr_sel_m <= ram_wr_select; -- Write store data to BRAM. This happens one cycle after the
-- store is in r0.
wr_data <= r1.req.data;
wr_sel <= r1.req.byte_sel;
wr_addr <= std_ulogic_vector(to_unsigned(get_row(r1.req.real_addr), ROW_BITS));
if i = r1.req.hit_way then
do_write <= '1';
end if;
else
-- Otherwise, we might be doing a reload or a DCBZ
if r1.dcbz = '1' then
wr_data <= (others => '0');
else
wr_data <= wishbone_in.dat;
end if;
wr_addr <= std_ulogic_vector(to_unsigned(r1.store_row, ROW_BITS));
wr_sel <= (others => '1');

if r1.state = RELOAD_WAIT_ACK and wishbone_in.ack = '1' and replace_way = i then
do_write <= '1';
end if;
end if;

-- Mask write selects with do_write since BRAM doesn't
-- have a global write-enable
if do_write = '1' then
wr_sel_m <= wr_sel;
end if; end if;


end process; end process;
@ -1173,60 +1163,20 @@ begin
-- It also handles error cases (TLB miss, cache paradox) -- It also handles error cases (TLB miss, cache paradox)
-- --
dcache_fast_hit : process(clk) dcache_fast_hit : process(clk)
variable j : integer;
variable sel : std_ulogic_vector(1 downto 0);
variable data_out : std_ulogic_vector(63 downto 0);
begin begin
if rising_edge(clk) then if rising_edge(clk) then
if req_op /= OP_NONE then if req_op /= OP_NONE then
report "op:" & op_t'image(req_op) & report "op:" & op_t'image(req_op) &
" addr:" & to_hstring(r0.req.addr) & " addr:" & to_hstring(r0.req.addr) &
" nc:" & std_ulogic'image(r0.req.nc) & " nc:" & std_ulogic'image(r0.req.nc) &
" idx:" & integer'image(req_index) & " idx:" & integer'image(req_index) &
" tag:" & to_hstring(req_tag) & " tag:" & to_hstring(req_tag) &
" way: " & integer'image(req_hit_way); " way: " & integer'image(req_hit_way);
end if; end if;
if r0_valid = '1' then if r0_valid = '1' then
r1.mmu_req <= r0.mmu_req; r1.mmu_req <= r0.mmu_req;
end if; end if;


-- Bypass/forwarding multiplexer for load data.
-- Use the bypass if are reading the row of BRAM that was written 0 or 1
-- cycles ago, including for the slow_valid = 1 cases (i.e. completing a
-- load miss or a non-cacheable load), which are handled via the r1.full case.
for i in 0 to 7 loop
if r1.full = '1' or use_forward_rl = '1' then
sel := '0' & r1.dcbz;
elsif use_forward_st = '1' and r1.req.byte_sel(i) = '1' then
sel := "01";
elsif use_forward2 = '1' and r1.forward_sel(i) = '1' then
sel := "10";
else
sel := "11";
end if;
j := i * 8;
case sel is
when "00" =>
data_out(j + 7 downto j) := wishbone_in.dat(j + 7 downto j);
when "01" =>
data_out(j + 7 downto j) := r1.req.data(j + 7 downto j);
when "10" =>
data_out(j + 7 downto j) := r1.forward_data(j + 7 downto j);
when others =>
data_out(j + 7 downto j) := cache_out(req_hit_way)(j + 7 downto j);
end case;
end loop;
r1.data_out <= data_out;

r1.forward_data <= ram_wr_data;
r1.forward_tag <= r1.reload_tag;
r1.forward_row <= r1.store_row;
r1.forward_sel <= ram_wr_select;
r1.forward_valid <= r1.write_bram;
if r1.state = RELOAD_WAIT_ACK and wishbone_in.ack = '1' then
r1.forward_valid <= '1';
end if;

-- Fast path for load/store hits. Set signals for the writeback controls. -- Fast path for load/store hits. Set signals for the writeback controls.
r1.hit_way <= req_hit_way; r1.hit_way <= req_hit_way;
r1.hit_index <= req_index; r1.hit_index <= req_index;
@ -1278,15 +1228,37 @@ begin
-- operates at stage 1. -- operates at stage 1.
-- --
dcache_slow : process(clk) dcache_slow : process(clk)
variable stbs_done : boolean; variable stbs_done : boolean;
variable req : mem_access_request_t; variable req : mem_access_request_t;
variable acks : unsigned(2 downto 0); variable acks : unsigned(2 downto 0);
begin begin
if rising_edge(clk) then if rising_edge(clk) then
ev.dcache_refill <= '0'; r1.use_forward1 <= use_forward1_next;
ev.load_miss <= '0'; r1.forward_sel <= (others => '0');
ev.store_miss <= '0'; if use_forward1_next = '1' then
ev.dtlb_miss <= tlb_miss; r1.forward_sel <= r1.req.byte_sel;
elsif use_forward2_next = '1' then
r1.forward_sel <= r1.forward_sel1;
end if;

r1.forward_data2 <= r1.forward_data1;
if r1.write_bram = '1' then
r1.forward_data1 <= r1.req.data;
r1.forward_sel1 <= r1.req.byte_sel;
r1.forward_way1 <= r1.req.hit_way;
r1.forward_row1 <= get_row(r1.req.real_addr);
r1.forward_valid1 <= '1';
else
if r1.dcbz = '1' then
r1.forward_data1 <= (others => '0');
else
r1.forward_data1 <= wishbone_in.dat;
end if;
r1.forward_sel1 <= (others => '1');
r1.forward_way1 <= replace_way;
r1.forward_row1 <= r1.store_row;
r1.forward_valid1 <= '0';
end if;


-- On reset, clear all valid bits to force misses -- On reset, clear all valid bits to force misses
if rst = '1' then if rst = '1' then
@ -1321,13 +1293,6 @@ begin
end if; end if;
end if; end if;


-- Do invalidations from snooped stores to memory
for i in way_t loop
if snoop_valid = '1' and read_tag(i, snoop_tag_set) = snoop_wrtag then
cache_valids(snoop_index)(i) <= '0';
end if;
end loop;

if r1.write_tag = '1' then if r1.write_tag = '1' then
-- Store new tag in selected way -- Store new tag in selected way
for i in 0 to NUM_WAYS-1 loop for i in 0 to NUM_WAYS-1 loop
@ -1359,7 +1324,7 @@ begin
req.data := d_in.data; req.data := d_in.data;
end if; end if;
-- Select all bytes for dcbz and for cacheable loads -- Select all bytes for dcbz and for cacheable loads
if r0.req.dcbz = '1' or (r0.req.load = '1' and r0.req.nc = '0' and perm_attr.nocache = '0') then if r0.req.dcbz = '1' or (r0.req.load = '1' and r0.req.nc = '0') then
req.byte_sel := (others => '1'); req.byte_sel := (others => '1');
else else
req.byte_sel := r0.req.byte_sel; req.byte_sel := r0.req.byte_sel;
@ -1379,7 +1344,7 @@ begin
-- Main state machine -- Main state machine
case r1.state is case r1.state is
when IDLE => when IDLE =>
r1.wb.adr <= addr_to_wb(req.real_addr); r1.wb.adr <= req.real_addr(r1.wb.adr'left downto 0);
r1.wb.sel <= req.byte_sel; r1.wb.sel <= req.byte_sel;
r1.wb.dat <= req.data; r1.wb.dat <= req.data;
r1.dcbz <= req.dcbz; r1.dcbz <= req.dcbz;
@ -1419,7 +1384,6 @@ begin
-- Track that we had one request sent -- Track that we had one request sent
r1.state <= RELOAD_WAIT_ACK; r1.state <= RELOAD_WAIT_ACK;
r1.write_tag <= '1'; r1.write_tag <= '1';
ev.load_miss <= '1';


when OP_LOAD_NC => when OP_LOAD_NC =>
r1.wb.cyc <= '1'; r1.wb.cyc <= '1';
@ -1452,9 +1416,6 @@ begin
r1.wb.we <= '1'; r1.wb.we <= '1';
r1.wb.cyc <= '1'; r1.wb.cyc <= '1';
r1.wb.stb <= '1'; r1.wb.stb <= '1';
if req.op = OP_STORE_MISS then
ev.store_miss <= '1';
end if;


-- OP_NONE and OP_BAD do nothing -- OP_NONE and OP_BAD do nothing
-- OP_BAD & OP_STCX_FAIL were handled above already -- OP_BAD & OP_STCX_FAIL were handled above already
@ -1464,29 +1425,36 @@ begin
end case; end case;


when RELOAD_WAIT_ACK => when RELOAD_WAIT_ACK =>
-- Requests are all sent if stb is 0
stbs_done := r1.wb.stb = '0';

-- If we are still sending requests, was one accepted ? -- If we are still sending requests, was one accepted ?
if wishbone_in.stall = '0' and r1.wb.stb = '1' then if wishbone_in.stall = '0' and not stbs_done then
-- That was the last word ? We are done sending. Clear stb. -- That was the last word ? We are done sending. Clear
if is_last_row_wb_addr(r1.wb.adr, r1.end_row_ix) then -- stb and set stbs_done so we can handle an eventual last
-- ack on the same cycle.
--
if is_last_row_addr(r1.wb.adr, r1.end_row_ix) then
r1.wb.stb <= '0'; r1.wb.stb <= '0';
stbs_done := true;
end if; end if;


-- Calculate the next row address -- Calculate the next row address
r1.wb.adr <= next_row_wb_addr(r1.wb.adr); r1.wb.adr <= next_row_addr(r1.wb.adr);
end if; end if;


-- Incoming acks processing -- Incoming acks processing
r1.forward_valid1 <= wishbone_in.ack;
if wishbone_in.ack = '1' then if wishbone_in.ack = '1' then
r1.rows_valid(r1.store_row mod ROW_PER_LINE) <= '1'; r1.rows_valid(r1.store_row mod ROW_PER_LINE) <= '1';
-- If this is the data we were looking for, we can -- If this is the data we were looking for, we can
-- complete the request next cycle. -- complete the request next cycle.
-- Compare the whole address in case the request in -- Compare the whole address in case the request in
-- r1.req is not the one that started this refill. -- r1.req is not the one that started this refill.
-- (Cases where req comes from r0 are handled as a load if req.valid = '1' and req.same_tag = '1' and
-- hit.) ((r1.dcbz = '1' and req.dcbz = '1') or
if r1.full = '1' and r1.req.same_tag = '1' and (r1.dcbz = '0' and req.op = OP_LOAD_MISS)) and
((r1.dcbz = '1' and req.dcbz = '1') or r1.req.op = OP_LOAD_MISS) and r1.store_row = get_row(req.real_addr) then
r1.store_row = get_row(r1.req.real_addr) then
r1.full <= '0'; r1.full <= '0';
r1.slow_valid <= '1'; r1.slow_valid <= '1';
if r1.mmu_req = '0' then if r1.mmu_req = '0' then
@ -1494,17 +1462,18 @@ begin
else else
r1.mmu_done <= '1'; r1.mmu_done <= '1';
end if; end if;
r1.forward_sel <= (others => '1');
r1.use_forward1 <= '1';
end if; end if;


-- Check for completion -- Check for completion
if is_last_row(r1.store_row, r1.end_row_ix) then if stbs_done and is_last_row(r1.store_row, r1.end_row_ix) then
-- Complete wishbone cycle -- Complete wishbone cycle
r1.wb.cyc <= '0'; r1.wb.cyc <= '0';


-- Cache line is now valid -- Cache line is now valid
cache_valids(r1.store_index)(r1.store_way) <= '1'; cache_valids(r1.store_index)(r1.store_way) <= '1';


ev.dcache_refill <= not r1.dcbz;
r1.state <= IDLE; r1.state <= IDLE;
end if; end if;


@ -1528,17 +1497,15 @@ begin
-- See if there is another store waiting to be done -- See if there is another store waiting to be done
-- which is in the same real page. -- which is in the same real page.
if req.valid = '1' then if req.valid = '1' then
r1.wb.adr(SET_SIZE_BITS - ROW_OFF_BITS - 1 downto 0) <= r1.wb.adr(SET_SIZE_BITS - 1 downto 0) <=
req.real_addr(SET_SIZE_BITS - 1 downto ROW_OFF_BITS); req.real_addr(SET_SIZE_BITS - 1 downto 0);
r1.wb.dat <= req.data; r1.wb.dat <= req.data;
r1.wb.sel <= req.byte_sel; r1.wb.sel <= req.byte_sel;
end if; end if;
if acks < 7 and req.same_tag = '1' and req.dcbz = '0' and if acks < 7 and req.same_tag = '1' and
(req.op = OP_STORE_MISS or req.op = OP_STORE_HIT) then (req.op = OP_STORE_MISS or req.op = OP_STORE_HIT) then
r1.wb.stb <= '1'; r1.wb.stb <= '1';
stbs_done := false; stbs_done := false;
r1.store_way <= req.hit_way;
r1.store_row <= get_row(req.real_addr);
if req.op = OP_STORE_HIT then if req.op = OP_STORE_HIT then
r1.write_bram <= '1'; r1.write_bram <= '1';
end if; end if;
@ -1580,6 +1547,8 @@ begin
else else
r1.mmu_done <= '1'; r1.mmu_done <= '1';
end if; end if;
r1.forward_sel <= (others => '1');
r1.use_forward1 <= '1';
r1.wb.cyc <= '0'; r1.wb.cyc <= '0';
r1.wb.stb <= '0'; r1.wb.stb <= '0';
end if; end if;
@ -1594,7 +1563,7 @@ begin
dcache_log: process(clk) dcache_log: process(clk)
begin begin
if rising_edge(clk) then if rising_edge(clk) then
log_data <= r1.wb.adr(2 downto 0) & log_data <= r1.wb.adr(5 downto 3) &
wishbone_in.stall & wishbone_in.stall &
wishbone_in.ack & wishbone_in.ack &
r1.wb.stb & r1.wb.cyc & r1.wb.stb & r1.wb.cyc &

@ -70,69 +70,69 @@ begin


stim: process stim: process
begin begin
-- Clear stuff -- Clear stuff
d_in.valid <= '0'; d_in.valid <= '0';
d_in.load <= '0'; d_in.load <= '0';
d_in.nc <= '0'; d_in.nc <= '0';
d_in.addr <= (others => '0'); d_in.addr <= (others => '0');
d_in.data <= (others => '0'); d_in.data <= (others => '0');
m_in.valid <= '0'; m_in.valid <= '0';
m_in.addr <= (others => '0'); m_in.addr <= (others => '0');
m_in.pte <= (others => '0'); m_in.pte <= (others => '0');


wait for 4*clk_period; wait for 4*clk_period;
wait until rising_edge(clk); wait until rising_edge(clk);


-- Cacheable read of address 4 -- Cacheable read of address 4
d_in.load <= '1'; d_in.load <= '1';
d_in.nc <= '0'; d_in.nc <= '0';
d_in.addr <= x"0000000000000004"; d_in.addr <= x"0000000000000004";
d_in.valid <= '1'; d_in.valid <= '1';
wait until rising_edge(clk); wait until rising_edge(clk);
d_in.valid <= '0'; d_in.valid <= '0';


wait until rising_edge(clk) and d_out.valid = '1'; wait until rising_edge(clk) and d_out.valid = '1';
assert d_out.data = x"0000000100000000" assert d_out.data = x"0000000100000000"
report "data @" & to_hstring(d_in.addr) & report "data @" & to_hstring(d_in.addr) &
"=" & to_hstring(d_out.data) & "=" & to_hstring(d_out.data) &
" expected 0000000100000000" " expected 0000000100000000"
severity failure; severity failure;
-- wait for clk_period; -- wait for clk_period;


-- Cacheable read of address 30 -- Cacheable read of address 30
d_in.load <= '1'; d_in.load <= '1';
d_in.nc <= '0'; d_in.nc <= '0';
d_in.addr <= x"0000000000000030"; d_in.addr <= x"0000000000000030";
d_in.valid <= '1'; d_in.valid <= '1';
wait until rising_edge(clk); wait until rising_edge(clk);
d_in.valid <= '0'; d_in.valid <= '0';


wait until rising_edge(clk) and d_out.valid = '1'; wait until rising_edge(clk) and d_out.valid = '1';
assert d_out.data = x"0000000D0000000C" assert d_out.data = x"0000000D0000000C"
report "data @" & to_hstring(d_in.addr) & report "data @" & to_hstring(d_in.addr) &
"=" & to_hstring(d_out.data) & "=" & to_hstring(d_out.data) &
" expected 0000000D0000000C" " expected 0000000D0000000C"
severity failure; severity failure;


-- Non-cacheable read of address 100 -- Non-cacheable read of address 100
d_in.load <= '1'; d_in.load <= '1';
d_in.nc <= '1'; d_in.nc <= '1';
d_in.addr <= x"0000000000000100"; d_in.addr <= x"0000000000000100";
d_in.valid <= '1'; d_in.valid <= '1';
wait until rising_edge(clk); wait until rising_edge(clk);
d_in.valid <= '0'; d_in.valid <= '0';
wait until rising_edge(clk) and d_out.valid = '1'; wait until rising_edge(clk) and d_out.valid = '1';
assert d_out.data = x"0000004100000040" assert d_out.data = x"0000004100000040"
report "data @" & to_hstring(d_in.addr) & report "data @" & to_hstring(d_in.addr) &
"=" & to_hstring(d_out.data) & "=" & to_hstring(d_out.data) &
" expected 0000004100000040" " expected 0000004100000040"
severity failure; severity failure;


wait until rising_edge(clk); wait until rising_edge(clk);
wait until rising_edge(clk); wait until rising_edge(clk);
wait until rising_edge(clk); wait until rising_edge(clk);
wait until rising_edge(clk); wait until rising_edge(clk);


std.env.finish; std.env.finish;
end process; end process;
end; end;

@ -114,8 +114,8 @@ architecture behaviour of decode1 is
36 => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_SI, RS, NONE, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- stw 36 => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_SI, RS, NONE, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- stw
37 => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_SI, RS, RA, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- stwu 37 => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_SI, RS, RA, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- stwu
8 => (ALU, NONE, OP_ADD, RA, CONST_SI, NONE, RT, '0', '0', '1', '0', ONE, '1', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- subfic 8 => (ALU, NONE, OP_ADD, RA, CONST_SI, NONE, RT, '0', '0', '1', '0', ONE, '1', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- subfic
2 => (ALU, NONE, OP_TRAP, RA, CONST_SI, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- tdi 2 => (ALU, NONE, OP_TRAP, RA, CONST_SI, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1', NONE), -- tdi
3 => (ALU, NONE, OP_TRAP, RA, CONST_SI, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', NONE, '0', '0', NONE), -- twi 3 => (ALU, NONE, OP_TRAP, RA, CONST_SI, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', NONE, '0', '1', NONE), -- twi
26 => (ALU, NONE, OP_XOR, NONE, CONST_UI, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- xori 26 => (ALU, NONE, OP_XOR, NONE, CONST_UI, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- xori
27 => (ALU, NONE, OP_XOR, NONE, CONST_UI_HI, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- xoris 27 => (ALU, NONE, OP_XOR, NONE, CONST_UI_HI, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- xoris
others => illegal_inst others => illegal_inst
@ -133,9 +133,9 @@ architecture behaviour of decode1 is
constant decode_op_4_array : op_4_subop_array_t := ( constant decode_op_4_array : op_4_subop_array_t := (
-- unit fac internal in1 in2 in3 out CR CR inv inv cry cry ldst BR sgn upd rsrv 32b sgn rc lk sgl rpt -- unit fac internal in1 in2 in3 out CR CR inv inv cry cry ldst BR sgn upd rsrv 32b sgn rc lk sgl rpt
-- op in out A out in out len ext pipe -- op in out A out in out len ext pipe
2#110000# => (ALU, NONE, OP_MUL_H64, RA, RB, RCR, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', NONE, '0', '0', NONE), -- maddhd 2#110000# => (ALU, NONE, OP_MUL_H64, RA, RB, RCR, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), -- maddhd
2#110001# => (ALU, NONE, OP_MUL_H64, RA, RB, RCR, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- maddhdu 2#110001# => (ALU, NONE, OP_MUL_H64, RA, RB, RCR, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- maddhdu
2#110011# => (ALU, NONE, OP_MUL_L64, RA, RB, RCR, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', NONE, '0', '0', NONE), -- maddld 2#110011# => (ALU, NONE, OP_MUL_L64, RA, RB, RCR, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), -- maddld
others => decode_rom_init others => decode_rom_init
); );


@ -166,7 +166,7 @@ architecture behaviour of decode1 is
-- mcrf; and cr logical ops -- mcrf; and cr logical ops
2#000# => (ALU, NONE, OP_CROP, NONE, NONE, NONE, NONE, '1', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), 2#000# => (ALU, NONE, OP_CROP, NONE, NONE, NONE, NONE, '1', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE),
-- addpcis -- addpcis
2#001# => (ALU, NONE, OP_ADD, CIA, CONST_DXHI4, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), 2#001# => (ALU, NONE, OP_ADD, CIA, CONST_DXHI4, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE),
-- bclr, bcctr, bctar -- bclr, bcctr, bctar
2#100# => (ALU, NONE, OP_BCREG, SPR, SPR, NONE, SPR, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '0', NONE), 2#100# => (ALU, NONE, OP_BCREG, SPR, SPR, NONE, SPR, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '0', NONE),
-- isync -- isync
@ -210,7 +210,7 @@ architecture behaviour of decode1 is
2#1011001010# => (ALU, NONE, OP_ADD, RA, NONE, NONE, RT, '0', '0', '0', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- addzeo 2#1011001010# => (ALU, NONE, OP_ADD, RA, NONE, NONE, RT, '0', '0', '0', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- addzeo
2#0000011100# => (ALU, NONE, OP_AND, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- and 2#0000011100# => (ALU, NONE, OP_AND, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- and
2#0000111100# => (ALU, NONE, OP_AND, NONE, RB, RS, RA, '0', '0', '1', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- andc 2#0000111100# => (ALU, NONE, OP_AND, NONE, RB, RS, RA, '0', '0', '1', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- andc
2#0011111100# => (ALU, NONE, OP_BPERM, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- bperm 2#0011111100# => (ALU, NONE, OP_BPERM, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- bperm
2#0100111010# => (ALU, NONE, OP_BCD, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- cbcdtd 2#0100111010# => (ALU, NONE, OP_BCD, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- cbcdtd
2#0100011010# => (ALU, NONE, OP_BCD, NONE, NONE, RS, RA, '0', '0', '1', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- cdtbcd 2#0100011010# => (ALU, NONE, OP_BCD, NONE, NONE, RS, RA, '0', '0', '1', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- cdtbcd
2#0000000000# => (ALU, NONE, OP_CMP, RA, RB, NONE, NONE, '0', '1', '1', '0', ONE, '0', NONE, '0', '0', '0', '0', '0', '1', NONE, '0', '0', NONE), -- cmp 2#0000000000# => (ALU, NONE, OP_CMP, RA, RB, NONE, NONE, '0', '1', '1', '0', ONE, '0', NONE, '0', '0', '0', '0', '0', '1', NONE, '0', '0', NONE), -- cmp
@ -256,7 +256,7 @@ architecture behaviour of decode1 is
2#1101111011# => (ALU, NONE, OP_EXTSWSLI, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- extswsli 2#1101111011# => (ALU, NONE, OP_EXTSWSLI, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- extswsli
2#1111010110# => (ALU, NONE, OP_ICBI, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1', NONE), -- icbi 2#1111010110# => (ALU, NONE, OP_ICBI, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1', NONE), -- icbi
2#0000010110# => (ALU, NONE, OP_ICBT, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1', NONE), -- icbt 2#0000010110# => (ALU, NONE, OP_ICBT, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1', NONE), -- icbt
2#0000001111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel 2#0000001111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1', NONE), -- isel
2#0000101111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel 2#0000101111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel
2#0001001111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel 2#0001001111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel
2#0001101111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel 2#0001101111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel
@ -410,8 +410,8 @@ architecture behaviour of decode1 is
2#0011001000# => (ALU, NONE, OP_ADD, RA, NONE, NONE, RT, '0', '0', '1', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- subfze 2#0011001000# => (ALU, NONE, OP_ADD, RA, NONE, NONE, RT, '0', '0', '1', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- subfze
2#1011001000# => (ALU, NONE, OP_ADD, RA, NONE, NONE, RT, '0', '0', '1', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- subfzeo 2#1011001000# => (ALU, NONE, OP_ADD, RA, NONE, NONE, RT, '0', '0', '1', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- subfzeo
2#1001010110# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1', NONE), -- sync 2#1001010110# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1', NONE), -- sync
2#0001000100# => (ALU, NONE, OP_TRAP, RA, RB, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- td 2#0001000100# => (ALU, NONE, OP_TRAP, RA, RB, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1', NONE), -- td
2#0000000100# => (ALU, NONE, OP_TRAP, RA, RB, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', NONE, '0', '0', NONE), -- tw 2#0000000100# => (ALU, NONE, OP_TRAP, RA, RB, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', NONE, '0', '1', NONE), -- tw
2#0100110010# => (LDST, NONE, OP_TLBIE, NONE, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- tlbie 2#0100110010# => (LDST, NONE, OP_TLBIE, NONE, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- tlbie
2#0100010010# => (LDST, NONE, OP_TLBIE, NONE, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- tlbiel 2#0100010010# => (LDST, NONE, OP_TLBIE, NONE, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- tlbiel
2#1000110110# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1', NONE), -- tlbsync 2#1000110110# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1', NONE), -- tlbsync
@ -609,7 +609,7 @@ begin
vi.force_single := '1'; vi.force_single := '1';
-- send MMU-related SPRs to loadstore1 -- send MMU-related SPRs to loadstore1
case sprn is case sprn is
when SPR_DAR | SPR_DSISR | SPR_PID | SPR_PTCR => when SPR_DAR | SPR_DSISR | SPR_PID | SPR_PRTBL =>
vi.override_decode.unit := LDST; vi.override_decode.unit := LDST;
vi.override_unit := '1'; vi.override_unit := '1';
when others => when others =>
@ -740,8 +740,6 @@ begin
bv.br_offset := br_offset; bv.br_offset := br_offset;
if f_in.next_predicted = '1' then if f_in.next_predicted = '1' then
v.br_pred := '1'; v.br_pred := '1';
elsif f_in.next_pred_ntaken = '1' then
v.br_pred := '0';
end if; end if;
bv.predict := v.br_pred and f_in.valid and not flush_in and not busy_out and not f_in.next_predicted; bv.predict := v.br_pred and f_in.valid and not flush_in and not busy_out and not f_in.next_predicted;
-- after a clock edge... -- after a clock edge...

@ -215,6 +215,7 @@ architecture behaviour of decode2 is
OP_AND => "001", -- logical_result OP_AND => "001", -- logical_result
OP_OR => "001", OP_OR => "001",
OP_XOR => "001", OP_XOR => "001",
OP_POPCNT => "001",
OP_PRTY => "001", OP_PRTY => "001",
OP_CMPB => "001", OP_CMPB => "001",
OP_EXTS => "001", OP_EXTS => "001",
@ -233,8 +234,7 @@ architecture behaviour of decode2 is
OP_DIV => "011", OP_DIV => "011",
OP_DIVE => "011", OP_DIVE => "011",
OP_MOD => "011", OP_MOD => "011",
OP_CNTZ => "100", -- countbits_result OP_CNTZ => "100", -- countzero_result
OP_POPCNT => "100",
OP_MFSPR => "101", -- spr_result OP_MFSPR => "101", -- spr_result
OP_B => "110", -- next_nia OP_B => "110", -- next_nia
OP_BC => "110", OP_BC => "110",

@ -42,8 +42,6 @@ begin
quot <= (others => '0'); quot <= (others => '0');
running <= '0'; running <= '0';
count <= "0000000"; count <= "0000000";
is_32bit <= '0';
overflow <= '0';
elsif d_in.valid = '1' then elsif d_in.valid = '1' then
if d_in.is_extended = '1' then if d_in.is_extended = '1' then
dend <= '0' & d_in.dividend & x"0000000000000000"; dend <= '0' & d_in.dividend & x"0000000000000000";
@ -125,9 +123,9 @@ begin
divider_out: process(clk) divider_out: process(clk)
begin begin
if rising_edge(clk) then if rising_edge(clk) then
d_out.valid <= '0'; d_out.valid <= '0';
d_out.write_reg_data <= oresult; d_out.write_reg_data <= oresult;
d_out.overflow <= did_ovf; d_out.overflow <= did_ovf;
if count = "1000000" then if count = "1000000" then
d_out.valid <= '1'; d_out.valid <= '1';
end if; end if;

@ -1,6 +1,3 @@
library vunit_lib;
context vunit_lib.vunit_context;

library ieee; library ieee;
use ieee.std_logic_1164.all; use ieee.std_logic_1164.all;
use ieee.numeric_std.all; use ieee.numeric_std.all;
@ -8,13 +5,10 @@ use ieee.numeric_std.all;
library work; library work;
use work.decode_types.all; use work.decode_types.all;
use work.common.all; use work.common.all;
use work.glibc_random.all;
use work.ppc_fx_insns.all; use work.ppc_fx_insns.all;


library osvvm;
use osvvm.RandomPkg.all;

entity divider_tb is entity divider_tb is
generic (runner_cfg : string := runner_cfg_default);
end divider_tb; end divider_tb;


architecture behave of divider_tb is architecture behave of divider_tb is
@ -43,481 +37,516 @@ begin
variable q128: std_ulogic_vector(127 downto 0); variable q128: std_ulogic_vector(127 downto 0);
variable q64: std_ulogic_vector(63 downto 0); variable q64: std_ulogic_vector(63 downto 0);
variable rem32: std_ulogic_vector(31 downto 0); variable rem32: std_ulogic_vector(31 downto 0);
variable rnd : RandomPType;
begin begin
rnd.InitSeed(stim_process'path_name); rst <= '1';
wait for clk_period;
rst <= '0';

d1.valid <= '1';
d1.dividend <= x"0000000010001000";
d1.divisor <= x"0000000000001111";
d1.is_signed <= '0';
d1.is_32bit <= '0';
d1.is_extended <= '0';
d1.is_modulus <= '0';
d1.neg_result <= '0';


test_runner_setup(runner, runner_cfg); wait for clk_period;
assert d2.valid = '0';


while test_suite loop d1.valid <= '0';
rst <= '1';
for j in 0 to 66 loop
wait for clk_period; wait for clk_period;
rst <= '0'; if d2.valid = '1' then
exit;
end if;
end loop;


d1.is_signed <= '0'; assert d2.valid = '1';
d1.neg_result <= '0'; assert d2.write_reg_data = x"000000000000f001" report "result " & to_hstring(d2.write_reg_data);
d1.is_extended <= '0';
d1.is_32bit <= '0';
d1.is_modulus <= '0';
d1.valid <= '0';


if run("Test interface") then wait for clk_period;
d1.valid <= '1'; assert d2.valid = '0' report "valid";
d1.dividend <= x"0000000010001000";
d1.divisor <= x"0000000000001111";


wait for clk_period; d1.valid <= '1';
check_false(?? d2.valid, result("for valid"));


d1.valid <= '0'; wait for clk_period;
assert d2.valid = '0' report "valid";


for j in 0 to 66 loop d1.valid <= '0';
wait for clk_period;
if d2.valid = '1' then
exit;
end if;
end loop;


check_true(?? d2.valid, result("for valid")); for j in 0 to 66 loop
check_equal(d2.write_reg_data, 16#f001#); wait for clk_period;
if d2.valid = '1' then
exit;
end if;
end loop;


wait for clk_period; assert d2.valid = '1';
check_false(?? d2.valid, result("for valid")); assert d2.write_reg_data = x"000000000000f001" report "result " & to_hstring(d2.write_reg_data);


d1.valid <= '1'; wait for clk_period;
assert d2.valid = '0';


wait for clk_period; -- test divd
check_false(?? d2.valid, result("for valid")); report "test divd";
divd_loop : for dlength in 1 to 8 loop
for vlength in 1 to dlength loop
for i in 0 to 100 loop
ra := std_ulogic_vector(resize(signed(pseudorand(dlength * 8)), 64));
rb := std_ulogic_vector(resize(signed(pseudorand(vlength * 8)), 64));


d1.valid <= '0'; d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra));
d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb));
d1.is_signed <= '1';
d1.neg_result <= ra(63) xor rb(63);
d1.valid <= '1';


for j in 0 to 66 loop
wait for clk_period; wait for clk_period;
if d2.valid = '1' then
exit;
end if;
end loop;


check_true(?? d2.valid, result("for valid")); d1.valid <= '0';
check_equal(d2.write_reg_data, 16#f001#); for j in 0 to 66 loop

wait for clk_period;
wait for clk_period; if d2.valid = '1' then
check_false(?? d2.valid, result("for valid")); exit;

end if;
elsif run("Test divd") then
divd_loop : for dlength in 1 to 8 loop
for vlength in 1 to dlength loop
for i in 0 to 100 loop
ra := std_ulogic_vector(resize(signed(rnd.RandSlv(dlength * 8)), 64));
rb := std_ulogic_vector(resize(signed(rnd.RandSlv(vlength * 8)), 64));

d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra));
d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb));
d1.is_signed <= '1';
d1.neg_result <= ra(63) xor rb(63);
d1.valid <= '1';

wait for clk_period;

d1.valid <= '0';
for j in 0 to 66 loop
wait for clk_period;
if d2.valid = '1' then
exit;
end if;
end loop;
check_true(?? d2.valid, result("for valid"));

behave_rt := (others => '0');
if rb /= x"0000000000000000" and (ra /= x"8000000000000000" or rb /= x"ffffffffffffffff") then
behave_rt := ppc_divd(ra, rb);
end if;
check_equal(d2.write_reg_data, behave_rt, result("for divd"));
end loop;
end loop; end loop;
assert d2.valid = '1';

behave_rt := (others => '0');
if rb /= x"0000000000000000" and (ra /= x"8000000000000000" or rb /= x"ffffffffffffffff") then
behave_rt := ppc_divd(ra, rb);
end if;
assert to_hstring(behave_rt) = to_hstring(d2.write_reg_data)
report "bad divd expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
end loop; end loop;
end loop;
end loop;

-- test divdu
report "test divdu";
divdu_loop : for dlength in 1 to 8 loop
for vlength in 1 to dlength loop
for i in 0 to 100 loop
ra := std_ulogic_vector(resize(unsigned(pseudorand(dlength * 8)), 64));
rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64));

d1.dividend <= ra;
d1.divisor <= rb;
d1.is_signed <= '0';
d1.neg_result <= '0';
d1.valid <= '1';

wait for clk_period;


elsif run("Test divdu") then d1.valid <= '0';
divdu_loop : for dlength in 1 to 8 loop for j in 0 to 66 loop
for vlength in 1 to dlength loop wait for clk_period;
for i in 0 to 100 loop if d2.valid = '1' then
ra := std_ulogic_vector(resize(unsigned(rnd.RandSlv(dlength * 8)), 64)); exit;
rb := std_ulogic_vector(resize(unsigned(rnd.RandSlv(vlength * 8)), 64)); end if;

d1.dividend <= ra;
d1.divisor <= rb;
d1.valid <= '1';

wait for clk_period;

d1.valid <= '0';
for j in 0 to 66 loop
wait for clk_period;
if d2.valid = '1' then
exit;
end if;
end loop;
check_true(?? d2.valid, result("for valid"));

behave_rt := (others => '0');
if rb /= x"0000000000000000" then
behave_rt := ppc_divdu(ra, rb);
end if;
check_equal(d2.write_reg_data, behave_rt, result("for divdu"));
end loop;
end loop; end loop;
assert d2.valid = '1';

behave_rt := (others => '0');
if rb /= x"0000000000000000" then
behave_rt := ppc_divdu(ra, rb);
end if;
assert to_hstring(behave_rt) = to_hstring(d2.write_reg_data)
report "bad divdu expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
end loop; end loop;
end loop;
end loop;

-- test divde
report "test divde";
divde_loop : for vlength in 1 to 8 loop
for dlength in 1 to vlength loop
for i in 0 to 100 loop
ra := std_ulogic_vector(resize(signed(pseudorand(dlength * 8)), 64));
rb := std_ulogic_vector(resize(signed(pseudorand(vlength * 8)), 64));

d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra));
d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb));
d1.is_signed <= '1';
d1.neg_result <= ra(63) xor rb(63);
d1.is_extended <= '1';
d1.valid <= '1';

wait for clk_period;


elsif run("Test divde") then d1.valid <= '0';
divde_loop : for vlength in 1 to 8 loop for j in 0 to 66 loop
for dlength in 1 to vlength loop wait for clk_period;
for i in 0 to 100 loop if d2.valid = '1' then
ra := std_ulogic_vector(resize(signed(rnd.RandSlv(dlength * 8)), 64)); exit;
rb := std_ulogic_vector(resize(signed(rnd.RandSlv(vlength * 8)), 64)); end if;

d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra));
d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb));
d1.is_signed <= '1';
d1.neg_result <= ra(63) xor rb(63);
d1.is_extended <= '1';
d1.valid <= '1';

wait for clk_period;

d1.valid <= '0';
for j in 0 to 66 loop
wait for clk_period;
if d2.valid = '1' then
exit;
end if;
end loop;
check_true(?? d2.valid, result("for valid"));

behave_rt := (others => '0');
if rb /= x"0000000000000000" then
d128 := ra & x"0000000000000000";
q128 := std_ulogic_vector(signed(d128) / signed(rb));
if q128(127 downto 63) = x"0000000000000000" & '0' or
q128(127 downto 63) = x"ffffffffffffffff" & '1' then
behave_rt := q128(63 downto 0);
end if;
end if;
check_equal(d2.write_reg_data, behave_rt, result("for divde"));
end loop;
end loop; end loop;
assert d2.valid = '1';

behave_rt := (others => '0');
if rb /= x"0000000000000000" then
d128 := ra & x"0000000000000000";
q128 := std_ulogic_vector(signed(d128) / signed(rb));
if q128(127 downto 63) = x"0000000000000000" & '0' or
q128(127 downto 63) = x"ffffffffffffffff" & '1' then
behave_rt := q128(63 downto 0);
end if;
end if;
assert to_hstring(behave_rt) = to_hstring(d2.write_reg_data)
report "bad divde expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data) & " for ra = " & to_hstring(ra) & " rb = " & to_hstring(rb);
end loop; end loop;
end loop;
end loop;

-- test divdeu
report "test divdeu";
divdeu_loop : for vlength in 1 to 8 loop
for dlength in 1 to vlength loop
for i in 0 to 100 loop
ra := std_ulogic_vector(resize(unsigned(pseudorand(dlength * 8)), 64));
rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64));

d1.dividend <= ra;
d1.divisor <= rb;
d1.is_signed <= '0';
d1.neg_result <= '0';
d1.is_extended <= '1';
d1.valid <= '1';

wait for clk_period;


elsif run("Test divdeu") then d1.valid <= '0';
divdeu_loop : for vlength in 1 to 8 loop for j in 0 to 66 loop
for dlength in 1 to vlength loop wait for clk_period;
for i in 0 to 100 loop if d2.valid = '1' then
ra := std_ulogic_vector(resize(unsigned(rnd.RandSlv(dlength * 8)), 64)); exit;
rb := std_ulogic_vector(resize(unsigned(rnd.RandSlv(vlength * 8)), 64)); end if;

d1.dividend <= ra;
d1.divisor <= rb;
d1.is_extended <= '1';
d1.valid <= '1';

wait for clk_period;

d1.valid <= '0';
for j in 0 to 66 loop
wait for clk_period;
if d2.valid = '1' then
exit;
end if;
end loop;
check_true(?? d2.valid, result("for valid"));

behave_rt := (others => '0');
if unsigned(rb) > unsigned(ra) then
d128 := ra & x"0000000000000000";
q128 := std_ulogic_vector(unsigned(d128) / unsigned(rb));
behave_rt := q128(63 downto 0);
end if;
check_equal(d2.write_reg_data, behave_rt, result("for divdeu"));
end loop;
end loop; end loop;
assert d2.valid = '1';

behave_rt := (others => '0');
if unsigned(rb) > unsigned(ra) then
d128 := ra & x"0000000000000000";
q128 := std_ulogic_vector(unsigned(d128) / unsigned(rb));
behave_rt := q128(63 downto 0);
end if;
assert to_hstring(behave_rt) = to_hstring(d2.write_reg_data)
report "bad divdeu expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data) & " for ra = " & to_hstring(ra) & " rb = " & to_hstring(rb);
end loop; end loop;
end loop;
end loop;

-- test divw
report "test divw";
divw_loop : for dlength in 1 to 4 loop
for vlength in 1 to dlength loop
for i in 0 to 100 loop
ra := std_ulogic_vector(resize(signed(pseudorand(dlength * 8)), 64));
rb := std_ulogic_vector(resize(signed(pseudorand(vlength * 8)), 64));

d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra));
d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb));
d1.is_signed <= '1';
d1.neg_result <= ra(63) xor rb(63);
d1.is_extended <= '0';
d1.is_32bit <= '1';
d1.valid <= '1';


elsif run("Test divw") then wait for clk_period;
divw_loop : for dlength in 1 to 4 loop
for vlength in 1 to dlength loop d1.valid <= '0';
for i in 0 to 100 loop for j in 0 to 66 loop
ra := std_ulogic_vector(resize(signed(rnd.RandSlv(dlength * 8)), 64)); wait for clk_period;
rb := std_ulogic_vector(resize(signed(rnd.RandSlv(vlength * 8)), 64)); if d2.valid = '1' then

exit;
d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra)); end if;
d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb));
d1.is_signed <= '1';
d1.neg_result <= ra(63) xor rb(63);
d1.is_32bit <= '1';
d1.valid <= '1';

wait for clk_period;

d1.valid <= '0';
for j in 0 to 66 loop
wait for clk_period;
if d2.valid = '1' then
exit;
end if;
end loop;
check_true(?? d2.valid, result("for valid"));

behave_rt := (others => '0');
if rb /= x"0000000000000000" and (ra /= x"ffffffff80000000" or rb /= x"ffffffffffffffff") then
behave_rt := ppc_divw(ra, rb);
end if;
check_equal(d2.write_reg_data, behave_rt, result("for divw"));
end loop;
end loop; end loop;
assert d2.valid = '1';

behave_rt := (others => '0');
if rb /= x"0000000000000000" and (ra /= x"ffffffff80000000" or rb /= x"ffffffffffffffff") then
behave_rt := ppc_divw(ra, rb);
end if;
assert behave_rt = d2.write_reg_data
report "bad divw expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
end loop; end loop;
end loop;
end loop;


elsif run("Test divwu") then -- test divwu
divwu_loop : for dlength in 1 to 4 loop report "test divwu";
for vlength in 1 to dlength loop divwu_loop : for dlength in 1 to 4 loop
for i in 0 to 100 loop for vlength in 1 to dlength loop
ra := std_ulogic_vector(resize(unsigned(rnd.RandSlv(dlength * 8)), 64)); for i in 0 to 100 loop
rb := std_ulogic_vector(resize(unsigned(rnd.RandSlv(vlength * 8)), 64)); ra := std_ulogic_vector(resize(unsigned(pseudorand(dlength * 8)), 64));

rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64));
d1.dividend <= ra;
d1.divisor <= rb; d1.dividend <= ra;
d1.is_32bit <= '1'; d1.divisor <= rb;
d1.valid <= '1'; d1.is_signed <= '0';

d1.neg_result <= '0';
wait for clk_period; d1.is_extended <= '0';

d1.is_32bit <= '1';
d1.valid <= '0'; d1.valid <= '1';
for j in 0 to 66 loop
wait for clk_period; wait for clk_period;
if d2.valid = '1' then
exit; d1.valid <= '0';
end if; for j in 0 to 66 loop
end loop; wait for clk_period;
check_true(?? d2.valid, result("for valid")); if d2.valid = '1' then

exit;
behave_rt := (others => '0'); end if;
if rb /= x"0000000000000000" then
behave_rt := ppc_divwu(ra, rb);
end if;
check_equal(d2.write_reg_data, behave_rt, result("for divwu"));
end loop;
end loop; end loop;
assert d2.valid = '1';

behave_rt := (others => '0');
if rb /= x"0000000000000000" then
behave_rt := ppc_divwu(ra, rb);
end if;
assert behave_rt = d2.write_reg_data
report "bad divwu expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
end loop; end loop;
end loop;
end loop;

-- test divwe
report "test divwe";
divwe_loop : for vlength in 1 to 4 loop
for dlength in 1 to vlength loop
for i in 0 to 100 loop
ra := std_ulogic_vector(resize(signed(pseudorand(dlength * 8)), 32)) & x"00000000";
rb := std_ulogic_vector(resize(signed(pseudorand(vlength * 8)), 64));

d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra));
d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb));
d1.is_signed <= '1';
d1.neg_result <= ra(63) xor rb(63);
d1.is_extended <= '0';
d1.is_32bit <= '1';
d1.valid <= '1';


elsif run("Test divwe") then wait for clk_period;
divwe_loop : for vlength in 1 to 4 loop
for dlength in 1 to vlength loop d1.valid <= '0';
for i in 0 to 100 loop for j in 0 to 66 loop
ra := std_ulogic_vector(resize(signed(rnd.RandSlv(dlength * 8)), 32)) & x"00000000"; wait for clk_period;
rb := std_ulogic_vector(resize(signed(rnd.RandSlv(vlength * 8)), 64)); if d2.valid = '1' then

exit;
d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra)); end if;
d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb));
d1.is_signed <= '1';
d1.neg_result <= ra(63) xor rb(63);
d1.is_32bit <= '1';
d1.valid <= '1';

wait for clk_period;

d1.valid <= '0';
for j in 0 to 66 loop
wait for clk_period;
if d2.valid = '1' then
exit;
end if;
end loop;
check_true(?? d2.valid, result("for valid"));

behave_rt := (others => '0');
if rb /= x"0000000000000000" then
q64 := std_ulogic_vector(signed(ra) / signed(rb));
if q64(63 downto 31) = x"00000000" & '0' or
q64(63 downto 31) = x"ffffffff" & '1' then
behave_rt := x"00000000" & q64(31 downto 0);
end if;
check_equal(d2.write_reg_data, behave_rt, result("for divwe"));
end if;
end loop;
end loop; end loop;
assert d2.valid = '1';

behave_rt := (others => '0');
if rb /= x"0000000000000000" then
q64 := std_ulogic_vector(signed(ra) / signed(rb));
if q64(63 downto 31) = x"00000000" & '0' or
q64(63 downto 31) = x"ffffffff" & '1' then
behave_rt := x"00000000" & q64(31 downto 0);
end if;
assert behave_rt = d2.write_reg_data
report "bad divwe expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data) & " for ra = " & to_hstring(ra) & " rb = " & to_hstring(rb);
end if;
end loop; end loop;
end loop;
end loop;

-- test divweu
report "test divweu";
divweu_loop : for vlength in 1 to 4 loop
for dlength in 1 to vlength loop
for i in 0 to 100 loop
ra := std_ulogic_vector(resize(unsigned(pseudorand(dlength * 8)), 32)) & x"00000000";
rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64));

d1.dividend <= ra;
d1.divisor <= rb;
d1.is_signed <= '0';
d1.neg_result <= '0';
d1.is_extended <= '0';
d1.is_32bit <= '1';
d1.valid <= '1';


elsif run("Test divweu") then wait for clk_period;
divweu_loop : for vlength in 1 to 4 loop
for dlength in 1 to vlength loop d1.valid <= '0';
for i in 0 to 100 loop for j in 0 to 66 loop
ra := std_ulogic_vector(resize(unsigned(rnd.RandSlv(dlength * 8)), 32)) & x"00000000"; wait for clk_period;
rb := std_ulogic_vector(resize(unsigned(rnd.RandSlv(vlength * 8)), 64)); if d2.valid = '1' then

exit;
d1.dividend <= ra; end if;
d1.divisor <= rb;
d1.is_32bit <= '1';
d1.valid <= '1';

wait for clk_period;

d1.valid <= '0';
for j in 0 to 66 loop
wait for clk_period;
if d2.valid = '1' then
exit;
end if;
end loop;
check_true(?? d2.valid, result("for valid"));

behave_rt := (others => '0');
if unsigned(rb(31 downto 0)) > unsigned(ra(63 downto 32)) then
behave_rt := std_ulogic_vector(unsigned(ra) / unsigned(rb));
end if;
check_equal(d2.write_reg_data, behave_rt, result("for divweu"));
end loop;
end loop; end loop;
assert d2.valid = '1';

behave_rt := (others => '0');
if unsigned(rb(31 downto 0)) > unsigned(ra(63 downto 32)) then
behave_rt := std_ulogic_vector(unsigned(ra) / unsigned(rb));
end if;
assert behave_rt = d2.write_reg_data
report "bad divweu expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data) & " for ra = " & to_hstring(ra) & " rb = " & to_hstring(rb);
end loop; end loop;
end loop;
end loop;

-- test modsd
report "test modsd";
modsd_loop : for dlength in 1 to 8 loop
for vlength in 1 to dlength loop
for i in 0 to 100 loop
ra := std_ulogic_vector(resize(signed(pseudorand(dlength * 8)), 64));
rb := std_ulogic_vector(resize(signed(pseudorand(vlength * 8)), 64));

d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra));
d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb));
d1.is_signed <= '1';
d1.neg_result <= ra(63);
d1.is_extended <= '0';
d1.is_32bit <= '0';
d1.is_modulus <= '1';
d1.valid <= '1';

wait for clk_period;


elsif run("Test modsd") then d1.valid <= '0';
modsd_loop : for dlength in 1 to 8 loop for j in 0 to 66 loop
for vlength in 1 to dlength loop wait for clk_period;
for i in 0 to 100 loop if d2.valid = '1' then
ra := std_ulogic_vector(resize(signed(rnd.RandSlv(dlength * 8)), 64)); exit;
rb := std_ulogic_vector(resize(signed(rnd.RandSlv(vlength * 8)), 64)); end if;

d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra));
d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb));
d1.is_signed <= '1';
d1.neg_result <= ra(63);
d1.is_modulus <= '1';
d1.valid <= '1';

wait for clk_period;

d1.valid <= '0';
for j in 0 to 66 loop
wait for clk_period;
if d2.valid = '1' then
exit;
end if;
end loop;
check_true(?? d2.valid, result("for valid"));

behave_rt := (others => '0');
if rb /= x"0000000000000000" then
behave_rt := std_ulogic_vector(signed(ra) rem signed(rb));
end if;
check_equal(d2.write_reg_data, behave_rt, result("for modsd"));
end loop;
end loop; end loop;
assert d2.valid = '1';

behave_rt := (others => '0');
if rb /= x"0000000000000000" then
behave_rt := std_ulogic_vector(signed(ra) rem signed(rb));
end if;
assert behave_rt = d2.write_reg_data
report "bad modsd expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
end loop; end loop;
end loop;
end loop;

-- test modud
report "test modud";
modud_loop : for dlength in 1 to 8 loop
for vlength in 1 to dlength loop
for i in 0 to 100 loop
ra := std_ulogic_vector(resize(unsigned(pseudorand(dlength * 8)), 64));
rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64));

d1.dividend <= ra;
d1.divisor <= rb;
d1.is_signed <= '0';
d1.neg_result <= '0';
d1.is_extended <= '0';
d1.is_32bit <= '0';
d1.is_modulus <= '1';
d1.valid <= '1';

wait for clk_period;


elsif run("Test modud") then d1.valid <= '0';
modud_loop : for dlength in 1 to 8 loop for j in 0 to 66 loop
for vlength in 1 to dlength loop wait for clk_period;
for i in 0 to 100 loop if d2.valid = '1' then
ra := std_ulogic_vector(resize(unsigned(rnd.RandSlv(dlength * 8)), 64)); exit;
rb := std_ulogic_vector(resize(unsigned(rnd.RandSlv(vlength * 8)), 64)); end if;

d1.dividend <= ra;
d1.divisor <= rb;
d1.is_modulus <= '1';
d1.valid <= '1';

wait for clk_period;

d1.valid <= '0';
for j in 0 to 66 loop
wait for clk_period;
if d2.valid = '1' then
exit;
end if;
end loop;
check_true(?? d2.valid, result("for valid"));

behave_rt := (others => '0');
if rb /= x"0000000000000000" then
behave_rt := std_ulogic_vector(unsigned(ra) rem unsigned(rb));
end if;
check_equal(d2.write_reg_data, behave_rt, result("for modud"));
end loop;
end loop; end loop;
assert d2.valid = '1';

behave_rt := (others => '0');
if rb /= x"0000000000000000" then
behave_rt := std_ulogic_vector(unsigned(ra) rem unsigned(rb));
end if;
assert behave_rt = d2.write_reg_data
report "bad modud expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
end loop; end loop;
end loop;
end loop;

-- test modsw
report "test modsw";
modsw_loop : for dlength in 1 to 4 loop
for vlength in 1 to dlength loop
for i in 0 to 100 loop
ra := std_ulogic_vector(resize(signed(pseudorand(dlength * 8)), 64));
rb := std_ulogic_vector(resize(signed(pseudorand(vlength * 8)), 64));

d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra));
d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb));
d1.is_signed <= '1';
d1.neg_result <= ra(63);
d1.is_extended <= '0';
d1.is_32bit <= '1';
d1.is_modulus <= '1';
d1.valid <= '1';


elsif run("Test modsw") then wait for clk_period;
modsw_loop : for dlength in 1 to 4 loop
for vlength in 1 to dlength loop d1.valid <= '0';
for i in 0 to 100 loop for j in 0 to 66 loop
ra := std_ulogic_vector(resize(signed(rnd.RandSlv(dlength * 8)), 64)); wait for clk_period;
rb := std_ulogic_vector(resize(signed(rnd.RandSlv(vlength * 8)), 64)); if d2.valid = '1' then

exit;
d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra)); end if;
d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb));
d1.is_signed <= '1';
d1.neg_result <= ra(63);
d1.is_32bit <= '1';
d1.is_modulus <= '1';
d1.valid <= '1';

wait for clk_period;

d1.valid <= '0';
for j in 0 to 66 loop
wait for clk_period;
if d2.valid = '1' then
exit;
end if;
end loop;
check_true(?? d2.valid, result("for valid"));

behave_rt := (others => '0');
if rb /= x"0000000000000000" then
rem32 := std_ulogic_vector(signed(ra(31 downto 0)) rem signed(rb(31 downto 0)));
if rem32(31) = '0' then
behave_rt := x"00000000" & rem32;
else
behave_rt := x"ffffffff" & rem32;
end if;
end if;
check_equal(d2.write_reg_data, behave_rt, result("for modsw"));
end loop;
end loop; end loop;
assert d2.valid = '1';

behave_rt := (others => '0');
if rb /= x"0000000000000000" then
rem32 := std_ulogic_vector(signed(ra(31 downto 0)) rem signed(rb(31 downto 0)));
if rem32(31) = '0' then
behave_rt := x"00000000" & rem32;
else
behave_rt := x"ffffffff" & rem32;
end if;
end if;
assert behave_rt = d2.write_reg_data
report "bad modsw expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
end loop; end loop;
end loop;
end loop;

-- test moduw
report "test moduw";
moduw_loop : for dlength in 1 to 4 loop
for vlength in 1 to dlength loop
for i in 0 to 100 loop
ra := std_ulogic_vector(resize(unsigned(pseudorand(dlength * 8)), 64));
rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64));

d1.dividend <= ra;
d1.divisor <= rb;
d1.is_signed <= '0';
d1.neg_result <= '0';
d1.is_extended <= '0';
d1.is_32bit <= '1';
d1.is_modulus <= '1';
d1.valid <= '1';


elsif run("Test moduw") then wait for clk_period;
moduw_loop : for dlength in 1 to 4 loop
for vlength in 1 to dlength loop d1.valid <= '0';
for i in 0 to 100 loop for j in 0 to 66 loop
ra := std_ulogic_vector(resize(unsigned(rnd.RandSlv(dlength * 8)), 64)); wait for clk_period;
rb := std_ulogic_vector(resize(unsigned(rnd.RandSlv(vlength * 8)), 64)); if d2.valid = '1' then

exit;
d1.dividend <= ra; end if;
d1.divisor <= rb;
d1.is_32bit <= '1';
d1.is_modulus <= '1';
d1.valid <= '1';

wait for clk_period;

d1.valid <= '0';
for j in 0 to 66 loop
wait for clk_period;
if d2.valid = '1' then
exit;
end if;
end loop;
check_true(?? d2.valid, result("for valid"));

behave_rt := (others => '0');
if rb /= x"0000000000000000" then
behave_rt := x"00000000" & std_ulogic_vector(unsigned(ra(31 downto 0)) rem unsigned(rb(31 downto 0)));
end if;
check_equal(d2.write_reg_data(31 downto 0), behave_rt(31 downto 0), result("for moduw"));
end loop;
end loop; end loop;
assert d2.valid = '1';

behave_rt := (others => '0');
if rb /= x"0000000000000000" then
behave_rt := x"00000000" & std_ulogic_vector(unsigned(ra(31 downto 0)) rem unsigned(rb(31 downto 0)));
end if;
assert behave_rt(31 downto 0) = d2.write_reg_data(31 downto 0)
report "bad moduw expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
end loop; end loop;
end if; end loop;
end loop; end loop;


test_runner_cleanup(runner); std.env.finish;
end process; end process;
end behave; end behave;

@ -1,298 +0,0 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.math_real.all;

library work;
use work.wishbone_types.all;

entity dmi_dtm is
generic(ABITS : INTEGER:=8;
DBITS : INTEGER:=64);

port(sys_clk : in std_ulogic;
sys_reset : in std_ulogic;
dmi_addr : out std_ulogic_vector(ABITS - 1 downto 0);
dmi_din : in std_ulogic_vector(DBITS - 1 downto 0);
dmi_dout : out std_ulogic_vector(DBITS - 1 downto 0);
dmi_req : out std_ulogic;
dmi_wr : out std_ulogic;
dmi_ack : in std_ulogic
-- dmi_err : in std_ulogic TODO: Add error response
);
end entity dmi_dtm;

architecture behaviour of dmi_dtm is
-- Signals coming out of the JTAGG block
signal jtag_reset_n : std_ulogic;
signal tdi : std_ulogic;
signal tdo : std_ulogic;
signal tck : std_ulogic;
signal jce1 : std_ulogic;
signal jshift : std_ulogic;
signal update : std_ulogic;

-- signals to match dmi_dtb_xilinx
signal jtag_reset : std_ulogic;
signal capture : std_ulogic;
signal jtag_clk : std_ulogic;
signal sel : std_ulogic;
signal shift : std_ulogic;

-- delays
signal jce1_d : std_ulogic;
constant TCK_DELAY : INTEGER := 8;
signal tck_d : std_ulogic_vector(TCK_DELAY+1 downto 1);

-- ** JTAG clock domain **

-- Shift register
signal shiftr : std_ulogic_vector(ABITS + DBITS + 1 downto 0);

-- Latched request
signal request : std_ulogic_vector(ABITS + DBITS + 1 downto 0);

-- A request is present
signal jtag_req : std_ulogic;

-- Synchronizer for jtag_rsp (sys clk -> jtag_clk)
signal dmi_ack_0 : std_ulogic;
signal dmi_ack_1 : std_ulogic;

-- ** sys clock domain **

-- Synchronizer for jtag_req (jtag clk -> sys clk)
signal jtag_req_0 : std_ulogic;
signal jtag_req_1 : std_ulogic;

-- ** combination signals
signal jtag_bsy : std_ulogic;
signal op_valid : std_ulogic;
signal rsp_op : std_ulogic_vector(1 downto 0);

-- ** Constants **
constant DMI_REQ_NOP : std_ulogic_vector(1 downto 0) := "00";
constant DMI_REQ_RD : std_ulogic_vector(1 downto 0) := "01";
constant DMI_REQ_WR : std_ulogic_vector(1 downto 0) := "10";
constant DMI_RSP_OK : std_ulogic_vector(1 downto 0) := "00";
constant DMI_RSP_BSY : std_ulogic_vector(1 downto 0) := "11";

attribute ASYNC_REG : string;
attribute ASYNC_REG of jtag_req_0: signal is "TRUE";
attribute ASYNC_REG of jtag_req_1: signal is "TRUE";
attribute ASYNC_REG of dmi_ack_0: signal is "TRUE";
attribute ASYNC_REG of dmi_ack_1: signal is "TRUE";

-- ECP5 JTAGG
component JTAGG is
generic (
ER1 : string := "ENABLED";
ER2 : string := "ENABLED"
);
port(
JTDO1 : in std_ulogic;
JTDO2 : in std_ulogic;
JTDI : out std_ulogic;
JTCK : out std_ulogic;
JRTI1 : out std_ulogic;
JRTI2 : out std_ulogic;
JSHIFT : out std_ulogic;
JUPDATE : out std_ulogic;
JRSTN : out std_ulogic;
JCE1 : out std_ulogic;
JCE2 : out std_ulogic
);
end component;

component LUT4 is
generic (
INIT : std_logic_vector
);
port(
A : in STD_ULOGIC;
B : in STD_ULOGIC;
C : in STD_ULOGIC;
D : in STD_ULOGIC;
Z : out STD_ULOGIC
);
end component;

begin

jtag: JTAGG
generic map(
ER2 => "DISABLED"
)
port map (
JTDO1 => tdo,
JTDO2 => '0',
JTDI => tdi,
JTCK => tck,
JRTI1 => open,
JRTI2 => open,
JSHIFT => jshift,
JUPDATE => update,
JRSTN => jtag_reset_n,
JCE1 => jce1,
JCE2 => open
);

-- JRTI1 looks like it could be connected to SEL, but
-- in practise JRTI1 is only high briefly, not for the duration
-- of the transmission. possibly mw_debug could be modified.
-- The ecp5 is probably the only jtag device anyway.
sel <= '1';

-- TDI needs to align with TCK, we use LUT delays here.
-- From https://github.com/enjoy-digital/litex/pull/1087
tck_d(1) <= tck;
del: for i in 1 to TCK_DELAY generate
attribute keep : boolean;
attribute keep of l: label is true;
begin
l: LUT4
generic map(
INIT => b"0000_0000_0000_0010"
)
port map (
A => tck_d(i),
B => '0', C => '0', D => '0',
Z => tck_d(i+1)
);
end generate;
jtag_clk <= tck_d(TCK_DELAY+1);

-- capture signal
jce1_sync : process(jtag_clk)
begin
if rising_edge(jtag_clk) then
jce1_d <= jce1;
capture <= jce1 and not jce1_d;
end if;
end process;

-- latch the shift signal, otherwise
-- we miss the last shift in
-- (maybe because we are delaying tck?)
shift_sync : process(jtag_clk)
begin
if (sys_reset = '1') then
shift <= '0';
elsif rising_edge(jtag_clk) then
shift <= jshift;
end if;
end process;

jtag_reset <= not jtag_reset_n;

-- dmi_req synchronization
dmi_req_sync : process(sys_clk)
begin
-- sys_reset is synchronous
if rising_edge(sys_clk) then
if (sys_reset = '1') then
jtag_req_0 <= '0';
jtag_req_1 <= '0';
else
jtag_req_0 <= jtag_req;
jtag_req_1 <= jtag_req_0;
end if;
end if;
end process;
dmi_req <= jtag_req_1;

-- dmi_ack synchronization
dmi_ack_sync: process(jtag_clk, jtag_reset)
begin
-- jtag_reset is async (see comments)
if jtag_reset = '1' then
dmi_ack_0 <= '0';
dmi_ack_1 <= '0';
elsif rising_edge(jtag_clk) then
dmi_ack_0 <= dmi_ack;
dmi_ack_1 <= dmi_ack_0;
end if;
end process;
-- jtag_bsy indicates whether we can start a new request, we can when
-- we aren't already processing one (jtag_req) and the synchronized ack
-- of the previous one is 0.
--
jtag_bsy <= jtag_req or dmi_ack_1;

-- decode request type in shift register
with shiftr(1 downto 0) select op_valid <=
'1' when DMI_REQ_RD,
'1' when DMI_REQ_WR,
'0' when others;

-- encode response op
rsp_op <= DMI_RSP_BSY when jtag_bsy = '1' else DMI_RSP_OK;

-- Some DMI out signals are directly driven from the request register
dmi_addr <= request(ABITS + DBITS + 1 downto DBITS + 2);
dmi_dout <= request(DBITS + 1 downto 2);
dmi_wr <= '1' when request(1 downto 0) = DMI_REQ_WR else '0';

-- TDO is wired to shift register bit 0
tdo <= shiftr(0);

-- Main state machine. Handles shift registers, request latch and
-- jtag_req latch. Could be split into 3 processes but it's probably
-- not worthwhile.
--
shifter: process(jtag_clk, jtag_reset, sys_reset)
begin
if jtag_reset = '1' or sys_reset = '1' then
shiftr <= (others => '0');
jtag_req <= '0';
request <= (others => '0');
elsif rising_edge(jtag_clk) then

-- Handle jtag "commands" when sel is 1
if sel = '1' then
-- Shift state, rotate the register
if shift = '1' then
shiftr <= tdi & shiftr(ABITS + DBITS + 1 downto 1);
end if;

-- Update state (trigger)
--
-- Latch the request if we aren't already processing one and
-- it has a valid command opcode.
--
if update = '1' and op_valid = '1' then
if jtag_bsy = '0' then
request <= shiftr;
jtag_req <= '1';
end if;
-- Set the shift register "op" to "busy". This will prevent
-- us from re-starting the command on the next update if
-- the command completes before that.
shiftr(1 downto 0) <= DMI_RSP_BSY;
end if;

-- Request completion.
--
-- Capture the response data for reads and clear request flag.
--
-- Note: We clear req (and thus dmi_req) here which relies on tck
-- ticking and sel set. This means we are stuck with dmi_req up if
-- the jtag interface stops. Slaves must be resilient to this.
--
if jtag_req = '1' and dmi_ack_1 = '1' then
jtag_req <= '0';
if request(1 downto 0) = DMI_REQ_RD then
request(DBITS + 1 downto 2) <= dmi_din;
end if;
end if;

-- Capture state, grab latch content with updated status
if capture = '1' then
shiftr <= request(ABITS + DBITS + 1 downto 2) & rsp_op;
end if;

end if;
end if;
end process;
end architecture behaviour;

@ -19,12 +19,12 @@ architecture behave of dmi_dtm_tb is
constant jclk_period : time := 30 ns; constant jclk_period : time := 30 ns;


-- DMI debug bus signals -- DMI debug bus signals
signal dmi_addr : std_ulogic_vector(7 downto 0); signal dmi_addr : std_ulogic_vector(7 downto 0);
signal dmi_din : std_ulogic_vector(63 downto 0); signal dmi_din : std_ulogic_vector(63 downto 0);
signal dmi_dout : std_ulogic_vector(63 downto 0); signal dmi_dout : std_ulogic_vector(63 downto 0);
signal dmi_req : std_ulogic; signal dmi_req : std_ulogic;
signal dmi_wr : std_ulogic; signal dmi_wr : std_ulogic;
signal dmi_ack : std_ulogic; signal dmi_ack : std_ulogic;


-- Global JTAG signals (used by BSCANE2 inside dmi_dtm -- Global JTAG signals (used by BSCANE2 inside dmi_dtm
alias j : glob_jtag_t is glob_jtag; alias j : glob_jtag_t is glob_jtag;
@ -35,216 +35,216 @@ architecture behave of dmi_dtm_tb is


begin begin
dtm: entity work.dmi_dtm dtm: entity work.dmi_dtm
generic map( generic map(
ABITS => 8, ABITS => 8,
DBITS => 64 DBITS => 64
) )
port map( port map(
sys_clk => clk, sys_clk => clk,
sys_reset => rst, sys_reset => rst,
dmi_addr => dmi_addr, dmi_addr => dmi_addr,
dmi_din => dmi_din, dmi_din => dmi_din,
dmi_dout => dmi_dout, dmi_dout => dmi_dout,
dmi_req => dmi_req, dmi_req => dmi_req,
dmi_wr => dmi_wr, dmi_wr => dmi_wr,
dmi_ack => dmi_ack dmi_ack => dmi_ack
); );


simple_ram_0: entity work.wishbone_bram_wrapper simple_ram_0: entity work.wishbone_bram_wrapper
generic map(RAM_INIT_FILE => "main_ram.bin", generic map(RAM_INIT_FILE => "main_ram.bin",
MEMORY_SIZE => 524288) MEMORY_SIZE => 524288)
port map(clk => clk, rst => rst, port map(clk => clk, rst => rst,
wishbone_in => wishbone_ram_out, wishbone_in => wishbone_ram_out,
wishbone_out => wishbone_ram_in); wishbone_out => wishbone_ram_in);


wishbone_debug_0: entity work.wishbone_debug_master wishbone_debug_0: entity work.wishbone_debug_master
port map(clk => clk, rst => rst, port map(clk => clk, rst => rst,
dmi_addr => dmi_addr(1 downto 0), dmi_addr => dmi_addr(1 downto 0),
dmi_dout => dmi_din, dmi_dout => dmi_din,
dmi_din => dmi_dout, dmi_din => dmi_dout,
dmi_wr => dmi_wr, dmi_wr => dmi_wr,
dmi_ack => dmi_ack, dmi_ack => dmi_ack,
dmi_req => dmi_req, dmi_req => dmi_req,
wb_in => wishbone_ram_in, wb_in => wishbone_ram_in,
wb_out => wishbone_ram_out); wb_out => wishbone_ram_out);


-- system clock -- system clock
sys_clk: process sys_clk: process
begin begin
clk <= '1'; clk <= '1';
wait for clk_period / 2; wait for clk_period / 2;
clk <= '0'; clk <= '0';
wait for clk_period / 2; wait for clk_period / 2;
end process sys_clk; end process sys_clk;


-- system sim: just reset and wait -- system sim: just reset and wait
sys_sim: process sys_sim: process
begin begin
rst <= '1'; rst <= '1';
wait for clk_period; wait for clk_period;
rst <= '0'; rst <= '0';
wait; wait;
end process; end process;


-- jtag sim process -- jtag sim process
sim_jtag: process sim_jtag: process
procedure clock(count: in INTEGER) is procedure clock(count: in INTEGER) is
begin begin
for i in 1 to count loop for i in 1 to count loop
j.tck <= '0'; j.tck <= '0';
wait for jclk_period/2; wait for jclk_period/2;
j.tck <= '1'; j.tck <= '1';
wait for jclk_period/2; wait for jclk_period/2;
end loop; end loop;
end procedure clock; end procedure clock;


procedure shift_out(val: in std_ulogic_vector) is procedure shift_out(val: in std_ulogic_vector) is
begin begin
for i in 0 to val'length-1 loop for i in 0 to val'length-1 loop
j.tdi <= val(i); j.tdi <= val(i);
clock(1); clock(1);
end loop; end loop;
end procedure shift_out; end procedure shift_out;


procedure shift_in(val: out std_ulogic_vector) is procedure shift_in(val: out std_ulogic_vector) is
begin begin
for i in val'length-1 downto 0 loop for i in val'length-1 downto 0 loop
val := j.tdo & val(val'length-1 downto 1); val := j.tdo & val(val'length-1 downto 1);
clock(1); clock(1);
end loop; end loop;
end procedure shift_in; end procedure shift_in;


procedure send_command( procedure send_command(
addr : in std_ulogic_vector(7 downto 0); addr : in std_ulogic_vector(7 downto 0);
data : in std_ulogic_vector(63 downto 0); data : in std_ulogic_vector(63 downto 0);
op : in std_ulogic_vector(1 downto 0)) is op : in std_ulogic_vector(1 downto 0)) is
begin begin
j.capture <= '1'; j.capture <= '1';
clock(1); clock(1);
j.capture <= '0'; j.capture <= '0';
clock(1); clock(1);
j.shift <= '1'; j.shift <= '1';
shift_out(op); shift_out(op);
shift_out(data); shift_out(data);
shift_out(addr); shift_out(addr);
j.shift <= '0'; j.shift <= '0';
j.update <= '1'; j.update <= '1';
clock(1); clock(1);
j.update <= '0'; j.update <= '0';
clock(1); clock(1);
end procedure send_command; end procedure send_command;


procedure read_resp( procedure read_resp(
op : out std_ulogic_vector(1 downto 0); op : out std_ulogic_vector(1 downto 0);
data : out std_ulogic_vector(63 downto 0)) is data : out std_ulogic_vector(63 downto 0)) is


variable addr : std_ulogic_vector(7 downto 0); variable addr : std_ulogic_vector(7 downto 0);
begin begin
j.capture <= '1'; j.capture <= '1';
clock(1); clock(1);
j.capture <= '0'; j.capture <= '0';
clock(1); clock(1);
j.shift <= '1'; j.shift <= '1';
shift_in(op); shift_in(op);
shift_in(data); shift_in(data);
shift_in(addr); shift_in(addr);
j.shift <= '0'; j.shift <= '0';
j.update <= '1'; j.update <= '1';
clock(1); clock(1);
j.update <= '0'; j.update <= '0';
clock(1); clock(1);
end procedure read_resp; end procedure read_resp;


procedure dmi_write(addr : in std_ulogic_vector(7 downto 0); procedure dmi_write(addr : in std_ulogic_vector(7 downto 0);
data : in std_ulogic_vector(63 downto 0)) is data : in std_ulogic_vector(63 downto 0)) is
variable resp_op : std_ulogic_vector(1 downto 0); variable resp_op : std_ulogic_vector(1 downto 0);
variable resp_data : std_ulogic_vector(63 downto 0); variable resp_data : std_ulogic_vector(63 downto 0);
variable timeout : integer; variable timeout : integer;
begin begin
send_command(addr, data, "10"); send_command(addr, data, "10");
loop loop
read_resp(resp_op, resp_data); read_resp(resp_op, resp_data);
case resp_op is case resp_op is
when "00" => when "00" =>
return; return;
when "11" => when "11" =>
timeout := timeout + 1; timeout := timeout + 1;
assert timeout < 0 assert timeout < 0
report "dmi_write timed out !" severity error; report "dmi_write timed out !" severity error;
when others => when others =>
assert 0 > 1 report "dmi_write got odd status: " & assert 0 > 1 report "dmi_write got odd status: " &
to_hstring(resp_op) severity error; to_hstring(resp_op) severity error;
end case; end case;
end loop; end loop;
end procedure dmi_write; end procedure dmi_write;


procedure dmi_read(addr : in std_ulogic_vector(7 downto 0); procedure dmi_read(addr : in std_ulogic_vector(7 downto 0);
data : out std_ulogic_vector(63 downto 0)) is data : out std_ulogic_vector(63 downto 0)) is
variable resp_op : std_ulogic_vector(1 downto 0); variable resp_op : std_ulogic_vector(1 downto 0);
variable timeout : integer; variable timeout : integer;
begin begin
send_command(addr, (others => '0'), "01"); send_command(addr, (others => '0'), "01");
loop loop
read_resp(resp_op, data); read_resp(resp_op, data);
case resp_op is case resp_op is
when "00" => when "00" =>
return; return;
when "11" => when "11" =>
timeout := timeout + 1; timeout := timeout + 1;
assert timeout < 0 assert timeout < 0
report "dmi_read timed out !" severity error; report "dmi_read timed out !" severity error;
when others => when others =>
assert 0 > 1 report "dmi_read got odd status: " & assert 0 > 1 report "dmi_read got odd status: " &
to_hstring(resp_op) severity error; to_hstring(resp_op) severity error;
end case; end case;
end loop; end loop;
end procedure dmi_read; end procedure dmi_read;


variable data : std_ulogic_vector(63 downto 0); variable data : std_ulogic_vector(63 downto 0);
begin begin
-- init & reset -- init & reset
j.reset <= '1'; j.reset <= '1';
j.sel <= "0000"; j.sel <= "0000";
j.capture <= '0'; j.capture <= '0';
j.update <= '0'; j.update <= '0';
j.shift <= '0'; j.shift <= '0';
j.tdi <= '0'; j.tdi <= '0';
j.tms <= '0'; j.tms <= '0';
j.runtest <= '0'; j.runtest <= '0';
clock(5); clock(5);
j.reset <= '0'; j.reset <= '0';
clock(5); clock(5);


-- select chain 2 -- select chain 2
j.sel <= "0010"; j.sel <= "0010";
clock(1); clock(1);


-- send command -- send command
dmi_read(x"00", data); dmi_read(x"00", data);
report "Read addr reg:" & to_hstring(data); report "Read addr reg:" & to_hstring(data);
report "Writing addr reg to all 1's"; report "Writing addr reg to all 1's";
dmi_write(x"00", (others => '1')); dmi_write(x"00", (others => '1'));
dmi_read(x"00", data); dmi_read(x"00", data);
report "Read addr reg:" & to_hstring(data); report "Read addr reg:" & to_hstring(data);


report "Writing ctrl reg to all 1's"; report "Writing ctrl reg to all 1's";
dmi_write(x"02", (others => '1')); dmi_write(x"02", (others => '1'));
dmi_read(x"02", data); dmi_read(x"02", data);
report "Read ctrl reg:" & to_hstring(data); report "Read ctrl reg:" & to_hstring(data);


report "Read memory at 0...\n"; report "Read memory at 0...\n";
dmi_write(x"00", x"0000000000000000"); dmi_write(x"00", x"0000000000000000");
dmi_write(x"02", x"00000000000007ff"); dmi_write(x"02", x"00000000000007ff");
dmi_read(x"01", data); dmi_read(x"01", data);
report "00:" & to_hstring(data); report "00:" & to_hstring(data);
dmi_read(x"01", data); dmi_read(x"01", data);
report "08:" & to_hstring(data); report "08:" & to_hstring(data);
dmi_read(x"01", data); dmi_read(x"01", data);
report "10:" & to_hstring(data); report "10:" & to_hstring(data);
dmi_read(x"01", data); dmi_read(x"01", data);
report "18:" & to_hstring(data); report "18:" & to_hstring(data);
clock(10); clock(10);
std.env.finish; std.env.finish;
end process; end process;
end behave; end behave;

@ -66,59 +66,59 @@ use unisim.vcomponents.all;


entity dmi_dtm is entity dmi_dtm is
generic(ABITS : INTEGER:=8; generic(ABITS : INTEGER:=8;
DBITS : INTEGER:=32); DBITS : INTEGER:=32);


port(sys_clk : in std_ulogic; port(sys_clk : in std_ulogic;
sys_reset : in std_ulogic; sys_reset : in std_ulogic;
dmi_addr : out std_ulogic_vector(ABITS - 1 downto 0); dmi_addr : out std_ulogic_vector(ABITS - 1 downto 0);
dmi_din : in std_ulogic_vector(DBITS - 1 downto 0); dmi_din : in std_ulogic_vector(DBITS - 1 downto 0);
dmi_dout : out std_ulogic_vector(DBITS - 1 downto 0); dmi_dout : out std_ulogic_vector(DBITS - 1 downto 0);
dmi_req : out std_ulogic; dmi_req : out std_ulogic;
dmi_wr : out std_ulogic; dmi_wr : out std_ulogic;
dmi_ack : in std_ulogic dmi_ack : in std_ulogic
-- dmi_err : in std_ulogic TODO: Add error response -- dmi_err : in std_ulogic TODO: Add error response
); );
end entity dmi_dtm; end entity dmi_dtm;


architecture behaviour of dmi_dtm is architecture behaviour of dmi_dtm is


-- Signals coming out of the BSCANE2 block -- Signals coming out of the BSCANE2 block
signal jtag_reset : std_ulogic; signal jtag_reset : std_ulogic;
signal capture : std_ulogic; signal capture : std_ulogic;
signal update : std_ulogic; signal update : std_ulogic;
signal drck : std_ulogic; signal drck : std_ulogic;
signal jtag_clk : std_ulogic; signal jtag_clk : std_ulogic;
signal sel : std_ulogic; signal sel : std_ulogic;
signal shift : std_ulogic; signal shift : std_ulogic;
signal tdi : std_ulogic; signal tdi : std_ulogic;
signal tdo : std_ulogic; signal tdo : std_ulogic;
signal tck : std_ulogic; signal tck : std_ulogic;


-- ** JTAG clock domain ** -- ** JTAG clock domain **


-- Shift register -- Shift register
signal shiftr : std_ulogic_vector(ABITS + DBITS + 1 downto 0); signal shiftr : std_ulogic_vector(ABITS + DBITS + 1 downto 0);


-- Latched request -- Latched request
signal request : std_ulogic_vector(ABITS + DBITS + 1 downto 0); signal request : std_ulogic_vector(ABITS + DBITS + 1 downto 0);


-- A request is present -- A request is present
signal jtag_req : std_ulogic; signal jtag_req : std_ulogic;


-- Synchronizer for jtag_rsp (sys clk -> jtag_clk) -- Synchronizer for jtag_rsp (sys clk -> jtag_clk)
signal dmi_ack_0 : std_ulogic; signal dmi_ack_0 : std_ulogic;
signal dmi_ack_1 : std_ulogic; signal dmi_ack_1 : std_ulogic;


-- ** sys clock domain ** -- ** sys clock domain **


-- Synchronizer for jtag_req (jtag clk -> sys clk) -- Synchronizer for jtag_req (jtag clk -> sys clk)
signal jtag_req_0 : std_ulogic; signal jtag_req_0 : std_ulogic;
signal jtag_req_1 : std_ulogic; signal jtag_req_1 : std_ulogic;


-- ** combination signals -- ** combination signals
signal jtag_bsy : std_ulogic; signal jtag_bsy : std_ulogic;
signal op_valid : std_ulogic; signal op_valid : std_ulogic;
signal rsp_op : std_ulogic_vector(1 downto 0); signal rsp_op : std_ulogic_vector(1 downto 0);


-- ** Constants ** -- ** Constants **
constant DMI_REQ_NOP : std_ulogic_vector(1 downto 0) := "00"; constant DMI_REQ_NOP : std_ulogic_vector(1 downto 0) := "00";
@ -137,22 +137,22 @@ begin
-- Implement the Xilinx bscan2 for series 7 devices (TODO: use PoC to -- Implement the Xilinx bscan2 for series 7 devices (TODO: use PoC to
-- wrap this if compatibility is required with older devices). -- wrap this if compatibility is required with older devices).
bscan : BSCANE2 bscan : BSCANE2
generic map ( generic map (
JTAG_CHAIN => 2 JTAG_CHAIN => 2
) )
port map ( port map (
CAPTURE => capture, CAPTURE => capture,
DRCK => drck, DRCK => drck,
RESET => jtag_reset, RESET => jtag_reset,
RUNTEST => open, RUNTEST => open,
SEL => sel, SEL => sel,
SHIFT => shift, SHIFT => shift,
TCK => tck, TCK => tck,
TDI => tdi, TDI => tdi,
TMS => open, TMS => open,
UPDATE => update, UPDATE => update,
TDO => tdo TDO => tdo
); );


-- Some examples out there suggest buffering the clock so it's -- Some examples out there suggest buffering the clock so it's
-- treated as a proper clock net. This is probably needed when using -- treated as a proper clock net. This is probably needed when using
@ -160,39 +160,39 @@ begin
-- missing the update phase so maybe not... -- missing the update phase so maybe not...
-- --
clkbuf : BUFG clkbuf : BUFG
port map ( port map (
-- I => drck, -- I => drck,
I => tck, I => tck,
O => jtag_clk O => jtag_clk
); );


-- dmi_req synchronization -- dmi_req synchronization
dmi_req_sync : process(sys_clk) dmi_req_sync : process(sys_clk)
begin begin
-- sys_reset is synchronous -- sys_reset is synchronous
if rising_edge(sys_clk) then if rising_edge(sys_clk) then
if (sys_reset = '1') then if (sys_reset = '1') then
jtag_req_0 <= '0'; jtag_req_0 <= '0';
jtag_req_1 <= '0'; jtag_req_1 <= '0';
else else
jtag_req_0 <= jtag_req; jtag_req_0 <= jtag_req;
jtag_req_1 <= jtag_req_0; jtag_req_1 <= jtag_req_0;
end if; end if;
end if; end if;
end process; end process;
dmi_req <= jtag_req_1; dmi_req <= jtag_req_1;


-- dmi_ack synchronization -- dmi_ack synchronization
dmi_ack_sync: process(jtag_clk, jtag_reset) dmi_ack_sync: process(jtag_clk, jtag_reset)
begin begin
-- jtag_reset is async (see comments) -- jtag_reset is async (see comments)
if jtag_reset = '1' then if jtag_reset = '1' then
dmi_ack_0 <= '0'; dmi_ack_0 <= '0';
dmi_ack_1 <= '0'; dmi_ack_1 <= '0';
elsif rising_edge(jtag_clk) then elsif rising_edge(jtag_clk) then
dmi_ack_0 <= dmi_ack; dmi_ack_0 <= dmi_ack;
dmi_ack_1 <= dmi_ack_0; dmi_ack_1 <= dmi_ack_0;
end if; end if;
end process; end process;
-- jtag_bsy indicates whether we can start a new request, we can when -- jtag_bsy indicates whether we can start a new request, we can when
@ -203,9 +203,9 @@ begin


-- decode request type in shift register -- decode request type in shift register
with shiftr(1 downto 0) select op_valid <= with shiftr(1 downto 0) select op_valid <=
'1' when DMI_REQ_RD, '1' when DMI_REQ_RD,
'1' when DMI_REQ_WR, '1' when DMI_REQ_WR,
'0' when others; '0' when others;


-- encode response op -- encode response op
rsp_op <= DMI_RSP_BSY when jtag_bsy = '1' else DMI_RSP_OK; rsp_op <= DMI_RSP_BSY when jtag_bsy = '1' else DMI_RSP_OK;
@ -224,57 +224,57 @@ begin
-- --
shifter: process(jtag_clk, jtag_reset, sys_reset) shifter: process(jtag_clk, jtag_reset, sys_reset)
begin begin
if jtag_reset = '1' or sys_reset = '1' then if jtag_reset = '1' or sys_reset = '1' then
shiftr <= (others => '0'); shiftr <= (others => '0');
jtag_req <= '0'; jtag_req <= '0';
request <= (others => '0'); request <= (others => '0');
elsif rising_edge(jtag_clk) then elsif rising_edge(jtag_clk) then


-- Handle jtag "commands" when sel is 1 -- Handle jtag "commands" when sel is 1
if sel = '1' then if sel = '1' then
-- Shift state, rotate the register -- Shift state, rotate the register
if shift = '1' then if shift = '1' then
shiftr <= tdi & shiftr(ABITS + DBITS + 1 downto 1); shiftr <= tdi & shiftr(ABITS + DBITS + 1 downto 1);
end if; end if;


-- Update state (trigger) -- Update state (trigger)
-- --
-- Latch the request if we aren't already processing one and -- Latch the request if we aren't already processing one and
-- it has a valid command opcode. -- it has a valid command opcode.
-- --
if update = '1' and op_valid = '1' then if update = '1' and op_valid = '1' then
if jtag_bsy = '0' then if jtag_bsy = '0' then
request <= shiftr; request <= shiftr;
jtag_req <= '1'; jtag_req <= '1';
end if; end if;
-- Set the shift register "op" to "busy". This will prevent -- Set the shift register "op" to "busy". This will prevent
-- us from re-starting the command on the next update if -- us from re-starting the command on the next update if
-- the command completes before that. -- the command completes before that.
shiftr(1 downto 0) <= DMI_RSP_BSY; shiftr(1 downto 0) <= DMI_RSP_BSY;
end if; end if;


-- Request completion. -- Request completion.
-- --
-- Capture the response data for reads and clear request flag. -- Capture the response data for reads and clear request flag.
-- --
-- Note: We clear req (and thus dmi_req) here which relies on tck -- Note: We clear req (and thus dmi_req) here which relies on tck
-- ticking and sel set. This means we are stuck with dmi_req up if -- ticking and sel set. This means we are stuck with dmi_req up if
-- the jtag interface stops. Slaves must be resilient to this. -- the jtag interface stops. Slaves must be resilient to this.
-- --
if jtag_req = '1' and dmi_ack_1 = '1' then if jtag_req = '1' and dmi_ack_1 = '1' then
jtag_req <= '0'; jtag_req <= '0';
if request(1 downto 0) = DMI_REQ_RD then if request(1 downto 0) = DMI_REQ_RD then
request(DBITS + 1 downto 2) <= dmi_din; request(DBITS + 1 downto 2) <= dmi_din;
end if; end if;
end if; end if;


-- Capture state, grab latch content with updated status -- Capture state, grab latch content with updated status
if capture = '1' then if capture = '1' then
shiftr <= request(ABITS + DBITS + 1 downto 2) & rsp_op; shiftr <= request(ABITS + DBITS + 1 downto 2) & rsp_op;
end if; end if;


end if; end if;
end if; end if;
end process; end process;
end architecture behaviour; end architecture behaviour;



@ -44,7 +44,6 @@ begin
DRAM_ABITS => 24, DRAM_ABITS => 24,
DRAM_ALINES => 1, DRAM_ALINES => 1,
DRAM_DLINES => 16, DRAM_DLINES => 16,
DRAM_CKLINES => 1,
DRAM_PORT_WIDTH => 128, DRAM_PORT_WIDTH => 128,
PAYLOAD_FILE => DRAM_INIT_FILE, PAYLOAD_FILE => DRAM_INIT_FILE,
PAYLOAD_SIZE => DRAM_INIT_SIZE PAYLOAD_SIZE => DRAM_INIT_SIZE
@ -105,10 +104,10 @@ begin


-- Read data receive queue -- Read data receive queue
data_queue: entity work.sync_fifo data_queue: entity work.sync_fifo
generic map ( generic map (
DEPTH => 16, DEPTH => 16,
WIDTH => rd_data'length WIDTH => rd_data'length
) )
port map ( port map (
clk => clk, clk => clk,
reset => soc_rst or reset_acks, reset => soc_rst or reset_acks,
@ -251,10 +250,10 @@ begin
report "Back to back 4 stores 4 reads on hit..."; report "Back to back 4 stores 4 reads on hit...";
clr_acks; clr_acks;
for i in 0 to 3 loop for i in 0 to 3 loop
wb_write(add_off(a, i), make_pattern(i), x"ff"); wb_write(add_off(a, i*8), make_pattern(i), x"ff");
end loop; end loop;
for i in 0 to 3 loop for i in 0 to 3 loop
wb_read(add_off(a, i)); wb_read(add_off(a, i*8));
end loop; end loop;
wait_acks(8); wait_acks(8);
for i in 0 to 7 loop for i in 0 to 7 loop
@ -269,10 +268,10 @@ begin
a(10) := '1'; a(10) := '1';
clr_acks; clr_acks;
for i in 0 to 3 loop for i in 0 to 3 loop
wb_write(add_off(a, i), make_pattern(i), x"ff"); wb_write(add_off(a, i*8), make_pattern(i), x"ff");
end loop; end loop;
for i in 0 to 3 loop for i in 0 to 3 loop
wb_read(add_off(a, i)); wb_read(add_off(a, i*8));
end loop; end loop;
wait_acks(8); wait_acks(8);
for i in 0 to 7 loop for i in 0 to 7 loop
@ -287,8 +286,8 @@ begin
a(10) := '1'; a(10) := '1';
clr_acks; clr_acks;
for i in 0 to 3 loop for i in 0 to 3 loop
wb_write(add_off(a, i), make_pattern(i), x"ff"); wb_write(add_off(a, i*8), make_pattern(i), x"ff");
wb_read(add_off(a, i)); wb_read(add_off(a, i*8));
end loop; end loop;
wait_acks(8); wait_acks(8);
for i in 0 to 3 loop for i in 0 to 3 loop
@ -300,29 +299,29 @@ begin
a(11) := '1'; a(11) := '1';
clr_acks; clr_acks;
wb_write(add_off(a, 0), x"1111111100000000", x"ff"); wb_write(add_off(a, 0), x"1111111100000000", x"ff");
wb_write(add_off(a, 1), x"3333333322222222", x"ff"); wb_write(add_off(a, 8), x"3333333322222222", x"ff");
wb_write(add_off(a, 2), x"5555555544444444", x"ff"); wb_write(add_off(a, 16), x"5555555544444444", x"ff");
wb_write(add_off(a, 3), x"7777777766666666", x"ff"); wb_write(add_off(a, 24), x"7777777766666666", x"ff");
wb_write(add_off(a, 4), x"9999999988888888", x"ff"); wb_write(add_off(a, 32), x"9999999988888888", x"ff");
wb_write(add_off(a, 5), x"bbbbbbbbaaaaaaaa", x"ff"); wb_write(add_off(a, 40), x"bbbbbbbbaaaaaaaa", x"ff");
wb_write(add_off(a, 6), x"ddddddddcccccccc", x"ff"); wb_write(add_off(a, 48), x"ddddddddcccccccc", x"ff");
wb_write(add_off(a, 7), x"ffffffffeeeeeeee", x"ff"); wb_write(add_off(a, 56), x"ffffffffeeeeeeee", x"ff");
wb_write(add_off(a, 8), x"1111111100000000", x"ff"); wb_write(add_off(a, 64), x"1111111100000000", x"ff");
wb_write(add_off(a, 9), x"3333333322222222", x"ff"); wb_write(add_off(a, 72), x"3333333322222222", x"ff");
wb_write(add_off(a, 10), x"5555555544444444", x"ff"); wb_write(add_off(a, 80), x"5555555544444444", x"ff");
wb_write(add_off(a, 11), x"7777777766666666", x"ff"); wb_write(add_off(a, 88), x"7777777766666666", x"ff");
wb_write(add_off(a, 12), x"9999999988888888", x"ff"); wb_write(add_off(a, 96), x"9999999988888888", x"ff");
wb_write(add_off(a, 13), x"bbbbbbbbaaaaaaaa", x"ff"); wb_write(add_off(a,104), x"bbbbbbbbaaaaaaaa", x"ff");
wb_write(add_off(a, 14), x"ddddddddcccccccc", x"ff"); wb_write(add_off(a,112), x"ddddddddcccccccc", x"ff");
wb_write(add_off(a, 15), x"ffffffffeeeeeeee", x"ff"); wb_write(add_off(a,120), x"ffffffffeeeeeeee", x"ff");
wait_acks(16); wait_acks(16);


report "Scattered from middle of line..."; report "Scattered from middle of line...";
clr_acks; clr_acks;
wb_read(add_off(a, 3)); wb_read(add_off(a,24));
wb_read(add_off(a, 4)); wb_read(add_off(a,32));
wb_read(add_off(a, 0)); wb_read(add_off(a, 0));
wb_read(add_off(a, 2)); wb_read(add_off(a,16));
wait_acks(4); wait_acks(4);
read_data(d); read_data(d);
assert d = x"7777777766666666" report "bad data (24), got " & to_hstring(d) severity failure; assert d = x"7777777766666666" report "bad data (24), got " & to_hstring(d) severity failure;

@ -14,7 +14,6 @@ entity execute1 is
generic ( generic (
EX1_BYPASS : boolean := true; EX1_BYPASS : boolean := true;
HAS_FPU : boolean := true; HAS_FPU : boolean := true;
HAS_SHORT_MULT : boolean := false;
-- Non-zero to enable log data collection -- Non-zero to enable log data collection
LOG_LENGTH : natural := 0 LOG_LENGTH : natural := 0
); );
@ -46,12 +45,6 @@ entity execute1 is
icache_inval : out std_ulogic; icache_inval : out std_ulogic;
terminate_out : out std_ulogic; terminate_out : out std_ulogic;


-- PMU event buses
wb_events : in WritebackEventType;
ls_events : in Loadstore1EventType;
dc_events : in DcacheEventType;
ic_events : in IcacheEventType;

log_out : out std_ulogic_vector(14 downto 0); log_out : out std_ulogic_vector(14 downto 0);
log_rd_addr : out std_ulogic_vector(31 downto 0); log_rd_addr : out std_ulogic_vector(31 downto 0);
log_rd_data : in std_ulogic_vector(63 downto 0); log_rd_data : in std_ulogic_vector(63 downto 0);
@ -65,7 +58,6 @@ architecture behaviour of execute1 is
cur_instr : Decode2ToExecute1Type; cur_instr : Decode2ToExecute1Type;
busy: std_ulogic; busy: std_ulogic;
terminate: std_ulogic; terminate: std_ulogic;
intr_pending : std_ulogic;
fp_exception_next : std_ulogic; fp_exception_next : std_ulogic;
trace_next : std_ulogic; trace_next : std_ulogic;
prev_op : insn_type_t; prev_op : insn_type_t;
@ -74,21 +66,14 @@ architecture behaviour of execute1 is
mul_finish : std_ulogic; mul_finish : std_ulogic;
div_in_progress : std_ulogic; div_in_progress : std_ulogic;
cntz_in_progress : std_ulogic; cntz_in_progress : std_ulogic;
no_instr_avail : std_ulogic;
instr_dispatch : std_ulogic;
ext_interrupt : std_ulogic;
taken_branch_event : std_ulogic;
br_mispredict : std_ulogic;
log_addr_spr : std_ulogic_vector(31 downto 0); log_addr_spr : std_ulogic_vector(31 downto 0);
end record; end record;
constant reg_type_init : reg_type := constant reg_type_init : reg_type :=
(e => Execute1ToWritebackInit, (e => Execute1ToWritebackInit,
cur_instr => Decode2ToExecute1Init, cur_instr => Decode2ToExecute1Init,
busy => '0', terminate => '0', intr_pending => '0', busy => '0', terminate => '0',
fp_exception_next => '0', trace_next => '0', prev_op => OP_ILLEGAL, br_taken => '0', fp_exception_next => '0', trace_next => '0', prev_op => OP_ILLEGAL, br_taken => '0',
mul_in_progress => '0', mul_finish => '0', div_in_progress => '0', cntz_in_progress => '0', mul_in_progress => '0', mul_finish => '0', div_in_progress => '0', cntz_in_progress => '0',
no_instr_avail => '0', instr_dispatch => '0', ext_interrupt => '0',
taken_branch_event => '0', br_mispredict => '0',
others => (others => '0')); others => (others => '0'));


signal r, rin : reg_type; signal r, rin : reg_type;
@ -96,23 +81,23 @@ architecture behaviour of execute1 is
signal a_in, b_in, c_in : std_ulogic_vector(63 downto 0); signal a_in, b_in, c_in : std_ulogic_vector(63 downto 0);
signal cr_in : std_ulogic_vector(31 downto 0); signal cr_in : std_ulogic_vector(31 downto 0);
signal xerc_in : xer_common_t; signal xerc_in : xer_common_t;
signal mshort_p : std_ulogic_vector(31 downto 0) := (others => '0');


signal valid_in : std_ulogic; signal valid_in : std_ulogic;
signal ctrl: ctrl_t; signal ctrl: ctrl_t := (others => (others => '0'));
signal ctrl_tmp: ctrl_t; signal ctrl_tmp: ctrl_t := (others => (others => '0'));
signal right_shift, rot_clear_left, rot_clear_right: std_ulogic; signal right_shift, rot_clear_left, rot_clear_right: std_ulogic;
signal rot_sign_ext: std_ulogic; signal rot_sign_ext: std_ulogic;
signal rotator_result: std_ulogic_vector(63 downto 0); signal rotator_result: std_ulogic_vector(63 downto 0);
signal rotator_carry: std_ulogic; signal rotator_carry: std_ulogic;
signal logical_result: std_ulogic_vector(63 downto 0); signal logical_result: std_ulogic_vector(63 downto 0);
signal do_popcnt: std_ulogic; signal countzero_result: std_ulogic_vector(63 downto 0);
signal countbits_result: std_ulogic_vector(63 downto 0);
signal alu_result: std_ulogic_vector(63 downto 0); signal alu_result: std_ulogic_vector(63 downto 0);
signal adder_result: std_ulogic_vector(63 downto 0); signal adder_result: std_ulogic_vector(63 downto 0);
signal misc_result: std_ulogic_vector(63 downto 0); signal misc_result: std_ulogic_vector(63 downto 0);
signal muldiv_result: std_ulogic_vector(63 downto 0); signal muldiv_result: std_ulogic_vector(63 downto 0);
signal spr_result: std_ulogic_vector(63 downto 0); signal spr_result: std_ulogic_vector(63 downto 0);
signal result_mux_sel: std_ulogic_vector(2 downto 0);
signal sub_mux_sel: std_ulogic_vector(2 downto 0);
signal next_nia : std_ulogic_vector(63 downto 0); signal next_nia : std_ulogic_vector(63 downto 0);
signal current: Decode2ToExecute1Type; signal current: Decode2ToExecute1Type;


@ -139,10 +124,6 @@ architecture behaviour of execute1 is
signal random_cond : std_ulogic_vector(63 downto 0); signal random_cond : std_ulogic_vector(63 downto 0);
signal random_err : std_ulogic; signal random_err : std_ulogic;


-- PMU signals
signal x_to_pmu : Execute1ToPMUType;
signal pmu_to_x : PMUToExecute1Type;

-- signals for logging -- signals for logging
signal exception_log : std_ulogic; signal exception_log : std_ulogic;
signal irq_valid_log : std_ulogic; signal irq_valid_log : std_ulogic;
@ -231,24 +212,6 @@ architecture behaviour of execute1 is
return msr_out; return msr_out;
end; end;


-- Work out whether a signed value fits into n bits,
-- that is, see if it is in the range -2^(n-1) .. 2^(n-1) - 1
function fits_in_n_bits(val: std_ulogic_vector; n: integer) return boolean is
variable x, xp1: std_ulogic_vector(val'left downto val'right);
begin
x := val;
if val(val'left) = '0' then
x := not val;
end if;
xp1 := bit_reverse(std_ulogic_vector(unsigned(bit_reverse(x)) + 1));
x := x and not xp1;
-- For positive inputs, x has ones at the positions
-- to the left of the leftmost 1 bit in val.
-- For negative inputs, x has ones to the left of
-- the leftmost 0 bit in val.
return x(n - 1) = '1';
end;

-- Tell vivado to keep the hierarchy for the random module so that the -- Tell vivado to keep the hierarchy for the random module so that the
-- net names in the xdc file match. -- net names in the xdc file match.
attribute keep_hierarchy : string; attribute keep_hierarchy : string;
@ -283,15 +246,13 @@ begin
datalen => e_in.data_len datalen => e_in.data_len
); );


countbits_0: entity work.bit_counter countzero_0: entity work.zero_counter
port map ( port map (
clk => clk, clk => clk,
rs => c_in, rs => c_in,
count_right => e_in.insn(10), count_right => e_in.insn(10),
is_32bit => e_in.is_32bit, is_32bit => e_in.is_32bit,
do_popcnt => do_popcnt, result => countzero_result
datalen => e_in.data_len,
result => countbits_result
); );


multiply_0: entity work.multiply multiply_0: entity work.multiply
@ -317,25 +278,6 @@ begin
err => random_err err => random_err
); );


pmu_0: entity work.pmu
port map (
clk => clk,
rst => rst,
p_in => x_to_pmu,
p_out => pmu_to_x
);

short_mult_0: if HAS_SHORT_MULT generate
begin
short_mult: entity work.short_multiply
port map (
clk => clk,
a_in => a_in(15 downto 0),
b_in => b_in(15 downto 0),
m_out => mshort_p
);
end generate;

dbg_msr_out <= ctrl.msr; dbg_msr_out <= ctrl.msr;
log_rd_addr <= r.log_addr_spr; log_rd_addr <= r.log_addr_spr;


@ -344,31 +286,6 @@ begin
c_in <= e_in.read_data3; c_in <= e_in.read_data3;
cr_in <= e_in.cr; cr_in <= e_in.cr;


x_to_pmu.occur <= (instr_complete => wb_events.instr_complete,
fp_complete => wb_events.fp_complete,
ld_complete => ls_events.load_complete,
st_complete => ls_events.store_complete,
itlb_miss => ls_events.itlb_miss,
dc_load_miss => dc_events.load_miss,
dc_ld_miss_resolved => dc_events.dcache_refill,
dc_store_miss => dc_events.store_miss,
dtlb_miss => dc_events.dtlb_miss,
dtlb_miss_resolved => dc_events.dtlb_miss_resolved,
icache_miss => ic_events.icache_miss,
itlb_miss_resolved => ic_events.itlb_miss_resolved,
no_instr_avail => r.no_instr_avail,
dispatch => r.instr_dispatch,
ext_interrupt => r.ext_interrupt,
br_taken_complete => r.taken_branch_event,
br_mispredict => r.br_mispredict,
others => '0');
x_to_pmu.nia <= current.nia;
x_to_pmu.addr <= (others => '0');
x_to_pmu.addr_v <= '0';
x_to_pmu.spr_num <= e_in.insn(20 downto 16);
x_to_pmu.spr_val <= c_in;
x_to_pmu.run <= '1';

-- XER forwarding. To avoid having to track XER hazards, we use -- XER forwarding. To avoid having to track XER hazards, we use
-- the previously latched value. Since the XER common bits -- the previously latched value. Since the XER common bits
-- (SO, OV[32] and CA[32]) are only modified by instructions that are -- (SO, OV[32] and CA[32]) are only modified by instructions that are
@ -392,7 +309,7 @@ begin
logical_result when "001", logical_result when "001",
rotator_result when "010", rotator_result when "010",
muldiv_result when "011", muldiv_result when "011",
countbits_result when "100", countzero_result when "100",
spr_result when "101", spr_result when "101",
next_nia when "110", next_nia when "110",
misc_result when others; misc_result when others;
@ -404,7 +321,6 @@ begin
r <= reg_type_init; r <= reg_type_init;
ctrl.tb <= (others => '0'); ctrl.tb <= (others => '0');
ctrl.dec <= (others => '0'); ctrl.dec <= (others => '0');
ctrl.cfar <= (others => '0');
ctrl.msr <= (MSR_SF => '1', MSR_LE => '1', others => '0'); ctrl.msr <= (MSR_SF => '1', MSR_LE => '1', others => '0');
else else
r <= rin; r <= rin;
@ -542,11 +458,7 @@ begin


case current.sub_select(1 downto 0) is case current.sub_select(1 downto 0) is
when "00" => when "00" =>
if HAS_SHORT_MULT and r.mul_in_progress = '0' then muldiv_result <= multiply_to_x.result(63 downto 0);
muldiv_result <= std_ulogic_vector(resize(signed(mshort_p), 64));
else
muldiv_result <= multiply_to_x.result(63 downto 0);
end if;
when "01" => when "01" =>
muldiv_result <= multiply_to_x.result(127 downto 64); muldiv_result <= multiply_to_x.result(127 downto 64);
when "10" => when "10" =>
@ -720,7 +632,7 @@ begin
end if; end if;
when "100" => when "100" =>
-- MCRXRX -- MCRXRX
newcrf := xerc_in.ov & xerc_in.ov32 & xerc_in.ca & xerc_in.ca32; newcrf := xerc_in.ov & xerc_in.ca & xerc_in.ov32 & xerc_in.ca32;
when others => when others =>
end case; end case;
if current.insn_type = OP_MTCRF then if current.insn_type = OP_MTCRF then
@ -743,6 +655,8 @@ begin


execute1_1: process(all) execute1_1: process(all)
variable v : reg_type; variable v : reg_type;
variable lo, hi : integer;
variable sh, mb, me : std_ulogic_vector(5 downto 0);
variable bo, bi : std_ulogic_vector(4 downto 0); variable bo, bi : std_ulogic_vector(4 downto 0);
variable overflow : std_ulogic; variable overflow : std_ulogic;
variable lv : Execute1ToLoadstore1Type; variable lv : Execute1ToLoadstore1Type;
@ -779,18 +693,6 @@ begin
v.div_in_progress := '0'; v.div_in_progress := '0';
v.cntz_in_progress := '0'; v.cntz_in_progress := '0';
v.mul_finish := '0'; v.mul_finish := '0';
v.ext_interrupt := '0';
v.taken_branch_event := '0';
v.br_mispredict := '0';

x_to_pmu.mfspr <= '0';
x_to_pmu.mtspr <= '0';
x_to_pmu.tbbits(3) <= ctrl.tb(63 - 47);
x_to_pmu.tbbits(2) <= ctrl.tb(63 - 51);
x_to_pmu.tbbits(1) <= ctrl.tb(63 - 55);
x_to_pmu.tbbits(0) <= ctrl.tb(63 - 63);
x_to_pmu.pmm_msr <= ctrl.msr(MSR_PMM);
x_to_pmu.pr_msr <= ctrl.msr(MSR_PR);


spr_result <= (others => '0'); spr_result <= (others => '0');
spr_val := (others => '0'); spr_val := (others => '0');
@ -800,7 +702,18 @@ begin
ctrl_tmp.tb <= std_ulogic_vector(unsigned(ctrl.tb) + 1); ctrl_tmp.tb <= std_ulogic_vector(unsigned(ctrl.tb) + 1);
ctrl_tmp.dec <= std_ulogic_vector(unsigned(ctrl.dec) - 1); ctrl_tmp.dec <= std_ulogic_vector(unsigned(ctrl.dec) - 1);


irq_valid := ctrl.msr(MSR_EE) and (pmu_to_x.intr or ctrl.dec(63) or ext_irq_in); irq_valid := '0';
if ctrl.msr(MSR_EE) = '1' then
if ctrl.dec(63) = '1' then
v.e.intr_vec := 16#900#;
report "IRQ valid: DEC";
irq_valid := '1';
elsif ext_irq_in = '1' then
v.e.intr_vec := 16#500#;
report "IRQ valid: External";
irq_valid := '1';
end if;
end if;


v.terminate := '0'; v.terminate := '0';
icache_inval <= '0'; icache_inval <= '0';
@ -815,13 +728,9 @@ begin
rot_clear_right <= '1' when e_in.insn_type = OP_RLC or e_in.insn_type = OP_RLCR else '0'; rot_clear_right <= '1' when e_in.insn_type = OP_RLC or e_in.insn_type = OP_RLCR else '0';
rot_sign_ext <= '1' when e_in.insn_type = OP_EXTSWSLI else '0'; rot_sign_ext <= '1' when e_in.insn_type = OP_EXTSWSLI else '0';


do_popcnt <= '1' when e_in.insn_type = OP_POPCNT else '0'; v.e.srr1 := (others => '0');

exception := '0';
illegal := '0'; illegal := '0';
if r.intr_pending = '1' then
v.e.srr1 := r.e.srr1;
v.e.intr_vec := r.e.intr_vec;
end if;
if valid_in = '1' then if valid_in = '1' then
v.e.last_nia := e_in.nia; v.e.last_nia := e_in.nia;
else else
@ -833,14 +742,12 @@ begin


do_trace := valid_in and ctrl.msr(MSR_SE); do_trace := valid_in and ctrl.msr(MSR_SE);
if valid_in = '1' then if valid_in = '1' then
v.cur_instr := e_in;
v.prev_op := e_in.insn_type; v.prev_op := e_in.insn_type;
end if; end if;


-- Determine if there is any interrupt to be taken -- Determine if there is any exception to be taken
-- before/instead of executing this instruction -- before/instead of executing this instruction
exception := r.intr_pending; if valid_in = '1' and e_in.second = '0' and l_in.in_progress = '0' then
if valid_in = '1' and e_in.second = '0' and r.intr_pending = '0' then
if HAS_FPU and r.fp_exception_next = '1' then if HAS_FPU and r.fp_exception_next = '1' then
-- This is used for FP-type program interrupts that -- This is used for FP-type program interrupts that
-- become pending due to MSR[FE0,FE1] changing from 00 to non-zero. -- become pending due to MSR[FE0,FE1] changing from 00 to non-zero.
@ -864,17 +771,6 @@ begin
elsif irq_valid = '1' then elsif irq_valid = '1' then
-- Don't deliver the interrupt until we have a valid instruction -- Don't deliver the interrupt until we have a valid instruction
-- coming in, so we have a valid NIA to put in SRR0. -- coming in, so we have a valid NIA to put in SRR0.
if pmu_to_x.intr = '1' then
v.e.intr_vec := 16#f00#;
report "IRQ valid: PMU";
elsif ctrl.dec(63) = '1' then
v.e.intr_vec := 16#900#;
report "IRQ valid: DEC";
elsif ext_irq_in = '1' then
v.e.intr_vec := 16#500#;
report "IRQ valid: External";
v.ext_interrupt := '1';
end if;
exception := '1'; exception := '1';


elsif ctrl.msr(MSR_PR) = '1' and instr_is_privileged(e_in.insn_type, e_in.insn) then elsif ctrl.msr(MSR_PR) = '1' and instr_is_privileged(e_in.insn_type, e_in.insn) then
@ -896,20 +792,9 @@ begin
report "FP unavailable interrupt"; report "FP unavailable interrupt";
end if; end if;
end if; end if;
if exception = '1' and l_in.in_progress = '1' then
-- We can't send this interrupt to writeback yet because there are
-- still instructions in loadstore1 that haven't completed.
v.intr_pending := '1';
v.busy := '1';
end if;
if l_in.interrupt = '1' then
v.intr_pending := '0';
end if;

v.no_instr_avail := not (e_in.valid or l_in.busy or l_in.in_progress or r.busy or fp_in.busy);
v.instr_dispatch := valid_in and not exception and not illegal;


if valid_in = '1' and exception = '0' and illegal = '0' and e_in.unit = ALU then if valid_in = '1' and exception = '0' and illegal = '0' and e_in.unit = ALU then
v.cur_instr := e_in;
v.e.valid := '1'; v.e.valid := '1';


case_0: case e_in.insn_type is case_0: case e_in.insn_type is
@ -967,7 +852,7 @@ begin
when OP_ADDG6S => when OP_ADDG6S =>
when OP_CMPRB => when OP_CMPRB =>
when OP_CMPEQB => when OP_CMPEQB =>
when OP_AND | OP_OR | OP_XOR | OP_PRTY | OP_CMPB | OP_EXTS | when OP_AND | OP_OR | OP_XOR | OP_POPCNT | OP_PRTY | OP_CMPB | OP_EXTS |
OP_BPERM | OP_BCD => OP_BPERM | OP_BCD =>


when OP_B => when OP_B =>
@ -978,7 +863,6 @@ begin
if ctrl.msr(MSR_BE) = '1' then if ctrl.msr(MSR_BE) = '1' then
do_trace := '1'; do_trace := '1';
end if; end if;
v.taken_branch_event := '1';
when OP_BC | OP_BCREG => when OP_BC | OP_BCREG =>
-- read_data1 is CTR -- read_data1 is CTR
-- for OP_BCREG, read_data2 is target register (CTR, LR or TAR) -- for OP_BCREG, read_data2 is target register (CTR, LR or TAR)
@ -994,7 +878,6 @@ begin
taken_branch := r.br_taken; taken_branch := r.br_taken;
end if; end if;
v.br_taken := taken_branch; v.br_taken := taken_branch;
v.taken_branch_event := taken_branch;
abs_branch := e_in.br_abs; abs_branch := e_in.br_abs;
if e_in.repeat = '0' or e_in.second = '1' then if e_in.repeat = '0' or e_in.second = '1' then
is_branch := '1'; is_branch := '1';
@ -1029,7 +912,7 @@ begin
end if; end if;
do_trace := '0'; do_trace := '0';


when OP_CNTZ | OP_POPCNT => when OP_CNTZ =>
v.e.valid := '0'; v.e.valid := '0';
v.cntz_in_progress := '1'; v.cntz_in_progress := '1';
v.busy := '1'; v.busy := '1';
@ -1073,12 +956,6 @@ begin
when 725 => -- LOG_DATA SPR when 725 => -- LOG_DATA SPR
spr_val := log_rd_data; spr_val := log_rd_data;
v.log_addr_spr := std_ulogic_vector(unsigned(r.log_addr_spr) + 1); v.log_addr_spr := std_ulogic_vector(unsigned(r.log_addr_spr) + 1);
when SPR_UPMC1 | SPR_UPMC2 | SPR_UPMC3 | SPR_UPMC4 | SPR_UPMC5 | SPR_UPMC6 |
SPR_UMMCR0 | SPR_UMMCR1 | SPR_UMMCR2 | SPR_UMMCRA | SPR_USIER | SPR_USIAR | SPR_USDAR |
SPR_PMC1 | SPR_PMC2 | SPR_PMC3 | SPR_PMC4 | SPR_PMC5 | SPR_PMC6 |
SPR_MMCR0 | SPR_MMCR1 | SPR_MMCR2 | SPR_MMCRA | SPR_SIER | SPR_SIAR | SPR_SDAR =>
x_to_pmu.mfspr <= '1';
spr_val := pmu_to_x.spr_val;
when others => when others =>
-- mfspr from unimplemented SPRs should be a nop in -- mfspr from unimplemented SPRs should be a nop in
-- supervisor mode and a program interrupt for user mode -- supervisor mode and a program interrupt for user mode
@ -1133,11 +1010,6 @@ begin
ctrl_tmp.dec <= c_in; ctrl_tmp.dec <= c_in;
when 724 => -- LOG_ADDR SPR when 724 => -- LOG_ADDR SPR
v.log_addr_spr := c_in(31 downto 0); v.log_addr_spr := c_in(31 downto 0);
when SPR_UPMC1 | SPR_UPMC2 | SPR_UPMC3 | SPR_UPMC4 | SPR_UPMC5 | SPR_UPMC6 |
SPR_UMMCR0 | SPR_UMMCR2 | SPR_UMMCRA |
SPR_PMC1 | SPR_PMC2 | SPR_PMC3 | SPR_PMC4 | SPR_PMC5 | SPR_PMC6 |
SPR_MMCR0 | SPR_MMCR1 | SPR_MMCR2 | SPR_MMCRA | SPR_SIER | SPR_SIAR | SPR_SDAR =>
x_to_pmu.mtspr <= '1';
when others => when others =>
-- mtspr to unimplemented SPRs should be a nop in -- mtspr to unimplemented SPRs should be a nop in
-- supervisor mode and a program interrupt for user mode -- supervisor mode and a program interrupt for user mode
@ -1160,20 +1032,10 @@ begin
icache_inval <= '1'; icache_inval <= '1';


when OP_MUL_L64 | OP_MUL_H64 | OP_MUL_H32 => when OP_MUL_L64 | OP_MUL_H64 | OP_MUL_H32 =>
if HAS_SHORT_MULT and e_in.insn_type = OP_MUL_L64 and e_in.insn(26) = '1' and v.e.valid := '0';
fits_in_n_bits(a_in, 16) and fits_in_n_bits(b_in, 16) then v.mul_in_progress := '1';
-- Operands fit into 16 bits, so use short multiplier v.busy := '1';
if e_in.oe = '1' then x_to_multiply.valid <= '1';
-- Note 16x16 multiply can't overflow, even for mullwo
set_ov(v.e, '0', '0');
end if;
else
-- Use standard multiplier
v.e.valid := '0';
v.mul_in_progress := '1';
v.busy := '1';
x_to_multiply.valid <= '1';
end if;


when OP_DIV | OP_DIVE | OP_MOD => when OP_DIV | OP_DIVE | OP_MOD =>
v.e.valid := '0'; v.e.valid := '0';
@ -1199,7 +1061,6 @@ begin
end if; end if;
if taken_branch /= e_in.br_pred then if taken_branch /= e_in.br_pred then
v.e.redirect := '1'; v.e.redirect := '1';
v.br_mispredict := is_direct_branch;
end if; end if;
v.e.br_last := is_direct_branch; v.e.br_last := is_direct_branch;
v.e.br_taken := taken_branch; v.e.br_taken := taken_branch;
@ -1224,7 +1085,7 @@ begin
-- valid_in = 0. Hence they don't happen in the same cycle as any of -- valid_in = 0. Hence they don't happen in the same cycle as any of
-- the cases above which depend on valid_in = 1. -- the cases above which depend on valid_in = 1.
if r.cntz_in_progress = '1' then if r.cntz_in_progress = '1' then
-- cnt[lt]z and popcnt* always take two cycles -- cnt[lt]z always takes two cycles
v.e.valid := '1'; v.e.valid := '1';
elsif r.mul_in_progress = '1' or r.div_in_progress = '1' then elsif r.mul_in_progress = '1' or r.div_in_progress = '1' then
if (r.mul_in_progress = '1' and multiply_to_x.valid = '1') or if (r.mul_in_progress = '1' and multiply_to_x.valid = '1') or
@ -1275,10 +1136,7 @@ begin
report "illegal"; report "illegal";
end if; end if;


v.e.interrupt := exception and not (l_in.in_progress or l_in.interrupt); v.e.interrupt := exception;
if v.e.interrupt = '1' then
v.intr_pending := '0';
end if;


if do_trace = '1' then if do_trace = '1' then
v.trace_next := '1'; v.trace_next := '1';
@ -1299,7 +1157,6 @@ begin
ctrl_tmp.msr(MSR_LE) <= '1'; ctrl_tmp.msr(MSR_LE) <= '1';
v.trace_next := '0'; v.trace_next := '0';
v.fp_exception_next := '0'; v.fp_exception_next := '0';
v.intr_pending := '0';
end if; end if;


if hold_wr_data = '0' then if hold_wr_data = '0' then

@ -40,8 +40,7 @@ architecture behaviour of fetch1 is
type reg_internal_t is record type reg_internal_t is record
mode_32bit: std_ulogic; mode_32bit: std_ulogic;
rd_is_niap4: std_ulogic; rd_is_niap4: std_ulogic;
predicted_taken: std_ulogic; predicted: std_ulogic;
pred_not_taken: std_ulogic;
predicted_nia: std_ulogic_vector(63 downto 0); predicted_nia: std_ulogic_vector(63 downto 0);
end record; end record;
signal r, r_next : Fetch1ToIcacheType; signal r, r_next : Fetch1ToIcacheType;
@ -53,7 +52,7 @@ architecture behaviour of fetch1 is
constant BTC_TAG_BITS : integer := 62 - BTC_ADDR_BITS; constant BTC_TAG_BITS : integer := 62 - BTC_ADDR_BITS;
constant BTC_TARGET_BITS : integer := 62; constant BTC_TARGET_BITS : integer := 62;
constant BTC_SIZE : integer := 2 ** BTC_ADDR_BITS; constant BTC_SIZE : integer := 2 ** BTC_ADDR_BITS;
constant BTC_WIDTH : integer := BTC_TAG_BITS + BTC_TARGET_BITS + 1; constant BTC_WIDTH : integer := BTC_TAG_BITS + BTC_TARGET_BITS;
type btc_mem_type is array (0 to BTC_SIZE - 1) of std_ulogic_vector(BTC_WIDTH - 1 downto 0); type btc_mem_type is array (0 to BTC_SIZE - 1) of std_ulogic_vector(BTC_WIDTH - 1 downto 0);


signal btc_rd_data : std_ulogic_vector(BTC_WIDTH - 1 downto 0) := (others => '0'); signal btc_rd_data : std_ulogic_vector(BTC_WIDTH - 1 downto 0) := (others => '0');
@ -84,13 +83,12 @@ begin
end if; end if;
if advance_nia = '1' then if advance_nia = '1' then
r.predicted <= r_next.predicted; r.predicted <= r_next.predicted;
r.pred_ntaken <= r_next.pred_ntaken;
r.nia <= r_next.nia; r.nia <= r_next.nia;
r_int.predicted_taken <= r_next_int.predicted_taken; r_int.predicted <= r_next_int.predicted;
r_int.pred_not_taken <= r_next_int.pred_not_taken;
r_int.predicted_nia <= r_next_int.predicted_nia; r_int.predicted_nia <= r_next_int.predicted_nia;
r_int.rd_is_niap4 <= r_next_int.rd_is_niap4; r_int.rd_is_niap4 <= r_next.sequential;
end if; end if;
r.sequential <= r_next.sequential and advance_nia;
-- always send the up-to-date stop mark and req -- always send the up-to-date stop mark and req
r.stop_mark <= stop_in; r.stop_mark <= stop_in;
r.req <= not rst; r.req <= not rst;
@ -109,12 +107,13 @@ begin
signal btc_wr : std_ulogic; signal btc_wr : std_ulogic;
signal btc_wr_data : std_ulogic_vector(BTC_WIDTH - 1 downto 0); signal btc_wr_data : std_ulogic_vector(BTC_WIDTH - 1 downto 0);
signal btc_wr_addr : std_ulogic_vector(BTC_ADDR_BITS - 1 downto 0); signal btc_wr_addr : std_ulogic_vector(BTC_ADDR_BITS - 1 downto 0);
signal btc_wr_v : std_ulogic;
begin begin
btc_wr_data <= w_in.br_taken & btc_wr_data <= w_in.br_nia(63 downto BTC_ADDR_BITS + 2) &
w_in.br_nia(63 downto BTC_ADDR_BITS + 2) &
w_in.redirect_nia(63 downto 2); w_in.redirect_nia(63 downto 2);
btc_wr_addr <= w_in.br_nia(BTC_ADDR_BITS + 1 downto 2); btc_wr_addr <= w_in.br_nia(BTC_ADDR_BITS + 1 downto 2);
btc_wr <= w_in.br_last; btc_wr <= w_in.br_last;
btc_wr_v <= w_in.br_taken;


btc_ram : process(clk) btc_ram : process(clk)
variable raddr : unsigned(BTC_ADDR_BITS - 1 downto 0); variable raddr : unsigned(BTC_ADDR_BITS - 1 downto 0);
@ -132,7 +131,7 @@ begin
if inval_btc = '1' or rst = '1' then if inval_btc = '1' or rst = '1' then
btc_valids <= (others => '0'); btc_valids <= (others => '0');
elsif btc_wr = '1' then elsif btc_wr = '1' then
btc_valids(to_integer(unsigned(btc_wr_addr))) <= '1'; btc_valids(to_integer(unsigned(btc_wr_addr))) <= btc_wr_v;
end if; end if;
end if; end if;
end process; end process;
@ -144,11 +143,9 @@ begin
begin begin
v := r; v := r;
v_int := r_int; v_int := r_int;
v.sequential := '0';
v.predicted := '0'; v.predicted := '0';
v.pred_ntaken := '0'; v_int.predicted := '0';
v_int.predicted_taken := '0';
v_int.pred_not_taken := '0';
v_int.rd_is_niap4 := '0';


if rst = '1' then if rst = '1' then
if alt_reset_in = '1' then if alt_reset_in = '1' then
@ -175,21 +172,19 @@ begin
if r_int.mode_32bit = '1' then if r_int.mode_32bit = '1' then
v.nia(63 downto 32) := (others => '0'); v.nia(63 downto 32) := (others => '0');
end if; end if;
elsif r_int.predicted_taken = '1' then elsif r_int.predicted = '1' then
v.nia := r_int.predicted_nia; v.nia := r_int.predicted_nia;
v.predicted := '1'; v.predicted := '1';
else else
v_int.rd_is_niap4 := '1'; v.sequential := '1';
v.pred_ntaken := r_int.pred_not_taken;
v.nia := std_ulogic_vector(unsigned(r.nia) + 4); v.nia := std_ulogic_vector(unsigned(r.nia) + 4);
if r_int.mode_32bit = '1' then if r_int.mode_32bit = '1' then
v.nia(63 downto 32) := x"00000000"; v.nia(63 downto 32) := x"00000000";
end if; end if;
if btc_rd_valid = '1' and r_int.rd_is_niap4 = '1' and if btc_rd_valid = '1' and r_int.rd_is_niap4 = '1' and
btc_rd_data(BTC_WIDTH - 2 downto BTC_TARGET_BITS) btc_rd_data(BTC_WIDTH - 1 downto BTC_TARGET_BITS)
= v.nia(BTC_TAG_BITS + BTC_ADDR_BITS + 1 downto BTC_ADDR_BITS + 2) then = v.nia(BTC_TAG_BITS + BTC_ADDR_BITS + 1 downto BTC_ADDR_BITS + 2) then
v_int.predicted_taken := btc_rd_data(BTC_WIDTH - 1); v_int.predicted := '1';
v_int.pred_not_taken := not btc_rd_data(BTC_WIDTH - 1);
end if; end if;
end if; end if;
v_int.predicted_nia := btc_rd_data(BTC_TARGET_BITS - 1 downto 0) & "00"; v_int.predicted_nia := btc_rd_data(BTC_TARGET_BITS - 1 downto 0) & "00";

@ -1,30 +0,0 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

library work;
use work.glibc_random.all;

entity random is
port (
clk : in std_ulogic;
data : out std_ulogic_vector(63 downto 0);
raw : out std_ulogic_vector(63 downto 0);
err : out std_ulogic
);
end entity random;

architecture behaviour of random is
begin
err <= '0';

process(clk)
variable rand : std_ulogic_vector(63 downto 0);
begin
if rising_edge(clk) then
rand := pseudorand(64);
data <= rand;
raw <= rand;
end if;
end process;
end behaviour;

@ -9,6 +9,15 @@ set_property -dict { PACKAGE_PIN C2 IOSTANDARD LVCMOS33 } [get_ports { ext_rst_
set_property -dict { PACKAGE_PIN D10 IOSTANDARD LVCMOS33 } [get_ports { uart_main_tx }]; set_property -dict { PACKAGE_PIN D10 IOSTANDARD LVCMOS33 } [get_ports { uart_main_tx }];
set_property -dict { PACKAGE_PIN A9 IOSTANDARD LVCMOS33 } [get_ports { uart_main_rx }]; set_property -dict { PACKAGE_PIN A9 IOSTANDARD LVCMOS33 } [get_ports { uart_main_rx }];


################################################################################
# Pmod Header JC: UART (bottom)
################################################################################

set_property -dict { PACKAGE_PIN U14 IOSTANDARD LVCMOS33 } [get_ports { uart_pmod_cts_n }];
set_property -dict { PACKAGE_PIN V14 IOSTANDARD LVCMOS33 } [get_ports { uart_pmod_tx }];
set_property -dict { PACKAGE_PIN T13 IOSTANDARD LVCMOS33 } [get_ports { uart_pmod_rx }];
set_property -dict { PACKAGE_PIN U13 IOSTANDARD LVCMOS33 } [get_ports { uart_pmod_rts_n }];

################################################################################ ################################################################################
# RGB LEDs # RGB LEDs
################################################################################ ################################################################################
@ -63,19 +72,6 @@ set_property IOB true [get_cells -hierarchical -filter {NAME =~*/spi_rxtx/input_
#set_property -dict { PACKAGE_PIN A18 IOSTANDARD LVCMOS33 } [get_ports { pmod_ja_9 }]; #set_property -dict { PACKAGE_PIN A18 IOSTANDARD LVCMOS33 } [get_ports { pmod_ja_9 }];
#set_property -dict { PACKAGE_PIN K16 IOSTANDARD LVCMOS33 } [get_ports { pmod_ja_10 }]; #set_property -dict { PACKAGE_PIN K16 IOSTANDARD LVCMOS33 } [get_ports { pmod_ja_10 }];


# connection to Digilent PmodSD on JA
set_property -dict { PACKAGE_PIN G13 IOSTANDARD LVCMOS33 SLEW FAST PULLUP TRUE } [get_ports { sdcard_data[3] }];
set_property -dict { PACKAGE_PIN B11 IOSTANDARD LVCMOS33 SLEW FAST PULLUP TRUE } [get_ports { sdcard_cmd }];
set_property -dict { PACKAGE_PIN A11 IOSTANDARD LVCMOS33 SLEW FAST PULLUP TRUE } [get_ports { sdcard_data[0] }];
set_property -dict { PACKAGE_PIN D12 IOSTANDARD LVCMOS33 SLEW FAST } [get_ports { sdcard_clk }];
set_property -dict { PACKAGE_PIN D13 IOSTANDARD LVCMOS33 SLEW FAST PULLUP TRUE } [get_ports { sdcard_data[1] }];
set_property -dict { PACKAGE_PIN B18 IOSTANDARD LVCMOS33 SLEW FAST PULLUP TRUE } [get_ports { sdcard_data[2] }];
set_property -dict { PACKAGE_PIN A18 IOSTANDARD LVCMOS33 } [get_ports { sdcard_cd }];
#set_property -dict { PACKAGE_PIN K16 IOSTANDARD LVCMOS33 } [get_ports { sdcard_wp }];

# Put registers into IOBs to improve timing
set_property IOB true [get_cells -hierarchical -filter {NAME =~*.litesdcard/sdcard_*}]

################################################################################ ################################################################################
# PMOD header JB (high-speed, no protection resisters) # PMOD header JB (high-speed, no protection resisters)
################################################################################ ################################################################################
@ -89,16 +85,6 @@ set_property IOB true [get_cells -hierarchical -filter {NAME =~*.litesdcard/sdca
#set_property -dict { PACKAGE_PIN K15 IOSTANDARD LVCMOS33 } [get_ports { pmod_jb_9 }]; #set_property -dict { PACKAGE_PIN K15 IOSTANDARD LVCMOS33 } [get_ports { pmod_jb_9 }];
#set_property -dict { PACKAGE_PIN J15 IOSTANDARD LVCMOS33 } [get_ports { pmod_jb_10 }]; #set_property -dict { PACKAGE_PIN J15 IOSTANDARD LVCMOS33 } [get_ports { pmod_jb_10 }];


# connection to Digilent PmodSD on JB
#set_property -dict { PACKAGE_PIN E15 IOSTANDARD LVCMOS33 SLEW FAST PULLUP TRUE } [get_ports { sdcard_data[3] }];
#set_property -dict { PACKAGE_PIN E16 IOSTANDARD LVCMOS33 SLEW FAST PULLUP TRUE } [get_ports { sdcard_cmd }];
#set_property -dict { PACKAGE_PIN D15 IOSTANDARD LVCMOS33 SLEW FAST PULLUP TRUE } [get_ports { sdcard_data[0] }];
#set_property -dict { PACKAGE_PIN C15 IOSTANDARD LVCMOS33 SLEW FAST } [get_ports { sdcard_clk }];
#set_property -dict { PACKAGE_PIN J17 IOSTANDARD LVCMOS33 SLEW FAST PULLUP TRUE } [get_ports { sdcard_data[1] }];
#set_property -dict { PACKAGE_PIN J18 IOSTANDARD LVCMOS33 SLEW FAST PULLUP TRUE } [get_ports { sdcard_data[2] }];
#set_property -dict { PACKAGE_PIN K15 IOSTANDARD LVCMOS33 } [get_ports { sdcard_cd }];
#set_property -dict { PACKAGE_PIN J15 IOSTANDARD LVCMOS33 } [get_ports { sdcard_wp }];

################################################################################ ################################################################################
# PMOD header JC (high-speed, no protection resisters) # PMOD header JC (high-speed, no protection resisters)
################################################################################ ################################################################################
@ -129,39 +115,39 @@ set_property IOB true [get_cells -hierarchical -filter {NAME =~*.litesdcard/sdca
# Arduino/chipKIT shield connector # Arduino/chipKIT shield connector
################################################################################ ################################################################################


set_property -dict { PACKAGE_PIN V15 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io[0] }]; #set_property -dict { PACKAGE_PIN V15 IOSTANDARD LVCMOS33 } [get_ports { shield_io0 }];
set_property -dict { PACKAGE_PIN U16 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io[1] }]; #set_property -dict { PACKAGE_PIN U16 IOSTANDARD LVCMOS33 } [get_ports { shield_io1 }];
set_property -dict { PACKAGE_PIN P14 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io[2] }]; #set_property -dict { PACKAGE_PIN P14 IOSTANDARD LVCMOS33 } [get_ports { shield_io2 }];
set_property -dict { PACKAGE_PIN T11 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io[3] }]; #set_property -dict { PACKAGE_PIN T11 IOSTANDARD LVCMOS33 } [get_ports { shield_io3 }];
set_property -dict { PACKAGE_PIN R12 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io[4] }]; #set_property -dict { PACKAGE_PIN R12 IOSTANDARD LVCMOS33 } [get_ports { shield_io4 }];
set_property -dict { PACKAGE_PIN T14 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io[5] }]; #set_property -dict { PACKAGE_PIN T14 IOSTANDARD LVCMOS33 } [get_ports { shield_io5 }];
set_property -dict { PACKAGE_PIN T15 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io[6] }]; #set_property -dict { PACKAGE_PIN T15 IOSTANDARD LVCMOS33 } [get_ports { shield_io6 }];
set_property -dict { PACKAGE_PIN T16 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io[7] }]; #set_property -dict { PACKAGE_PIN T16 IOSTANDARD LVCMOS33 } [get_ports { shield_io7 }];
set_property -dict { PACKAGE_PIN N15 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io[8] }]; #set_property -dict { PACKAGE_PIN N15 IOSTANDARD LVCMOS33 } [get_ports { shield_io8 }];
set_property -dict { PACKAGE_PIN M16 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io[9] }]; #set_property -dict { PACKAGE_PIN M16 IOSTANDARD LVCMOS33 } [get_ports { shield_io9 }];
set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io[10] }]; #set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 } [get_ports { shield_io10 }];
set_property -dict { PACKAGE_PIN U18 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io[11] }]; #set_property -dict { PACKAGE_PIN U18 IOSTANDARD LVCMOS33 } [get_ports { shield_io11 }];
set_property -dict { PACKAGE_PIN R17 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io[12] }]; #set_property -dict { PACKAGE_PIN R17 IOSTANDARD LVCMOS33 } [get_ports { shield_io12 }];
set_property -dict { PACKAGE_PIN P17 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io[13] }]; #set_property -dict { PACKAGE_PIN P17 IOSTANDARD LVCMOS33 } [get_ports { shield_io13 }];
set_property -dict { PACKAGE_PIN U11 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io[26] }]; #set_property -dict { PACKAGE_PIN U11 IOSTANDARD LVCMOS33 } [get_ports { shield_io26 }];
set_property -dict { PACKAGE_PIN V16 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io[27] }]; #set_property -dict { PACKAGE_PIN V16 IOSTANDARD LVCMOS33 } [get_ports { shield_io27 }];
set_property -dict { PACKAGE_PIN M13 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io[28] }]; #set_property -dict { PACKAGE_PIN M13 IOSTANDARD LVCMOS33 } [get_ports { shield_io28 }];
set_property -dict { PACKAGE_PIN R10 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io[29] }]; #set_property -dict { PACKAGE_PIN R10 IOSTANDARD LVCMOS33 } [get_ports { shield_io29 }];
set_property -dict { PACKAGE_PIN R11 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io[30] }]; #set_property -dict { PACKAGE_PIN R11 IOSTANDARD LVCMOS33 } [get_ports { shield_io30 }];
set_property -dict { PACKAGE_PIN R13 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io[31] }]; #set_property -dict { PACKAGE_PIN R13 IOSTANDARD LVCMOS33 } [get_ports { shield_io31 }];
set_property -dict { PACKAGE_PIN R15 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io[32] }]; #set_property -dict { PACKAGE_PIN R15 IOSTANDARD LVCMOS33 } [get_ports { shield_io32 }];
set_property -dict { PACKAGE_PIN P15 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io[33] }]; #set_property -dict { PACKAGE_PIN P15 IOSTANDARD LVCMOS33 } [get_ports { shield_io33 }];
set_property -dict { PACKAGE_PIN R16 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io[34] }]; #set_property -dict { PACKAGE_PIN R16 IOSTANDARD LVCMOS33 } [get_ports { shield_io34 }];
set_property -dict { PACKAGE_PIN N16 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io[35] }]; #set_property -dict { PACKAGE_PIN N16 IOSTANDARD LVCMOS33 } [get_ports { shield_io35 }];
set_property -dict { PACKAGE_PIN N14 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io[36] }]; #set_property -dict { PACKAGE_PIN N14 IOSTANDARD LVCMOS33 } [get_ports { shield_io36 }];
set_property -dict { PACKAGE_PIN U17 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io[37] }]; #set_property -dict { PACKAGE_PIN U17 IOSTANDARD LVCMOS33 } [get_ports { shield_io37 }];
set_property -dict { PACKAGE_PIN T18 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io[38] }]; #set_property -dict { PACKAGE_PIN T18 IOSTANDARD LVCMOS33 } [get_ports { shield_io38 }];
set_property -dict { PACKAGE_PIN R18 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io[39] }]; #set_property -dict { PACKAGE_PIN R18 IOSTANDARD LVCMOS33 } [get_ports { shield_io39 }];
set_property -dict { PACKAGE_PIN P18 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io[40] }]; #set_property -dict { PACKAGE_PIN P18 IOSTANDARD LVCMOS33 } [get_ports { shield_io40 }];
set_property -dict { PACKAGE_PIN N17 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io[41] }]; #set_property -dict { PACKAGE_PIN N17 IOSTANDARD LVCMOS33 } [get_ports { shield_io41 }];
set_property -dict { PACKAGE_PIN M17 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io[42] }]; # A #set_property -dict { PACKAGE_PIN M17 IOSTANDARD LVCMOS33 } [get_ports { shield_ioa }];
set_property -dict { PACKAGE_PIN L18 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io[43] }]; # SCL #set_property -dict { PACKAGE_PIN L18 IOSTANDARD LVCMOS33 } [get_ports { shield_scl }];
set_property -dict { PACKAGE_PIN M18 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io[44] }]; # SDA #set_property -dict { PACKAGE_PIN M18 IOSTANDARD LVCMOS33 } [get_ports { shield_sda }];
#set_property -dict { PACKAGE_PIN C2 IOSTANDARD LVCMOS33 } [get_ports { shield_rst }]; #set_property -dict { PACKAGE_PIN C2 IOSTANDARD LVCMOS33 } [get_ports { shield_rst }];


#set_property -dict { PACKAGE_PIN C1 IOSTANDARD LVCMOS33 } [get_ports { spi_hdr_ss }]; #set_property -dict { PACKAGE_PIN C1 IOSTANDARD LVCMOS33 } [get_ports { spi_hdr_ss }];
@ -531,7 +517,7 @@ set_property CONFIG_MODE SPIx4 [current_design]
# Clock constraints # Clock constraints
################################################################################ ################################################################################


create_clock -name sys_clk_pin -period 10.00 [get_ports { ext_clk }]; create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports { ext_clk }];


create_clock -name eth_rx_clk -period 40.0 [get_ports { eth_clocks_rx }] create_clock -name eth_rx_clk -period 40.0 [get_ports { eth_clocks_rx }]



@ -8,11 +8,11 @@ entity clock_generator is
); );


port ( port (
ext_clk : in std_logic; ext_clk : in std_logic;
pll_rst_in : in std_logic; pll_rst_in : in std_logic;
pll_clk_out : out std_logic; pll_clk_out : out std_logic;
pll_locked_out : out std_logic pll_locked_out : out std_logic
); );


end entity clock_generator; end entity clock_generator;


@ -20,117 +20,108 @@ architecture bypass of clock_generator is


-- prototype of ECP5 PLL -- prototype of ECP5 PLL
component EHXPLLL is component EHXPLLL is
generic ( generic (
CLKI_DIV : integer := 1; CLKI_DIV : integer := 1;
CLKFB_DIV : integer := 1; CLKFB_DIV : integer := 1;
CLKOP_DIV : integer := 8; CLKOP_DIV : integer := 8;
CLKOS_DIV : integer := 8; CLKOS_DIV : integer := 8;
CLKOS2_DIV : integer := 8; CLKOS2_DIV : integer := 8;
CLKOS3_DIV : integer := 8; CLKOS3_DIV : integer := 8;
CLKOP_ENABLE : string := "ENABLED"; CLKOP_ENABLE : string := "ENABLED";
CLKOS_ENABLE : string := "DISABLED"; CLKOS_ENABLE : string := "DISABLED";
CLKOS2_ENABLE : string := "DISABLED"; CLKOS2_ENABLE : string := "DISABLED";
CLKOS3_ENABLE : string := "DISABLED"; CLKOS3_ENABLE : string := "DISABLED";
CLKOP_CPHASE : integer := 0; CLKOP_CPHASE : integer := 0;
CLKOS_CPHASE : integer := 0; CLKOS_CPHASE : integer := 0;
CLKOS2_CPHASE : integer := 0; CLKOS2_CPHASE : integer := 0;
CLKOS3_CPHASE : integer := 0; CLKOS3_CPHASE : integer := 0;
CLKOP_FPHASE : integer := 0; CLKOP_FPHASE : integer := 0;
CLKOS_FPHASE : integer := 0; CLKOS_FPHASE : integer := 0;
CLKOS2_FPHASE : integer := 0; CLKOS2_FPHASE : integer := 0;
CLKOS3_FPHASE : integer := 0; CLKOS3_FPHASE : integer := 0;
FEEDBK_PATH : string := "CLKOP"; FEEDBK_PATH : string := "CLKOP";
CLKOP_TRIM_POL : string := "RISING"; CLKOP_TRIM_POL : string := "RISING";
CLKOP_TRIM_DELAY : integer := 0; CLKOP_TRIM_DELAY : integer := 0;
CLKOS_TRIM_POL : string := "RISING"; CLKOS_TRIM_POL : string := "RISING";
CLKOS_TRIM_DELAY : integer := 0; CLKOS_TRIM_DELAY : integer := 0;
OUTDIVIDER_MUXA : string := "DIVA"; OUTDIVIDER_MUXA : string := "DIVA";
OUTDIVIDER_MUXB : string := "DIVB"; OUTDIVIDER_MUXB : string := "DIVB";
OUTDIVIDER_MUXC : string := "DIVC"; OUTDIVIDER_MUXC : string := "DIVC";
OUTDIVIDER_MUXD : string := "DIVD"; OUTDIVIDER_MUXD : string := "DIVD";
PLL_LOCK_MODE : integer := 0; PLL_LOCK_MODE : integer := 0;
PLL_LOCK_DELAY : integer := 200; PLL_LOCK_DELAY : integer := 200;
STDBY_ENABLE : string := "DISABLED"; STDBY_ENABLE : string := "DISABLED";
REFIN_RESET : string := "DISABLED"; REFIN_RESET : string := "DISABLED";
SYNC_ENABLE : string := "DISABLED"; SYNC_ENABLE : string := "DISABLED";
INT_LOCK_STICKY : string := "ENABLED"; INT_LOCK_STICKY : string := "ENABLED";
DPHASE_SOURCE : string := "DISABLED"; DPHASE_SOURCE : string := "DISABLED";
PLLRST_ENA : string := "DISABLED"; PLLRST_ENA : string := "DISABLED";
INTFB_WAKE : string := "DISABLED" ); INTFB_WAKE : string := "DISABLED" );
port ( port (
CLKI : in std_logic; CLKI : in std_logic;
CLKFB : in std_logic; CLKFB : in std_logic;
PHASESEL1 : in std_logic; PHASESEL1 : in std_logic;
PHASESEL0 : in std_logic; PHASESEL0 : in std_logic;
PHASEDIR : in std_logic; PHASEDIR : in std_logic;
PHASESTEP : in std_logic; PHASESTEP : in std_logic;
PHASELOADREG : in std_logic; PHASELOADREG : in std_logic;
STDBY : in std_logic; STDBY : in std_logic;
PLLWAKESYNC : in std_logic; PLLWAKESYNC : in std_logic;
RST : in std_logic; RST : in std_logic;
ENCLKOP : in std_logic; ENCLKOP : in std_logic;
ENCLKOS : in std_logic; ENCLKOS : in std_logic;
ENCLKOS2 : in std_logic; ENCLKOS2 : in std_logic;
ENCLKOS3 : in std_logic; ENCLKOS3 : in std_logic;
CLKOP : out std_logic; CLKOP : out std_logic;
CLKOS : out std_logic; CLKOS : out std_logic;
CLKOS2 : out std_logic; CLKOS2 : out std_logic;
CLKOS3 : out std_logic; CLKOS3 : out std_logic;
LOCK : out std_logic; LOCK : out std_logic;
INTLOCK : out std_logic; INTLOCK : out std_logic;
REFCLK : out std_logic; REFCLK : out std_logic;
CLKINTFB : out std_logic ); CLKINTFB : out std_logic );
end component; end component;


signal clkos : std_ulogic;
signal clkop : std_logic; signal clkop : std_logic;
signal lock : std_logic; signal lock : std_logic;


-- PLL constants -- PLL constants based on prjtrellis example
-- According to the datasheet, PLL_IN needs to be between 10 and 400 MHz constant PLL_IN : natural := 2000000;
-- PLL_OUT needs to be between 400 and 800 MHz constant PLL_OUT : natural := 600000000;
-- PLL_IN is chosen based on 12 and 48 MHz being common values
-- for the reference clock.
constant PLL_IN : natural := 12000000;
constant PLL_OUT : natural := 480000000;


-- Configration for ECP5 PLL -- Configration for ECP5 PLL
constant PLL_CLKOP_DIV : natural := PLL_OUT/CLK_OUTPUT_HZ; constant PLL_CLKOP_DIV : natural := PLL_OUT/CLK_OUTPUT_HZ;
constant PLL_CLKOS_DIV : natural := 2; constant PLL_CLKFB_DIV : natural := CLK_OUTPUT_HZ/PLL_IN;
constant PLL_CLKFB_DIV : natural := PLL_OUT/PLL_CLKOS_DIV/PLL_IN;
constant PLL_CLKI_DIV : natural := CLK_INPUT_HZ/PLL_IN; constant PLL_CLKI_DIV : natural := CLK_INPUT_HZ/PLL_IN;


begin begin
pll_clk_out <= clkop; pll_clk_out <= clkop;
pll_locked_out <= lock; pll_locked_out <= not lock; -- FIXME: EHXPLLL lock signal active low?!?


clkgen: EHXPLLL clkgen: EHXPLLL
generic map( generic map(
CLKOP_CPHASE => 11, -- FIXME: Copied from prjtrells.
CLKOP_DIV => PLL_CLKOP_DIV, CLKOP_DIV => PLL_CLKOP_DIV,
CLKOS_ENABLE => "ENABLED", CLKFB_DIV => PLL_CLKFB_DIV,
CLKOS_DIV => PLL_CLKOS_DIV, CLKI_DIV => PLL_CLKI_DIV
CLKFB_DIV => PLL_CLKFB_DIV, )
CLKI_DIV => PLL_CLKI_DIV, port map (
FEEDBK_PATH => "CLKOS" CLKI => ext_clk,
) CLKOP => clkop,
port map ( CLKFB => clkop,
CLKI => ext_clk, LOCK => lock,
CLKOP => clkop, RST => pll_rst_in,
CLKOS => clkos, PHASESEL1 => '0',
CLKFB => clkos, PHASESEL0 => '0',
LOCK => lock, PHASEDIR => '0',
RST => pll_rst_in, PHASESTEP => '0',
PHASESEL1 => '0', PHASELOADREG => '0',
PHASESEL0 => '0', STDBY => '0',
PHASEDIR => '0', PLLWAKESYNC => '0',
PHASESTEP => '0', ENCLKOP => '0',
PHASELOADREG => '0', ENCLKOS => '0',
STDBY => '0', ENCLKOS2 => '0',
PLLWAKESYNC => '0', ENCLKOS3 => '0'
ENCLKOP => '1',
ENCLKOS => '1',
ENCLKOS2 => '0',
ENCLKOS3 => '0'
); );


end architecture bypass; end architecture bypass;

@ -8,7 +8,7 @@ entity clock_generator is
generic ( generic (
CLK_INPUT_HZ : positive := 12000000; CLK_INPUT_HZ : positive := 12000000;
CLK_OUTPUT_HZ : positive := 50000000 CLK_OUTPUT_HZ : positive := 50000000
); );
port ( port (
ext_clk : in std_logic; ext_clk : in std_logic;
pll_rst_in : in std_logic; pll_rst_in : in std_logic;
@ -24,66 +24,66 @@ architecture rtl of clock_generator is
clkfbout_mult : real range 2.0 to 64.0; clkfbout_mult : real range 2.0 to 64.0;
clkout_divide : real range 1.0 to 128.0; clkout_divide : real range 1.0 to 128.0;
divclk_divide : integer range 1 to 106; divclk_divide : integer range 1 to 106;
force_rst : std_ulogic; force_rst : std_ulogic;
end record; end record;


function gen_pll_settings ( function gen_pll_settings (
constant input_hz : positive; constant input_hz : positive;
constant output_hz : positive) constant output_hz : positive)
return pll_settings_t is return pll_settings_t is


constant bad_settings : pll_settings_t := constant bad_settings : pll_settings_t :=
(clkin_period => 0.0, (clkin_period => 0.0,
clkfbout_mult => 2.0, clkfbout_mult => 2.0,
clkout_divide => 1.0, clkout_divide => 1.0,
divclk_divide => 1, divclk_divide => 1,
force_rst => '1'); force_rst => '1');
begin begin
case input_hz is case input_hz is
when 100000000 => when 100000000 =>
case output_hz is case output_hz is
when 100000000 => when 100000000 =>
return (clkin_period => 10.0, return (clkin_period => 10.0,
clkfbout_mult => 16.0, clkfbout_mult => 16.0,
clkout_divide => 16.0, clkout_divide => 16.0,
divclk_divide => 1, divclk_divide => 1,
force_rst => '0'); force_rst => '0');
when 50000000 => when 50000000 =>
return (clkin_period => 10.0, return (clkin_period => 10.0,
clkfbout_mult => 16.0, clkfbout_mult => 16.0,
clkout_divide => 32.0, clkout_divide => 32.0,
divclk_divide => 1, divclk_divide => 1,
force_rst => '0'); force_rst => '0');
when others => when others =>
report "Unsupported output frequency" severity failure; report "Unsupported output frequency" severity failure;
return bad_settings; return bad_settings;
end case; end case;
when 12000000 => when 12000000 =>
case output_hz is case output_hz is
when 100000000 => when 100000000 =>
return (clkin_period => 83.33, return (clkin_period => 83.33,
clkfbout_mult => 50.0, clkfbout_mult => 50.0,
clkout_divide => 6.0, clkout_divide => 6.0,
divclk_divide => 1, divclk_divide => 1,
force_rst => '0'); force_rst => '0');
when 50000000 => when 50000000 =>
return (clkin_period => 83.33, return (clkin_period => 83.33,
clkfbout_mult => 50.0, clkfbout_mult => 50.0,
clkout_divide => 12.0, clkout_divide => 12.0,
divclk_divide => 1, divclk_divide => 1,
force_rst => '0'); force_rst => '0');
when others => when others =>
report "Unsupported output frequency" severity failure; report "Unsupported output frequency" severity failure;
return bad_settings; return bad_settings;
end case; end case;
when others => when others =>
report "Unsupported input frequency" severity failure; report "Unsupported input frequency" severity failure;
return bad_settings; return bad_settings;
end case; end case;
end function gen_pll_settings; end function gen_pll_settings;


constant pll_settings : pll_settings_t := gen_pll_settings(clk_input_hz, constant pll_settings : pll_settings_t := gen_pll_settings(clk_input_hz,
clk_output_hz); clk_output_hz);
begin begin
pll : MMCME2_BASE pll : MMCME2_BASE
generic map ( generic map (
@ -111,6 +111,6 @@ begin
CLKFBIN => clkfb, CLKFBIN => clkfb,
CLKIN1 => ext_clk, CLKIN1 => ext_clk,
PWRDWN => '0', PWRDWN => '0',
RST => pll_rst_in or pll_settings.force_rst RST => pll_rst_in or pll_settings.force_rst
); );
end architecture rtl; end architecture rtl;

@ -6,112 +6,100 @@ use UNISIM.vcomponents.all;


entity clock_generator is entity clock_generator is
generic ( generic (
CLK_INPUT_HZ : positive := 100000000; CLK_INPUT_HZ : positive := 100000000;
CLK_OUTPUT_HZ : positive := 100000000 CLK_OUTPUT_HZ : positive := 100000000
); );
port ( port (
ext_clk : in std_logic; ext_clk : in std_logic;
pll_rst_in : in std_logic; pll_rst_in : in std_logic;
pll_clk_out : out std_logic; pll_clk_out : out std_logic;
pll_locked_out : out std_logic); pll_locked_out : out std_logic);
end entity clock_generator; end entity clock_generator;


architecture rtl of clock_generator is architecture rtl of clock_generator is
signal clkfb : std_ulogic; signal clkfb : std_ulogic;


type pll_settings_t is record type pll_settings_t is record
clkin_period : real range 0.000 to 52.631; clkin_period : real range 0.000 to 52.631;
clkfbout_mult : integer range 2 to 64; clkfbout_mult : integer range 2 to 64;
clkout_divide : integer range 1 to 128; clkout_divide : integer range 1 to 128;
divclk_divide : integer range 1 to 56; divclk_divide : integer range 1 to 56;
force_rst : std_ulogic; force_rst : std_ulogic;
end record; end record;


function gen_pll_settings ( function gen_pll_settings (
constant input_hz : positive; constant input_hz : positive;
constant output_hz : positive) constant output_hz : positive)
return pll_settings_t is return pll_settings_t is


constant bad_settings : pll_settings_t := constant bad_settings : pll_settings_t :=
(clkin_period => 0.0, (clkin_period => 0.0,
clkfbout_mult => 2, clkfbout_mult => 2,
clkout_divide => 1, clkout_divide => 1,
divclk_divide => 1, divclk_divide => 1,
force_rst => '1'); force_rst => '1');
begin begin
case input_hz is case input_hz is
when 200000000 => when 200000000 =>
case output_hz is case output_hz is
when 100000000 => when 100000000 =>
return (clkin_period => 5.0, return (clkin_period => 5.0,
clkfbout_mult => 8, clkfbout_mult => 8,
clkout_divide => 16, clkout_divide => 16,
divclk_divide => 1, divclk_divide => 1,
force_rst => '0'); force_rst => '0');
when others => when others =>
report "Unsupported output frequency" severity failure; report "Unsupported output frequency" severity failure;
return bad_settings; return bad_settings;
end case; end case;
when 100000000 => when 100000000 =>
case output_hz is case output_hz is
when 100000000 => when 100000000 =>
return (clkin_period => 10.0, return (clkin_period => 10.0,
clkfbout_mult => 16, clkfbout_mult => 16,
clkout_divide => 16, clkout_divide => 16,
divclk_divide => 1, divclk_divide => 1,
force_rst => '0'); force_rst => '0');
when 50000000 => when 50000000 =>
return (clkin_period => 10.0, return (clkin_period => 10.0,
clkfbout_mult => 16, clkfbout_mult => 16,
clkout_divide => 32, clkout_divide => 32,
divclk_divide => 1, divclk_divide => 1,
force_rst => '0'); force_rst => '0');
when others => when others =>
report "Unsupported output frequency" severity failure; report "Unsupported output frequency" severity failure;
return bad_settings; return bad_settings;
end case; end case;
when 50000000 => when others =>
case output_hz is report "Unsupported input frequency" severity failure;
when 100000000 => return bad_settings;
return (clkin_period => 20.0, end case;
clkfbout_mult => 32,
clkout_divide => 16,
divclk_divide => 1,
force_rst => '0');
when others =>
report "Unsupported output frequency" severity failure;
return bad_settings;
end case;
when others =>
report "Unsupported input frequency" severity failure;
return bad_settings;
end case;
end function gen_pll_settings; end function gen_pll_settings;


constant pll_settings : pll_settings_t := gen_pll_settings(clk_input_hz, constant pll_settings : pll_settings_t := gen_pll_settings(clk_input_hz,
clk_output_hz); clk_output_hz);
begin begin


pll : PLLE2_BASE pll : PLLE2_BASE
generic map ( generic map (
BANDWIDTH => "OPTIMIZED", BANDWIDTH => "OPTIMIZED",
CLKFBOUT_MULT => pll_settings.clkfbout_mult, CLKFBOUT_MULT => pll_settings.clkfbout_mult,
CLKIN1_PERIOD => pll_settings.clkin_period, CLKIN1_PERIOD => pll_settings.clkin_period,
CLKOUT0_DIVIDE => pll_settings.clkout_divide, CLKOUT0_DIVIDE => pll_settings.clkout_divide,
DIVCLK_DIVIDE => pll_settings.divclk_divide, DIVCLK_DIVIDE => pll_settings.divclk_divide,
STARTUP_WAIT => "FALSE") STARTUP_WAIT => "FALSE")
port map ( port map (
CLKOUT0 => pll_clk_out, CLKOUT0 => pll_clk_out,
CLKOUT1 => open, CLKOUT1 => open,
CLKOUT2 => open, CLKOUT2 => open,
CLKOUT3 => open, CLKOUT3 => open,
CLKOUT4 => open, CLKOUT4 => open,
CLKOUT5 => open, CLKOUT5 => open,
CLKFBOUT => clkfb, CLKFBOUT => clkfb,
LOCKED => pll_locked_out, LOCKED => pll_locked_out,
CLKIN1 => ext_clk, CLKIN1 => ext_clk,
PWRDWN => '0', PWRDWN => '0',
RST => pll_rst_in or pll_settings.force_rst, RST => pll_rst_in or pll_settings.force_rst,
CLKFBIN => clkfb); CLKFBIN => clkfb);


end architecture rtl; end architecture rtl;

@ -1,6 +1,6 @@
## Clock signal 12 MHz ## Clock signal 12 MHz
set_property -dict { PACKAGE_PIN L17 IOSTANDARD LVCMOS33 } [get_ports { ext_clk }]; set_property -dict { PACKAGE_PIN L17 IOSTANDARD LVCMOS33 } [get_ports { ext_clk }];
create_clock -name sys_clk_pin -period 83.33 [get_ports {ext_clk}]; create_clock -add -name sys_clk_pin -period 83.33 -waveform {0 41.66} [get_ports {ext_clk}];


set_property -dict { PACKAGE_PIN J18 IOSTANDARD LVCMOS33 } [get_ports { uart0_txd }]; set_property -dict { PACKAGE_PIN J18 IOSTANDARD LVCMOS33 } [get_ports { uart0_txd }];
set_property -dict { PACKAGE_PIN J17 IOSTANDARD LVCMOS33 } [get_ports { uart0_rxd }]; set_property -dict { PACKAGE_PIN J17 IOSTANDARD LVCMOS33 } [get_ports { uart0_rxd }];

@ -3,8 +3,8 @@
## Clock & Reset ## Clock & Reset
set_property -dict { PACKAGE_PIN AD11 IOSTANDARD LVDS } [get_ports { clk200_n }] set_property -dict { PACKAGE_PIN AD11 IOSTANDARD LVDS } [get_ports { clk200_n }]
set_property -dict { PACKAGE_PIN AD12 IOSTANDARD LVDS } [get_ports { clk200_p }] set_property -dict { PACKAGE_PIN AD12 IOSTANDARD LVDS } [get_ports { clk200_p }]
create_clock -period 5.000 -name tc_clk100_p [get_ports clk200_p] create_clock -period 5.000 -name tc_clk100_p -waveform {0.000 2.500} [get_ports clk200_p]
create_clock -period 5.000 -name tc_clk100_n [get_ports clk200_n] create_clock -period 5.000 -name tc_clk100_n -waveform {2.500 5.000} [get_ports clk200_n]


set_property -dict { PACKAGE_PIN R19 IOSTANDARD LVCMOS33 } [get_ports { ext_rst }] set_property -dict { PACKAGE_PIN R19 IOSTANDARD LVCMOS33 } [get_ports { ext_rst }]



@ -9,20 +9,20 @@ library work;


entity main_bram is entity main_bram is
generic( generic(
WIDTH : natural := 64; WIDTH : natural := 64;
HEIGHT_BITS : natural := 1024; HEIGHT_BITS : natural := 1024;
MEMORY_SIZE : natural := 65536; MEMORY_SIZE : natural := 65536;
RAM_INIT_FILE : string RAM_INIT_FILE : string
); );
port( port(
clk : in std_logic; clk : in std_logic;
addr : in std_logic_vector(HEIGHT_BITS - 1 downto 0) ; addr : in std_logic_vector(HEIGHT_BITS - 1 downto 0) ;
din : in std_logic_vector(WIDTH-1 downto 0); di : in std_logic_vector(WIDTH-1 downto 0);
dout : out std_logic_vector(WIDTH-1 downto 0); do : out std_logic_vector(WIDTH-1 downto 0);
sel : in std_logic_vector((WIDTH/8)-1 downto 0); sel : in std_logic_vector((WIDTH/8)-1 downto 0);
re : in std_ulogic; re : in std_ulogic;
we : in std_ulogic we : in std_ulogic
); );
end entity main_bram; end entity main_bram;


architecture behaviour of main_bram is architecture behaviour of main_bram is
@ -63,20 +63,20 @@ begin
-- Actual RAM template -- Actual RAM template
memory_0: process(clk) memory_0: process(clk)
begin begin
if rising_edge(clk) then if rising_edge(clk) then
if we = '1' then if we = '1' then
for i in 0 to 7 loop for i in 0 to 7 loop
if sel(i) = '1' then if sel(i) = '1' then
memory(to_integer(unsigned(addr)))((i + 1) * 8 - 1 downto i * 8) <= memory(to_integer(unsigned(addr)))((i + 1) * 8 - 1 downto i * 8) <=
din((i + 1) * 8 - 1 downto i * 8); di((i + 1) * 8 - 1 downto i * 8);
end if; end if;
end loop; end loop;
end if; end if;
if re = '1' then if re = '1' then
obuf <= memory(to_integer(unsigned(addr))); obuf <= memory(to_integer(unsigned(addr)));
end if; end if;
dout <= obuf; do <= obuf;
end if; end if;
end process; end process;


end architecture behaviour; end architecture behaviour;

@ -4,7 +4,7 @@


set_property -dict {PACKAGE_PIN R4 IOSTANDARD LVCMOS33} [get_ports ext_clk] set_property -dict {PACKAGE_PIN R4 IOSTANDARD LVCMOS33} [get_ports ext_clk]


set_property -dict {PACKAGE_PIN G4 IOSTANDARD LVCMOS15} [get_ports ext_rst_n] set_property -dict {PACKAGE_PIN G4 IOSTANDARD LVCMOS15} [get_ports ext_rst]


set_property -dict {PACKAGE_PIN AA19 IOSTANDARD LVCMOS33} [get_ports uart_main_tx] set_property -dict {PACKAGE_PIN AA19 IOSTANDARD LVCMOS33} [get_ports uart_main_tx]
set_property -dict {PACKAGE_PIN V18 IOSTANDARD LVCMOS33} [get_ports uart_main_rx] set_property -dict {PACKAGE_PIN V18 IOSTANDARD LVCMOS33} [get_ports uart_main_rx]
@ -22,14 +22,8 @@ set_property -dict {PACKAGE_PIN V18 IOSTANDARD LVCMOS33} [get_ports uart_main_rx
# LEDs # LEDs
################################################################################ ################################################################################


set_property -dict { PACKAGE_PIN T14 IOSTANDARD LVCMOS25 } [get_ports { led0 }]; set_property -dict { PACKAGE_PIN T14 IOSTANDARD LVCMOS33 } [get_ports { led0 }];
set_property -dict { PACKAGE_PIN T15 IOSTANDARD LVCMOS25 } [get_ports { led1 }]; set_property -dict { PACKAGE_PIN T15 IOSTANDARD LVCMOS33 } [get_ports { led1 }];
set_property -dict { PACKAGE_PIN T16 IOSTANDARD LVCMOS25 } [get_ports { led2 }];
set_property -dict { PACKAGE_PIN U16 IOSTANDARD LVCMOS25 } [get_ports { led3 }];
set_property -dict { PACKAGE_PIN V15 IOSTANDARD LVCMOS25 } [get_ports { led4 }];
set_property -dict { PACKAGE_PIN W16 IOSTANDARD LVCMOS25 } [get_ports { led5 }];
set_property -dict { PACKAGE_PIN W15 IOSTANDARD LVCMOS25 } [get_ports { led6 }];
set_property -dict { PACKAGE_PIN Y13 IOSTANDARD LVCMOS25 } [get_ports { led7 }];


################################################################################ ################################################################################
# SPI Flash # SPI Flash
@ -41,91 +35,6 @@ set_property -dict { PACKAGE_PIN R22 IOSTANDARD LVCMOS33 } [get_ports { spi_flas
set_property -dict { PACKAGE_PIN P21 IOSTANDARD LVCMOS33 } [get_ports { spi_flash_wp_n }]; set_property -dict { PACKAGE_PIN P21 IOSTANDARD LVCMOS33 } [get_ports { spi_flash_wp_n }];
set_property -dict { PACKAGE_PIN R21 IOSTANDARD LVCMOS33 } [get_ports { spi_flash_hold_n }]; set_property -dict { PACKAGE_PIN R21 IOSTANDARD LVCMOS33 } [get_ports { spi_flash_hold_n }];


################################################################################
# SD card
################################################################################

set_property -dict { PACKAGE_PIN W19 IOSTANDARD LVCMOS33 SLEW FAST } [get_ports { sdcard_clk }]
set_property -dict { PACKAGE_PIN T18 IOSTANDARD LVCMOS33 } [get_ports { sdcard_cd }]
set_property -dict { PACKAGE_PIN W20 IOSTANDARD LVCMOS33 SLEW FAST } [get_ports { sdcard_cmd }]
set_property -dict { PACKAGE_PIN V19 IOSTANDARD LVCMOS33 SLEW FAST } [get_ports { sdcard_data[0] }]
set_property -dict { PACKAGE_PIN T21 IOSTANDARD LVCMOS33 SLEW FAST } [get_ports { sdcard_data[1] }]
set_property -dict { PACKAGE_PIN T20 IOSTANDARD LVCMOS33 SLEW FAST } [get_ports { sdcard_data[2] }]
set_property -dict { PACKAGE_PIN U18 IOSTANDARD LVCMOS33 SLEW FAST } [get_ports { sdcard_data[3] }]
set_property -dict { PACKAGE_PIN V20 IOSTANDARD LVCMOS33 } [get_ports { sdcard_reset }]

# Put registers into IOBs to improve timing
set_property IOB true [get_cells -hierarchical -filter {NAME =~*.litesdcard/sdcard_*}]

################################################################################
# Ethernet (generated by LiteX)
################################################################################

# eth_clocks:0.tx
set_property LOC AA14 [get_ports {eth_clocks_tx}]
set_property IOSTANDARD LVCMOS25 [get_ports {eth_clocks_tx}]

# eth_clocks:0.rx
set_property LOC V13 [get_ports {eth_clocks_rx}]
set_property IOSTANDARD LVCMOS25 [get_ports {eth_clocks_rx}]

# eth:0.rst_n
set_property LOC U7 [get_ports {eth_rst_n}]
set_property IOSTANDARD LVCMOS25 [get_ports {eth_rst_n}]
set_property IOSTANDARD LVCMOS33 [get_ports {eth_rst_n}]

# eth:0.int_n
set_property LOC Y14 [get_ports {eth_int_n}]
set_property IOSTANDARD LVCMOS25 [get_ports {eth_int_n}]

# eth:0.mdio
set_property LOC Y16 [get_ports {eth_mdio}]
set_property IOSTANDARD LVCMOS25 [get_ports {eth_mdio}]

# eth:0.mdc
set_property LOC AA16 [get_ports {eth_mdc}]
set_property IOSTANDARD LVCMOS25 [get_ports {eth_mdc}]

# eth:0.rx_ctl
set_property LOC W10 [get_ports {eth_rx_ctl}]
set_property IOSTANDARD LVCMOS25 [get_ports {eth_rx_ctl}]

# eth:0.rx_data
set_property LOC AB16 [get_ports {eth_rx_data[0]}]
set_property IOSTANDARD LVCMOS25 [get_ports {eth_rx_data[0]}]

# eth:0.rx_data
set_property LOC AA15 [get_ports {eth_rx_data[1]}]
set_property IOSTANDARD LVCMOS25 [get_ports {eth_rx_data[1]}]

# eth:0.rx_data
set_property LOC AB15 [get_ports {eth_rx_data[2]}]
set_property IOSTANDARD LVCMOS25 [get_ports {eth_rx_data[2]}]

# eth:0.rx_data
set_property LOC AB11 [get_ports {eth_rx_data[3]}]
set_property IOSTANDARD LVCMOS25 [get_ports {eth_rx_data[3]}]

# eth:0.tx_ctl
set_property LOC V10 [get_ports {eth_tx_ctl}]
set_property IOSTANDARD LVCMOS25 [get_ports {eth_tx_ctl}]

# eth:0.tx_data
set_property LOC Y12 [get_ports {eth_tx_data[0]}]
set_property IOSTANDARD LVCMOS25 [get_ports {eth_tx_data[0]}]

# eth:0.tx_data
set_property LOC W12 [get_ports {eth_tx_data[1]}]
set_property IOSTANDARD LVCMOS25 [get_ports {eth_tx_data[1]}]

# eth:0.tx_data
set_property LOC W11 [get_ports {eth_tx_data[2]}]
set_property IOSTANDARD LVCMOS25 [get_ports {eth_tx_data[2]}]

# eth:0.tx_data
set_property LOC Y11 [get_ports {eth_tx_data[3]}]
set_property IOSTANDARD LVCMOS25 [get_ports {eth_tx_data[3]}]

################################################################################ ################################################################################
# DRAM (generated by LiteX) # DRAM (generated by LiteX)
################################################################################ ################################################################################
@ -404,18 +313,12 @@ set_property CONFIG_MODE SPIx4 [current_design]
# Clock constraints # Clock constraints
################################################################################ ################################################################################


create_clock -name sys_clk_pin -period 10.00 [get_ports { ext_clk }]; create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports { ext_clk }];

create_clock -name eth_clocks_rx -period 8.0 [get_ports { eth_clocks_rx }]

set_clock_groups -asynchronous -group [get_clocks sys_clk_pin -include_generated_clocks] -group [get_clocks eth_clocks_rx -include_generated_clocks]


################################################################################ ################################################################################
# False path constraints (from LiteX as they relate to LiteDRAM and LiteEth) # False path constraints (from LiteX as they relate to LiteDRAM)
################################################################################ ################################################################################


set_false_path -quiet -through [get_nets -hierarchical -filter {mr_ff == TRUE}]

set_false_path -quiet -to [get_pins -filter {REF_PIN_NAME == PRE} -of_objects [get_cells -hierarchical -filter {ars_ff1 == TRUE || ars_ff2 == TRUE}]] set_false_path -quiet -to [get_pins -filter {REF_PIN_NAME == PRE} -of_objects [get_cells -hierarchical -filter {ars_ff1 == TRUE || ars_ff2 == TRUE}]]


set_max_delay 2 -quiet -from [get_pins -filter {REF_PIN_NAME == C} -of_objects [get_cells -hierarchical -filter {ars_ff1 == TRUE}]] -to [get_pins -filter {REF_PIN_NAME == D} -of_objects [get_cells -hierarchical -filter {ars_ff2 == TRUE}]] set_max_delay 2 -quiet -from [get_pins -filter {REF_PIN_NAME == C} -of_objects [get_cells -hierarchical -filter {ars_ff1 == TRUE}]] -to [get_pins -filter {REF_PIN_NAME == D} -of_objects [get_cells -hierarchical -filter {ars_ff2 == TRUE}]]

@ -1,5 +1,5 @@
set_property -dict {PACKAGE_PIN E3 IOSTANDARD LVCMOS33} [get_ports ext_clk] set_property -dict {PACKAGE_PIN E3 IOSTANDARD LVCMOS33} [get_ports ext_clk]
create_clock -period 10.000 -name sys_clk_pin [get_ports ext_clk] create_clock -period 10.000 -name sys_clk_pin -waveform {0.000 5.000} -add [get_ports ext_clk]


set_property -dict {PACKAGE_PIN C12 IOSTANDARD LVCMOS33} [get_ports ext_rst] set_property -dict {PACKAGE_PIN C12 IOSTANDARD LVCMOS33} [get_ports ext_rst]



@ -94,10 +94,6 @@ architecture behaviour of toplevel is
signal spi_sdat_oe : std_ulogic_vector(3 downto 0); signal spi_sdat_oe : std_ulogic_vector(3 downto 0);
signal spi_sdat_i : std_ulogic_vector(3 downto 0); signal spi_sdat_i : std_ulogic_vector(3 downto 0);


-- ddram clock signals as vectors
signal ddram_clk_p_vec : std_logic_vector(0 downto 0);
signal ddram_clk_n_vec : std_logic_vector(0 downto 0);

-- Fixup various memory sizes based on generics -- Fixup various memory sizes based on generics
function get_bram_size return natural is function get_bram_size return natural is
begin begin
@ -256,9 +252,6 @@ begin
-- but for now, assert it's 100Mhz -- but for now, assert it's 100Mhz
assert CLK_FREQUENCY = 100000000; assert CLK_FREQUENCY = 100000000;


ddram_clk_p_vec <= (others => ddram_clk_p);
ddram_clk_n_vec <= (others => ddram_clk_n);

reset_controller: entity work.soc_reset reset_controller: entity work.soc_reset
generic map( generic map(
RESET_LOW => false, RESET_LOW => false,
@ -279,7 +272,6 @@ begin
DRAM_ABITS => 26, DRAM_ABITS => 26,
DRAM_ALINES => 16, DRAM_ALINES => 16,
DRAM_DLINES => 16, DRAM_DLINES => 16,
DRAM_CKLINES => 1,
DRAM_PORT_WIDTH => 128, DRAM_PORT_WIDTH => 128,
PAYLOAD_FILE => RAM_INIT_FILE, PAYLOAD_FILE => RAM_INIT_FILE,
PAYLOAD_SIZE => PAYLOAD_SIZE PAYLOAD_SIZE => PAYLOAD_SIZE
@ -312,8 +304,8 @@ begin
ddram_dq => ddram_dq, ddram_dq => ddram_dq,
ddram_dqs_p => ddram_dqs_p, ddram_dqs_p => ddram_dqs_p,
ddram_dqs_n => ddram_dqs_n, ddram_dqs_n => ddram_dqs_n,
ddram_clk_p => ddram_clk_p_vec, ddram_clk_p => ddram_clk_p,
ddram_clk_n => ddram_clk_n_vec, ddram_clk_n => ddram_clk_n,
ddram_cke => ddram_cke, ddram_cke => ddram_cke,
ddram_odt => ddram_odt, ddram_odt => ddram_odt,
ddram_reset_n => ddram_reset_n ddram_reset_n => ddram_reset_n

@ -16,7 +16,6 @@ entity toplevel is
CLK_FREQUENCY : positive := 100000000; CLK_FREQUENCY : positive := 100000000;
HAS_FPU : boolean := true; HAS_FPU : boolean := true;
HAS_BTC : boolean := true; HAS_BTC : boolean := true;
HAS_SHORT_MULT : boolean := false;
USE_LITEDRAM : boolean := false; USE_LITEDRAM : boolean := false;
NO_BRAM : boolean := false; NO_BRAM : boolean := false;
DISABLE_FLATTEN_CORE : boolean := false; DISABLE_FLATTEN_CORE : boolean := false;
@ -27,10 +26,7 @@ entity toplevel is
LOG_LENGTH : natural := 512; LOG_LENGTH : natural := 512;
USE_LITEETH : boolean := false; USE_LITEETH : boolean := false;
UART_IS_16550 : boolean := false; UART_IS_16550 : boolean := false;
HAS_UART1 : boolean := true; HAS_UART1 : boolean := true
USE_LITESDCARD : boolean := false;
HAS_GPIO : boolean := true;
NGPIO : natural := 32
); );
port( port(
ext_clk : in std_ulogic; ext_clk : in std_ulogic;
@ -40,6 +36,12 @@ entity toplevel is
uart_main_tx : out std_ulogic; uart_main_tx : out std_ulogic;
uart_main_rx : in std_ulogic; uart_main_rx : in std_ulogic;


-- UART1 signals:
uart_pmod_tx : out std_ulogic;
uart_pmod_rx : in std_ulogic;
uart_pmod_cts_n : in std_ulogic;
uart_pmod_rts_n : out std_ulogic;

-- LEDs -- LEDs
led0_b : out std_ulogic; led0_b : out std_ulogic;
led0_g : out std_ulogic; led0_g : out std_ulogic;
@ -57,9 +59,6 @@ entity toplevel is
spi_flash_wp_n : inout std_ulogic; spi_flash_wp_n : inout std_ulogic;
spi_flash_hold_n : inout std_ulogic; spi_flash_hold_n : inout std_ulogic;


-- GPIO
shield_io : inout std_ulogic_vector(44 downto 0);

-- Ethernet -- Ethernet
eth_ref_clk : out std_ulogic; eth_ref_clk : out std_ulogic;
eth_clocks_tx : in std_ulogic; eth_clocks_tx : in std_ulogic;
@ -75,12 +74,6 @@ entity toplevel is
eth_col : in std_ulogic; eth_col : in std_ulogic;
eth_crs : in std_ulogic; eth_crs : in std_ulogic;


-- SD card
sdcard_data : inout std_ulogic_vector(3 downto 0);
sdcard_cmd : inout std_ulogic;
sdcard_clk : out std_ulogic;
sdcard_cd : in std_ulogic;

-- DRAM wires -- DRAM wires
ddram_a : out std_ulogic_vector(13 downto 0); ddram_a : out std_ulogic_vector(13 downto 0);
ddram_ba : out std_ulogic_vector(2 downto 0); ddram_ba : out std_ulogic_vector(2 downto 0);
@ -117,7 +110,6 @@ architecture behaviour of toplevel is
signal wb_ext_is_dram_csr : std_ulogic; signal wb_ext_is_dram_csr : std_ulogic;
signal wb_ext_is_dram_init : std_ulogic; signal wb_ext_is_dram_init : std_ulogic;
signal wb_ext_is_eth : std_ulogic; signal wb_ext_is_eth : std_ulogic;
signal wb_ext_is_sdcard : std_ulogic;


-- DRAM main data wishbone connection -- DRAM main data wishbone connection
signal wb_dram_in : wishbone_master_out; signal wb_dram_in : wishbone_master_out;
@ -130,16 +122,6 @@ architecture behaviour of toplevel is
signal ext_irq_eth : std_ulogic; signal ext_irq_eth : std_ulogic;
signal wb_eth_out : wb_io_slave_out := wb_io_slave_out_init; signal wb_eth_out : wb_io_slave_out := wb_io_slave_out_init;


-- LiteSDCard connection
signal ext_irq_sdcard : std_ulogic := '0';
signal wb_sdcard_out : wb_io_slave_out := wb_io_slave_out_init;
signal wb_sddma_out : wb_io_master_out := wb_io_master_out_init;
signal wb_sddma_in : wb_io_slave_out;
signal wb_sddma_nr : wb_io_master_out;
signal wb_sddma_ir : wb_io_slave_out;
-- for conversion from non-pipelined wishbone to pipelined
signal wb_sddma_stb_sent : std_ulogic;

-- Control/status -- Control/status
signal core_alt_reset : std_ulogic; signal core_alt_reset : std_ulogic;


@ -158,15 +140,6 @@ architecture behaviour of toplevel is
signal spi_sdat_oe : std_ulogic_vector(3 downto 0); signal spi_sdat_oe : std_ulogic_vector(3 downto 0);
signal spi_sdat_i : std_ulogic_vector(3 downto 0); signal spi_sdat_i : std_ulogic_vector(3 downto 0);


-- GPIO
signal gpio_in : std_ulogic_vector(NGPIO - 1 downto 0);
signal gpio_out : std_ulogic_vector(NGPIO - 1 downto 0);
signal gpio_dir : std_ulogic_vector(NGPIO - 1 downto 0);

-- ddram clock signals as vectors
signal ddram_clk_p_vec : std_logic_vector(0 downto 0);
signal ddram_clk_n_vec : std_logic_vector(0 downto 0);

-- Fixup various memory sizes based on generics -- Fixup various memory sizes based on generics
function get_bram_size return natural is function get_bram_size return natural is
begin begin
@ -199,7 +172,6 @@ begin
CLK_FREQ => CLK_FREQUENCY, CLK_FREQ => CLK_FREQUENCY,
HAS_FPU => HAS_FPU, HAS_FPU => HAS_FPU,
HAS_BTC => HAS_BTC, HAS_BTC => HAS_BTC,
HAS_SHORT_MULT => HAS_SHORT_MULT,
HAS_DRAM => USE_LITEDRAM, HAS_DRAM => USE_LITEDRAM,
DRAM_SIZE => 256 * 1024 * 1024, DRAM_SIZE => 256 * 1024 * 1024,
DRAM_INIT_SIZE => PAYLOAD_SIZE, DRAM_INIT_SIZE => PAYLOAD_SIZE,
@ -212,10 +184,7 @@ begin
LOG_LENGTH => LOG_LENGTH, LOG_LENGTH => LOG_LENGTH,
HAS_LITEETH => USE_LITEETH, HAS_LITEETH => USE_LITEETH,
UART0_IS_16550 => UART_IS_16550, UART0_IS_16550 => UART_IS_16550,
HAS_UART1 => HAS_UART1, HAS_UART1 => HAS_UART1
HAS_SD_CARD => USE_LITESDCARD,
HAS_GPIO => HAS_GPIO,
NGPIO => NGPIO
) )
port map ( port map (
-- System signals -- System signals
@ -227,8 +196,8 @@ begin
uart0_rxd => uart_main_rx, uart0_rxd => uart_main_rx,


-- UART1 signals -- UART1 signals
--uart1_txd => uart_pmod_tx, uart1_txd => uart_pmod_tx,
--uart1_rxd => uart_pmod_rx, uart1_rxd => uart_pmod_rx,


-- SPI signals -- SPI signals
spi_flash_sck => spi_sck, spi_flash_sck => spi_sck,
@ -237,35 +206,21 @@ begin
spi_flash_sdat_oe => spi_sdat_oe, spi_flash_sdat_oe => spi_sdat_oe,
spi_flash_sdat_i => spi_sdat_i, spi_flash_sdat_i => spi_sdat_i,


-- GPIO signals
gpio_in => gpio_in,
gpio_out => gpio_out,
gpio_dir => gpio_dir,

-- External interrupts -- External interrupts
ext_irq_eth => ext_irq_eth, ext_irq_eth => ext_irq_eth,
ext_irq_sdcard => ext_irq_sdcard,


-- DRAM wishbone -- DRAM wishbone
wb_dram_in => wb_dram_in, wb_dram_in => wb_dram_in,
wb_dram_out => wb_dram_out, wb_dram_out => wb_dram_out,

-- IO wishbone
wb_ext_io_in => wb_ext_io_in, wb_ext_io_in => wb_ext_io_in,
wb_ext_io_out => wb_ext_io_out, wb_ext_io_out => wb_ext_io_out,
wb_ext_is_dram_csr => wb_ext_is_dram_csr, wb_ext_is_dram_csr => wb_ext_is_dram_csr,
wb_ext_is_dram_init => wb_ext_is_dram_init, wb_ext_is_dram_init => wb_ext_is_dram_init,
wb_ext_is_eth => wb_ext_is_eth, wb_ext_is_eth => wb_ext_is_eth,
wb_ext_is_sdcard => wb_ext_is_sdcard,

-- DMA wishbone
wishbone_dma_in => wb_sddma_in,
wishbone_dma_out => wb_sddma_out,

alt_reset => core_alt_reset alt_reset => core_alt_reset
); );


--uart_pmod_rts_n <= '0'; uart_pmod_rts_n <= '0';


-- SPI Flash -- SPI Flash
-- --
@ -386,15 +341,11 @@ begin
end if; end if;
end process; end process;


ddram_clk_p_vec <= (others => ddram_clk_p);
ddram_clk_n_vec <= (others => ddram_clk_n);

dram: entity work.litedram_wrapper dram: entity work.litedram_wrapper
generic map( generic map(
DRAM_ABITS => 24, DRAM_ABITS => 24,
DRAM_ALINES => 14, DRAM_ALINES => 14,
DRAM_DLINES => 16, DRAM_DLINES => 16,
DRAM_CKLINES => 1,
DRAM_PORT_WIDTH => 128, DRAM_PORT_WIDTH => 128,
PAYLOAD_FILE => RAM_INIT_FILE, PAYLOAD_FILE => RAM_INIT_FILE,
PAYLOAD_SIZE => PAYLOAD_SIZE PAYLOAD_SIZE => PAYLOAD_SIZE
@ -427,8 +378,8 @@ begin
ddram_dq => ddram_dq, ddram_dq => ddram_dq,
ddram_dqs_p => ddram_dqs_p, ddram_dqs_p => ddram_dqs_p,
ddram_dqs_n => ddram_dqs_n, ddram_dqs_n => ddram_dqs_n,
ddram_clk_p => ddram_clk_p_vec, ddram_clk_p => ddram_clk_p,
ddram_clk_n => ddram_clk_n_vec, ddram_clk_n => ddram_clk_n,
ddram_cke => ddram_cke, ddram_cke => ddram_cke,
ddram_odt => ddram_odt, ddram_odt => ddram_odt,
ddram_reset_n => ddram_reset_n ddram_reset_n => ddram_reset_n
@ -560,7 +511,7 @@ begin
wb_eth_cyc <= wb_ext_io_in.cyc and wb_ext_is_eth; wb_eth_cyc <= wb_ext_io_in.cyc and wb_ext_is_eth;


-- Remove top address bits as liteeth decoder doesn't know about them -- Remove top address bits as liteeth decoder doesn't know about them
wb_eth_adr <= x"000" & "000" & wb_ext_io_in.adr(14 downto 0); wb_eth_adr <= x"000" & "000" & wb_ext_io_in.adr(16 downto 2);


-- LiteETH isn't pipelined -- LiteETH isn't pipelined
wb_eth_out.stall <= not wb_eth_out.ack; wb_eth_out.stall <= not wb_eth_out.ack;
@ -572,113 +523,8 @@ begin
ext_irq_eth <= '0'; ext_irq_eth <= '0';
end generate; end generate;


-- SD card pmod
has_sdcard : if USE_LITESDCARD generate
component litesdcard_core port (
clk : in std_ulogic;
rst : in std_ulogic;
-- wishbone for accessing control registers
wb_ctrl_adr : in std_ulogic_vector(29 downto 0);
wb_ctrl_dat_w : in std_ulogic_vector(31 downto 0);
wb_ctrl_dat_r : out std_ulogic_vector(31 downto 0);
wb_ctrl_sel : in std_ulogic_vector(3 downto 0);
wb_ctrl_cyc : in std_ulogic;
wb_ctrl_stb : in std_ulogic;
wb_ctrl_ack : out std_ulogic;
wb_ctrl_we : in std_ulogic;
wb_ctrl_cti : in std_ulogic_vector(2 downto 0);
wb_ctrl_bte : in std_ulogic_vector(1 downto 0);
wb_ctrl_err : out std_ulogic;
-- wishbone for SD card core to use for DMA
wb_dma_adr : out std_ulogic_vector(29 downto 0);
wb_dma_dat_w : out std_ulogic_vector(31 downto 0);
wb_dma_dat_r : in std_ulogic_vector(31 downto 0);
wb_dma_sel : out std_ulogic_vector(3 downto 0);
wb_dma_cyc : out std_ulogic;
wb_dma_stb : out std_ulogic;
wb_dma_ack : in std_ulogic;
wb_dma_we : out std_ulogic;
wb_dma_cti : out std_ulogic_vector(2 downto 0);
wb_dma_bte : out std_ulogic_vector(1 downto 0);
wb_dma_err : in std_ulogic;
-- connections to SD card
sdcard_data : inout std_ulogic_vector(3 downto 0);
sdcard_cmd : inout std_ulogic;
sdcard_clk : out std_ulogic;
sdcard_cd : in std_ulogic;
irq : out std_ulogic
);
end component;

signal wb_sdcard_cyc : std_ulogic;
signal wb_sdcard_adr : std_ulogic_vector(29 downto 0);

begin
litesdcard : litesdcard_core
port map (
clk => system_clk,
rst => soc_rst,
wb_ctrl_adr => wb_sdcard_adr,
wb_ctrl_dat_w => wb_ext_io_in.dat,
wb_ctrl_dat_r => wb_sdcard_out.dat,
wb_ctrl_sel => wb_ext_io_in.sel,
wb_ctrl_cyc => wb_sdcard_cyc,
wb_ctrl_stb => wb_ext_io_in.stb,
wb_ctrl_ack => wb_sdcard_out.ack,
wb_ctrl_we => wb_ext_io_in.we,
wb_ctrl_cti => "000",
wb_ctrl_bte => "00",
wb_ctrl_err => open,
wb_dma_adr => wb_sddma_nr.adr,
wb_dma_dat_w => wb_sddma_nr.dat,
wb_dma_dat_r => wb_sddma_ir.dat,
wb_dma_sel => wb_sddma_nr.sel,
wb_dma_cyc => wb_sddma_nr.cyc,
wb_dma_stb => wb_sddma_nr.stb,
wb_dma_ack => wb_sddma_ir.ack,
wb_dma_we => wb_sddma_nr.we,
wb_dma_cti => open,
wb_dma_bte => open,
wb_dma_err => '0',
sdcard_data => sdcard_data,
sdcard_cmd => sdcard_cmd,
sdcard_clk => sdcard_clk,
sdcard_cd => sdcard_cd,
irq => ext_irq_sdcard
);

-- Gate cyc with chip select from SoC
wb_sdcard_cyc <= wb_ext_io_in.cyc and wb_ext_is_sdcard;

wb_sdcard_adr <= x"0000" & wb_ext_io_in.adr(13 downto 0);

wb_sdcard_out.stall <= not wb_sdcard_out.ack;

-- Convert non-pipelined DMA wishbone to pipelined by suppressing
-- non-acknowledged strobes
process(system_clk)
begin
if rising_edge(system_clk) then
wb_sddma_out <= wb_sddma_nr;
if wb_sddma_stb_sent = '1' or
(wb_sddma_out.stb = '1' and wb_sddma_in.stall = '0') then
wb_sddma_out.stb <= '0';
end if;
if wb_sddma_nr.cyc = '0' or wb_sddma_ir.ack = '1' then
wb_sddma_stb_sent <= '0';
elsif wb_sddma_in.stall = '0' then
wb_sddma_stb_sent <= wb_sddma_nr.stb;
end if;
wb_sddma_ir <= wb_sddma_in;
end if;
end process;

end generate;

-- Mux WB response on the IO bus -- Mux WB response on the IO bus
wb_ext_io_out <= wb_eth_out when wb_ext_is_eth = '1' else wb_ext_io_out <= wb_eth_out when wb_ext_is_eth = '1' else wb_dram_ctrl_out;
wb_sdcard_out when wb_ext_is_sdcard = '1' else
wb_dram_ctrl_out;


leds_pwm : process(system_clk) leds_pwm : process(system_clk)
begin begin
@ -699,72 +545,6 @@ begin
led4 <= system_clk_locked; led4 <= system_clk_locked;
led5 <= eth_clk_locked; led5 <= eth_clk_locked;
led6 <= not soc_rst; led6 <= not soc_rst;

led7 <= not spi_flash_cs_n;
-- GPIO
gpio_in(0) <= shield_io(0);
gpio_in(1) <= shield_io(1);
gpio_in(2) <= shield_io(2);
gpio_in(3) <= shield_io(3);
gpio_in(4) <= shield_io(4);
gpio_in(5) <= shield_io(5);
gpio_in(6) <= shield_io(6);
gpio_in(7) <= shield_io(7);
gpio_in(8) <= shield_io(8);
gpio_in(9) <= shield_io(9);
gpio_in(10) <= shield_io(10);
gpio_in(11) <= shield_io(11);
gpio_in(12) <= shield_io(12);
gpio_in(13) <= shield_io(13);
gpio_in(14) <= shield_io(26);
gpio_in(15) <= shield_io(27);
gpio_in(16) <= shield_io(28);
gpio_in(17) <= shield_io(29);
gpio_in(18) <= shield_io(30);
gpio_in(19) <= shield_io(31);
gpio_in(20) <= shield_io(32);
gpio_in(21) <= shield_io(33);
gpio_in(22) <= shield_io(34);
gpio_in(23) <= shield_io(35);
gpio_in(24) <= shield_io(36);
gpio_in(25) <= shield_io(37);
gpio_in(26) <= shield_io(38);
gpio_in(27) <= shield_io(39);
gpio_in(28) <= shield_io(40);
gpio_in(29) <= shield_io(41);
gpio_in(30) <= shield_io(43);
gpio_in(31) <= shield_io(44);

shield_io(0) <= gpio_out(0) when gpio_dir(0) = '1' else 'Z';
shield_io(1) <= gpio_out(1) when gpio_dir(1) = '1' else 'Z';
shield_io(2) <= gpio_out(2) when gpio_dir(2) = '1' else 'Z';
shield_io(3) <= gpio_out(3) when gpio_dir(3) = '1' else 'Z';
shield_io(4) <= gpio_out(4) when gpio_dir(4) = '1' else 'Z';
shield_io(5) <= gpio_out(5) when gpio_dir(5) = '1' else 'Z';
shield_io(6) <= gpio_out(6) when gpio_dir(6) = '1' else 'Z';
shield_io(7) <= gpio_out(7) when gpio_dir(7) = '1' else 'Z';
shield_io(8) <= gpio_out(8) when gpio_dir(8) = '1' else 'Z';
shield_io(9) <= gpio_out(9) when gpio_dir(9) = '1' else 'Z';
shield_io(10) <= gpio_out(10) when gpio_dir(10) = '1' else 'Z';
shield_io(11) <= gpio_out(11) when gpio_dir(11) = '1' else 'Z';
shield_io(12) <= gpio_out(12) when gpio_dir(12) = '1' else 'Z';
shield_io(13) <= gpio_out(13) when gpio_dir(13) = '1' else 'Z';
shield_io(26) <= gpio_out(14) when gpio_dir(14) = '1' else 'Z';
shield_io(27) <= gpio_out(15) when gpio_dir(15) = '1' else 'Z';
shield_io(28) <= gpio_out(16) when gpio_dir(16) = '1' else 'Z';
shield_io(29) <= gpio_out(17) when gpio_dir(17) = '1' else 'Z';
shield_io(30) <= gpio_out(18) when gpio_dir(18) = '1' else 'Z';
shield_io(31) <= gpio_out(19) when gpio_dir(19) = '1' else 'Z';
shield_io(32) <= gpio_out(20) when gpio_dir(20) = '1' else 'Z';
shield_io(33) <= gpio_out(21) when gpio_dir(21) = '1' else 'Z';
shield_io(34) <= gpio_out(22) when gpio_dir(22) = '1' else 'Z';
shield_io(35) <= gpio_out(23) when gpio_dir(23) = '1' else 'Z';
shield_io(36) <= gpio_out(24) when gpio_dir(24) = '1' else 'Z';
shield_io(37) <= gpio_out(25) when gpio_dir(25) = '1' else 'Z';
shield_io(38) <= gpio_out(26) when gpio_dir(26) = '1' else 'Z';
shield_io(39) <= gpio_out(27) when gpio_dir(27) = '1' else 'Z';
shield_io(40) <= gpio_out(28) when gpio_dir(28) = '1' else 'Z';
shield_io(41) <= gpio_out(29) when gpio_dir(29) = '1' else 'Z';
shield_io(43) <= gpio_out(30) when gpio_dir(30) = '1' else 'Z';
shield_io(44) <= gpio_out(31) when gpio_dir(31) = '1' else 'Z';


end architecture behaviour; end architecture behaviour;

@ -13,8 +13,6 @@ entity toplevel is
CLK_FREQUENCY : positive := 100000000; CLK_FREQUENCY : positive := 100000000;
HAS_FPU : boolean := true; HAS_FPU : boolean := true;
HAS_BTC : boolean := false; HAS_BTC : boolean := false;
HAS_SHORT_MULT: boolean := false;
ICACHE_NUM_LINES : natural := 64;
LOG_LENGTH : natural := 512; LOG_LENGTH : natural := 512;
DISABLE_FLATTEN_CORE : boolean := false; DISABLE_FLATTEN_CORE : boolean := false;
UART_IS_16550 : boolean := true UART_IS_16550 : boolean := true
@ -75,8 +73,6 @@ begin
CLK_FREQ => CLK_FREQUENCY, CLK_FREQ => CLK_FREQUENCY,
HAS_FPU => HAS_FPU, HAS_FPU => HAS_FPU,
HAS_BTC => HAS_BTC, HAS_BTC => HAS_BTC,
HAS_SHORT_MULT => HAS_SHORT_MULT,
ICACHE_NUM_LINES => ICACHE_NUM_LINES,
LOG_LENGTH => LOG_LENGTH, LOG_LENGTH => LOG_LENGTH,
DISABLE_FLATTEN_CORE => DISABLE_FLATTEN_CORE, DISABLE_FLATTEN_CORE => DISABLE_FLATTEN_CORE,
UART0_IS_16550 => UART_IS_16550 UART0_IS_16550 => UART_IS_16550

@ -97,10 +97,6 @@ architecture behaviour of toplevel is
signal spi_sdat_oe : std_ulogic_vector(3 downto 0); signal spi_sdat_oe : std_ulogic_vector(3 downto 0);
signal spi_sdat_i : std_ulogic_vector(3 downto 0); signal spi_sdat_i : std_ulogic_vector(3 downto 0);


-- ddram clock signals as vectors
signal ddram_clk_p_vec : std_logic_vector(0 downto 0);
signal ddram_clk_n_vec : std_logic_vector(0 downto 0);

-- Fixup various memory sizes based on generics -- Fixup various memory sizes based on generics
function get_bram_size return natural is function get_bram_size return natural is
begin begin
@ -274,15 +270,11 @@ begin
rst_out => open rst_out => open
); );


ddram_clk_p_vec <= (others => ddram_clk_p);
ddram_clk_n_vec <= (others => ddram_clk_n);

dram: entity work.litedram_wrapper dram: entity work.litedram_wrapper
generic map( generic map(
DRAM_ABITS => 25, DRAM_ABITS => 25,
DRAM_ALINES => 15, DRAM_ALINES => 15,
DRAM_DLINES => 32, DRAM_DLINES => 32,
DRAM_CKLINES => 1,
DRAM_PORT_WIDTH => 256, DRAM_PORT_WIDTH => 256,
PAYLOAD_FILE => RAM_INIT_FILE, PAYLOAD_FILE => RAM_INIT_FILE,
PAYLOAD_SIZE => PAYLOAD_SIZE PAYLOAD_SIZE => PAYLOAD_SIZE
@ -315,8 +307,8 @@ begin
ddram_dq => ddram_dq, ddram_dq => ddram_dq,
ddram_dqs_p => ddram_dqs_p, ddram_dqs_p => ddram_dqs_p,
ddram_dqs_n => ddram_dqs_n, ddram_dqs_n => ddram_dqs_n,
ddram_clk_p => ddram_clk_p_vec, ddram_clk_p => ddram_clk_p,
ddram_clk_n => ddram_clk_n_vec, ddram_clk_n => ddram_clk_n,
ddram_cke => ddram_cke, ddram_cke => ddram_cke,
ddram_odt => ddram_odt, ddram_odt => ddram_odt,
ddram_reset_n => ddram_reset_n ddram_reset_n => ddram_reset_n

@ -16,7 +16,6 @@ entity toplevel is
CLK_FREQUENCY : positive := 100000000; CLK_FREQUENCY : positive := 100000000;
HAS_FPU : boolean := true; HAS_FPU : boolean := true;
HAS_BTC : boolean := true; HAS_BTC : boolean := true;
HAS_SHORT_MULT: boolean := false;
USE_LITEDRAM : boolean := false; USE_LITEDRAM : boolean := false;
NO_BRAM : boolean := false; NO_BRAM : boolean := false;
DISABLE_FLATTEN_CORE : boolean := false; DISABLE_FLATTEN_CORE : boolean := false;
@ -24,27 +23,19 @@ entity toplevel is
SPI_FLASH_DEF_CKDV : natural := 1; SPI_FLASH_DEF_CKDV : natural := 1;
SPI_FLASH_DEF_QUAD : boolean := true; SPI_FLASH_DEF_QUAD : boolean := true;
LOG_LENGTH : natural := 2048; LOG_LENGTH : natural := 2048;
UART_IS_16550 : boolean := true; UART_IS_16550 : boolean := true
USE_LITEETH : boolean := false;
USE_LITESDCARD : boolean := false
); );
port( port(
ext_clk : in std_ulogic; ext_clk : in std_ulogic;
ext_rst_n : in std_ulogic; ext_rst : in std_ulogic;


-- UART0 signals: -- UART0 signals:
uart_main_tx : out std_ulogic; uart_main_tx : out std_ulogic;
uart_main_rx : in std_ulogic; uart_main_rx : in std_ulogic;


-- LEDs -- LEDs
led0 : out std_ulogic; led0 : out std_logic;
led1 : out std_ulogic; led1 : out std_logic;
led2 : out std_ulogic;
led3 : out std_ulogic;
led4 : out std_ulogic;
led5 : out std_ulogic;
led6 : out std_ulogic;
led7 : out std_ulogic;


-- SPI -- SPI
spi_flash_cs_n : out std_ulogic; spi_flash_cs_n : out std_ulogic;
@ -53,25 +44,6 @@ entity toplevel is
spi_flash_wp_n : inout std_ulogic; spi_flash_wp_n : inout std_ulogic;
spi_flash_hold_n : inout std_ulogic; spi_flash_hold_n : inout std_ulogic;


-- Ethernet
eth_clocks_tx : out std_ulogic;
eth_clocks_rx : in std_ulogic;
eth_rst_n : out std_ulogic;
eth_int_n : in std_ulogic;
eth_mdio : inout std_ulogic;
eth_mdc : out std_ulogic;
eth_rx_ctl : in std_ulogic;
eth_rx_data : in std_ulogic_vector(3 downto 0);
eth_tx_ctl : out std_ulogic;
eth_tx_data : out std_ulogic_vector(3 downto 0);

-- SD card
sdcard_data : inout std_ulogic_vector(3 downto 0);
sdcard_cmd : inout std_ulogic;
sdcard_clk : out std_ulogic;
sdcard_cd : in std_ulogic;
sdcard_reset : out std_ulogic;

-- DRAM wires -- DRAM wires
ddram_a : out std_logic_vector(14 downto 0); ddram_a : out std_logic_vector(14 downto 0);
ddram_ba : out std_logic_vector(2 downto 0); ddram_ba : out std_logic_vector(2 downto 0);
@ -97,37 +69,18 @@ architecture behaviour of toplevel is
signal pll_rst : std_ulogic; signal pll_rst : std_ulogic;


-- Internal clock signals: -- Internal clock signals:
signal system_clk : std_ulogic; signal system_clk : std_ulogic;
signal system_clk_locked : std_ulogic; signal system_clk_locked : std_ulogic;


-- External IOs from the SoC
signal wb_ext_io_in : wb_io_master_out;
signal wb_ext_io_out : wb_io_slave_out;
signal wb_ext_is_dram_csr : std_ulogic;
signal wb_ext_is_dram_init : std_ulogic;
signal wb_ext_is_eth : std_ulogic;
signal wb_ext_is_sdcard : std_ulogic;

-- DRAM main data wishbone connection -- DRAM main data wishbone connection
signal wb_dram_in : wishbone_master_out; signal wb_dram_in : wishbone_master_out;
signal wb_dram_out : wishbone_slave_out; signal wb_dram_out : wishbone_slave_out;


-- DRAM control wishbone connection -- DRAM control wishbone connection
signal wb_dram_ctrl_out : wb_io_slave_out := wb_io_slave_out_init; signal wb_ext_io_in : wb_io_master_out;

signal wb_ext_io_out : wb_io_slave_out;
-- LiteEth connection signal wb_ext_is_dram_csr : std_ulogic;
signal ext_irq_eth : std_ulogic; signal wb_ext_is_dram_init : std_ulogic;
signal wb_eth_out : wb_io_slave_out := wb_io_slave_out_init;

-- LiteSDCard connection
signal ext_irq_sdcard : std_ulogic := '0';
signal wb_sdcard_out : wb_io_slave_out := wb_io_slave_out_init;
signal wb_sddma_out : wb_io_master_out := wb_io_master_out_init;
signal wb_sddma_in : wb_io_slave_out;
signal wb_sddma_nr : wb_io_master_out;
signal wb_sddma_ir : wb_io_slave_out;
-- for conversion from non-pipelined wishbone to pipelined
signal wb_sddma_stb_sent : std_ulogic;


-- Control/status -- Control/status
signal core_alt_reset : std_ulogic; signal core_alt_reset : std_ulogic;
@ -139,10 +92,6 @@ architecture behaviour of toplevel is
signal spi_sdat_oe : std_ulogic_vector(3 downto 0); signal spi_sdat_oe : std_ulogic_vector(3 downto 0);
signal spi_sdat_i : std_ulogic_vector(3 downto 0); signal spi_sdat_i : std_ulogic_vector(3 downto 0);


-- ddram clock signals as vectors
signal ddram_clk_p_vec : std_logic_vector(0 downto 0);
signal ddram_clk_n_vec : std_logic_vector(0 downto 0);

-- Fixup various memory sizes based on generics -- Fixup various memory sizes based on generics
function get_bram_size return natural is function get_bram_size return natural is
begin begin
@ -175,7 +124,6 @@ begin
CLK_FREQ => CLK_FREQUENCY, CLK_FREQ => CLK_FREQUENCY,
HAS_FPU => HAS_FPU, HAS_FPU => HAS_FPU,
HAS_BTC => HAS_BTC, HAS_BTC => HAS_BTC,
HAS_SHORT_MULT=> HAS_SHORT_MULT,
HAS_DRAM => USE_LITEDRAM, HAS_DRAM => USE_LITEDRAM,
DRAM_SIZE => 512 * 1024 * 1024, DRAM_SIZE => 512 * 1024 * 1024,
DRAM_INIT_SIZE => PAYLOAD_SIZE, DRAM_INIT_SIZE => PAYLOAD_SIZE,
@ -186,9 +134,7 @@ begin
SPI_FLASH_DEF_CKDV => SPI_FLASH_DEF_CKDV, SPI_FLASH_DEF_CKDV => SPI_FLASH_DEF_CKDV,
SPI_FLASH_DEF_QUAD => SPI_FLASH_DEF_QUAD, SPI_FLASH_DEF_QUAD => SPI_FLASH_DEF_QUAD,
LOG_LENGTH => LOG_LENGTH, LOG_LENGTH => LOG_LENGTH,
UART0_IS_16550 => UART_IS_16550, UART0_IS_16550 => UART_IS_16550
HAS_LITEETH => USE_LITEETH,
HAS_SD_CARD => USE_LITESDCARD
) )
port map ( port map (
-- System signals -- System signals
@ -206,24 +152,13 @@ begin
spi_flash_sdat_oe => spi_sdat_oe, spi_flash_sdat_oe => spi_sdat_oe,
spi_flash_sdat_i => spi_sdat_i, spi_flash_sdat_i => spi_sdat_i,


-- External interrupts -- DRAM wishbone
ext_irq_eth => ext_irq_eth,
ext_irq_sdcard => ext_irq_sdcard,

-- IO wishbone
wb_dram_in => wb_dram_in, wb_dram_in => wb_dram_in,
wb_dram_out => wb_dram_out, wb_dram_out => wb_dram_out,
wb_ext_io_in => wb_ext_io_in, wb_ext_io_in => wb_ext_io_in,
wb_ext_io_out => wb_ext_io_out, wb_ext_io_out => wb_ext_io_out,
wb_ext_is_dram_csr => wb_ext_is_dram_csr, wb_ext_is_dram_csr => wb_ext_is_dram_csr,
wb_ext_is_dram_init => wb_ext_is_dram_init, wb_ext_is_dram_init => wb_ext_is_dram_init,
wb_ext_is_eth => wb_ext_is_eth,
wb_ext_is_sdcard => wb_ext_is_sdcard,

-- DMA wishbone
wishbone_dma_in => wb_sddma_in,
wishbone_dma_out => wb_sddma_out,

alt_reset => core_alt_reset alt_reset => core_alt_reset
); );


@ -263,8 +198,8 @@ begin
port map( port map(
ext_clk => ext_clk, ext_clk => ext_clk,
pll_clk => system_clk, pll_clk => system_clk,
pll_locked_in => system_clk_locked, pll_locked_in => system_clk_locked,
ext_rst_in => ext_rst_n, ext_rst_in => ext_rst,
pll_rst_out => pll_rst, pll_rst_out => pll_rst,
rst_out => soc_rst rst_out => soc_rst
); );
@ -283,7 +218,6 @@ begin


led0 <= '1'; led0 <= '1';
led1 <= not soc_rst; led1 <= not soc_rst;
led2 <= '0';
core_alt_reset <= '0'; core_alt_reset <= '0';


-- Vivado barfs on those differential signals if left -- Vivado barfs on those differential signals if left
@ -318,31 +252,17 @@ begin
port map( port map(
ext_clk => ext_clk, ext_clk => ext_clk,
pll_clk => system_clk, pll_clk => system_clk,
pll_locked_in => '1', pll_locked_in => '1',
ext_rst_in => ext_rst_n, ext_rst_in => ext_rst,
pll_rst_out => pll_rst, pll_rst_out => pll_rst,
rst_out => open rst_out => open
); );


-- Generate SoC reset
soc_rst_gen: process(system_clk)
begin
if ext_rst_n = '0' then
soc_rst <= '1';
elsif rising_edge(system_clk) then
soc_rst <= dram_sys_rst or not system_clk_locked;
end if;
end process;

ddram_clk_p_vec <= (others => ddram_clk_p);
ddram_clk_n_vec <= (others => ddram_clk_n);

dram: entity work.litedram_wrapper dram: entity work.litedram_wrapper
generic map( generic map(
DRAM_ABITS => 25, DRAM_ABITS => 25,
DRAM_ALINES => 15, DRAM_ALINES => 15,
DRAM_DLINES => 16, DRAM_DLINES => 16,
DRAM_CKLINES => 1,
DRAM_PORT_WIDTH => 128, DRAM_PORT_WIDTH => 128,
PAYLOAD_FILE => RAM_INIT_FILE, PAYLOAD_FILE => RAM_INIT_FILE,
PAYLOAD_SIZE => PAYLOAD_SIZE PAYLOAD_SIZE => PAYLOAD_SIZE
@ -351,14 +271,14 @@ begin
clk_in => ext_clk, clk_in => ext_clk,
rst => pll_rst, rst => pll_rst,
system_clk => system_clk, system_clk => system_clk,
system_reset => dram_sys_rst, system_reset => soc_rst,
core_alt_reset => core_alt_reset, core_alt_reset => core_alt_reset,
pll_locked => system_clk_locked, pll_locked => system_clk_locked,


wb_in => wb_dram_in, wb_in => wb_dram_in,
wb_out => wb_dram_out, wb_out => wb_dram_out,
wb_ctrl_in => wb_ext_io_in, wb_ctrl_in => wb_ext_io_in,
wb_ctrl_out => wb_dram_ctrl_out, wb_ctrl_out => wb_ext_io_out,
wb_ctrl_is_csr => wb_ext_is_dram_csr, wb_ctrl_is_csr => wb_ext_is_dram_csr,
wb_ctrl_is_init => wb_ext_is_dram_init, wb_ctrl_is_init => wb_ext_is_dram_init,


@ -375,213 +295,15 @@ begin
ddram_dq => ddram_dq, ddram_dq => ddram_dq,
ddram_dqs_p => ddram_dqs_p, ddram_dqs_p => ddram_dqs_p,
ddram_dqs_n => ddram_dqs_n, ddram_dqs_n => ddram_dqs_n,
ddram_clk_p => ddram_clk_p_vec, ddram_clk_p => ddram_clk_p,
ddram_clk_n => ddram_clk_n_vec, ddram_clk_n => ddram_clk_n,
ddram_cke => ddram_cke, ddram_cke => ddram_cke,
ddram_odt => ddram_odt, ddram_odt => ddram_odt,
ddram_reset_n => ddram_reset_n ddram_reset_n => ddram_reset_n
); );


led0 <= not dram_init_done; led0 <= dram_init_done and not dram_init_error;
led1 <= dram_init_error; -- Make it blink ? led1 <= dram_init_error; -- Make it blink ?
led2 <= dram_init_done and not dram_init_error;

end generate;

has_liteeth : if USE_LITEETH generate

component liteeth_core port (
sys_clock : in std_ulogic;
sys_reset : in std_ulogic;
rgmii_eth_clocks_tx : out std_ulogic;
rgmii_eth_clocks_rx : in std_ulogic;
rgmii_eth_rst_n : out std_ulogic;
rgmii_eth_int_n : in std_ulogic;
rgmii_eth_mdio : inout std_ulogic;
rgmii_eth_mdc : out std_ulogic;
rgmii_eth_rx_ctl : in std_ulogic;
rgmii_eth_rx_data : in std_ulogic_vector(3 downto 0);
rgmii_eth_tx_ctl : out std_ulogic;
rgmii_eth_tx_data : out std_ulogic_vector(3 downto 0);
wishbone_adr : in std_ulogic_vector(29 downto 0);
wishbone_dat_w : in std_ulogic_vector(31 downto 0);
wishbone_dat_r : out std_ulogic_vector(31 downto 0);
wishbone_sel : in std_ulogic_vector(3 downto 0);
wishbone_cyc : in std_ulogic;
wishbone_stb : in std_ulogic;
wishbone_ack : out std_ulogic;
wishbone_we : in std_ulogic;
wishbone_cti : in std_ulogic_vector(2 downto 0);
wishbone_bte : in std_ulogic_vector(1 downto 0);
wishbone_err : out std_ulogic;
interrupt : out std_ulogic
);
end component;

signal wb_eth_cyc : std_ulogic;
signal wb_eth_adr : std_ulogic_vector(29 downto 0);

begin
liteeth : liteeth_core
port map(
sys_clock => system_clk,
sys_reset => soc_rst,
rgmii_eth_clocks_tx => eth_clocks_tx,
rgmii_eth_clocks_rx => eth_clocks_rx,
rgmii_eth_rst_n => eth_rst_n,
rgmii_eth_int_n => eth_int_n,
rgmii_eth_mdio => eth_mdio,
rgmii_eth_mdc => eth_mdc,
rgmii_eth_rx_ctl => eth_rx_ctl,
rgmii_eth_rx_data => eth_rx_data,
rgmii_eth_tx_ctl => eth_tx_ctl,
rgmii_eth_tx_data => eth_tx_data,
wishbone_adr => wb_eth_adr,
wishbone_dat_w => wb_ext_io_in.dat,
wishbone_dat_r => wb_eth_out.dat,
wishbone_sel => wb_ext_io_in.sel,
wishbone_cyc => wb_eth_cyc,
wishbone_stb => wb_ext_io_in.stb,
wishbone_ack => wb_eth_out.ack,
wishbone_we => wb_ext_io_in.we,
wishbone_cti => "000",
wishbone_bte => "00",
wishbone_err => open,
interrupt => ext_irq_eth
);

-- Gate cyc with "chip select" from soc
wb_eth_cyc <= wb_ext_io_in.cyc and wb_ext_is_eth;

-- Remove top address bits as liteeth decoder doesn't know about them
wb_eth_adr <= x"000" & "000" & wb_ext_io_in.adr(14 downto 0);

-- LiteETH isn't pipelined
wb_eth_out.stall <= not wb_eth_out.ack;

end generate;

no_liteeth : if not USE_LITEETH generate
ext_irq_eth <= '0';
end generate;

-- SD card
has_sdcard : if USE_LITESDCARD generate
component litesdcard_core port (
clk : in std_ulogic;
rst : in std_ulogic;
-- wishbone for accessing control registers
wb_ctrl_adr : in std_ulogic_vector(29 downto 0);
wb_ctrl_dat_w : in std_ulogic_vector(31 downto 0);
wb_ctrl_dat_r : out std_ulogic_vector(31 downto 0);
wb_ctrl_sel : in std_ulogic_vector(3 downto 0);
wb_ctrl_cyc : in std_ulogic;
wb_ctrl_stb : in std_ulogic;
wb_ctrl_ack : out std_ulogic;
wb_ctrl_we : in std_ulogic;
wb_ctrl_cti : in std_ulogic_vector(2 downto 0);
wb_ctrl_bte : in std_ulogic_vector(1 downto 0);
wb_ctrl_err : out std_ulogic;
-- wishbone for SD card core to use for DMA
wb_dma_adr : out std_ulogic_vector(29 downto 0);
wb_dma_dat_w : out std_ulogic_vector(31 downto 0);
wb_dma_dat_r : in std_ulogic_vector(31 downto 0);
wb_dma_sel : out std_ulogic_vector(3 downto 0);
wb_dma_cyc : out std_ulogic;
wb_dma_stb : out std_ulogic;
wb_dma_ack : in std_ulogic;
wb_dma_we : out std_ulogic;
wb_dma_cti : out std_ulogic_vector(2 downto 0);
wb_dma_bte : out std_ulogic_vector(1 downto 0);
wb_dma_err : in std_ulogic;
-- connections to SD card
sdcard_data : inout std_ulogic_vector(3 downto 0);
sdcard_cmd : inout std_ulogic;
sdcard_clk : out std_ulogic;
sdcard_cd : in std_ulogic;
irq : out std_ulogic
);
end component;

signal wb_sdcard_cyc : std_ulogic;
signal wb_sdcard_adr : std_ulogic_vector(29 downto 0);

begin
litesdcard : litesdcard_core
port map (
clk => system_clk,
rst => soc_rst,
wb_ctrl_adr => wb_sdcard_adr,
wb_ctrl_dat_w => wb_ext_io_in.dat,
wb_ctrl_dat_r => wb_sdcard_out.dat,
wb_ctrl_sel => wb_ext_io_in.sel,
wb_ctrl_cyc => wb_sdcard_cyc,
wb_ctrl_stb => wb_ext_io_in.stb,
wb_ctrl_ack => wb_sdcard_out.ack,
wb_ctrl_we => wb_ext_io_in.we,
wb_ctrl_cti => "000",
wb_ctrl_bte => "00",
wb_ctrl_err => open,
wb_dma_adr => wb_sddma_nr.adr,
wb_dma_dat_w => wb_sddma_nr.dat,
wb_dma_dat_r => wb_sddma_ir.dat,
wb_dma_sel => wb_sddma_nr.sel,
wb_dma_cyc => wb_sddma_nr.cyc,
wb_dma_stb => wb_sddma_nr.stb,
wb_dma_ack => wb_sddma_ir.ack,
wb_dma_we => wb_sddma_nr.we,
wb_dma_cti => open,
wb_dma_bte => open,
wb_dma_err => '0',
sdcard_data => sdcard_data,
sdcard_cmd => sdcard_cmd,
sdcard_clk => sdcard_clk,
sdcard_cd => sdcard_cd,
irq => ext_irq_sdcard
);

-- Gate cyc with chip select from SoC
wb_sdcard_cyc <= wb_ext_io_in.cyc and wb_ext_is_sdcard;

wb_sdcard_adr <= x"0000" & wb_ext_io_in.adr(13 downto 0);

wb_sdcard_out.stall <= not wb_sdcard_out.ack;

sdcard_reset <= '0';

-- Convert non-pipelined DMA wishbone to pipelined by suppressing
-- non-acknowledged strobes
process(system_clk)
begin
if rising_edge(system_clk) then
wb_sddma_out <= wb_sddma_nr;
if wb_sddma_stb_sent = '1' or
(wb_sddma_out.stb = '1' and wb_sddma_in.stall = '0') then
wb_sddma_out.stb <= '0';
end if;
if wb_sddma_nr.cyc = '0' or wb_sddma_ir.ack = '1' then
wb_sddma_stb_sent <= '0';
elsif wb_sddma_in.stall = '0' then
wb_sddma_stb_sent <= wb_sddma_nr.stb;
end if;
wb_sddma_ir <= wb_sddma_in;
end if;
end process;


end generate; end generate;

no_sdcard : if not USE_LITESDCARD generate
sdcard_reset <= '1';
end generate;

-- Mux WB response on the IO bus
wb_ext_io_out <= wb_eth_out when wb_ext_is_eth = '1' else
wb_sdcard_out when wb_ext_is_sdcard = '1' else
wb_dram_ctrl_out;

led4 <= system_clk_locked;
led5 <= '1';
led6 <= not soc_rst;
led7 <= '0';

end architecture behaviour; end architecture behaviour;

@ -1,512 +0,0 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

library work;
use work.wishbone_types.all;

entity toplevel is
generic (
MEMORY_SIZE : integer := 16384;
RAM_INIT_FILE : string := "firmware.hex";
RESET_LOW : boolean := true;
CLK_INPUT : positive := 100000000;
CLK_FREQUENCY : positive := 100000000;
HAS_FPU : boolean := true;
HAS_BTC : boolean := false;
USE_LITEDRAM : boolean := true;
NO_BRAM : boolean := true;
SCLK_STARTUPE2 : boolean := false;
SPI_FLASH_OFFSET : integer := 4194304;
SPI_FLASH_DEF_CKDV : natural := 1;
SPI_FLASH_DEF_QUAD : boolean := true;
LOG_LENGTH : natural := 0;
UART_IS_16550 : boolean := true;
HAS_UART1 : boolean := false;
USE_LITESDCARD : boolean := true;
ICACHE_NUM_LINES : natural := 64;
NGPIO : natural := 0
);
port(
ext_clk : in std_ulogic;
ext_rst_n : in std_ulogic;

-- UART0 signals:
pin_gpio_0 : out std_ulogic;
pin_gpio_1 : in std_ulogic;

-- LEDs
led0_b : out std_ulogic;
led0_g : out std_ulogic;
led0_r : out std_ulogic;

-- SPI
spi_flash_cs_n : out std_ulogic;
spi_flash_mosi : inout std_ulogic;
spi_flash_miso : inout std_ulogic;
spi_flash_wp_n : inout std_ulogic;
spi_flash_hold_n : inout std_ulogic;

-- SD card wires
sdcard_data : inout std_ulogic_vector(3 downto 0);
sdcard_cmd : inout std_ulogic;
sdcard_clk : out std_ulogic;
sdcard_cd : in std_ulogic;

-- DRAM wires
ddram_a : out std_ulogic_vector(13 downto 0);
ddram_ba : out std_ulogic_vector(2 downto 0);
ddram_ras_n : out std_ulogic;
ddram_cas_n : out std_ulogic;
ddram_we_n : out std_ulogic;
ddram_cs_n : out std_ulogic;
ddram_dm : out std_ulogic_vector(1 downto 0);
ddram_dq : inout std_ulogic_vector(15 downto 0);
ddram_dqs_p : inout std_ulogic_vector(1 downto 0);
ddram_clk_p : out std_ulogic_vector(0 downto 0);
-- only the positive differential pin is instantiated
--ddram_dqs_n : inout std_ulogic_vector(1 downto 0);
--ddram_clk_n : out std_ulogic_vector(0 downto 0);
ddram_cke : out std_ulogic;
ddram_odt : out std_ulogic;
ddram_reset_n : out std_ulogic;

ddram_gnd : out std_ulogic_vector(1 downto 0);
ddram_vccio : out std_ulogic_vector(5 downto 0)
);
end entity toplevel;

architecture behaviour of toplevel is

-- Reset signals:
signal soc_rst : std_ulogic;
signal pll_rst : std_ulogic;

-- Internal clock signals:
signal system_clk : std_ulogic;
signal system_clk_locked : std_ulogic;

-- External IOs from the SoC
signal wb_ext_io_in : wb_io_master_out;
signal wb_ext_io_out : wb_io_slave_out;
signal wb_ext_is_dram_csr : std_ulogic;
signal wb_ext_is_dram_init : std_ulogic;
signal wb_ext_is_sdcard : std_ulogic;

-- DRAM main data wishbone connection
signal wb_dram_in : wishbone_master_out;
signal wb_dram_out : wishbone_slave_out;

-- DRAM control wishbone connection
signal wb_dram_ctrl_out : wb_io_slave_out := wb_io_slave_out_init;

-- LiteSDCard connection
signal ext_irq_sdcard : std_ulogic := '0';
signal wb_sdcard_out : wb_io_slave_out := wb_io_slave_out_init;
signal wb_sddma_out : wb_io_master_out := wb_io_master_out_init;
signal wb_sddma_in : wb_io_slave_out;
signal wb_sddma_nr : wb_io_master_out;
signal wb_sddma_ir : wb_io_slave_out;
-- for conversion from non-pipelined wishbone to pipelined
signal wb_sddma_stb_sent : std_ulogic;

-- Control/status
signal core_alt_reset : std_ulogic;

-- Status LED
signal led0_b_pwm : std_ulogic;
signal led0_r_pwm : std_ulogic;
signal led0_g_pwm : std_ulogic;

-- Dumb PWM for the LEDs, those RGB LEDs are too bright otherwise
signal pwm_counter : std_ulogic_vector(8 downto 0);

-- SPI flash
signal spi_sck : std_ulogic;
signal spi_cs_n : std_ulogic;
signal spi_sdat_o : std_ulogic_vector(3 downto 0);
signal spi_sdat_oe : std_ulogic_vector(3 downto 0);
signal spi_sdat_i : std_ulogic_vector(3 downto 0);

-- GPIO
signal gpio_in : std_ulogic_vector(NGPIO - 1 downto 0);
signal gpio_out : std_ulogic_vector(NGPIO - 1 downto 0);
signal gpio_dir : std_ulogic_vector(NGPIO - 1 downto 0);

-- Fixup various memory sizes based on generics
function get_bram_size return natural is
begin
if USE_LITEDRAM and NO_BRAM then
return 0;
else
return MEMORY_SIZE;
end if;
end function;

function get_payload_size return natural is
begin
if USE_LITEDRAM and NO_BRAM then
return MEMORY_SIZE;
else
return 0;
end if;
end function;

constant BRAM_SIZE : natural := get_bram_size;
constant PAYLOAD_SIZE : natural := get_payload_size;

COMPONENT USRMCLK
PORT(
USRMCLKI : IN STD_ULOGIC;
USRMCLKTS : IN STD_ULOGIC
);
END COMPONENT;
attribute syn_noprune: boolean ;
attribute syn_noprune of USRMCLK: component is true;

begin

-- Main SoC
soc0: entity work.soc
generic map(
MEMORY_SIZE => BRAM_SIZE,
RAM_INIT_FILE => RAM_INIT_FILE,
SIM => false,
CLK_FREQ => CLK_FREQUENCY,
HAS_FPU => HAS_FPU,
HAS_BTC => HAS_BTC,
HAS_DRAM => USE_LITEDRAM,
DRAM_SIZE => 256 * 1024 * 1024,
DRAM_INIT_SIZE => PAYLOAD_SIZE,
HAS_SPI_FLASH => true,
SPI_FLASH_DLINES => 4,
SPI_FLASH_OFFSET => SPI_FLASH_OFFSET,
SPI_FLASH_DEF_CKDV => SPI_FLASH_DEF_CKDV,
SPI_FLASH_DEF_QUAD => SPI_FLASH_DEF_QUAD,
LOG_LENGTH => LOG_LENGTH,
UART0_IS_16550 => UART_IS_16550,
HAS_UART1 => HAS_UART1,
HAS_SD_CARD => USE_LITESDCARD,
ICACHE_NUM_LINES => ICACHE_NUM_LINES,
HAS_SHORT_MULT => true,
NGPIO => NGPIO
)
port map (
-- System signals
system_clk => system_clk,
rst => soc_rst,

-- UART signals
uart0_txd => pin_gpio_0,
uart0_rxd => pin_gpio_1,

-- UART1 signals
--uart1_txd => uart_pmod_tx,
--uart1_rxd => uart_pmod_rx,

-- SPI signals
spi_flash_sck => spi_sck,
spi_flash_cs_n => spi_cs_n,
spi_flash_sdat_o => spi_sdat_o,
spi_flash_sdat_oe => spi_sdat_oe,
spi_flash_sdat_i => spi_sdat_i,

-- GPIO signals
gpio_in => gpio_in,
gpio_out => gpio_out,
gpio_dir => gpio_dir,

-- External interrupts
ext_irq_sdcard => ext_irq_sdcard,

-- DRAM wishbone
wb_dram_in => wb_dram_in,
wb_dram_out => wb_dram_out,

-- IO wishbone
wb_ext_io_in => wb_ext_io_in,
wb_ext_io_out => wb_ext_io_out,
wb_ext_is_dram_csr => wb_ext_is_dram_csr,
wb_ext_is_dram_init => wb_ext_is_dram_init,
wb_ext_is_sdcard => wb_ext_is_sdcard,

-- DMA wishbone
wishbone_dma_in => wb_sddma_in,
wishbone_dma_out => wb_sddma_out,

alt_reset => core_alt_reset
);

-- SPI Flash
--
spi_flash_cs_n <= spi_cs_n;
spi_flash_mosi <= spi_sdat_o(0) when spi_sdat_oe(0) = '1' else 'Z';
spi_flash_miso <= spi_sdat_o(1) when spi_sdat_oe(1) = '1' else 'Z';
spi_flash_wp_n <= spi_sdat_o(2) when spi_sdat_oe(2) = '1' else 'Z';
spi_flash_hold_n <= spi_sdat_o(3) when spi_sdat_oe(3) = '1' else 'Z';
spi_sdat_i(0) <= spi_flash_mosi;
spi_sdat_i(1) <= spi_flash_miso;
spi_sdat_i(2) <= spi_flash_wp_n;
spi_sdat_i(3) <= spi_flash_hold_n;

uclk: USRMCLK port map (
USRMCLKI => spi_sck,
USRMCLKTS => '0'
);

nodram: if not USE_LITEDRAM generate
signal ddram_clk_dummy : std_ulogic;
begin
reset_controller: entity work.soc_reset
generic map(
RESET_LOW => RESET_LOW
)
port map(
ext_clk => ext_clk,
pll_clk => system_clk,
pll_locked_in => system_clk_locked,
ext_rst_in => ext_rst_n,
pll_rst_out => pll_rst,
rst_out => soc_rst
);

clkgen: entity work.clock_generator
generic map(
CLK_INPUT_HZ => CLK_INPUT,
CLK_OUTPUT_HZ => CLK_FREQUENCY
)
port map(
ext_clk => ext_clk,
pll_rst_in => pll_rst,
pll_clk_out => system_clk,
pll_locked_out => system_clk_locked
);

led0_b_pwm <= '1';
led0_r_pwm <= '1';
led0_g_pwm <= '0';
core_alt_reset <= '0';

end generate;

has_dram: if USE_LITEDRAM generate
signal dram_init_done : std_ulogic;
signal dram_init_error : std_ulogic;
signal dram_sys_rst : std_ulogic;
signal rst_gen_rst : std_ulogic;
begin

-- Eventually dig out the frequency from
-- litesdram generate.py sys_clk_freq
-- but for now, assert it's 48Mhz for orangecrab
assert CLK_FREQUENCY = 48000000;

reset_controller: entity work.soc_reset
generic map(
RESET_LOW => RESET_LOW,
PLL_RESET_BITS => 18,
SOC_RESET_BITS => 1
)
port map(
ext_clk => ext_clk,
pll_clk => system_clk,
pll_locked_in => system_clk_locked,
ext_rst_in => ext_rst_n,
pll_rst_out => pll_rst,
rst_out => rst_gen_rst
);

-- Generate SoC reset
soc_rst_gen: process(system_clk)
begin
if ext_rst_n = '0' then
soc_rst <= '1';
elsif rising_edge(system_clk) then
soc_rst <= dram_sys_rst or not system_clk_locked;
end if;
end process;

dram: entity work.litedram_wrapper
generic map(
DRAM_ABITS => 24,
DRAM_ALINES => 14,
DRAM_DLINES => 16,
DRAM_CKLINES => 1,
DRAM_PORT_WIDTH => 128,
NUM_LINES => 8, -- reduce from default of 64 to make smaller/timing
PAYLOAD_FILE => RAM_INIT_FILE,
PAYLOAD_SIZE => PAYLOAD_SIZE
)
port map(
clk_in => ext_clk,
rst => pll_rst,
system_clk => system_clk,
system_reset => dram_sys_rst,
core_alt_reset => core_alt_reset,
pll_locked => system_clk_locked,

wb_in => wb_dram_in,
wb_out => wb_dram_out,
wb_ctrl_in => wb_ext_io_in,
wb_ctrl_out => wb_dram_ctrl_out,
wb_ctrl_is_csr => wb_ext_is_dram_csr,
wb_ctrl_is_init => wb_ext_is_dram_init,

init_done => dram_init_done,
init_error => dram_init_error,

ddram_a => ddram_a,
ddram_ba => ddram_ba,
ddram_ras_n => ddram_ras_n,
ddram_cas_n => ddram_cas_n,
ddram_we_n => ddram_we_n,
ddram_cs_n => ddram_cs_n,
ddram_dm => ddram_dm,
ddram_dq => ddram_dq,
ddram_dqs_p => ddram_dqs_p,
ddram_clk_p => ddram_clk_p,
-- only the positive differential pin is instantiated
--ddram_dqs_n => ddram_dqs_n,
--ddram_clk_n => ddram_clk_n,
ddram_cke => ddram_cke,
ddram_odt => ddram_odt,

ddram_reset_n => ddram_reset_n
);

ddram_gnd <= "00";
-- for power consumption.
-- https://github.com/orangecrab-fpga/orangecrab-hardware/issues/19#issuecomment-683479378
ddram_vccio <= "111111";

led0_b_pwm <= not dram_init_done;
led0_r_pwm <= dram_init_error;
led0_g_pwm <= dram_init_done and not dram_init_error;

end generate;


-- SD card pmod
has_sdcard : if USE_LITESDCARD generate
component litesdcard_core port (
clk : in std_ulogic;
rst : in std_ulogic;
-- wishbone for accessing control registers
wb_ctrl_adr : in std_ulogic_vector(29 downto 0);
wb_ctrl_dat_w : in std_ulogic_vector(31 downto 0);
wb_ctrl_dat_r : out std_ulogic_vector(31 downto 0);
wb_ctrl_sel : in std_ulogic_vector(3 downto 0);
wb_ctrl_cyc : in std_ulogic;
wb_ctrl_stb : in std_ulogic;
wb_ctrl_ack : out std_ulogic;
wb_ctrl_we : in std_ulogic;
wb_ctrl_cti : in std_ulogic_vector(2 downto 0);
wb_ctrl_bte : in std_ulogic_vector(1 downto 0);
wb_ctrl_err : out std_ulogic;
-- wishbone for SD card core to use for DMA
wb_dma_adr : out std_ulogic_vector(29 downto 0);
wb_dma_dat_w : out std_ulogic_vector(31 downto 0);
wb_dma_dat_r : in std_ulogic_vector(31 downto 0);
wb_dma_sel : out std_ulogic_vector(3 downto 0);
wb_dma_cyc : out std_ulogic;
wb_dma_stb : out std_ulogic;
wb_dma_ack : in std_ulogic;
wb_dma_we : out std_ulogic;
wb_dma_cti : out std_ulogic_vector(2 downto 0);
wb_dma_bte : out std_ulogic_vector(1 downto 0);
wb_dma_err : in std_ulogic;
-- connections to SD card
sdcard_data : inout std_ulogic_vector(3 downto 0);
sdcard_cmd : inout std_ulogic;
sdcard_clk : out std_ulogic;
sdcard_cd : in std_ulogic;
irq : out std_ulogic
);
end component;

signal wb_sdcard_cyc : std_ulogic;
signal wb_sdcard_adr : std_ulogic_vector(29 downto 0);

begin
litesdcard : litesdcard_core
port map (
clk => system_clk,
rst => soc_rst,
wb_ctrl_adr => wb_sdcard_adr,
wb_ctrl_dat_w => wb_ext_io_in.dat,
wb_ctrl_dat_r => wb_sdcard_out.dat,
wb_ctrl_sel => wb_ext_io_in.sel,
wb_ctrl_cyc => wb_sdcard_cyc,
wb_ctrl_stb => wb_ext_io_in.stb,
wb_ctrl_ack => wb_sdcard_out.ack,
wb_ctrl_we => wb_ext_io_in.we,
wb_ctrl_cti => "000",
wb_ctrl_bte => "00",
wb_ctrl_err => open,
wb_dma_adr => wb_sddma_nr.adr,
wb_dma_dat_w => wb_sddma_nr.dat,
wb_dma_dat_r => wb_sddma_ir.dat,
wb_dma_sel => wb_sddma_nr.sel,
wb_dma_cyc => wb_sddma_nr.cyc,
wb_dma_stb => wb_sddma_nr.stb,
wb_dma_ack => wb_sddma_ir.ack,
wb_dma_we => wb_sddma_nr.we,
wb_dma_cti => open,
wb_dma_bte => open,
wb_dma_err => '0',
sdcard_data => sdcard_data,
sdcard_cmd => sdcard_cmd,
sdcard_clk => sdcard_clk,
sdcard_cd => sdcard_cd,
irq => ext_irq_sdcard
);

-- Gate cyc with chip select from SoC
wb_sdcard_cyc <= wb_ext_io_in.cyc and wb_ext_is_sdcard;

wb_sdcard_adr <= x"0000" & wb_ext_io_in.adr(13 downto 0);

wb_sdcard_out.stall <= not wb_sdcard_out.ack;

-- Convert non-pipelined DMA wishbone to pipelined by suppressing
-- non-acknowledged strobes
process(system_clk)
begin
if rising_edge(system_clk) then
wb_sddma_out <= wb_sddma_nr;
if wb_sddma_stb_sent = '1' or
(wb_sddma_out.stb = '1' and wb_sddma_in.stall = '0') then
wb_sddma_out.stb <= '0';
end if;
if wb_sddma_nr.cyc = '0' or wb_sddma_ir.ack = '1' then
wb_sddma_stb_sent <= '0';
elsif wb_sddma_in.stall = '0' then
wb_sddma_stb_sent <= wb_sddma_nr.stb;
end if;
wb_sddma_ir <= wb_sddma_in;
end if;
end process;

end generate;

-- Mux WB response on the IO bus
wb_ext_io_out <= wb_sdcard_out when wb_ext_is_sdcard = '1' else
wb_dram_ctrl_out;

leds_pwm : process(system_clk)
begin
if rising_edge(system_clk) then
pwm_counter <= std_ulogic_vector(signed(pwm_counter) + 1);
if pwm_counter(8 downto 4) = "00000" then
led0_b <= led0_b_pwm;
led0_r <= led0_r_pwm;
led0_g <= led0_g_pwm;
else
led0_b <= '0';
led0_r <= '0';
led0_g <= '0';
end if;
end if;
end process;

end architecture behaviour;

@ -1,587 +0,0 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

library unisim;
use unisim.vcomponents.all;

library work;
use work.wishbone_types.all;

entity toplevel is
generic (
MEMORY_SIZE : integer := 16384;
RAM_INIT_FILE : string := "firmware.hex";
RESET_LOW : boolean := true;
CLK_FREQUENCY : positive := 100000000;
HAS_FPU : boolean := true;
HAS_BTC : boolean := true;
HAS_SHORT_MULT : boolean := false;
USE_LITEDRAM : boolean := false;
NO_BRAM : boolean := false;
DISABLE_FLATTEN_CORE : boolean := false;
SPI_FLASH_OFFSET : integer := 4194304;
SPI_FLASH_DEF_CKDV : natural := 1;
SPI_FLASH_DEF_QUAD : boolean := true;
LOG_LENGTH : natural := 512;
USE_LITEETH : boolean := false;
UART_IS_16550 : boolean := true;
HAS_UART1 : boolean := false;
USE_LITESDCARD : boolean := false;
HAS_GPIO : boolean := false;
NGPIO : natural := 32
);
port(
ext_clk : in std_ulogic;
ext_rst_n : in std_ulogic;

-- UART0 signals:
uart_main_tx : out std_ulogic;
uart_main_rx : in std_ulogic;

-- LEDs
led0_n : out std_ulogic;
led1_n : out std_ulogic;

-- SPI
spi_flash_cs_n : out std_ulogic;
spi_flash_mosi : inout std_ulogic;
spi_flash_miso : inout std_ulogic;
spi_flash_wp_n : inout std_ulogic;
spi_flash_hold_n : inout std_ulogic;

-- Ethernet
eth_clocks_tx : in std_ulogic;
eth_clocks_gtx : out std_ulogic;
eth_clocks_rx : in std_ulogic;
eth_rst_n : out std_ulogic;
eth_mdio : inout std_ulogic;
eth_mdc : out std_ulogic;
eth_rx_dv : in std_ulogic;
eth_rx_er : in std_ulogic;
eth_rx_data : in std_ulogic_vector(7 downto 0);
eth_tx_en : out std_ulogic;
eth_tx_er : out std_ulogic;
eth_tx_data : out std_ulogic_vector(7 downto 0);
eth_col : in std_ulogic;
eth_crs : in std_ulogic;

-- SD card
sdcard_data : inout std_ulogic_vector(3 downto 0);
sdcard_cmd : inout std_ulogic;
sdcard_clk : out std_ulogic;
sdcard_cd : in std_ulogic;

-- DRAM wires
ddram_a : out std_ulogic_vector(13 downto 0);
ddram_ba : out std_ulogic_vector(2 downto 0);
ddram_ras_n : out std_ulogic;
ddram_cas_n : out std_ulogic;
ddram_we_n : out std_ulogic;
ddram_dm : out std_ulogic_vector(1 downto 0);
ddram_dq : inout std_ulogic_vector(15 downto 0);
ddram_dqs_p : inout std_ulogic_vector(1 downto 0);
ddram_dqs_n : inout std_ulogic_vector(1 downto 0);
ddram_clk_p : out std_ulogic;
ddram_clk_n : out std_ulogic;
ddram_cke : out std_ulogic;
ddram_odt : out std_ulogic;
ddram_reset_n : out std_ulogic
);
end entity toplevel;

architecture behaviour of toplevel is

-- Reset signals:
signal soc_rst : std_ulogic;
signal pll_rst : std_ulogic;

-- Internal clock signals:
signal system_clk : std_ulogic;
signal system_clk_locked : std_ulogic;

-- External IOs from the SoC
signal wb_ext_io_in : wb_io_master_out;
signal wb_ext_io_out : wb_io_slave_out;
signal wb_ext_is_dram_csr : std_ulogic;
signal wb_ext_is_dram_init : std_ulogic;
signal wb_ext_is_eth : std_ulogic;
signal wb_ext_is_sdcard : std_ulogic;

-- DRAM main data wishbone connection
signal wb_dram_in : wishbone_master_out;
signal wb_dram_out : wishbone_slave_out;

-- DRAM control wishbone connection
signal wb_dram_ctrl_out : wb_io_slave_out := wb_io_slave_out_init;

-- LiteEth connection
signal ext_irq_eth : std_ulogic;
signal wb_eth_out : wb_io_slave_out := wb_io_slave_out_init;

-- LiteSDCard connection
signal ext_irq_sdcard : std_ulogic := '0';
signal wb_sdcard_out : wb_io_slave_out := wb_io_slave_out_init;
signal wb_sddma_out : wb_io_master_out := wb_io_master_out_init;
signal wb_sddma_in : wb_io_slave_out;
signal wb_sddma_nr : wb_io_master_out;
signal wb_sddma_ir : wb_io_slave_out;
-- for conversion from non-pipelined wishbone to pipelined
signal wb_sddma_stb_sent : std_ulogic;

-- Control/status
signal core_alt_reset : std_ulogic;

-- SPI flash
signal spi_sck : std_ulogic;
signal spi_cs_n : std_ulogic;
signal spi_sdat_o : std_ulogic_vector(3 downto 0);
signal spi_sdat_oe : std_ulogic_vector(3 downto 0);
signal spi_sdat_i : std_ulogic_vector(3 downto 0);

-- ddram clock signals as vectors
signal ddram_clk_p_vec : std_ulogic_vector(0 downto 0);
signal ddram_clk_n_vec : std_ulogic_vector(0 downto 0);

-- Fixup various memory sizes based on generics
function get_bram_size return natural is
begin
if USE_LITEDRAM and NO_BRAM then
return 0;
else
return MEMORY_SIZE;
end if;
end function;

function get_payload_size return natural is
begin
if USE_LITEDRAM and NO_BRAM then
return MEMORY_SIZE;
else
return 0;
end if;
end function;
constant BRAM_SIZE : natural := get_bram_size;
constant PAYLOAD_SIZE : natural := get_payload_size;
begin

-- Main SoC
soc0: entity work.soc
generic map(
MEMORY_SIZE => BRAM_SIZE,
RAM_INIT_FILE => RAM_INIT_FILE,
SIM => false,
CLK_FREQ => CLK_FREQUENCY,
HAS_FPU => HAS_FPU,
HAS_BTC => HAS_BTC,
HAS_SHORT_MULT => HAS_SHORT_MULT,
HAS_DRAM => USE_LITEDRAM,
DRAM_SIZE => 256 * 1024 * 1024,
DRAM_INIT_SIZE => PAYLOAD_SIZE,
DISABLE_FLATTEN_CORE => DISABLE_FLATTEN_CORE,
HAS_SPI_FLASH => true,
SPI_FLASH_DLINES => 4,
SPI_FLASH_OFFSET => SPI_FLASH_OFFSET,
SPI_FLASH_DEF_CKDV => SPI_FLASH_DEF_CKDV,
SPI_FLASH_DEF_QUAD => SPI_FLASH_DEF_QUAD,
LOG_LENGTH => LOG_LENGTH,
HAS_LITEETH => USE_LITEETH,
UART0_IS_16550 => UART_IS_16550,
HAS_UART1 => HAS_UART1,
HAS_SD_CARD => USE_LITESDCARD,
HAS_GPIO => HAS_GPIO,
NGPIO => NGPIO
)
port map (
-- System signals
system_clk => system_clk,
rst => soc_rst,

-- UART signals
uart0_txd => uart_main_tx,
uart0_rxd => uart_main_rx,

-- SPI signals
spi_flash_sck => spi_sck,
spi_flash_cs_n => spi_cs_n,
spi_flash_sdat_o => spi_sdat_o,
spi_flash_sdat_oe => spi_sdat_oe,
spi_flash_sdat_i => spi_sdat_i,

-- External interrupts
ext_irq_eth => ext_irq_eth,
ext_irq_sdcard => ext_irq_sdcard,

-- DRAM wishbone
wb_dram_in => wb_dram_in,
wb_dram_out => wb_dram_out,

-- IO wishbone
wb_ext_io_in => wb_ext_io_in,
wb_ext_io_out => wb_ext_io_out,
wb_ext_is_dram_csr => wb_ext_is_dram_csr,
wb_ext_is_dram_init => wb_ext_is_dram_init,
wb_ext_is_eth => wb_ext_is_eth,
wb_ext_is_sdcard => wb_ext_is_sdcard,

-- DMA wishbone
wishbone_dma_in => wb_sddma_in,
wishbone_dma_out => wb_sddma_out,

alt_reset => core_alt_reset
);

-- SPI Flash
spi_flash_cs_n <= spi_cs_n;
spi_flash_mosi <= spi_sdat_o(0) when spi_sdat_oe(0) = '1' else 'Z';
spi_flash_miso <= spi_sdat_o(1) when spi_sdat_oe(1) = '1' else 'Z';
spi_flash_wp_n <= spi_sdat_o(2) when spi_sdat_oe(2) = '1' else 'Z';
spi_flash_hold_n <= spi_sdat_o(3) when spi_sdat_oe(3) = '1' else 'Z';
spi_sdat_i(0) <= spi_flash_mosi;
spi_sdat_i(1) <= spi_flash_miso;
spi_sdat_i(2) <= spi_flash_wp_n;
spi_sdat_i(3) <= spi_flash_hold_n;

STARTUPE2_INST: STARTUPE2
port map (
CLK => '0',
GSR => '0',
GTS => '0',
KEYCLEARB => '0',
PACK => '0',
USRCCLKO => spi_sck,
USRCCLKTS => '0',
USRDONEO => '1',
USRDONETS => '0'
);

nodram: if not USE_LITEDRAM generate
signal ddram_clk_dummy : std_ulogic;
begin
reset_controller: entity work.soc_reset
generic map(
RESET_LOW => RESET_LOW
)
port map(
ext_clk => ext_clk,
pll_clk => system_clk,
pll_locked_in => system_clk_locked,
ext_rst_in => ext_rst_n,
pll_rst_out => pll_rst,
rst_out => soc_rst
);

clkgen: entity work.clock_generator
generic map(
CLK_INPUT_HZ => 50000000,
CLK_OUTPUT_HZ => CLK_FREQUENCY
)
port map(
ext_clk => ext_clk,
pll_rst_in => pll_rst,
pll_clk_out => system_clk,
pll_locked_out => system_clk_locked
);

core_alt_reset <= '0';

-- Vivado barfs on those differential signals if left
-- unconnected. So instanciate a diff. buffer and feed
-- it a constant '0'.
dummy_dram_clk: OBUFDS
port map (
O => ddram_clk_p,
OB => ddram_clk_n,
I => ddram_clk_dummy
);
ddram_clk_dummy <= '0';

end generate;

has_dram: if USE_LITEDRAM generate
signal dram_init_done : std_ulogic;
signal dram_init_error : std_ulogic;
signal dram_sys_rst : std_ulogic;
signal rst_gen_rst : std_ulogic;
begin

-- Eventually dig out the frequency from the generator
-- but for now, assert it's 100Mhz
assert CLK_FREQUENCY = 100000000;

reset_controller: entity work.soc_reset
generic map(
RESET_LOW => RESET_LOW,
PLL_RESET_BITS => 18,
SOC_RESET_BITS => 1
)
port map(
ext_clk => ext_clk,
pll_clk => system_clk,
pll_locked_in => system_clk_locked,
ext_rst_in => ext_rst_n,
pll_rst_out => pll_rst,
rst_out => rst_gen_rst
);

-- Generate SoC reset
soc_rst_gen: process(system_clk)
begin
if ext_rst_n = '0' then
soc_rst <= '1';
elsif rising_edge(system_clk) then
soc_rst <= dram_sys_rst or not system_clk_locked;
end if;
end process;

ddram_clk_p_vec <= (others => ddram_clk_p);
ddram_clk_n_vec <= (others => ddram_clk_n);

dram: entity work.litedram_wrapper
generic map(
DRAM_ABITS => 24,
DRAM_ALINES => 14,
DRAM_DLINES => 16,
DRAM_CKLINES => 1,
DRAM_PORT_WIDTH => 128,
PAYLOAD_FILE => RAM_INIT_FILE,
PAYLOAD_SIZE => PAYLOAD_SIZE
)
port map(
clk_in => ext_clk,
rst => pll_rst,
system_clk => system_clk,
system_reset => dram_sys_rst,
core_alt_reset => core_alt_reset,
pll_locked => system_clk_locked,

wb_in => wb_dram_in,
wb_out => wb_dram_out,
wb_ctrl_in => wb_ext_io_in,
wb_ctrl_out => wb_dram_ctrl_out,
wb_ctrl_is_csr => wb_ext_is_dram_csr,
wb_ctrl_is_init => wb_ext_is_dram_init,

init_done => dram_init_done,
init_error => dram_init_error,

ddram_a => ddram_a,
ddram_ba => ddram_ba,
ddram_ras_n => ddram_ras_n,
ddram_cas_n => ddram_cas_n,
ddram_we_n => ddram_we_n,
ddram_cs_n => open,
ddram_dm => ddram_dm,
ddram_dq => ddram_dq,
ddram_dqs_p => ddram_dqs_p,
ddram_dqs_n => ddram_dqs_n,
ddram_clk_p => ddram_clk_p_vec,
ddram_clk_n => ddram_clk_n_vec,
ddram_cke => ddram_cke,
ddram_odt => ddram_odt,
ddram_reset_n => ddram_reset_n
);

end generate;

has_liteeth : if USE_LITEETH generate

component liteeth_core port (
sys_clock : in std_ulogic;
sys_reset : in std_ulogic;
gmii_eth_clocks_tx : in std_ulogic;
gmii_eth_clocks_gtx : out std_ulogic;
gmii_eth_clocks_rx : in std_ulogic;
gmii_eth_rst_n : out std_ulogic;
gmii_eth_mdio : inout std_ulogic;
gmii_eth_mdc : out std_ulogic;
gmii_eth_rx_dv : in std_ulogic;
gmii_eth_rx_er : in std_ulogic;
gmii_eth_rx_data : in std_ulogic_vector(7 downto 0);
gmii_eth_tx_en : out std_ulogic;
gmii_eth_tx_er : out std_ulogic;
gmii_eth_tx_data : out std_ulogic_vector(7 downto 0);
gmii_eth_col : in std_ulogic;
gmii_eth_crs : in std_ulogic;
wishbone_adr : in std_ulogic_vector(29 downto 0);
wishbone_dat_w : in std_ulogic_vector(31 downto 0);
wishbone_dat_r : out std_ulogic_vector(31 downto 0);
wishbone_sel : in std_ulogic_vector(3 downto 0);
wishbone_cyc : in std_ulogic;
wishbone_stb : in std_ulogic;
wishbone_ack : out std_ulogic;
wishbone_we : in std_ulogic;
wishbone_cti : in std_ulogic_vector(2 downto 0);
wishbone_bte : in std_ulogic_vector(1 downto 0);
wishbone_err : out std_ulogic;
interrupt : out std_ulogic
);
end component;

signal wb_eth_cyc : std_ulogic;
signal wb_eth_adr : std_ulogic_vector(29 downto 0);

-- Change this to use a PLL instead of a BUFR to generate the 25Mhz
-- reference clock to the PHY.
constant USE_PLL : boolean := false;
begin
liteeth : liteeth_core
port map(
sys_clock => system_clk,
sys_reset => soc_rst,
gmii_eth_clocks_tx => eth_clocks_tx,
gmii_eth_clocks_gtx => eth_clocks_gtx,
gmii_eth_clocks_rx => eth_clocks_rx,
gmii_eth_rst_n => eth_rst_n,
gmii_eth_mdio => eth_mdio,
gmii_eth_mdc => eth_mdc,
gmii_eth_rx_dv => eth_rx_dv,
gmii_eth_rx_er => eth_rx_er,
gmii_eth_rx_data => eth_rx_data,
gmii_eth_tx_en => eth_tx_en,
gmii_eth_tx_er => eth_tx_er,
gmii_eth_tx_data => eth_tx_data,
gmii_eth_col => eth_col,
gmii_eth_crs => eth_crs,
wishbone_adr => wb_eth_adr,
wishbone_dat_w => wb_ext_io_in.dat,
wishbone_dat_r => wb_eth_out.dat,
wishbone_sel => wb_ext_io_in.sel,
wishbone_cyc => wb_eth_cyc,
wishbone_stb => wb_ext_io_in.stb,
wishbone_ack => wb_eth_out.ack,
wishbone_we => wb_ext_io_in.we,
wishbone_cti => "000",
wishbone_bte => "00",
wishbone_err => open,
interrupt => ext_irq_eth
);

-- Gate cyc with "chip select" from soc
wb_eth_cyc <= wb_ext_io_in.cyc and wb_ext_is_eth;

-- Remove top address bits as liteeth decoder doesn't know about them
wb_eth_adr <= x"000" & "000" & wb_ext_io_in.adr(14 downto 0);

-- LiteETH isn't pipelined
wb_eth_out.stall <= not wb_eth_out.ack;

end generate;

no_liteeth : if not USE_LITEETH generate
ext_irq_eth <= '0';
end generate;

-- SD card pmod
has_sdcard : if USE_LITESDCARD generate
component litesdcard_core port (
clk : in std_ulogic;
rst : in std_ulogic;
-- wishbone for accessing control registers
wb_ctrl_adr : in std_ulogic_vector(29 downto 0);
wb_ctrl_dat_w : in std_ulogic_vector(31 downto 0);
wb_ctrl_dat_r : out std_ulogic_vector(31 downto 0);
wb_ctrl_sel : in std_ulogic_vector(3 downto 0);
wb_ctrl_cyc : in std_ulogic;
wb_ctrl_stb : in std_ulogic;
wb_ctrl_ack : out std_ulogic;
wb_ctrl_we : in std_ulogic;
wb_ctrl_cti : in std_ulogic_vector(2 downto 0);
wb_ctrl_bte : in std_ulogic_vector(1 downto 0);
wb_ctrl_err : out std_ulogic;
-- wishbone for SD card core to use for DMA
wb_dma_adr : out std_ulogic_vector(29 downto 0);
wb_dma_dat_w : out std_ulogic_vector(31 downto 0);
wb_dma_dat_r : in std_ulogic_vector(31 downto 0);
wb_dma_sel : out std_ulogic_vector(3 downto 0);
wb_dma_cyc : out std_ulogic;
wb_dma_stb : out std_ulogic;
wb_dma_ack : in std_ulogic;
wb_dma_we : out std_ulogic;
wb_dma_cti : out std_ulogic_vector(2 downto 0);
wb_dma_bte : out std_ulogic_vector(1 downto 0);
wb_dma_err : in std_ulogic;
-- connections to SD card
sdcard_data : inout std_ulogic_vector(3 downto 0);
sdcard_cmd : inout std_ulogic;
sdcard_clk : out std_ulogic;
sdcard_cd : in std_ulogic;
irq : out std_ulogic
);
end component;

signal wb_sdcard_cyc : std_ulogic;
signal wb_sdcard_adr : std_ulogic_vector(29 downto 0);

begin
litesdcard : litesdcard_core
port map (
clk => system_clk,
rst => soc_rst,
wb_ctrl_adr => wb_sdcard_adr,
wb_ctrl_dat_w => wb_ext_io_in.dat,
wb_ctrl_dat_r => wb_sdcard_out.dat,
wb_ctrl_sel => wb_ext_io_in.sel,
wb_ctrl_cyc => wb_sdcard_cyc,
wb_ctrl_stb => wb_ext_io_in.stb,
wb_ctrl_ack => wb_sdcard_out.ack,
wb_ctrl_we => wb_ext_io_in.we,
wb_ctrl_cti => "000",
wb_ctrl_bte => "00",
wb_ctrl_err => open,
wb_dma_adr => wb_sddma_nr.adr,
wb_dma_dat_w => wb_sddma_nr.dat,
wb_dma_dat_r => wb_sddma_ir.dat,
wb_dma_sel => wb_sddma_nr.sel,
wb_dma_cyc => wb_sddma_nr.cyc,
wb_dma_stb => wb_sddma_nr.stb,
wb_dma_ack => wb_sddma_ir.ack,
wb_dma_we => wb_sddma_nr.we,
wb_dma_cti => open,
wb_dma_bte => open,
wb_dma_err => '0',
sdcard_data => sdcard_data,
sdcard_cmd => sdcard_cmd,
sdcard_clk => sdcard_clk,
sdcard_cd => sdcard_cd,
irq => ext_irq_sdcard
);

-- Gate cyc with chip select from SoC
wb_sdcard_cyc <= wb_ext_io_in.cyc and wb_ext_is_sdcard;

wb_sdcard_adr <= x"0000" & wb_ext_io_in.adr(13 downto 0);

wb_sdcard_out.stall <= not wb_sdcard_out.ack;

-- Convert non-pipelined DMA wishbone to pipelined by suppressing
-- non-acknowledged strobes
process(system_clk)
begin
if rising_edge(system_clk) then
wb_sddma_out <= wb_sddma_nr;
if wb_sddma_stb_sent = '1' or
(wb_sddma_out.stb = '1' and wb_sddma_in.stall = '0') then
wb_sddma_out.stb <= '0';
end if;
if wb_sddma_nr.cyc = '0' or wb_sddma_ir.ack = '1' then
wb_sddma_stb_sent <= '0';
elsif wb_sddma_in.stall = '0' then
wb_sddma_stb_sent <= wb_sddma_nr.stb;
end if;
wb_sddma_ir <= wb_sddma_in;
end if;
end process;

end generate;

-- Mux WB response on the IO bus
wb_ext_io_out <= wb_eth_out when wb_ext_is_eth = '1' else
wb_sdcard_out when wb_ext_is_sdcard = '1' else
wb_dram_ctrl_out;

led0_n <= system_clk_locked;
led1_n <= not soc_rst;

end architecture behaviour;

@ -1,487 +0,0 @@
################################################################################
# clkin, reset, uart pins...
################################################################################

set_property -dict { PACKAGE_PIN M21 IOSTANDARD LVCMOS33 } [get_ports { ext_clk }];

set_property -dict { PACKAGE_PIN H7 IOSTANDARD LVCMOS33 } [get_ports { ext_rst_n }];

set_property -dict { PACKAGE_PIN E3 IOSTANDARD LVCMOS33 } [get_ports { uart_main_tx }];
set_property -dict { PACKAGE_PIN F3 IOSTANDARD LVCMOS33 } [get_ports { uart_main_rx }];

################################################################################
# LEDs
################################################################################

set_property -dict { PACKAGE_PIN V16 IOSTANDARD LVCMOS33 } [get_ports { led0_n }];
set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 } [get_ports { led1_n }];

################################################################################
# SPI Flash
################################################################################ema

set_property -dict { PACKAGE_PIN P18 IOSTANDARD LVCMOS33 } [get_ports { spi_flash_cs_n }];
set_property -dict { PACKAGE_PIN R14 IOSTANDARD LVCMOS33 } [get_ports { spi_flash_mosi }];
set_property -dict { PACKAGE_PIN R15 IOSTANDARD LVCMOS33 } [get_ports { spi_flash_miso }];
set_property -dict { PACKAGE_PIN P14 IOSTANDARD LVCMOS33 } [get_ports { spi_flash_wp_n }];
set_property -dict { PACKAGE_PIN N14 IOSTANDARD LVCMOS33 } [get_ports { spi_flash_hold_n }];

################################################################################
# Micro SD
################################################################################

set_property -dict { PACKAGE_PIN M5 IOSTANDARD LVCMOS33 SLEW FAST } [get_ports { sdcard_data[0] }];
set_property -dict { PACKAGE_PIN M7 IOSTANDARD LVCMOS33 SLEW FAST } [get_ports { sdcard_data[1] }];
set_property -dict { PACKAGE_PIN H6 IOSTANDARD LVCMOS33 SLEW FAST } [get_ports { sdcard_data[2] }];
set_property -dict { PACKAGE_PIN J6 IOSTANDARD LVCMOS33 SLEW FAST } [get_ports { sdcard_data[3] }];
set_property -dict { PACKAGE_PIN J8 IOSTANDARD LVCMOS33 SLEW FAST } [get_ports { sdcard_cmd }];
set_property -dict { PACKAGE_PIN L4 IOSTANDARD LVCMOS33 SLEW FAST } [get_ports { sdcard_clk }];
set_property -dict { PACKAGE_PIN N6 IOSTANDARD LVCMOS33 } [get_ports { sdcard_cd }];

# Put registers into IOBs to improve timing
set_property IOB true [get_cells -hierarchical -filter {NAME =~*.litesdcard/sdcard_*}]

################################################################################
# PMOD header J10 (high-speed, no protection resisters)
################################################################################

#set_property -dict { PACKAGE_PIN D5 IOSTANDARD LVCMOS33 } [get_ports { pmod_j10_1 }];
#set_property -dict { PACKAGE_PIN G5 IOSTANDARD LVCMOS33 } [get_ports { pmod_j10_2 }];
#set_property -dict { PACKAGE_PIN G7 IOSTANDARD LVCMOS33 } [get_ports { pmod_j10_3 }];
#set_property -dict { PACKAGE_PIN G8 IOSTANDARD LVCMOS33 } [get_ports { pmod_j10_4 }];
#set_property -dict { PACKAGE_PIN E5 IOSTANDARD LVCMOS33 } [get_ports { pmod_j10_7 }];
#set_property -dict { PACKAGE_PIN E6 IOSTANDARD LVCMOS33 } [get_ports { pmod_j10_8 }];
#set_property -dict { PACKAGE_PIN D6 IOSTANDARD LVCMOS33 } [get_ports { pmod_j10_9 }];
#set_property -dict { PACKAGE_PIN G6 IOSTANDARD LVCMOS33 } [get_ports { pmod_j10_10 }];

################################################################################
# PMOD header J11 (high-speed, no protection resisters)
################################################################################

#set_property -dict { PACKAGE_PIN H4 IOSTANDARD LVCMOS33 } [get_ports { pmod_j11_1 }];
#set_property -dict { PACKAGE_PIN F4 IOSTANDARD LVCMOS33 } [get_ports { pmod_j11_2 }];
#set_property -dict { PACKAGE_PIN A4 IOSTANDARD LVCMOS33 } [get_ports { pmod_j11_3 }];
#set_property -dict { PACKAGE_PIN A5 IOSTANDARD LVCMOS33 } [get_ports { pmod_j11_4 }];
#set_property -dict { PACKAGE_PIN J4 IOSTANDARD LVCMOS33 } [get_ports { pmod_j11_7 }];
#set_property -dict { PACKAGE_PIN G4 IOSTANDARD LVCMOS33 } [get_ports { pmod_j11_8 }];
#set_property -dict { PACKAGE_PIN B4 IOSTANDARD LVCMOS33 } [get_ports { pmod_j11_9 }];
#set_property -dict { PACKAGE_PIN B5 IOSTANDARD LVCMOS33 } [get_ports { pmod_j11_10 }];

################################################################################
# HDR 20X2 connector
################################################################################

## TODO

################################################################################
# Ethernet (generated by LiteX)
################################################################################

# eth_clocks:0.tx
set_property LOC M2 [get_ports {eth_clocks_tx}]
set_property IOSTANDARD LVCMOS33 [get_ports {eth_clocks_tx}]

# eth_clocks:0.gtx
set_property LOC U1 [get_ports {eth_clocks_gtx}]
set_property IOSTANDARD LVCMOS33 [get_ports {eth_clocks_gtx}]

# eth_clocks:0.rx
set_property LOC P4 [get_ports {eth_clocks_rx}]
set_property IOSTANDARD LVCMOS33 [get_ports {eth_clocks_rx}]

# eth:0.rst_n
set_property LOC R1 [get_ports {eth_rst_n}]
set_property IOSTANDARD LVCMOS33 [get_ports {eth_rst_n}]

# eth:0.mdio
set_property LOC H1 [get_ports {eth_mdio}]
set_property IOSTANDARD LVCMOS33 [get_ports {eth_mdio}]

# eth:0.mdc
set_property LOC H2 [get_ports {eth_mdc}]
set_property IOSTANDARD LVCMOS33 [get_ports {eth_mdc}]

# eth:0.rx_dv
set_property LOC L3 [get_ports {eth_rx_dv}]
set_property IOSTANDARD LVCMOS33 [get_ports {eth_rx_dv}]

# eth:0.rx_er
set_property LOC U5 [get_ports {eth_rx_er}]
set_property IOSTANDARD LVCMOS33 [get_ports {eth_rx_er}]

# eth:0.rx_data
set_property LOC M4 [get_ports {eth_rx_data[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {eth_rx_data[0]}]

# eth:0.rx_data
set_property LOC N3 [get_ports {eth_rx_data[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {eth_rx_data[1]}]

# eth:0.rx_data
set_property LOC N4 [get_ports {eth_rx_data[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {eth_rx_data[2]}]

# eth:0.rx_data
set_property LOC P3 [get_ports {eth_rx_data[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {eth_rx_data[3]}]

# eth:0.rx_data
set_property LOC R3 [get_ports {eth_rx_data[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {eth_rx_data[4]}]

# eth:0.rx_data
set_property LOC T3 [get_ports {eth_rx_data[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {eth_rx_data[5]}]

# eth:0.rx_data
set_property LOC T4 [get_ports {eth_rx_data[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {eth_rx_data[6]}]

# eth:0.rx_data
set_property LOC T5 [get_ports {eth_rx_data[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {eth_rx_data[7]}]

# eth:0.tx_en
set_property LOC T2 [get_ports {eth_tx_en}]
set_property IOSTANDARD LVCMOS33 [get_ports {eth_tx_en}]

# eth:0.tx_er
set_property LOC J1 [get_ports {eth_tx_er}]
set_property IOSTANDARD LVCMOS33 [get_ports {eth_tx_er}]

# eth:0.tx_data
set_property LOC R2 [get_ports {eth_tx_data[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {eth_tx_data[0]}]

# eth:0.tx_data
set_property LOC P1 [get_ports {eth_tx_data[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {eth_tx_data[1]}]

# eth:0.tx_data
set_property LOC N2 [get_ports {eth_tx_data[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {eth_tx_data[2]}]

# eth:0.tx_data
set_property LOC N1 [get_ports {eth_tx_data[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {eth_tx_data[3]}]

# eth:0.tx_data
set_property LOC M1 [get_ports {eth_tx_data[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {eth_tx_data[4]}]

# eth:0.tx_data
set_property LOC L2 [get_ports {eth_tx_data[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {eth_tx_data[5]}]

# eth:0.tx_data
set_property LOC K2 [get_ports {eth_tx_data[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {eth_tx_data[6]}]

# eth:0.tx_data
set_property LOC K1 [get_ports {eth_tx_data[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {eth_tx_data[7]}]

# eth:0.col
set_property LOC U4 [get_ports {eth_col}]
set_property IOSTANDARD LVCMOS33 [get_ports {eth_col}]

# eth:0.crs
set_property LOC U2 [get_ports {eth_crs}]
set_property IOSTANDARD LVCMOS33 [get_ports {eth_crs}]

################################################################################
# DRAM (generated by LiteX)
################################################################################

# ddram:0.a
set_property LOC E17 [get_ports {ddram_a[0]}]
set_property SLEW FAST [get_ports {ddram_a[0]}]
set_property IOSTANDARD SSTL135 [get_ports {ddram_a[0]}]

# ddram:0.a
set_property LOC G17 [get_ports {ddram_a[1]}]
set_property SLEW FAST [get_ports {ddram_a[1]}]
set_property IOSTANDARD SSTL135 [get_ports {ddram_a[1]}]

# ddram:0.a
set_property LOC F17 [get_ports {ddram_a[2]}]
set_property SLEW FAST [get_ports {ddram_a[2]}]
set_property IOSTANDARD SSTL135 [get_ports {ddram_a[2]}]

# ddram:0.a
set_property LOC C17 [get_ports {ddram_a[3]}]
set_property SLEW FAST [get_ports {ddram_a[3]}]
set_property IOSTANDARD SSTL135 [get_ports {ddram_a[3]}]

# ddram:0.a
set_property LOC G16 [get_ports {ddram_a[4]}]
set_property SLEW FAST [get_ports {ddram_a[4]}]
set_property IOSTANDARD SSTL135 [get_ports {ddram_a[4]}]

# ddram:0.a
set_property LOC D16 [get_ports {ddram_a[5]}]
set_property SLEW FAST [get_ports {ddram_a[5]}]
set_property IOSTANDARD SSTL135 [get_ports {ddram_a[5]}]

# ddram:0.a
set_property LOC H16 [get_ports {ddram_a[6]}]
set_property SLEW FAST [get_ports {ddram_a[6]}]
set_property IOSTANDARD SSTL135 [get_ports {ddram_a[6]}]

# ddram:0.a
set_property LOC E16 [get_ports {ddram_a[7]}]
set_property SLEW FAST [get_ports {ddram_a[7]}]
set_property IOSTANDARD SSTL135 [get_ports {ddram_a[7]}]

# ddram:0.a
set_property LOC H14 [get_ports {ddram_a[8]}]
set_property SLEW FAST [get_ports {ddram_a[8]}]
set_property IOSTANDARD SSTL135 [get_ports {ddram_a[8]}]

# ddram:0.a
set_property LOC F15 [get_ports {ddram_a[9]}]
set_property SLEW FAST [get_ports {ddram_a[9]}]
set_property IOSTANDARD SSTL135 [get_ports {ddram_a[9]}]

# ddram:0.a
set_property LOC F20 [get_ports {ddram_a[10]}]
set_property SLEW FAST [get_ports {ddram_a[10]}]
set_property IOSTANDARD SSTL135 [get_ports {ddram_a[10]}]

# ddram:0.a
set_property LOC H15 [get_ports {ddram_a[11]}]
set_property SLEW FAST [get_ports {ddram_a[11]}]
set_property IOSTANDARD SSTL135 [get_ports {ddram_a[11]}]

# ddram:0.a
set_property LOC C18 [get_ports {ddram_a[12]}]
set_property SLEW FAST [get_ports {ddram_a[12]}]
set_property IOSTANDARD SSTL135 [get_ports {ddram_a[12]}]

# ddram:0.a
set_property LOC G15 [get_ports {ddram_a[13]}]
set_property SLEW FAST [get_ports {ddram_a[13]}]
set_property IOSTANDARD SSTL135 [get_ports {ddram_a[13]}]

# ddram:0.ba
set_property LOC B17 [get_ports {ddram_ba[0]}]
set_property SLEW FAST [get_ports {ddram_ba[0]}]
set_property IOSTANDARD SSTL135 [get_ports {ddram_ba[0]}]

# ddram:0.ba
set_property LOC D18 [get_ports {ddram_ba[1]}]
set_property SLEW FAST [get_ports {ddram_ba[1]}]
set_property IOSTANDARD SSTL135 [get_ports {ddram_ba[1]}]

# ddram:0.ba
set_property LOC A17 [get_ports {ddram_ba[2]}]
set_property SLEW FAST [get_ports {ddram_ba[2]}]
set_property IOSTANDARD SSTL135 [get_ports {ddram_ba[2]}]

# ddram:0.ras_n
set_property LOC A19 [get_ports {ddram_ras_n}]
set_property SLEW FAST [get_ports {ddram_ras_n}]
set_property IOSTANDARD SSTL135 [get_ports {ddram_ras_n}]

# ddram:0.cas_n
set_property LOC B19 [get_ports {ddram_cas_n}]
set_property SLEW FAST [get_ports {ddram_cas_n}]
set_property IOSTANDARD SSTL135 [get_ports {ddram_cas_n}]

# ddram:0.we_n
set_property LOC A18 [get_ports {ddram_we_n}]
set_property SLEW FAST [get_ports {ddram_we_n}]
set_property IOSTANDARD SSTL135 [get_ports {ddram_we_n}]

# ddram:0.dm
set_property LOC A22 [get_ports {ddram_dm[0]}]
set_property SLEW FAST [get_ports {ddram_dm[0]}]
set_property IOSTANDARD SSTL135 [get_ports {ddram_dm[0]}]

# ddram:0.dm
set_property LOC C22 [get_ports {ddram_dm[1]}]
set_property SLEW FAST [get_ports {ddram_dm[1]}]
set_property IOSTANDARD SSTL135 [get_ports {ddram_dm[1]}]

# ddram:0.dq
set_property LOC D21 [get_ports {ddram_dq[0]}]
set_property SLEW FAST [get_ports {ddram_dq[0]}]
set_property IOSTANDARD SSTL135 [get_ports {ddram_dq[0]}]
set_property IN_TERM UNTUNED_SPLIT_40 [get_ports {ddram_dq[0]}]

# ddram:0.dq
set_property LOC C21 [get_ports {ddram_dq[1]}]
set_property SLEW FAST [get_ports {ddram_dq[1]}]
set_property IOSTANDARD SSTL135 [get_ports {ddram_dq[1]}]
set_property IN_TERM UNTUNED_SPLIT_40 [get_ports {ddram_dq[1]}]

# ddram:0.dq
set_property LOC B22 [get_ports {ddram_dq[2]}]
set_property SLEW FAST [get_ports {ddram_dq[2]}]
set_property IOSTANDARD SSTL135 [get_ports {ddram_dq[2]}]
set_property IN_TERM UNTUNED_SPLIT_40 [get_ports {ddram_dq[2]}]

# ddram:0.dq
set_property LOC B21 [get_ports {ddram_dq[3]}]
set_property SLEW FAST [get_ports {ddram_dq[3]}]
set_property IOSTANDARD SSTL135 [get_ports {ddram_dq[3]}]
set_property IN_TERM UNTUNED_SPLIT_40 [get_ports {ddram_dq[3]}]

# ddram:0.dq
set_property LOC D19 [get_ports {ddram_dq[4]}]
set_property SLEW FAST [get_ports {ddram_dq[4]}]
set_property IOSTANDARD SSTL135 [get_ports {ddram_dq[4]}]
set_property IN_TERM UNTUNED_SPLIT_40 [get_ports {ddram_dq[4]}]

# ddram:0.dq
set_property LOC E20 [get_ports {ddram_dq[5]}]
set_property SLEW FAST [get_ports {ddram_dq[5]}]
set_property IOSTANDARD SSTL135 [get_ports {ddram_dq[5]}]
set_property IN_TERM UNTUNED_SPLIT_40 [get_ports {ddram_dq[5]}]

# ddram:0.dq
set_property LOC C19 [get_ports {ddram_dq[6]}]
set_property SLEW FAST [get_ports {ddram_dq[6]}]
set_property IOSTANDARD SSTL135 [get_ports {ddram_dq[6]}]
set_property IN_TERM UNTUNED_SPLIT_40 [get_ports {ddram_dq[6]}]

# ddram:0.dq
set_property LOC D20 [get_ports {ddram_dq[7]}]
set_property SLEW FAST [get_ports {ddram_dq[7]}]
set_property IOSTANDARD SSTL135 [get_ports {ddram_dq[7]}]
set_property IN_TERM UNTUNED_SPLIT_40 [get_ports {ddram_dq[7]}]

# ddram:0.dq
set_property LOC C23 [get_ports {ddram_dq[8]}]
set_property SLEW FAST [get_ports {ddram_dq[8]}]
set_property IOSTANDARD SSTL135 [get_ports {ddram_dq[8]}]
set_property IN_TERM UNTUNED_SPLIT_40 [get_ports {ddram_dq[8]}]

# ddram:0.dq
set_property LOC D23 [get_ports {ddram_dq[9]}]
set_property SLEW FAST [get_ports {ddram_dq[9]}]
set_property IOSTANDARD SSTL135 [get_ports {ddram_dq[9]}]
set_property IN_TERM UNTUNED_SPLIT_40 [get_ports {ddram_dq[9]}]

# ddram:0.dq
set_property LOC B24 [get_ports {ddram_dq[10]}]
set_property SLEW FAST [get_ports {ddram_dq[10]}]
set_property IOSTANDARD SSTL135 [get_ports {ddram_dq[10]}]
set_property IN_TERM UNTUNED_SPLIT_40 [get_ports {ddram_dq[10]}]

# ddram:0.dq
set_property LOC B25 [get_ports {ddram_dq[11]}]
set_property SLEW FAST [get_ports {ddram_dq[11]}]
set_property IOSTANDARD SSTL135 [get_ports {ddram_dq[11]}]
set_property IN_TERM UNTUNED_SPLIT_40 [get_ports {ddram_dq[11]}]

# ddram:0.dq
set_property LOC C24 [get_ports {ddram_dq[12]}]
set_property SLEW FAST [get_ports {ddram_dq[12]}]
set_property IOSTANDARD SSTL135 [get_ports {ddram_dq[12]}]
set_property IN_TERM UNTUNED_SPLIT_40 [get_ports {ddram_dq[12]}]

# ddram:0.dq
set_property LOC C26 [get_ports {ddram_dq[13]}]
set_property SLEW FAST [get_ports {ddram_dq[13]}]
set_property IOSTANDARD SSTL135 [get_ports {ddram_dq[13]}]
set_property IN_TERM UNTUNED_SPLIT_40 [get_ports {ddram_dq[13]}]

# ddram:0.dq
set_property LOC A25 [get_ports {ddram_dq[14]}]
set_property SLEW FAST [get_ports {ddram_dq[14]}]
set_property IOSTANDARD SSTL135 [get_ports {ddram_dq[14]}]
set_property IN_TERM UNTUNED_SPLIT_40 [get_ports {ddram_dq[14]}]

# ddram:0.dq
set_property LOC B26 [get_ports {ddram_dq[15]}]
set_property SLEW FAST [get_ports {ddram_dq[15]}]
set_property IOSTANDARD SSTL135 [get_ports {ddram_dq[15]}]
set_property IN_TERM UNTUNED_SPLIT_40 [get_ports {ddram_dq[15]}]

# ddram:0.dqs_p
set_property LOC B20 [get_ports {ddram_dqs_p[0]}]
set_property SLEW FAST [get_ports {ddram_dqs_p[0]}]
set_property IOSTANDARD DIFF_SSTL135 [get_ports {ddram_dqs_p[0]}]
set_property IN_TERM UNTUNED_SPLIT_40 [get_ports {ddram_dqs_p[0]}]

# ddram:0.dqs_p
set_property LOC A23 [get_ports {ddram_dqs_p[1]}]
set_property SLEW FAST [get_ports {ddram_dqs_p[1]}]
set_property IOSTANDARD DIFF_SSTL135 [get_ports {ddram_dqs_p[1]}]
set_property IN_TERM UNTUNED_SPLIT_40 [get_ports {ddram_dqs_p[1]}]

# ddram:0.dqs_n
set_property LOC A20 [get_ports {ddram_dqs_n[0]}]
set_property SLEW FAST [get_ports {ddram_dqs_n[0]}]
set_property IOSTANDARD DIFF_SSTL135 [get_ports {ddram_dqs_n[0]}]
set_property IN_TERM UNTUNED_SPLIT_40 [get_ports {ddram_dqs_n[0]}]

# ddram:0.dqs_n
set_property LOC A24 [get_ports {ddram_dqs_n[1]}]
set_property SLEW FAST [get_ports {ddram_dqs_n[1]}]
set_property IOSTANDARD DIFF_SSTL135 [get_ports {ddram_dqs_n[1]}]
set_property IN_TERM UNTUNED_SPLIT_40 [get_ports {ddram_dqs_n[1]}]

# ddram:0.clk_p
set_property LOC F18 [get_ports {ddram_clk_p}]
set_property SLEW FAST [get_ports {ddram_clk_p}]
set_property IOSTANDARD DIFF_SSTL135 [get_ports {ddram_clk_p}]

# ddram:0.clk_n
set_property LOC F19 [get_ports {ddram_clk_n}]
set_property SLEW FAST [get_ports {ddram_clk_n}]
set_property IOSTANDARD DIFF_SSTL135 [get_ports {ddram_clk_n}]

# ddram:0.cke
set_property LOC E18 [get_ports {ddram_cke}]
set_property SLEW FAST [get_ports {ddram_cke}]
set_property IOSTANDARD SSTL135 [get_ports {ddram_cke}]

# ddram:0.odt
set_property LOC G19 [get_ports {ddram_odt}]
set_property SLEW FAST [get_ports {ddram_odt}]
set_property IOSTANDARD SSTL135 [get_ports {ddram_odt}]

# ddram:0.reset_n
set_property LOC H17 [get_ports {ddram_reset_n}]
set_property SLEW FAST [get_ports {ddram_reset_n}]
set_property IOSTANDARD SSTL135 [get_ports {ddram_reset_n}]

################################################################################
# Design constraints and bitsteam attributes
################################################################################

set_property INTERNAL_VREF 0.675 [get_iobanks 16]

set_property CONFIG_VOLTAGE 3.3 [current_design]
set_property CFGBVS VCCO [current_design]

set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design]
set_property BITSTREAM.CONFIG.CONFIGRATE 33 [current_design]
set_property CONFIG_MODE SPIx4 [current_design]

################################################################################
# Clock constraints
################################################################################

create_clock -name sys_clk_pin -period 20.00 [get_ports { ext_clk }];

create_clock -name eth_rx_clk -period 8.0 [get_nets has_liteeth.liteeth/eth_rx_clk]
create_clock -name eth_tx_clk -period 8.0 [get_nets has_liteeth.liteeth/eth_tx_clk]

set_clock_groups -group [get_clocks -include_generated_clocks -of [get_nets has_liteeth.liteeth/sys_clk]] -group [get_clocks -include_generated_clocks -of [get_nets has_liteeth.liteeth/eth_rx_clk]] -asynchronous

set_clock_groups -group [get_clocks -include_generated_clocks -of [get_nets has_liteeth.liteeth/sys_clk]] -group [get_clocks -include_generated_clocks -of [get_nets has_liteeth.liteeth/eth_tx_clk]] -asynchronous

set_clock_groups -group [get_clocks -include_generated_clocks -of [get_nets has_liteeth.liteeth/eth_rx_clk]] -group [get_clocks -include_generated_clocks -of [get_nets has_liteeth.liteeth/eth_tx_clk]] -asynchronous

################################################################################
# False path constraints (from LiteX as they relate to LiteDRAM and LiteEth)
################################################################################

set_false_path -quiet -through [get_nets -hierarchical -filter {mr_ff == TRUE}]

set_false_path -quiet -to [get_pins -filter {REF_PIN_NAME == PRE} -of_objects [get_cells -hierarchical -filter {ars_ff1 == TRUE || ars_ff2 == TRUE}]]

set_max_delay 2 -quiet -from [get_pins -filter {REF_PIN_NAME == C} -of_objects [get_cells -hierarchical -filter {ars_ff1 == TRUE}]] -to [get_pins -filter {REF_PIN_NAME == D} -of_objects [get_cells -hierarchical -filter {ars_ff2 == TRUE}]]

@ -16,7 +16,7 @@ entity fpu is
clk : in std_ulogic; clk : in std_ulogic;
rst : in std_ulogic; rst : in std_ulogic;


e_in : in Execute1ToFPUType; e_in : in Execute1toFPUType;
e_out : out FPUToExecute1Type; e_out : out FPUToExecute1Type;


w_out : out FPUToWritebackType w_out : out FPUToWritebackType
@ -197,7 +197,7 @@ architecture behaviour of fpu is
-- Each output value is the inverse of the center of the input -- Each output value is the inverse of the center of the input
-- range for the value, i.e. entry 0 is 1 / (1 + 1/512), -- range for the value, i.e. entry 0 is 1 / (1 + 1/512),
-- entry 1 is 1 / (1 + 3/512), etc. -- entry 1 is 1 / (1 + 3/512), etc.
constant inverse_table : lookup_table := ( signal inverse_table : lookup_table := (
-- 1/x lookup table -- 1/x lookup table
-- Unit bit is assumed to be 1, so input range is [1, 2) -- Unit bit is assumed to be 1, so input range is [1, 2)
18x"3fc01", 18x"3f411", 18x"3ec31", 18x"3e460", 18x"3dc9f", 18x"3d4ec", 18x"3cd49", 18x"3c5b5", 18x"3fc01", 18x"3f411", 18x"3ec31", 18x"3e460", 18x"3dc9f", 18x"3d4ec", 18x"3cd49", 18x"3c5b5",
@ -549,10 +549,6 @@ begin
r.do_intr <= '0'; r.do_intr <= '0';
r.fpscr <= (others => '0'); r.fpscr <= (others => '0');
r.writing_back <= '0'; r.writing_back <= '0';
r.dest_fpr <= (others =>'0');
r.cr_mask <= (others =>'0');
r.cr_result <= (others =>'0');
r.instr_tag.valid <= '0';
else else
assert not (r.state /= IDLE and e_in.valid = '1') severity failure; assert not (r.state /= IDLE and e_in.valid = '1') severity failure;
r <= rin; r <= rin;

@ -1,99 +0,0 @@
-- GPIO module for microwatt
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

library work;
use work.wishbone_types.all;

entity gpio is
generic (
NGPIO : integer := 32
);
port (
clk : in std_ulogic;
rst : in std_ulogic;

-- Wishbone
wb_in : in wb_io_master_out;
wb_out : out wb_io_slave_out;

-- GPIO lines
gpio_in : in std_ulogic_vector(NGPIO - 1 downto 0);
gpio_out : out std_ulogic_vector(NGPIO - 1 downto 0);
-- 1 = output, 0 = input
gpio_dir : out std_ulogic_vector(NGPIO - 1 downto 0);

-- Interrupt
intr : out std_ulogic
);
end entity gpio;

architecture behaviour of gpio is
constant GPIO_REG_BITS : positive := 5;

-- Register addresses, matching addr downto 2, so 4 bytes per reg
constant GPIO_REG_DATA_OUT : std_ulogic_vector(GPIO_REG_BITS-1 downto 0) := "00000";
constant GPIO_REG_DATA_IN : std_ulogic_vector(GPIO_REG_BITS-1 downto 0) := "00001";
constant GPIO_REG_DIR : std_ulogic_vector(GPIO_REG_BITS-1 downto 0) := "00010";
constant GPIO_REG_DATA_SET : std_ulogic_vector(GPIO_REG_BITS-1 downto 0) := "00100";
constant GPIO_REG_DATA_CLR : std_ulogic_vector(GPIO_REG_BITS-1 downto 0) := "00101";

-- Current output value and direction
signal reg_data : std_ulogic_vector(NGPIO - 1 downto 0);
signal reg_dirn : std_ulogic_vector(NGPIO - 1 downto 0);
signal reg_in1 : std_ulogic_vector(NGPIO - 1 downto 0);
signal reg_in2 : std_ulogic_vector(NGPIO - 1 downto 0);

signal wb_rsp : wb_io_slave_out;
signal reg_out : std_ulogic_vector(NGPIO - 1 downto 0);

begin

-- No interrupt facility for now
intr <= '0';

gpio_out <= reg_data;
gpio_dir <= reg_dirn;

-- Wishbone response
wb_rsp.ack <= wb_in.cyc and wb_in.stb;
with wb_in.adr(GPIO_REG_BITS - 1 downto 0) select reg_out <=
reg_data when GPIO_REG_DATA_OUT,
reg_in2 when GPIO_REG_DATA_IN,
reg_dirn when GPIO_REG_DIR,
(others => '0') when others;
wb_rsp.dat(wb_rsp.dat'left downto NGPIO) <= (others => '0');
wb_rsp.dat(NGPIO - 1 downto 0) <= reg_out;
wb_rsp.stall <= '0';

regs_rw: process(clk)
begin
if rising_edge(clk) then
wb_out <= wb_rsp;
reg_in2 <= reg_in1;
reg_in1 <= gpio_in;
if rst = '1' then
reg_data <= (others => '0');
reg_dirn <= (others => '0');
wb_out.ack <= '0';
else
if wb_in.cyc = '1' and wb_in.stb = '1' and wb_in.we = '1' then
case wb_in.adr(GPIO_REG_BITS - 1 downto 0) is
when GPIO_REG_DATA_OUT =>
reg_data <= wb_in.dat(NGPIO - 1 downto 0);
when GPIO_REG_DIR =>
reg_dirn <= wb_in.dat(NGPIO - 1 downto 0);
when GPIO_REG_DATA_SET =>
reg_data <= reg_data or wb_in.dat(NGPIO - 1 downto 0);
when GPIO_REG_DATA_CLR =>
reg_data <= reg_data and not wb_in.dat(NGPIO - 1 downto 0);
when others =>
end case;
end if;
end if;
end if;
end process;

end architecture behaviour;

@ -60,25 +60,11 @@ _start:


.global boot_entry .global boot_entry
boot_entry: boot_entry:
LOAD_IMM64(%r10,__bss_start)
LOAD_IMM64(%r11,__bss_end)
subf %r11,%r10,%r11
addi %r11,%r11,63
srdi. %r11,%r11,6
beq 2f
mtctr %r11
1: dcbz 0,%r10
addi %r10,%r10,64
bdnz 1b

/* setup stack */ /* setup stack */
2: LOAD_IMM64(%r1,__stack_top) LOAD_IMM64(%r1, STACK_TOP - 0x100)
li %r0,0
stdu %r0,-32(%r1)
LOAD_IMM64(%r12, main) LOAD_IMM64(%r12, main)
mtctr %r12 mtctr %r12,
bctrl bctrl
attn // terminate on exit
b . b .


#define EXCEPTION(nr) \ #define EXCEPTION(nr) \

Binary file not shown.

Binary file not shown.

@ -35,24 +35,24 @@ a64b5a7d14004a39
a602487d05009f42 a602487d05009f42
a64b5a7d14004a39 a64b5a7d14004a39
2402004ca64b7b7d 2402004ca64b7b7d
3d40000048000004 3c20000048000004
794a07c6614a0000
614a1900654a0000
616b00003d600000
656b0000796b07c6
7d6a5850616b1980
796bd183396b003f
7d6903a641820014
394a00407c0057ec
3c2000004200fff8
782107c660210000 782107c660210000
6021398064210000 60211f0064210000
f801ffe138000000 618c00003d800000
3d8000007c1243a6 658c0000798c07c6
798c07c6618c0000 7d8903a6618c1014
618c1000658c0000 480000004e800421
4e8004217d8903a6 0000000000000000
4800000000000200 0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000 0000000000000000
0000000000000000 0000000000000000
0000000000000000 0000000000000000
@ -510,150 +510,150 @@ f801ffe138000000
0000000000000000 0000000000000000
0000000000000000 0000000000000000
0000000000000000 0000000000000000
384298003c400001 e8010010ebc1fff0
fbe1fff87c0802a6 7c0803a6ebe1fff8
f821ffd1f8010010 3c4000014e800020
60000000480001ed 7c0802a638429800
3862800060000000 f8010010fbe1fff8
6000000048000155 480001edf821ffd1
6000000048000049 6000000060000000
5463063e7c7f1b78 4800015538628000
480000b957ff063e 4800004960000000
2c1f000d60000000 7c7f1b7860000000
3860000a4082ffe0 57ff063e5463063e
60000000480000a5 60000000480000b9
4082ffe02c1f000d
480000a53860000a
4bffffd060000000
0100000000000000
3c40000100000180
6000000038429800
6000000089228090
2c09000039428088
e92a000041820030
7c0004ac39290014
712900017d204eaa
e86a00004182ffec
7c601eaa7c0004ac
4e8000205463063e
39290010e92a0000
7d204eea7c0004ac
4082ffec71290001
38630008e86a0000
7c601eea7c0004ac
000000004bffffd0 000000004bffffd0
0000018001000000 0000000000000000
384298003c400001 384298003c400001
8922810860000000 8922809060000000
3942810060000000 3942808860000000
418200302c090000 4182002c2c090000
39290014e92a0000 39290014e92a0000
7d204eaa7c0004ac 7d204eaa7c0004ac
4182ffec71290001 4182ffec71290020
7c0004ace86a0000 7c0004ace92a0000
5463063e7c601eaa 4e8000207c604faa
e92a00004e800020 39290010e92a0000
7c0004ac39290010 7d204eea7c0004ac
712900017d204eea 4082ffec71290008
e86a00004082ffec e94a00005469063e
7c0004ac38630008 7d2057ea7c0004ac
4bffffd07c601eea 000000004e800020
0000000000000000
3c40000100000000
6000000038429800
6000000089228108
2c09000039428100
e92a00004182002c
7c0004ac39290014
712900207d204eaa
e92a00004182ffec
7c604faa7c0004ac
e92a00004e800020
7c0004ac39290010
712900087d204eea
5469063e4082ffec
7c0004ace94a0000
4e8000207d2057ea
0000000000000000 0000000000000000
3c40000100000000 384298003c400001
7c0802a638429800 fbe1fff87c0802a6
fbc1fff0fbe1fff8 3be3fffffbc1fff0
f80100103be3ffff f821ffd1f8010010
8fdf0001f821ffd1 2c3e00008fdf0001
408200102c3e0000 3821003040820010
3860000038210030 4bfffe4438600000
281e000a480001e8 4082000c281e000a
3860000d4082000c 4bffff453860000d
7fc3f3784bffff45 4bffff3d7fc3f378
4bffffd04bffff3d 000000004bffffd0
0100000000000000 0000028001000000
7c691b7800000280 386000007c691b78
7d4918ae38600000 2c0a00007d4918ae
4d8200202c0a0000 386300014d820020
4bfffff038630001 000000004bfffff0
0000000000000000 0000000000000000
3c40000100000000 384298003c400001
3d40c00038429800 614a00203d40c000
794a0020614a0020 7c0004ac794a0020
7d4056ea7c0004ac 3d20c0007d4056ea
794a06003d20c000 61290008794a0600
7929002061290008
7d204eea7c0004ac
4182001871290020
612900403d20c000
7c0004ac79290020 7c0004ac79290020
7929f8047d204eea 712900207d204eea
79290fc33d00c000 3d20c00041820018
7908002061082000 7929002061290040
f902810060000000 7d204eea7c0004ac
610820003d00001c 3d00c0007929f804
418200847d4a4392 6108200079290fc3
3920000160000000 6000000079080020
3d00c00099228108 3d00001cf9028088
3920ff806108200c 7d4a439261082000
7c0004ac79080020 6000000041820084
e92281007d2047aa 9922809039200001
7d404faa7c0004ac 6108200c3d00c000
794ac202e9228100 790800203920ff80
7c0004ac39290004 7d2047aa7c0004ac
e92281007d404faa 7c0004ace9228088
3929000c39400003 e92280887d404faa
39290004794ac202
7d404faa7c0004ac 7d404faa7c0004ac
39290010e9228100 39400003e9228088
7c0004ac3929000c
e92280887d404faa
7c0004ac39290010
e92280887d404faa
3929000839400007
7d404faa7c0004ac 7d404faa7c0004ac
39400007e9228100 600000004e800020
7c0004ac39290008 99228090394affff
4e8000207d404faa 612920183d20c000
394affff60000000 7c0004ac79290020
3d20c00099228108 4e8000207d404fea
7929002061292018
7d404fea7c0004ac
000000004e800020
0000000000000000 0000000000000000
384298003c400001 3c40000100000000
8922810860000000 6000000038429800
600000002c090000 2c24000089228090
41820024e9228100 600000002f890000
78840e282c230000 419e0030e9228088
6084000141820008 3940000241820024
7c0004ac39290004 418200082c230000
4e8000207c804faa 39290004614a0001
418200082c240000 7d404faa7c0004ac
394000004e800020
418200084bffffe0
3929002060630002 3929002060630002
7c604fea7c0004ac 7c604fea7c0004ac
000000004e800020 000000004e800020
0000000000000000 0000000000000000
e8010010ebc1fff0 0000000000000010
7c0803a6ebe1fff8 0141780400527a01
000000104e800020 0000001800010c1b
00527a0100000000 fffffc4800000018
00010c1b01417804 300e460000000070
0000001800000018 000000019f7e4111
00000070fffffc40 0000000000000010
9f7e4111300e4600 0141780400527a01
0000001000000001 0000001000010c1b
00527a0100000000 fffffc8800000018
00010c1b01417804 0000000000000084
0000001800000010 0000002c00000010
00000084fffffc80 00000080fffffcf8
0000001000000000 0000002800000000
fffffcf00000002c fffffd6400000040
0000000000000080 4109450000000060
0000004000000028 300e43029e019f00
00000060fffffd5c 42000e0a447e4111
9e019f0041094500 0000000b4106dedf
447e4111300e4302 0000006c00000010
4106dedf42000e0a 00000028fffffd98
000000100000000b
fffffd900000006c
0000000000000028
0000008000000010
0000012cfffffda4
0000001000000000 0000001000000000
fffffebc00000094 fffffdac00000080
0000000000000068 000000000000012c
0000000000000000 0000009400000010
00000074fffffec4
0000000000000000 0000000000000000
0000000000000000 0000000000000000
0000000000000000 0000000000000000

@ -1,27 +1,13 @@
SECTIONS SECTIONS
{ {
. = 0;
_start = .; _start = .;
. = 0;
.head : { .head : {
KEEP(*(.head)) KEEP(*(.head))
} }
. = 0x1000; . = 0x1000;
.text : { *(.text) *(.text.*) *(.rodata) *(.rodata.*) } .text : { *(.text) }
. = 0x1800; . = 0x1800;
.data : { *(.data) *(.data.*) *(.got) *(.toc) } .data : { *(.data) }
. = ALIGN(0x80); .bss : { *(.bss) }
__bss_start = .;
.bss : {
*(.dynsbss)
*(.sbss)
*(.scommon)
*(.dynbss)
*(.bss)
*(.common)
*(.bss.*)
}
. = ALIGN(0x80);
__bss_end = .;
. = . + 0x2000;
__stack_top = .;
} }

@ -28,9 +28,7 @@ package helpers is


function bit_reverse(a: std_ulogic_vector) return std_ulogic_vector; function bit_reverse(a: std_ulogic_vector) return std_ulogic_vector;
function bit_number(a: std_ulogic_vector(63 downto 0)) return std_ulogic_vector; function bit_number(a: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function edgelocation(v: std_ulogic_vector; nbits: natural) return std_ulogic_vector;
function count_left_zeroes(val: std_ulogic_vector) return std_ulogic_vector; function count_left_zeroes(val: std_ulogic_vector) return std_ulogic_vector;
function count_right_zeroes(val: std_ulogic_vector) return std_ulogic_vector;
end package helpers; end package helpers;


package body helpers is package body helpers is
@ -249,50 +247,16 @@ package body helpers is
return ret; return ret;
end; end;


-- Assuming the input 'v' is a value of the form 1...10...0, -- Count leading zeroes operation
-- the output is the bit number of the rightmost 1 bit in v.
-- If v is zero, the result is zero.
function edgelocation(v: std_ulogic_vector; nbits: natural) return std_ulogic_vector is
variable p: std_ulogic_vector(nbits - 1 downto 0);
variable stride: natural;
variable b: std_ulogic;
variable k: natural;
begin
stride := 2;
for i in 0 to nbits - 1 loop
b := '0';
for j in 0 to (2**nbits / stride) - 1 loop
k := j * stride;
b := b or (v(k + stride - 1) and not v(k + (stride/2) - 1));
end loop;
p(i) := b;
stride := stride * 2;
end loop;
return p;
end function;

-- Count leading zeroes operations
-- Assumes the value passed in is not zero (if it is, zero is returned) -- Assumes the value passed in is not zero (if it is, zero is returned)
function count_right_zeroes(val: std_ulogic_vector) return std_ulogic_vector is
variable sum: std_ulogic_vector(val'left downto val'right);
variable onehot: std_ulogic_vector(val'left downto val'right);
variable edge: std_ulogic_vector(val'left downto val'right);
variable bn, bn_e, bn_o: std_ulogic_vector(5 downto 0);
begin
sum := std_ulogic_vector(- signed(val));
onehot := sum and val;
edge := sum or val;
bn_e := edgelocation(std_ulogic_vector(resize(signed(edge), 64)), 6);
bn_o := bit_number(std_ulogic_vector(resize(unsigned(onehot), 64)));
bn := bn_e(5 downto 2) & bn_o(1 downto 0);
return bn;
end;

function count_left_zeroes(val: std_ulogic_vector) return std_ulogic_vector is function count_left_zeroes(val: std_ulogic_vector) return std_ulogic_vector is
variable rev: std_ulogic_vector(val'left downto val'right); variable rev: std_ulogic_vector(val'left downto val'right);
variable sum: std_ulogic_vector(val'left downto val'right);
variable onehot: std_ulogic_vector(val'left downto val'right);
begin begin
rev := bit_reverse(val); rev := bit_reverse(val);
return count_right_zeroes(rev); sum := std_ulogic_vector(- signed(rev));
onehot := sum and rev;
return bit_number(std_ulogic_vector(resize(unsigned(onehot), 64)));
end; end;

end package body helpers; end package body helpers;

@ -46,6 +46,8 @@ entity icache is
TLB_SIZE : positive := 64; TLB_SIZE : positive := 64;
-- L1 ITLB log_2(page_size) -- L1 ITLB log_2(page_size)
TLB_LG_PGSZ : positive := 12; TLB_LG_PGSZ : positive := 12;
-- Number of real address bits that we store
REAL_ADDR_BITS : positive := 56;
-- Non-zero to enable log data collection -- Non-zero to enable log data collection
LOG_LENGTH : natural := 0 LOG_LENGTH : natural := 0
); );
@ -66,9 +68,6 @@ entity icache is
wishbone_out : out wishbone_master_out; wishbone_out : out wishbone_master_out;
wishbone_in : in wishbone_slave_out; wishbone_in : in wishbone_slave_out;


wb_snoop_in : in wishbone_master_out := wishbone_master_out_init;

events : out IcacheEventType;
log_out : out std_ulogic_vector(53 downto 0) log_out : out std_ulogic_vector(53 downto 0)
); );
end entity icache; end entity icache;
@ -169,7 +168,7 @@ architecture rtl of icache is
signal eaa_priv : std_ulogic; signal eaa_priv : std_ulogic;


-- Cache reload state machine -- Cache reload state machine
type state_t is (IDLE, STOP_RELOAD, CLR_TAG, WAIT_ACK); type state_t is (IDLE, CLR_TAG, WAIT_ACK);


type reg_internal_t is record type reg_internal_t is record
-- Cache hit state (Latches for 1 cycle BRAM access) -- Cache hit state (Latches for 1 cycle BRAM access)
@ -196,8 +195,6 @@ architecture rtl of icache is


signal r : reg_internal_t; signal r : reg_internal_t;


signal ev : IcacheEventType;

-- Async signals on incoming request -- Async signals on incoming request
signal req_index : index_t; signal req_index : index_t;
signal req_row : row_t; signal req_row : row_t;
@ -205,13 +202,14 @@ architecture rtl of icache is
signal req_tag : cache_tag_t; signal req_tag : cache_tag_t;
signal req_is_hit : std_ulogic; signal req_is_hit : std_ulogic;
signal req_is_miss : std_ulogic; signal req_is_miss : std_ulogic;
signal req_raddr : real_addr_t; signal req_laddr : std_ulogic_vector(63 downto 0);


signal tlb_req_index : tlb_index_t; signal tlb_req_index : tlb_index_t;
signal real_addr : real_addr_t; signal real_addr : std_ulogic_vector(REAL_ADDR_BITS - 1 downto 0);
signal ra_valid : std_ulogic; signal ra_valid : std_ulogic;
signal priv_fault : std_ulogic; signal priv_fault : std_ulogic;
signal access_ok : std_ulogic; signal access_ok : std_ulogic;
signal use_previous : std_ulogic;


-- Cache RAM interface -- Cache RAM interface
type cache_ram_out_t is array(way_t) of cache_row_t; type cache_ram_out_t is array(way_t) of cache_row_t;
@ -222,19 +220,14 @@ architecture rtl of icache is
signal plru_victim : plru_out_t; signal plru_victim : plru_out_t;
signal replace_way : way_t; signal replace_way : way_t;


-- Memory write snoop signals
signal snoop_valid : std_ulogic;
signal snoop_index : index_t;
signal snoop_hits : cache_way_valids_t;

-- Return the cache line index (tag index) for an address -- Return the cache line index (tag index) for an address
function get_index(addr: std_ulogic_vector) return index_t is function get_index(addr: std_ulogic_vector(63 downto 0)) return index_t is
begin begin
return to_integer(unsigned(addr(SET_SIZE_BITS - 1 downto LINE_OFF_BITS))); return to_integer(unsigned(addr(SET_SIZE_BITS - 1 downto LINE_OFF_BITS)));
end; end;


-- Return the cache row index (data memory) for an address -- Return the cache row index (data memory) for an address
function get_row(addr: std_ulogic_vector) return row_t is function get_row(addr: std_ulogic_vector(63 downto 0)) return row_t is
begin begin
return to_integer(unsigned(addr(SET_SIZE_BITS - 1 downto ROW_OFF_BITS))); return to_integer(unsigned(addr(SET_SIZE_BITS - 1 downto ROW_OFF_BITS)));
end; end;
@ -248,9 +241,9 @@ architecture rtl of icache is
end; end;


-- Returns whether this is the last row of a line -- Returns whether this is the last row of a line
function is_last_row_wb_addr(wb_addr: wishbone_addr_type; last: row_in_line_t) return boolean is function is_last_row_addr(addr: wishbone_addr_type; last: row_in_line_t) return boolean is
begin begin
return unsigned(wb_addr(LINE_OFF_BITS - ROW_OFF_BITS - 1 downto 0)) = last; return unsigned(addr(LINE_OFF_BITS-1 downto ROW_OFF_BITS)) = last;
end; end;


-- Returns whether this is the last row of a line -- Returns whether this is the last row of a line
@ -260,16 +253,16 @@ architecture rtl of icache is
end; end;


-- Return the address of the next row in the current cache line -- Return the address of the next row in the current cache line
function next_row_wb_addr(wb_addr: wishbone_addr_type) function next_row_addr(addr: wishbone_addr_type)
return std_ulogic_vector is return std_ulogic_vector is
variable row_idx : std_ulogic_vector(ROW_LINEBITS-1 downto 0); variable row_idx : std_ulogic_vector(ROW_LINEBITS-1 downto 0);
variable result : wishbone_addr_type; variable result : wishbone_addr_type;
begin begin
-- Is there no simpler way in VHDL to generate that 3 bits adder ? -- Is there no simpler way in VHDL to generate that 3 bits adder ?
row_idx := wb_addr(ROW_LINEBITS - 1 downto 0); row_idx := addr(LINE_OFF_BITS-1 downto ROW_OFF_BITS);
row_idx := std_ulogic_vector(unsigned(row_idx) + 1); row_idx := std_ulogic_vector(unsigned(row_idx) + 1);
result := wb_addr; result := addr;
result(ROW_LINEBITS - 1 downto 0) := row_idx; result(LINE_OFF_BITS-1 downto ROW_OFF_BITS) := row_idx;
return result; return result;
end; end;


@ -298,9 +291,10 @@ architecture rtl of icache is
end; end;


-- Get the tag value from the address -- Get the tag value from the address
function get_tag(addr: real_addr_t; endian: std_ulogic) return cache_tag_t is function get_tag(addr: std_ulogic_vector(REAL_ADDR_BITS - 1 downto 0);
endian: std_ulogic) return cache_tag_t is
begin begin
return endian & addr(addr'left downto SET_SIZE_BITS); return endian & addr(REAL_ADDR_BITS - 1 downto SET_SIZE_BITS);
end; end;


-- Read a tag from a tag memory row -- Read a tag from a tag memory row
@ -396,7 +390,7 @@ begin
wr_dat(ii * 8 + 7 downto ii * 8) <= wishbone_in.dat(j * 8 + 7 downto j * 8); wr_dat(ii * 8 + 7 downto ii * 8) <= wishbone_in.dat(j * 8 + 7 downto j * 8);
end loop; end loop;
end if; end if;
do_read <= not stall_in; do_read <= not (stall_in or use_previous);
do_write <= '0'; do_write <= '0';
if wishbone_in.ack = '1' and replace_way = i then if wishbone_in.ack = '1' and replace_way = i then
do_write <= '1'; do_write <= '1';
@ -464,7 +458,7 @@ begin
end if; end if;
eaa_priv <= pte(3); eaa_priv <= pte(3);
else else
real_addr <= addr_to_real(i_in.nia); real_addr <= i_in.nia(REAL_ADDR_BITS - 1 downto 0);
ra_valid <= '1'; ra_valid <= '1';
eaa_priv <= '1'; eaa_priv <= '1';
end if; end if;
@ -493,7 +487,6 @@ begin
itlb_ptes(wr_index) <= m_in.pte; itlb_ptes(wr_index) <= m_in.pte;
itlb_valids(wr_index) <= '1'; itlb_valids(wr_index) <= '1';
end if; end if;
ev.itlb_miss_resolved <= m_in.tlbld and not rst;
end if; end if;
end process; end process;


@ -502,6 +495,16 @@ begin
variable is_hit : std_ulogic; variable is_hit : std_ulogic;
variable hit_way : way_t; variable hit_way : way_t;
begin begin
-- i_in.sequential means that i_in.nia this cycle is 4 more than
-- last cycle. If we read more than 32 bits at a time, had a cache hit
-- last cycle, and we don't want the first 32-bit chunk, then we can
-- keep the data we read last cycle and just use that.
if unsigned(i_in.nia(INSN_BITS+2-1 downto 2)) /= 0 then
use_previous <= i_in.req and i_in.sequential and r.hit_valid;
else
use_previous <= '0';
end if;

-- Extract line, row and tag from request -- Extract line, row and tag from request
req_index <= get_index(i_in.nia); req_index <= get_index(i_in.nia);
req_row <= get_row(i_in.nia); req_row <= get_row(i_in.nia);
@ -510,7 +513,8 @@ begin
-- Calculate address of beginning of cache row, will be -- Calculate address of beginning of cache row, will be
-- used for cache miss processing if needed -- used for cache miss processing if needed
-- --
req_raddr <= real_addr(REAL_ADDR_BITS - 1 downto ROW_OFF_BITS) & req_laddr <= (63 downto REAL_ADDR_BITS => '0') &
real_addr(REAL_ADDR_BITS - 1 downto ROW_OFF_BITS) &
(ROW_OFF_BITS-1 downto 0 => '0'); (ROW_OFF_BITS-1 downto 0 => '0');


-- Test if pending request is a hit on any way -- Test if pending request is a hit on any way
@ -555,18 +559,13 @@ begin
-- I prefer not to do just yet as it would force fetch2 to know about -- I prefer not to do just yet as it would force fetch2 to know about
-- some of the cache geometry information. -- some of the cache geometry information.
-- --
if r.hit_valid = '1' then i_out.insn <= read_insn_word(r.hit_nia, cache_out(r.hit_way));
i_out.insn <= read_insn_word(r.hit_nia, cache_out(r.hit_way));
else
i_out.insn <= (others => '0');
end if;
i_out.valid <= r.hit_valid; i_out.valid <= r.hit_valid;
i_out.nia <= r.hit_nia; i_out.nia <= r.hit_nia;
i_out.stop_mark <= r.hit_smark; i_out.stop_mark <= r.hit_smark;
i_out.fetch_failed <= r.fetch_failed; i_out.fetch_failed <= r.fetch_failed;
i_out.big_endian <= r.big_endian; i_out.big_endian <= r.big_endian;
i_out.next_predicted <= i_in.predicted; i_out.next_predicted <= i_in.predicted;
i_out.next_pred_ntaken <= i_in.pred_ntaken;


-- Stall fetch1 if we have a miss on cache or TLB or a protection fault -- Stall fetch1 if we have a miss on cache or TLB or a protection fault
stall_out <= not (is_hit and access_ok); stall_out <= not (is_hit and access_ok);
@ -581,7 +580,8 @@ begin
if rising_edge(clk) then if rising_edge(clk) then
-- keep outputs to fetch2 unchanged on a stall -- keep outputs to fetch2 unchanged on a stall
-- except that flush or reset sets valid to 0 -- except that flush or reset sets valid to 0
if stall_in = '1' then -- If use_previous, keep the same data as last cycle and use the second half
if stall_in = '1' or use_previous = '1' then
if rst = '1' or flush_in = '1' then if rst = '1' or flush_in = '1' then
r.hit_valid <= '0'; r.hit_valid <= '0';
end if; end if;
@ -614,13 +614,9 @@ begin
-- Cache miss/reload synchronous machine -- Cache miss/reload synchronous machine
icache_miss : process(clk) icache_miss : process(clk)
variable tagset : cache_tags_set_t; variable tagset : cache_tags_set_t;
variable tag : cache_tag_t; variable stbs_done : boolean;
variable snoop_addr : real_addr_t;
variable snoop_tag : cache_tag_t;
variable snoop_cache_tags : cache_tags_set_t;
begin begin
if rising_edge(clk) then if rising_edge(clk) then
ev.icache_miss <= '0';
-- On reset, clear all valid bits to force misses -- On reset, clear all valid bits to force misses
if rst = '1' then if rst = '1' then
for i in index_t loop for i in index_t loop
@ -637,42 +633,13 @@ begin


-- Not useful normally but helps avoiding tons of sim warnings -- Not useful normally but helps avoiding tons of sim warnings
r.wb.adr <= (others => '0'); r.wb.adr <= (others => '0');

snoop_valid <= '0';
snoop_index <= 0;
snoop_hits <= (others => '0');
else else
-- Detect snooped writes and decode address into index and tag
-- Since we never write, any write should be snooped
snoop_valid <= wb_snoop_in.cyc and wb_snoop_in.stb and wb_snoop_in.we;
snoop_addr := addr_to_real(wb_to_addr(wb_snoop_in.adr));
snoop_index <= get_index(snoop_addr);
snoop_cache_tags := cache_tags(get_index(snoop_addr));
snoop_tag := get_tag(snoop_addr, '0');
snoop_hits <= (others => '0');
for i in way_t loop
tag := read_tag(i, snoop_cache_tags);
-- Ignore endian bit in comparison
tag(TAG_BITS - 1) := '0';
if tag = snoop_tag then
snoop_hits(i) <= '1';
end if;
end loop;

-- Process cache invalidations -- Process cache invalidations
if inval_in = '1' then if inval_in = '1' then
for i in index_t loop for i in index_t loop
cache_valids(i) <= (others => '0'); cache_valids(i) <= (others => '0');
end loop; end loop;
r.store_valid <= '0'; r.store_valid <= '0';
else
-- Do invalidations from snooped stores to memory, one
-- cycle after the address appears on wb_snoop_in.
for i in way_t loop
if snoop_valid = '1' and snoop_hits(i) = '1' then
cache_valids(snoop_index)(i) <= '0';
end if;
end loop;
end if; end if;


-- Main state machine -- Main state machine
@ -692,19 +659,18 @@ begin
" way:" & integer'image(replace_way) & " way:" & integer'image(replace_way) &
" tag:" & to_hstring(req_tag) & " tag:" & to_hstring(req_tag) &
" RA:" & to_hstring(real_addr); " RA:" & to_hstring(real_addr);
ev.icache_miss <= '1';


-- Keep track of our index and way for subsequent stores -- Keep track of our index and way for subsequent stores
r.store_index <= req_index; r.store_index <= req_index;
r.store_row <= get_row(req_raddr); r.store_row <= get_row(req_laddr);
r.store_tag <= req_tag; r.store_tag <= req_tag;
r.store_valid <= '1'; r.store_valid <= '1';
r.end_row_ix <= get_row_of_line(get_row(req_raddr)) - 1; r.end_row_ix <= get_row_of_line(get_row(req_laddr)) - 1;


-- Prep for first wishbone read. We calculate the address of -- Prep for first wishbone read. We calculate the address of
-- the start of the cache line and start the WB cycle. -- the start of the cache line and start the WB cycle.
-- --
r.wb.adr <= addr_to_wb(req_raddr); r.wb.adr <= req_laddr(r.wb.adr'left downto 0);
r.wb.cyc <= '1'; r.wb.cyc <= '1';
r.wb.stb <= '1'; r.wb.stb <= '1';


@ -731,30 +697,29 @@ begin


r.state <= WAIT_ACK; r.state <= WAIT_ACK;
end if; end if;
-- Requests are all sent if stb is 0
stbs_done := r.wb.stb = '0';


-- If we are still sending requests, was one accepted ? -- If we are still sending requests, was one accepted ?
if wishbone_in.stall = '0' and r.wb.stb = '1' then if wishbone_in.stall = '0' and not stbs_done then
-- That was the last word ? We are done sending. Clear stb. -- That was the last word ? We are done sending. Clear
-- stb and set stbs_done so we can handle an eventual last
-- ack on the same cycle.
-- --
if is_last_row_wb_addr(r.wb.adr, r.end_row_ix) then if is_last_row_addr(r.wb.adr, r.end_row_ix) then
r.wb.stb <= '0'; r.wb.stb <= '0';
stbs_done := true;
end if; end if;


-- Calculate the next row address -- Calculate the next row address
r.wb.adr <= next_row_wb_addr(r.wb.adr); r.wb.adr <= next_row_addr(r.wb.adr);
end if; end if;


-- Abort reload if we get an invalidation
if inval_in = '1' then
r.wb.stb <= '0';
r.state <= STOP_RELOAD;
end if;

-- Incoming acks processing -- Incoming acks processing
if wishbone_in.ack = '1' then if wishbone_in.ack = '1' then
r.rows_valid(r.store_row mod ROW_PER_LINE) <= not inval_in; r.rows_valid(r.store_row mod ROW_PER_LINE) <= '1';
-- Check for completion -- Check for completion
if is_last_row(r.store_row, r.end_row_ix) then if stbs_done and is_last_row(r.store_row, r.end_row_ix) then
-- Complete wishbone cycle -- Complete wishbone cycle
r.wb.cyc <= '0'; r.wb.cyc <= '0';


@ -768,18 +733,6 @@ begin
-- Increment store row counter -- Increment store row counter
r.store_row <= next_row(r.store_row); r.store_row <= next_row(r.store_row);
end if; end if;

when STOP_RELOAD =>
-- Wait for all outstanding requests to be satisfied, then
-- go to IDLE state.
if get_row_of_line(r.store_row) = get_row_of_line(get_row(wb_to_addr(r.wb.adr))) then
r.wb.cyc <= '0';
r.state <= IDLE;
end if;
if wishbone_in.ack = '1' then
-- Increment store row counter
r.store_row <= next_row(r.store_row);
end if;
end case; end case;
end if; end if;


@ -809,7 +762,7 @@ begin
log_data <= i_out.valid & log_data <= i_out.valid &
i_out.insn & i_out.insn &
wishbone_in.ack & wishbone_in.ack &
r.wb.adr(2 downto 0) & r.wb.adr(5 downto 3) &
r.wb.stb & r.wb.cyc & r.wb.stb & r.wb.cyc &
wishbone_in.stall & wishbone_in.stall &
stall_out & stall_out &
@ -824,7 +777,4 @@ begin
end process; end process;
log_out <= log_data; log_out <= log_data;
end generate; end generate;

events <= ev;

end; end;

@ -34,7 +34,7 @@ begin
i_out => i_in, i_out => i_in,
m_in => m_out, m_in => m_out,
stall_in => '0', stall_in => '0',
flush_in => '0', flush_in => '0',
inval_in => '0', inval_in => '0',
wishbone_out => wb_bram_in, wishbone_out => wb_bram_in,
wishbone_in => wb_bram_out wishbone_in => wb_bram_out
@ -73,10 +73,7 @@ begin
begin begin
i_out.req <= '0'; i_out.req <= '0';
i_out.nia <= (others => '0'); i_out.nia <= (others => '0');
i_out.stop_mark <= '0'; i_out.stop_mark <= '0';
i_out.priv_mode <= '1';
i_out.virt_mode <= '0';
i_out.big_endian <= '0';


m_out.tlbld <= '0'; m_out.tlbld <= '0';
m_out.tlbie <= '0'; m_out.tlbie <= '0';
@ -96,10 +93,10 @@ begin


assert i_in.valid = '1' severity failure; assert i_in.valid = '1' severity failure;
assert i_in.insn = x"00000001" assert i_in.insn = x"00000001"
report "insn @" & to_hstring(i_out.nia) & report "insn @" & to_hstring(i_out.nia) &
"=" & to_hstring(i_in.insn) & "=" & to_hstring(i_in.insn) &
" expected 00000001" " expected 00000001"
severity failure; severity failure;


i_out.req <= '0'; i_out.req <= '0';


@ -112,10 +109,10 @@ begin
wait until rising_edge(clk); wait until rising_edge(clk);
assert i_in.valid = '1' severity failure; assert i_in.valid = '1' severity failure;
assert i_in.insn = x"00000002" assert i_in.insn = x"00000002"
report "insn @" & to_hstring(i_out.nia) & report "insn @" & to_hstring(i_out.nia) &
"=" & to_hstring(i_in.insn) & "=" & to_hstring(i_in.insn) &
" expected 00000002" " expected 00000002"
severity failure; severity failure;
wait until rising_edge(clk); wait until rising_edge(clk);


-- another miss -- another miss
@ -127,10 +124,10 @@ begin


assert i_in.valid = '1' severity failure; assert i_in.valid = '1' severity failure;
assert i_in.insn = x"00000010" assert i_in.insn = x"00000010"
report "insn @" & to_hstring(i_out.nia) & report "insn @" & to_hstring(i_out.nia) &
"=" & to_hstring(i_in.insn) & "=" & to_hstring(i_in.insn) &
" expected 00000010" " expected 00000010"
severity failure; severity failure;


-- test something that aliases -- test something that aliases
i_out.req <= '1'; i_out.req <= '1';
@ -145,10 +142,10 @@ begin


assert i_in.valid = '1' severity failure; assert i_in.valid = '1' severity failure;
assert i_in.insn = x"00000040" assert i_in.insn = x"00000040"
report "insn @" & to_hstring(i_out.nia) & report "insn @" & to_hstring(i_out.nia) &
"=" & to_hstring(i_in.insn) & "=" & to_hstring(i_in.insn) &
" expected 00000040" " expected 00000040"
severity failure; severity failure;


i_out.req <= '0'; i_out.req <= '0';



@ -17,7 +17,6 @@
#define DRAM_CTRL_BASE 0xc8000000 /* LiteDRAM control registers */ #define DRAM_CTRL_BASE 0xc8000000 /* LiteDRAM control registers */
#define LETH_CSR_BASE 0xc8020000 /* LiteEth CSR registers */ #define LETH_CSR_BASE 0xc8020000 /* LiteEth CSR registers */
#define LETH_SRAM_BASE 0xc8030000 /* LiteEth MMIO space */ #define LETH_SRAM_BASE 0xc8030000 /* LiteEth MMIO space */
#define LSDC_CSR_BASE 0xc8040000 /* LiteSDCard MMIO space */
#define SPI_FLASH_BASE 0xf0000000 /* SPI Flash memory map */ #define SPI_FLASH_BASE 0xf0000000 /* SPI Flash memory map */
#define DRAM_INIT_BASE 0xff000000 /* Internal DRAM init firmware */ #define DRAM_INIT_BASE 0xff000000 /* Internal DRAM init firmware */


@ -41,7 +40,6 @@
#define SYS_REG_INFO_HAS_LARGE_SYSCON (1ull << 5) #define SYS_REG_INFO_HAS_LARGE_SYSCON (1ull << 5)
#define SYS_REG_INFO_HAS_UART1 (1ull << 6) #define SYS_REG_INFO_HAS_UART1 (1ull << 6)
#define SYS_REG_INFO_HAS_ARTB (1ull << 7) #define SYS_REG_INFO_HAS_ARTB (1ull << 7)
#define SYS_REG_INFO_HAS_LITESDCARD (1ull << 8)
#define SYS_REG_BRAMINFO 0x10 #define SYS_REG_BRAMINFO 0x10
#define SYS_REG_BRAMINFO_SIZE_MASK 0xfffffffffffffull #define SYS_REG_BRAMINFO_SIZE_MASK 0xfffffffffffffull
#define SYS_REG_DRAMINFO 0x18 #define SYS_REG_DRAMINFO 0x18

@ -13,7 +13,6 @@ entity litedram_wrapper is
DRAM_ABITS : positive; DRAM_ABITS : positive;
DRAM_ALINES : natural; DRAM_ALINES : natural;
DRAM_DLINES : natural; DRAM_DLINES : natural;
DRAM_CKLINES : natural;
DRAM_PORT_WIDTH : positive; DRAM_PORT_WIDTH : positive;


-- Pseudo-ROM payload -- Pseudo-ROM payload
@ -70,8 +69,8 @@ entity litedram_wrapper is
ddram_dq : inout std_ulogic_vector(DRAM_DLINES-1 downto 0); ddram_dq : inout std_ulogic_vector(DRAM_DLINES-1 downto 0);
ddram_dqs_p : inout std_ulogic_vector(DRAM_DLINES/8-1 downto 0); ddram_dqs_p : inout std_ulogic_vector(DRAM_DLINES/8-1 downto 0);
ddram_dqs_n : inout std_ulogic_vector(DRAM_DLINES/8-1 downto 0); ddram_dqs_n : inout std_ulogic_vector(DRAM_DLINES/8-1 downto 0);
ddram_clk_p : out std_ulogic_vector(DRAM_CKLINES-1 downto 0); ddram_clk_p : out std_ulogic;
ddram_clk_n : out std_ulogic_vector(DRAM_CKLINES-1 downto 0); ddram_clk_n : out std_ulogic;
ddram_cke : out std_ulogic; ddram_cke : out std_ulogic;
ddram_odt : out std_ulogic; ddram_odt : out std_ulogic;
ddram_reset_n : out std_ulogic ddram_reset_n : out std_ulogic
@ -94,8 +93,8 @@ architecture behaviour of litedram_wrapper is
ddram_dq : inout std_ulogic_vector(DRAM_DLINES-1 downto 0); ddram_dq : inout std_ulogic_vector(DRAM_DLINES-1 downto 0);
ddram_dqs_p : inout std_ulogic_vector(DRAM_DLINES/8-1 downto 0); ddram_dqs_p : inout std_ulogic_vector(DRAM_DLINES/8-1 downto 0);
ddram_dqs_n : inout std_ulogic_vector(DRAM_DLINES/8-1 downto 0); ddram_dqs_n : inout std_ulogic_vector(DRAM_DLINES/8-1 downto 0);
ddram_clk_p : out std_ulogic_vector(DRAM_CKLINES-1 downto 0); ddram_clk_p : out std_ulogic;
ddram_clk_n : out std_ulogic_vector(DRAM_CKLINES-1 downto 0); ddram_clk_n : out std_ulogic;
ddram_cke : out std_ulogic; ddram_cke : out std_ulogic;
ddram_odt : out std_ulogic; ddram_odt : out std_ulogic;
ddram_reset_n : out std_ulogic; ddram_reset_n : out std_ulogic;
@ -164,6 +163,7 @@ architecture behaviour of litedram_wrapper is
-- Select a WB word inside DRAM port width -- Select a WB word inside DRAM port width
constant WB_WORD_COUNT : positive := DRAM_DBITS/WBL; constant WB_WORD_COUNT : positive := DRAM_DBITS/WBL;
constant WB_WSEL_BITS : positive := log2(WB_WORD_COUNT); constant WB_WSEL_BITS : positive := log2(WB_WORD_COUNT);
constant WB_WSEL_RIGHT : positive := log2(WBL/8);


-- BRAM organisation: We never access more than wishbone_data_bits at -- BRAM organisation: We never access more than wishbone_data_bits at
-- a time so to save resources we make the array only that wide, and -- a time so to save resources we make the array only that wide, and
@ -312,20 +312,10 @@ architecture behaviour of litedram_wrapper is
-- Helper functions to decode incoming requests -- Helper functions to decode incoming requests
-- --


-- Return the DRAM real address from a wishbone address
function get_real_addr(addr: wishbone_addr_type) return std_ulogic_vector is
variable ra: std_ulogic_vector(REAL_ADDR_BITS - 1 downto 0) := (others => '0');
begin
ra(REAL_ADDR_BITS - 1 downto wishbone_log2_width) :=
addr(REAL_ADDR_BITS - wishbone_log2_width - 1 downto 0);
return ra;
end;

-- Return the cache line index (tag index) for an address -- Return the cache line index (tag index) for an address
function get_index(addr: wishbone_addr_type) return index_t is function get_index(addr: wishbone_addr_type) return index_t is
begin begin
return to_integer(unsigned(addr(SET_SIZE_BITS - wishbone_log2_width - 1 downto return to_integer(unsigned(addr(SET_SIZE_BITS - 1 downto LINE_OFF_BITS)));
LINE_OFF_BITS - wishbone_log2_width)));
end; end;


-- Return the cache row index (data memory) for an address -- Return the cache row index (data memory) for an address
@ -388,8 +378,7 @@ architecture behaviour of litedram_wrapper is
-- Get the tag value from the address -- Get the tag value from the address
function get_tag(addr: wishbone_addr_type) return cache_tag_t is function get_tag(addr: wishbone_addr_type) return cache_tag_t is
begin begin
return addr(REAL_ADDR_BITS - wishbone_log2_width - 1 downto return addr(REAL_ADDR_BITS - 1 downto SET_SIZE_BITS);
SET_SIZE_BITS - wishbone_log2_width);
end; end;


-- Read a tag from a tag memory row -- Read a tag from a tag memory row
@ -458,7 +447,7 @@ begin
wb_ctrl_stb <= '0'; wb_ctrl_stb <= '0';
else else
-- XXX Maybe only update addr when cyc = '1' to save power ? -- XXX Maybe only update addr when cyc = '1' to save power ?
wb_ctrl_adr <= x"0000" & wb_ctrl_in.adr(13 downto 0); wb_ctrl_adr <= x"0000" & wb_ctrl_in.adr(15 downto 2);
wb_ctrl_dat_w <= wb_ctrl_in.dat; wb_ctrl_dat_w <= wb_ctrl_in.dat;
wb_ctrl_sel <= wb_ctrl_in.sel; wb_ctrl_sel <= wb_ctrl_in.sel;
wb_ctrl_we <= wb_ctrl_in.we; wb_ctrl_we <= wb_ctrl_in.we;
@ -619,7 +608,7 @@ begin
if stall = '1' and wb_out.stall = '0' and wb_in.cyc = '1' and wb_in.stb = '1' then if stall = '1' and wb_out.stall = '0' and wb_in.cyc = '1' and wb_in.stb = '1' then
wb_stash <= wb_in; wb_stash <= wb_in;
if TRACE then if TRACE then
report "stashed wb req ! addr:" & to_hstring(wb_in.adr & "000") & report "stashed wb req ! addr:" & to_hstring(wb_in.adr) &
" we:" & std_ulogic'image(wb_in.we) & " we:" & std_ulogic'image(wb_in.we) &
" sel:" & to_hstring(wb_in.sel); " sel:" & to_hstring(wb_in.sel);
end if; end if;
@ -632,7 +621,7 @@ begin
wb_req <= wb_stash; wb_req <= wb_stash;
wb_stash.cyc <= '0'; wb_stash.cyc <= '0';
if TRACE then if TRACE then
report "unstashed wb req ! addr:" & to_hstring(wb_stash.adr & "000") & report "unstashed wb req ! addr:" & to_hstring(wb_stash.adr) &
" we:" & std_ulogic'image(wb_stash.we) & " we:" & std_ulogic'image(wb_stash.we) &
" sel:" & to_hstring(wb_stash.sel); " sel:" & to_hstring(wb_stash.sel);
end if; end if;
@ -647,7 +636,7 @@ begin


if TRACE then if TRACE then
if wb_in.cyc = '1' and wb_in.stb = '1' then if wb_in.cyc = '1' and wb_in.stb = '1' then
report "latch new wb req ! addr:" & to_hstring(wb_in.adr & "000") & report "latch new wb req ! addr:" & to_hstring(wb_in.adr) &
" we:" & std_ulogic'image(wb_in.we) & " we:" & std_ulogic'image(wb_in.we) &
" sel:" & to_hstring(wb_in.sel); " sel:" & to_hstring(wb_in.sel);
end if; end if;
@ -676,12 +665,12 @@ begin


if TRACE then if TRACE then
if req_op = OP_LOAD_HIT then if req_op = OP_LOAD_HIT then
report "Load hit addr:" & to_hstring(wb_req.adr & "000") & report "Load hit addr:" & to_hstring(wb_req.adr) &
" idx:" & integer'image(req_index) & " idx:" & integer'image(req_index) &
" tag:" & to_hstring(req_tag) & " tag:" & to_hstring(req_tag) &
" way:" & integer'image(req_hit_way); " way:" & integer'image(req_hit_way);
elsif req_op = OP_LOAD_MISS then elsif req_op = OP_LOAD_MISS then
report "Load miss addr:" & to_hstring(wb_req.adr & "000"); report "Load miss addr:" & to_hstring(wb_req.adr);
end if; end if;
if read_ack_0 = '1' then if read_ack_0 = '1' then
report "read data:" & to_hstring(cache_out(read_way_0)); report "read data:" & to_hstring(cache_out(read_way_0));
@ -782,19 +771,20 @@ begin
begin begin
-- Extract line, row and tag from request -- Extract line, row and tag from request
req_index <= get_index(wb_req.adr); req_index <= get_index(wb_req.adr);
req_row <= get_row(get_real_addr(wb_req.adr)); req_row <= get_row(wb_req.adr(REAL_ADDR_BITS-1 downto 0));
req_tag <= get_tag(wb_req.adr); req_tag <= get_tag(wb_req.adr);


-- Calculate address of beginning of cache row, will be -- Calculate address of beginning of cache row, will be
-- used for cache miss processing if needed -- used for cache miss processing if needed
req_laddr <= get_real_addr(wb_req.adr); req_laddr <= wb_req.adr(REAL_ADDR_BITS - 1 downto ROW_OFF_BITS) &
(ROW_OFF_BITS-1 downto 0 => '0');




-- Do we have a valid request in the WB latch ? -- Do we have a valid request in the WB latch ?
valid := wb_req.cyc = '1' and wb_req.stb = '1'; valid := wb_req.cyc = '1' and wb_req.stb = '1';


-- Store signals (hard wired for 64-bit wishbone at the moment) -- Store signals (hard wired for 64-bit wishbone at the moment)
req_wsl <= wb_req.adr(WB_WSEL_BITS-1 downto 0); req_wsl <= wb_req.adr(WB_WSEL_RIGHT+WB_WSEL_BITS-1 downto WB_WSEL_RIGHT);
for i in 0 to WB_WORD_COUNT-1 loop for i in 0 to WB_WORD_COUNT-1 loop
if to_integer(unsigned(req_wsl)) = i then if to_integer(unsigned(req_wsl)) = i then
req_we(WBSL*(i+1)-1 downto WBSL*i) <= wb_req.sel; req_we(WBSL*(i+1)-1 downto WBSL*i) <= wb_req.sel;
@ -902,7 +892,7 @@ begin
variable stq_wsl : std_ulogic_vector(WB_WSEL_BITS-1 downto 0); variable stq_wsl : std_ulogic_vector(WB_WSEL_BITS-1 downto 0);
begin begin
storeq_wr_data <= wb_req.dat & wb_req.sel & storeq_wr_data <= wb_req.dat & wb_req.sel &
wb_req.adr(WB_WSEL_BITS-1 downto 0); wb_req.adr(WB_WSEL_RIGHT+WB_WSEL_BITS-1 downto WB_WSEL_RIGHT);


-- Only queue stores if we can also send a command -- Only queue stores if we can also send a command
if req_op = OP_STORE_HIT or req_op = OP_STORE_MISS then if req_op = OP_STORE_HIT or req_op = OP_STORE_MISS then
@ -937,13 +927,13 @@ begin
if rising_edge(system_clk) then if rising_edge(system_clk) then
if req_op = OP_STORE_HIT then if req_op = OP_STORE_HIT then
report "Store hit to:" & report "Store hit to:" &
to_hstring(wb_req.adr(DRAM_ABITS downto 0) & "000") & to_hstring(wb_req.adr(DRAM_ABITS+3 downto 0)) &
" data:" & to_hstring(req_wdata) & " data:" & to_hstring(req_wdata) &
" we:" & to_hstring(req_we) & " we:" & to_hstring(req_we) &
" V:" & std_ulogic'image(user_port0_cmd_ready); " V:" & std_ulogic'image(user_port0_cmd_ready);
else else
report "Store miss to:" & report "Store miss to:" &
to_hstring(wb_req.adr(DRAM_ABITS downto 0) & "000") & to_hstring(wb_req.adr(DRAM_ABITS+3 downto 0)) &
" data:" & to_hstring(req_wdata) & " data:" & to_hstring(req_wdata) &
" we:" & to_hstring(req_we) & " we:" & to_hstring(req_we) &
" V:" & std_ulogic'image(user_port0_cmd_ready); " V:" & std_ulogic'image(user_port0_cmd_ready);
@ -964,8 +954,7 @@ begin
if req_op = OP_STORE_HIT or req_op = OP_STORE_MISS then if req_op = OP_STORE_HIT or req_op = OP_STORE_MISS then
-- For stores, forward signals directly. Only send command if -- For stores, forward signals directly. Only send command if
-- the FIFO can accept a store. -- the FIFO can accept a store.
user_port0_cmd_addr <= wb_req.adr(DRAM_ABITS + ROW_OFF_BITS - wishbone_log2_width - 1 downto user_port0_cmd_addr <= wb_req.adr(DRAM_ABITS+ROW_OFF_BITS-1 downto ROW_OFF_BITS);
ROW_OFF_BITS - wishbone_log2_width);
user_port0_cmd_we <= '1'; user_port0_cmd_we <= '1';
user_port0_cmd_valid <= storeq_wr_ready; user_port0_cmd_valid <= storeq_wr_ready;
else else

@ -102,8 +102,8 @@ entity litedram_core is
ddram_dq : inout std_ulogic_vector(15 downto 0); ddram_dq : inout std_ulogic_vector(15 downto 0);
ddram_dqs_p : inout std_ulogic_vector(1 downto 0); ddram_dqs_p : inout std_ulogic_vector(1 downto 0);
ddram_dqs_n : inout std_ulogic_vector(1 downto 0); ddram_dqs_n : inout std_ulogic_vector(1 downto 0);
ddram_clk_p : out std_ulogic_vector(0 downto 0); ddram_clk_p : out std_ulogic;
ddram_clk_n : out std_ulogic_vector(0 downto 0); ddram_clk_n : out std_ulogic;
ddram_cke : out std_ulogic; ddram_cke : out std_ulogic;
ddram_odt : out std_ulogic; ddram_odt : out std_ulogic;
ddram_reset_n : out std_ulogic; ddram_reset_n : out std_ulogic;

@ -3,11 +3,13 @@


{ {
# General ------------------------------------------------------------------ # General ------------------------------------------------------------------
"cpu": "None", # CPU type (ex vexriscv, serv, None) "cpu": "None", # Type of CPU used for init/calib (vexriscv, lm32)
"cpu_variant":"standard",
"speedgrade": -2, # FPGA speedgrade "speedgrade": -2, # FPGA speedgrade
"memtype": "DDR3", # DRAM type "memtype": "DDR3", # DRAM type


# PHY ---------------------------------------------------------------------- # PHY ----------------------------------------------------------------------
"cmd_delay": 0, # Command additional delay (in taps)
"cmd_latency": 0, # Command additional latency "cmd_latency": 0, # Command additional latency
"sdram_module": "MT41K512M16", # SDRAM modules of the board or SO-DIMM "sdram_module": "MT41K512M16", # SDRAM modules of the board or SO-DIMM
"sdram_module_nb": 2, # Number of byte groups "sdram_module_nb": 2, # Number of byte groups
@ -31,7 +33,10 @@
"user_ports": { "user_ports": {
"native_0": { "native_0": {
"type": "native", "type": "native",
"block_until_ready": False,
}, },
}, },

# CSR Port -----------------------------------------------------------------
"csr_alignment" : 32,
"csr_data_width" : 32,
} }

@ -3,11 +3,13 @@


{ {
# General ------------------------------------------------------------------ # General ------------------------------------------------------------------
"cpu": "None", # CPU type (ex vexriscv, serv, None) "cpu": "None", # Type of CPU used for init/calib (vexriscv, lm32)
"cpu_variant":"standard",
"speedgrade": -1, # FPGA speedgrade "speedgrade": -1, # FPGA speedgrade
"memtype": "DDR3", # DRAM type "memtype": "DDR3", # DRAM type


# PHY ---------------------------------------------------------------------- # PHY ----------------------------------------------------------------------
"cmd_delay": 0, # Command additional delay (in taps)
"cmd_latency": 0, # Command additional latency "cmd_latency": 0, # Command additional latency
"sdram_module": "MT41K128M16", # SDRAM modules of the board or SO-DIMM "sdram_module": "MT41K128M16", # SDRAM modules of the board or SO-DIMM
"sdram_module_nb": 2, # Number of byte groups "sdram_module_nb": 2, # Number of byte groups
@ -31,7 +33,10 @@
"user_ports": { "user_ports": {
"native_0": { "native_0": {
"type": "native", "type": "native",
"block_until_ready": False,
}, },
}, },

# CSR Port -----------------------------------------------------------------
"csr_alignment" : 32,
"csr_data_width" : 32,
} }

@ -100,7 +100,7 @@ begin
if rising_edge(clk) then if rising_edge(clk) then
oack <= '0'; oack <= '0';
if (wb_in.cyc and wb_in.stb) = '1' then if (wb_in.cyc and wb_in.stb) = '1' then
adr := to_integer((unsigned(wb_in.adr(INIT_RAM_ABITS - 3 downto 0)))); adr := to_integer((unsigned(wb_in.adr(INIT_RAM_ABITS-1 downto 2))));
if wb_in.we = '0' then if wb_in.we = '0' then
obuf <= init_ram(adr); obuf <= init_ram(adr);
else else

@ -1,10 +1,17 @@
#!/usr/bin/python3 #!/usr/bin/python3


from fusesoc.capi2.generator import Generator
from litex.build.tools import write_to_file from litex.build.tools import write_to_file
from litex.build.tools import replace_in_file from litex.build.tools import replace_in_file
from litex.build.generic_platform import *
from litex.build.xilinx import XilinxPlatform
from litex.build.lattice import LatticePlatform
from litex.soc.integration.builder import *
from litedram.gen import * from litedram.gen import *
import subprocess import subprocess
import os import os
import sys
import yaml
import shutil import shutil


def make_new_dir(base, added): def make_new_dir(base, added):
@ -21,6 +28,9 @@ gen_src_dir = os.path.join(base_dir, "gen-src")
gen_dir = make_new_dir(base_dir, "generated") gen_dir = make_new_dir(base_dir, "generated")


# Build the init code for microwatt-initialized DRAM # Build the init code for microwatt-initialized DRAM
#
# XXX Not working yet
#
def build_init_code(build_dir, is_sim): def build_init_code(build_dir, is_sim):


# More path fudging # More path fudging
@ -35,7 +45,7 @@ def build_init_code(build_dir, is_sim):
print(" lx src dir:", lxbios_src_dir) print(" lx src dir:", lxbios_src_dir)


# Generate mem.h (hard wire size, it's not important) # Generate mem.h (hard wire size, it's not important)
mem_h = "#define MAIN_RAM_BASE 0x40000000UL\n#define MAIN_RAM_SIZE 0x10000000UL\n" mem_h = "#define MAIN_RAM_BASE 0x40000000\n#define MAIN_RAM_SIZE 0x10000000"
write_to_file(os.path.join(gen_inc_dir, "mem.h"), mem_h) write_to_file(os.path.join(gen_inc_dir, "mem.h"), mem_h)


# Environment # Environment
@ -45,19 +55,18 @@ def build_init_code(build_dir, is_sim):
def add_var(k, v): def add_var(k, v):
env_vars.append("{}={}\n".format(k, _makefile_escape(v))) env_vars.append("{}={}\n".format(k, _makefile_escape(v)))


makefile = os.path.join(src_dir, "Makefile") add_var("BUILD_DIR", sw_dir)
cmd = ["make", "-C", build_dir, "-f", makefile] add_var("SRC_DIR", src_dir)
cmd.append("BUILD_DIR=%s" % sw_dir) add_var("GENINC_DIR", sw_inc_dir)
cmd.append("SRC_DIR=%s" % src_dir) add_var("LXSRC_DIR", lxbios_src_dir)
cmd.append("GENINC_DIR=%s" % sw_inc_dir)
cmd.append("LXSRC_DIR=%s" % lxbios_src_dir)

if is_sim: if is_sim:
cmd.append("EXTRA_CFLAGS=%s" % "-D__SIM__") add_var("EXTRA_CFLAGS", "-D__SIM__")
write_to_file(os.path.join(gen_inc_dir, "variables.mak"), "".join(env_vars))


# Build init code # Build init code
print(" Generating init software...") print(" Generating init software...")
r = subprocess.check_call(cmd) makefile = os.path.join(src_dir, "Makefile")
r = subprocess.check_call(["make", "-C", build_dir, "-I", gen_inc_dir, "-f", makefile])
print("Make result:", r) print("Make result:", r)


return os.path.join(sw_dir, "obj", "sdram_init.hex") return os.path.join(sw_dir, "obj", "sdram_init.hex")
@ -67,17 +76,48 @@ def generate_one(t):
print("Generating target:", t) print("Generating target:", t)


# Is it a simulation ? # Is it a simulation ?
is_sim = "sim" in t is_sim = t is "sim"


# Muck with directory path # Muck with directory path
build_dir = make_new_dir(build_top_dir, t) build_dir = make_new_dir(build_top_dir, t)
t_dir = make_new_dir(gen_dir, t) t_dir = make_new_dir(gen_dir, t)


cmd = ["litedram_gen", "--output-dir=%s" % build_dir] # Grab config file
cfile = os.path.join(gen_src_dir, t + ".yml")
core_config = yaml.load(open(cfile).read(), Loader=yaml.Loader)

### TODO: Make most stuff below a function in litedram gen.py and
### call it rather than duplicate it
###

# Convert YAML elements to Python/LiteX
for k, v in core_config.items():
replaces = {"False": False, "True": True, "None": None}
for r in replaces.keys():
if v == r:
core_config[k] = replaces[r]
if "clk_freq" in k:
core_config[k] = float(core_config[k])
if k == "sdram_module":
core_config[k] = getattr(litedram_modules, core_config[k])
if k == "sdram_phy":
core_config[k] = getattr(litedram_phys, core_config[k])

# Generate core
if is_sim: if is_sim:
cmd.append("--sim") platform = SimPlatform("", io=[])
cmd.append("%s.yml" % t) elif core_config["sdram_phy"] in [litedram_phys.ECP5DDRPHY]:
subprocess.check_call(cmd) platform = LatticePlatform("LFE5UM5G-45F-8BG381C", io=[], toolchain="trellis")
elif core_config["sdram_phy"] in [litedram_phys.A7DDRPHY, litedram_phys.K7DDRPHY, litedram_phys.V7DDRPHY]:
platform = XilinxPlatform("", io=[], toolchain="vivado")
else:
raise ValueError("Unsupported SDRAM PHY: {}".format(core_config["sdram_phy"]))

soc = LiteDRAMCore(platform, core_config, is_sim = is_sim, integrated_rom_size=0x6000)

# Build into build_dir
builder = Builder(soc, output_dir=build_dir, compile_gateware=False)
vns = builder.build(build_name="litedram_core", regular_comb=False)


# Grab generated gatewar dir # Grab generated gatewar dir
gw_dir = os.path.join(build_dir, "gateware") gw_dir = os.path.join(build_dir, "gateware")
@ -100,7 +140,7 @@ def generate_one(t):


def main(): def main():


targets = ['arty','nexys-video', 'genesys2', 'acorn-cle-215', 'wukong-v2', 'orangecrab-85-0.2', 'sim'] targets = ['arty','nexys-video', 'genesys2', 'acorn-cle-215', 'sim']
for t in targets: for t in targets:
generate_one(t) generate_one(t)

@ -3,7 +3,8 @@


{ {
# General ------------------------------------------------------------------ # General ------------------------------------------------------------------
"cpu": "None", # CPU type (ex vexriscv, serv, None) "cpu": "None", # Type of CPU used for init/calib (vexriscv, lm32)
"cpu_variant":"standard",
"speedgrade": -2, # FPGA speedgrade "speedgrade": -2, # FPGA speedgrade
"memtype": "DDR3", # DRAM type "memtype": "DDR3", # DRAM type


@ -12,12 +13,12 @@
"sdram_module": "MT41J256M16", # SDRAM modules of the board or SO-DIMM "sdram_module": "MT41J256M16", # SDRAM modules of the board or SO-DIMM
"sdram_module_nb": 4, # Number of byte groups "sdram_module_nb": 4, # Number of byte groups
"sdram_rank_nb": 1, # Number of ranks "sdram_rank_nb": 1, # Number of ranks
"sdram_phy": "K7DDRPHY", # Type of FPGA PHY "sdram_phy": K7DDRPHY, # Type of FPGA PHY


# Electrical --------------------------------------------------------------- # Electrical ---------------------------------------------------------------
"rtt_nom": "60ohm", # Nominal termination "rtt_nom": "60ohm", # Nominal termination
"rtt_wr": "60ohm", # Write termination "rtt_wr": "60ohm", # Write termination
"ron": "34ohm", # Output driver impedance "ron": "34ohm", # Output driver impedance


# Frequency ---------------------------------------------------------------- # Frequency ----------------------------------------------------------------
"input_clk_freq": 200e6, # Input clock frequency "input_clk_freq": 200e6, # Input clock frequency
@ -31,7 +32,10 @@
"user_ports": { "user_ports": {
"native_0": { "native_0": {
"type": "native", "type": "native",
"block_until_ready": False,
}, },
}, },

# CSR Port -----------------------------------------------------------------
"csr_alignment" : 32,
"csr_data_width" : 32,
} }

@ -3,11 +3,13 @@


{ {
# General ------------------------------------------------------------------ # General ------------------------------------------------------------------
"cpu": "None", # CPU type (ex vexriscv, serv, None) "cpu": "None", # Type of CPU used for init/calib (vexriscv, lm32)
"cpu_variant":"standard",
"speedgrade": -1, # FPGA speedgrade "speedgrade": -1, # FPGA speedgrade
"memtype": "DDR3", # DRAM type "memtype": "DDR3", # DRAM type


# PHY ---------------------------------------------------------------------- # PHY ----------------------------------------------------------------------
"cmd_delay": 0, # Command additional delay (in taps)
"cmd_latency": 0, # Command additional latency "cmd_latency": 0, # Command additional latency
"sdram_module": "MT41K256M16", # SDRAM modules of the board or SO-DIMM "sdram_module": "MT41K256M16", # SDRAM modules of the board or SO-DIMM
"sdram_module_nb": 2, # Number of byte groups "sdram_module_nb": 2, # Number of byte groups
@ -31,7 +33,10 @@
"user_ports": { "user_ports": {
"native_0": { "native_0": {
"type": "native", "type": "native",
"block_until_ready": False,
}, },
}, },

# CSR Port -----------------------------------------------------------------
"csr_alignment" : 32,
"csr_data_width" : 32,
} }

@ -1,39 +0,0 @@
# Matt Johnston 2021
# Based on parameters from Greg Davill's Orangecrab-test-sw

{
"cpu": "None", # CPU type (ex vexriscv, serv, None)
"device": "LFE5U-85F-8MG285C",
"memtype": "DDR3", # DRAM type

"sdram_module": "MT41K256M16", # SDRAM modules of the board or SO-DIMM
"sdram_module_nb": 2, # Number of byte groups
"sdram_rank_nb": 1, # Number of ranks
"sdram_phy": "ECP5DDRPHY", # Type of FPGA PHY

# Electrical ---------------------------------------------------------------
"rtt_nom": "disabled", # Nominal termination. ("disabled" from orangecrab)
"rtt_wr": "60ohm", # Write termination. (Default)
"ron": "34ohm", # Output driver impedance. (Default)

# Frequency ----------------------------------------------------------------
"init_clk_freq": 24e6,
"input_clk_freq": 48e6, # Input clock frequency
"sys_clk_freq": 48e6, # System clock frequency (DDR_clk = 4 x sys_clk)

# 0 if freq >64e6 else 100. https://github.com/enjoy-digital/litedram/issues/130
"cmd_delay": 100,

# Core ---------------------------------------------------------------------
"cmd_buffer_depth": 16, # Depth of the command buffer

"dm_swap": true,

# User Ports ---------------------------------------------------------------
"user_ports": {
"native_0": {
"type": "native",
"block_until_ready": False,
},
},
}

@ -1,5 +1,6 @@
#### Directories #### Directories


include variables.mak
OBJ = $(BUILD_DIR)/obj OBJ = $(BUILD_DIR)/obj


LXINC_DIR=$(LXSRC_DIR)/include LXINC_DIR=$(LXSRC_DIR)/include
@ -32,7 +33,6 @@ CPPFLAGS += -I$(LXSRC_DIR) -I$(LXINC_DIR) -I$(LXINC_DIR)/base -I$(LXSRC_DIR)/lib


CPPFLAGS += -isystem $(shell $(CC) -print-file-name=include) CPPFLAGS += -isystem $(shell $(CC) -print-file-name=include)
CFLAGS = -Os -g -Wall -std=c99 -m64 -mabi=elfv2 -msoft-float -mno-string -mno-multiple -mno-vsx -mno-altivec -mlittle-endian -fno-stack-protector -mstrict-align -ffreestanding -fdata-sections -ffunction-sections -fno-delete-null-pointer-checks CFLAGS = -Os -g -Wall -std=c99 -m64 -mabi=elfv2 -msoft-float -mno-string -mno-multiple -mno-vsx -mno-altivec -mlittle-endian -fno-stack-protector -mstrict-align -ffreestanding -fdata-sections -ffunction-sections -fno-delete-null-pointer-checks
CFLAGS += -Werror
ASFLAGS = $(CPPFLAGS) $(CFLAGS) ASFLAGS = $(CPPFLAGS) $(CFLAGS)
LDFLAGS = -static -nostdlib -T $(OBJ)/$(PROGRAM).lds --gc-sections LDFLAGS = -static -nostdlib -T $(OBJ)/$(PROGRAM).lds --gc-sections



@ -125,7 +125,7 @@ static bool check_flash(void)


/* Supported flash types for quad mode */ /* Supported flash types for quad mode */
if (id[0] == 0x01 && if (id[0] == 0x01 &&
(id[1] == 0x02 || id[1] == 0x20 || id[1] == 0x60) && (id[1] == 0x02 || id[1] == 0x20) &&
(id[2] == 0x18 || id[2] == 0x19)) { (id[2] == 0x18 || id[2] == 0x19)) {
check_spansion_quad_mode(); check_spansion_quad_mode();
quad = true; quad = true;
@ -262,8 +262,6 @@ uint64_t main(void)
printf("SPIFLASH "); printf("SPIFLASH ");
if (ftr & SYS_REG_INFO_HAS_LITEETH) if (ftr & SYS_REG_INFO_HAS_LITEETH)
printf("ETHERNET "); printf("ETHERNET ");
if (ftr & SYS_REG_INFO_HAS_LITESDCARD)
printf("SDCARD ");
printf("\n"); printf("\n");
if (ftr & SYS_REG_INFO_HAS_BRAM) { if (ftr & SYS_REG_INFO_HAS_BRAM) {
val = readq(SYSCON_BASE + SYS_REG_BRAMINFO) & SYS_REG_BRAMINFO_SIZE_MASK; val = readq(SYSCON_BASE + SYS_REG_BRAMINFO) & SYS_REG_BRAMINFO_SIZE_MASK;
@ -288,7 +286,7 @@ uint64_t main(void)
if (ftr & SYS_REG_INFO_HAS_DRAM) { if (ftr & SYS_REG_INFO_HAS_DRAM) {
printf("LiteDRAM built from Migen %s and LiteX %s\n", printf("LiteDRAM built from Migen %s and LiteX %s\n",
MIGEN_GIT_SHA1, LITEX_GIT_SHA1); MIGEN_GIT_SHA1, LITEX_GIT_SHA1);
sdram_init(); sdrinit();
} }
if (ftr & SYS_REG_INFO_HAS_BRAM) { if (ftr & SYS_REG_INFO_HAS_BRAM) {
printf("Booting from BRAM...\n"); printf("Booting from BRAM...\n");

@ -3,11 +3,14 @@


{ {
# General ------------------------------------------------------------------ # General ------------------------------------------------------------------
"cpu": "None", # CPU type (ex vexriscv, serv, None) "cpu": "None", # Type of CPU used for init/calib (vexriscv, lm32)
"cpu_variant":"standard",
"speedgrade": -1, # FPGA speedgrade "speedgrade": -1, # FPGA speedgrade
"memtype": "DDR3", # DRAM type "memtype": "DDR3", # DRAM type
"sim" : "True",


# PHY ---------------------------------------------------------------------- # PHY ----------------------------------------------------------------------
"cmd_delay": 0, # Command additional delay (in taps)
"cmd_latency": 0, # Command additional latency "cmd_latency": 0, # Command additional latency
"sdram_module": "MT41K128M16", # SDRAM modules of the board or SO-DIMM "sdram_module": "MT41K128M16", # SDRAM modules of the board or SO-DIMM
"sdram_module_nb": 2, # Number of byte groups "sdram_module_nb": 2, # Number of byte groups
@ -31,7 +34,10 @@
"user_ports": { "user_ports": {
"native_0": { "native_0": {
"type": "native", "type": "native",
"block_until_ready": False,
}, },
}, },

# CSR Port -----------------------------------------------------------------
"csr_alignment" : 32,
"csr_data_width" : 32,
} }

@ -1,37 +0,0 @@
# This file is Copyright (c) 2018-2019 Florent Kermarrec <florent@enjoy-digital.fr>
# License: BSD

{
# General ------------------------------------------------------------------
"cpu": "None", # CPU type (ex vexriscv, serv, None)
"speedgrade": -1, # FPGA speedgrade
"memtype": "DDR3", # DRAM type

# PHY ----------------------------------------------------------------------
"cmd_latency": 0, # Command additional latency
"sdram_module": "MT41K128M16", # SDRAM modules of the board or SO-DIMM
"sdram_module_nb": 2, # Number of byte groups
"sdram_rank_nb": 1, # Number of ranks
"sdram_phy": "A7DDRPHY", # Type of FPGA PHY

# Electrical ---------------------------------------------------------------
"rtt_nom": "60ohm", # Nominal termination
"rtt_wr": "60ohm", # Write termination
"ron": "34ohm", # Output driver impedance

# Frequency ----------------------------------------------------------------
"input_clk_freq": 50e6, # Input clock frequency
"sys_clk_freq": 100e6, # System clock frequency (DDR_clk = 4 x sys_clk)
"iodelay_clk_freq": 200e6, # IODELAYs reference clock frequency

# Core ---------------------------------------------------------------------
"cmd_buffer_depth": 16, # Depth of the command buffer

# User Ports ---------------------------------------------------------------
"user_ports": {
"native_0": {
"type": "native",
"block_until_ready": False,
},
},
}

@ -100,7 +100,7 @@ begin
if rising_edge(clk) then if rising_edge(clk) then
oack <= '0'; oack <= '0';
if (wb_in.cyc and wb_in.stb) = '1' then if (wb_in.cyc and wb_in.stb) = '1' then
adr := to_integer((unsigned(wb_in.adr(INIT_RAM_ABITS - 3 downto 0)))); adr := to_integer((unsigned(wb_in.adr(INIT_RAM_ABITS-1 downto 2))));
if wb_in.we = '0' then if wb_in.we = '0' then
obuf <= init_ram(adr); obuf <= init_ram(adr);
else else

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

@ -100,7 +100,7 @@ begin
if rising_edge(clk) then if rising_edge(clk) then
oack <= '0'; oack <= '0';
if (wb_in.cyc and wb_in.stb) = '1' then if (wb_in.cyc and wb_in.stb) = '1' then
adr := to_integer((unsigned(wb_in.adr(INIT_RAM_ABITS - 3 downto 0)))); adr := to_integer((unsigned(wb_in.adr(INIT_RAM_ABITS-1 downto 2))));
if wb_in.we = '0' then if wb_in.we = '0' then
obuf <= init_ram(adr); obuf <= init_ram(adr);
else else

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

@ -100,7 +100,7 @@ begin
if rising_edge(clk) then if rising_edge(clk) then
oack <= '0'; oack <= '0';
if (wb_in.cyc and wb_in.stb) = '1' then if (wb_in.cyc and wb_in.stb) = '1' then
adr := to_integer((unsigned(wb_in.adr(INIT_RAM_ABITS - 3 downto 0)))); adr := to_integer((unsigned(wb_in.adr(INIT_RAM_ABITS-1 downto 2))));
if wb_in.we = '0' then if wb_in.we = '0' then
obuf <= init_ram(adr); obuf <= init_ram(adr);
else else

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

@ -100,7 +100,7 @@ begin
if rising_edge(clk) then if rising_edge(clk) then
oack <= '0'; oack <= '0';
if (wb_in.cyc and wb_in.stb) = '1' then if (wb_in.cyc and wb_in.stb) = '1' then
adr := to_integer((unsigned(wb_in.adr(INIT_RAM_ABITS - 3 downto 0)))); adr := to_integer((unsigned(wb_in.adr(INIT_RAM_ABITS-1 downto 2))));
if wb_in.we = '0' then if wb_in.we = '0' then
obuf <= init_ram(adr); obuf <= init_ram(adr);
else else

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

@ -1,123 +0,0 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.textio.all;

library work;
use work.wishbone_types.all;
use work.utils.all;

entity dram_init_mem is
generic (
EXTRA_PAYLOAD_FILE : string := "";
EXTRA_PAYLOAD_SIZE : integer := 0
);
port (
clk : in std_ulogic;
wb_in : in wb_io_master_out;
wb_out : out wb_io_slave_out
);
end entity dram_init_mem;

architecture rtl of dram_init_mem is

constant INIT_RAM_SIZE : integer := 24576;
constant RND_PAYLOAD_SIZE : integer := round_up(EXTRA_PAYLOAD_SIZE, 8);
constant TOTAL_RAM_SIZE : integer := INIT_RAM_SIZE + RND_PAYLOAD_SIZE;
constant INIT_RAM_ABITS : integer := log2ceil(TOTAL_RAM_SIZE-1);
constant INIT_RAM_FILE : string := "litedram_core.init";

type ram_t is array(0 to (TOTAL_RAM_SIZE / 4) - 1) of std_logic_vector(31 downto 0);

-- XXX FIXME: Have a single init function called twice with
-- an offset as argument
procedure init_load_payload(ram: inout ram_t; filename: string) is
file payload_file : text open read_mode is filename;
variable ram_line : line;
variable temp_word : std_logic_vector(63 downto 0);
begin
for i in 0 to RND_PAYLOAD_SIZE-1 loop
exit when endfile(payload_file);
readline(payload_file, ram_line);
hread(ram_line, temp_word);
ram((INIT_RAM_SIZE/4) + i*2) := temp_word(31 downto 0);
ram((INIT_RAM_SIZE/4) + i*2+1) := temp_word(63 downto 32);
end loop;
assert endfile(payload_file) report "Payload too big !" severity failure;
end procedure;

impure function init_load_ram(name : string) return ram_t is
file ram_file : text open read_mode is name;
variable temp_word : std_logic_vector(63 downto 0);
variable temp_ram : ram_t := (others => (others => '0'));
variable ram_line : line;
begin
report "Payload size:" & integer'image(EXTRA_PAYLOAD_SIZE) &
" rounded to:" & integer'image(RND_PAYLOAD_SIZE);
report "Total RAM size:" & integer'image(TOTAL_RAM_SIZE) &
" bytes using " & integer'image(INIT_RAM_ABITS) &
" address bits";
for i in 0 to (INIT_RAM_SIZE/8)-1 loop
exit when endfile(ram_file);
readline(ram_file, ram_line);
hread(ram_line, temp_word);
temp_ram(i*2) := temp_word(31 downto 0);
temp_ram(i*2+1) := temp_word(63 downto 32);
end loop;
if RND_PAYLOAD_SIZE /= 0 then
init_load_payload(temp_ram, EXTRA_PAYLOAD_FILE);
end if;
return temp_ram;
end function;

impure function init_zero return ram_t is
variable temp_ram : ram_t := (others => (others => '0'));
begin
return temp_ram;
end function;

impure function initialize_ram(filename: string) return ram_t is
begin
report "Opening file " & filename;
if filename'length = 0 then
return init_zero;
else
return init_load_ram(filename);
end if;
end function;
signal init_ram : ram_t := initialize_ram(INIT_RAM_FILE);

attribute ram_style : string;
attribute ram_style of init_ram: signal is "block";

signal obuf : std_ulogic_vector(31 downto 0);
signal oack : std_ulogic;
begin

init_ram_0: process(clk)
variable adr : integer;
begin
if rising_edge(clk) then
oack <= '0';
if (wb_in.cyc and wb_in.stb) = '1' then
adr := to_integer((unsigned(wb_in.adr(INIT_RAM_ABITS - 3 downto 0))));
if wb_in.we = '0' then
obuf <= init_ram(adr);
else
for i in 0 to 3 loop
if wb_in.sel(i) = '1' then
init_ram(adr)(((i + 1) * 8) - 1 downto i * 8) <=
wb_in.dat(((i + 1) * 8) - 1 downto i * 8);
end if;
end loop;
end if;
oack <= '1';
end if;
wb_out.ack <= oack;
wb_out.dat <= obuf;
end if;
end process;

wb_out.stall <= '0';

end architecture rtl;

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

@ -100,7 +100,7 @@ begin
if rising_edge(clk) then if rising_edge(clk) then
oack <= '0'; oack <= '0';
if (wb_in.cyc and wb_in.stb) = '1' then if (wb_in.cyc and wb_in.stb) = '1' then
adr := to_integer((unsigned(wb_in.adr(INIT_RAM_ABITS - 3 downto 0)))); adr := to_integer((unsigned(wb_in.adr(INIT_RAM_ABITS-1 downto 2))));
if wb_in.we = '0' then if wb_in.we = '0' then
obuf <= init_ram(adr); obuf <= init_ram(adr);
else else

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

@ -1,123 +0,0 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.textio.all;

library work;
use work.wishbone_types.all;
use work.utils.all;

entity dram_init_mem is
generic (
EXTRA_PAYLOAD_FILE : string := "";
EXTRA_PAYLOAD_SIZE : integer := 0
);
port (
clk : in std_ulogic;
wb_in : in wb_io_master_out;
wb_out : out wb_io_slave_out
);
end entity dram_init_mem;

architecture rtl of dram_init_mem is

constant INIT_RAM_SIZE : integer := 24576;
constant RND_PAYLOAD_SIZE : integer := round_up(EXTRA_PAYLOAD_SIZE, 8);
constant TOTAL_RAM_SIZE : integer := INIT_RAM_SIZE + RND_PAYLOAD_SIZE;
constant INIT_RAM_ABITS : integer := log2ceil(TOTAL_RAM_SIZE-1);
constant INIT_RAM_FILE : string := "litedram_core.init";

type ram_t is array(0 to (TOTAL_RAM_SIZE / 4) - 1) of std_logic_vector(31 downto 0);

-- XXX FIXME: Have a single init function called twice with
-- an offset as argument
procedure init_load_payload(ram: inout ram_t; filename: string) is
file payload_file : text open read_mode is filename;
variable ram_line : line;
variable temp_word : std_logic_vector(63 downto 0);
begin
for i in 0 to RND_PAYLOAD_SIZE-1 loop
exit when endfile(payload_file);
readline(payload_file, ram_line);
hread(ram_line, temp_word);
ram((INIT_RAM_SIZE/4) + i*2) := temp_word(31 downto 0);
ram((INIT_RAM_SIZE/4) + i*2+1) := temp_word(63 downto 32);
end loop;
assert endfile(payload_file) report "Payload too big !" severity failure;
end procedure;

impure function init_load_ram(name : string) return ram_t is
file ram_file : text open read_mode is name;
variable temp_word : std_logic_vector(63 downto 0);
variable temp_ram : ram_t := (others => (others => '0'));
variable ram_line : line;
begin
report "Payload size:" & integer'image(EXTRA_PAYLOAD_SIZE) &
" rounded to:" & integer'image(RND_PAYLOAD_SIZE);
report "Total RAM size:" & integer'image(TOTAL_RAM_SIZE) &
" bytes using " & integer'image(INIT_RAM_ABITS) &
" address bits";
for i in 0 to (INIT_RAM_SIZE/8)-1 loop
exit when endfile(ram_file);
readline(ram_file, ram_line);
hread(ram_line, temp_word);
temp_ram(i*2) := temp_word(31 downto 0);
temp_ram(i*2+1) := temp_word(63 downto 32);
end loop;
if RND_PAYLOAD_SIZE /= 0 then
init_load_payload(temp_ram, EXTRA_PAYLOAD_FILE);
end if;
return temp_ram;
end function;

impure function init_zero return ram_t is
variable temp_ram : ram_t := (others => (others => '0'));
begin
return temp_ram;
end function;

impure function initialize_ram(filename: string) return ram_t is
begin
report "Opening file " & filename;
if filename'length = 0 then
return init_zero;
else
return init_load_ram(filename);
end if;
end function;
signal init_ram : ram_t := initialize_ram(INIT_RAM_FILE);

attribute ram_style : string;
attribute ram_style of init_ram: signal is "block";

signal obuf : std_ulogic_vector(31 downto 0);
signal oack : std_ulogic;
begin

init_ram_0: process(clk)
variable adr : integer;
begin
if rising_edge(clk) then
oack <= '0';
if (wb_in.cyc and wb_in.stb) = '1' then
adr := to_integer((unsigned(wb_in.adr(INIT_RAM_ABITS - 3 downto 0))));
if wb_in.we = '0' then
obuf <= init_ram(adr);
else
for i in 0 to 3 loop
if wb_in.sel(i) = '1' then
init_ram(adr)(((i + 1) * 8) - 1 downto i * 8) <=
wb_in.dat(((i + 1) * 8) - 1 downto i * 8);
end if;
end loop;
end if;
oack <= '1';
end if;
wb_out.ack <= oack;
wb_out.dat <= obuf;
end if;
end process;

wb_out.stall <= '0';

end architecture rtl;

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

@ -8,9 +8,8 @@ vendor: xilinx
clk_freq: 100e6 clk_freq: 100e6
core: wishbone core: wishbone
endianness: little endianness: little
ntxslots: 2
nrxslots: 2


soc: soc:
mem_map: mem_map:
ethmac: 0x00010000 ethmac: 0x00010000
csr_data_width: 32

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash


TARGETS="arty nexys-video wukong-v2" TARGETS=arty


ME=$(realpath $0) ME=$(realpath $0)
echo ME=$ME echo ME=$ME

@ -1,16 +0,0 @@
# This file is Copyright (c) 2020 Florent Kermarrec <florent@enjoy-digital.fr>
# License: BSD

# PHY ----------------------------------------------------------------------
phy: LiteEthS7PHYRGMII
vendor: xilinx
# Core ---------------------------------------------------------------------
clk_freq: 125e6
core: wishbone
endianness: little
ntxslots: 2
nrxslots: 2

soc:
mem_map:
ethmac: 0x00010000

@ -1,17 +0,0 @@
# This file is Copyright (c) 2020 Florent Kermarrec <florent@enjoy-digital.fr>
# License: BSD

# PHY ----------------------------------------------------------------------
phy: LiteEthPHYGMIIMII
vendor: xilinx
device: xc7
# Core ---------------------------------------------------------------------
clk_freq: 100e6
core: wishbone
endianness: little
ntxslots: 2
nrxslots: 2

soc:
mem_map:
ethmac: 0x00010000

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save