Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ec57dcbe66 |
Vendored
+100
@@ -0,0 +1,100 @@
|
||||
-----------------------------------------------------------------
|
||||
Changes in release 13
|
||||
-----------------------------------------------------------------
|
||||
- mips_biu.vhd: added asynchronous BUS-FIFOs to support different clocks for CPU and BUS
|
||||
- mips_dcache.vhd: improved instant-RAW stall behavior (faster execution)
|
||||
- uart_WB.vhd: added simulate_TX generic for plain TX output in simulation log
|
||||
|
||||
-----------------------------------------------------------------
|
||||
Changes in release 12
|
||||
-----------------------------------------------------------------
|
||||
- reworked GCC-toolchain: Valid mips*-elf-binaries are now compiled and linked
|
||||
using a single mips*-elf-gcc command.
|
||||
To use: Copy $THIS_RELEASE/bsp/toolchain/specs to $MIPS_GCC_PREFIX/lib/gcc/mipsel-elf/$GCC_VERSION/,
|
||||
and see bsp/examples/Makefile gcc usage
|
||||
GCC-provided crt*-functions are now called without problems.
|
||||
In summary: The toolchain is now more compliant to the intentional use of GCC.
|
||||
- mips_biu.vhd: Addresses 0xA0000000..0xBFFFFFFF are now un-dcached for memory-mapped I/O,
|
||||
which is now compliant to literature.
|
||||
- gpio_wb.vhd: Timer hard-reset is now removed. This helps to keep current time in case of CPU hard-reset.
|
||||
- new bsp-example source: gunzip
|
||||
- updated drawing 'mips_jbus_timing.pdf'
|
||||
- added drawing 'memory_map.pdf'
|
||||
- moved COP0 from mips_pipeline.vhd to mips_top.vhd. Created new cop-interface for later COPz connection.
|
||||
- added I/D-cache info (size and linesize) to upper 16 bits of PrID-Register.
|
||||
Example of reading cache info is done in bsp/examples/testbench::PrintCPUinfo()
|
||||
- simplified instruction decoder in mips_instr.vhd. Now there are less warnings during synthesis.
|
||||
Removed idecode_rom.vhd from project as consequence.
|
||||
- added cop0 instructions to invalidate I-cache and D-Cache
|
||||
- added copz instructions lwcz and swcz
|
||||
- gpio_wb.vhd: added 32 bit timer with interrupt and auto reload
|
||||
- added debugger in libsys. New files are mipsdis.c/h and dbg.c/h
|
||||
- exception handlers can now be registered to any exception type
|
||||
- bugfix mips_pipeline/mips_cop: cop0 registers were not written during exception commit. Cop registers now behave like general registers.
|
||||
- added pin 'eb' to mips_top.vhd to select CPU-endianess at reset time (eb = 0 : little-endian, eb = 1 : big-endian)
|
||||
- Status register bit 'RE'= 1 (bit 25) reverses endianess in user-mode
|
||||
- Status register bit 'TS' (TLB Shutdown, bit 21) is tied high to indicate the absence of an MMU.
|
||||
- uart_wb.vhd: added interrupt enable
|
||||
- Interrupt pending flags (IP) are not anymore masked by Interrupt mask flags (IM) in H/W.
|
||||
Masking has to be done in S/W. H/W masking was removed because it isn't MIPS-compliant.
|
||||
- added NMI/RST pin (more MIPS compliant). Transition Asserting/Deasserting causes exception.
|
||||
Exception vector is reset (0xBFC00000). It's a soft-reset, which can help debugging. NMI/RST is not maskable.
|
||||
Using NMI/RST as reset is dangerous because periphery may not be reseted. Has to be done in S/W.
|
||||
Drawback of using NMI/RST: Unitialized/unreseted periphery may cause trouble (e.g. firing unwanted interrupts), but I think you know that already.
|
||||
- Bootloader: Startup.S now invalidates I/D-Caches at boot.
|
||||
- uart_wb.vhd: fixed crappy tx-empty interrupt, Added Tx-IRQ acknowledge.
|
||||
- Bugfix in mips_pipeline: register bypass with same target register, used for unaligned loads (LWL, LWR), was incorrect.
|
||||
Newlib's MIPS-optimized version of memcpy() uses this for unaligned copy which revealed the bug.
|
||||
Symptom: Consecutive load instructions without nops using same target register (which is legal) like
|
||||
lw $1, 0(mem)
|
||||
lwl $1, 1(mem)
|
||||
or
|
||||
lwl $1, 0(mem)
|
||||
lwr $1, 1(mem)
|
||||
or similar, lead to incorrect result. Now it's fixed.
|
||||
- Bugfix mips_biu: instructions uncached LW => cached LW (with cache-miss) was buggy.
|
||||
Symptom:
|
||||
...
|
||||
1.: lw $a0, 32($s0) # Uncached load from memory mapped I/O
|
||||
2.: lw $a2, 4($v0) # Cached load and cache-miss.
|
||||
# $a0 receives same value as $a2.
|
||||
# CPU skips writing $a0 due to busy flag of D-Cache,
|
||||
# which is already active in the previous cycle
|
||||
...
|
||||
|
||||
-----------------------------------------------------------------
|
||||
Changes in release 11
|
||||
-----------------------------------------------------------------
|
||||
- bugfix in mips_pipeline: pc_is_branch is now initialized at reset
|
||||
(fixes CPU unrecoverable state after reset)
|
||||
- reverted "optimization" in mips_dcache, which behaved buggy during exceptions
|
||||
- new example source: test_exception
|
||||
- minor changes in libsys
|
||||
- added async_port_timing in doc
|
||||
- examples/testbench: date set now really works
|
||||
|
||||
-----------------------------------------------------------------
|
||||
Changes in release 10b
|
||||
-----------------------------------------------------------------
|
||||
- bugfix: fixed compiler bug (missing nop after lw) in bootloader,
|
||||
which caused exception during boot
|
||||
|
||||
-----------------------------------------------------------------
|
||||
Changes in release 10a
|
||||
-----------------------------------------------------------------
|
||||
async_port_wb:
|
||||
- added byte enable for async_port
|
||||
|
||||
bootloader.c
|
||||
- bugfix: fixed compiler bug (missing nop after lw)
|
||||
|
||||
mips-core
|
||||
- bugfix: SEL_O lines are also asserted correctly during reads
|
||||
|
||||
tools/romgen
|
||||
- TCL-Jtag now compatible with Chipscope 10.1
|
||||
|
||||
mips_sys.c
|
||||
- use byte enable for sram and flash
|
||||
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
-----------------------------------------------------------------
|
||||
J-MIPS Features
|
||||
-----------------------------------------------------------------
|
||||
|
||||
- Synchrones Design
|
||||
- Portable Beschreibung in VHDL
|
||||
- Kompatible zur GNU Toolchain (Binutils, GCC, Newlib)
|
||||
- Befehle kompatibel mit MIPS-1 ISA (z.B. MIPS R3000)
|
||||
- 5-Stufige Pipeline und Hazardvermeidung durch Forwarding
|
||||
- 64Bit Multiplier (32Bit Operanden), 12 Cycles Latenz
|
||||
- 64Bit Divider (32Bit Operanden), 36 Cycles Latenz
|
||||
- Coprocessor 0 (COP0) für Exceptionhandling
|
||||
- Direct-mapped Instruction Cache mit variabler Größe, 8-words per Line
|
||||
- Direct-mapped Data Cache mit variabler Größe, 8-words per Line
|
||||
- J-Bus kompatible Bus Interface Unit (J-Bus ist im wesentlichen FIFO interface mit 'wichtigen' Signalnamen)
|
||||
- 1,2 DMIPS/MHz mit 16Kbyte I/D-Cache (Dhrystone 2.1, GCC 4.3)
|
||||
- Endianness umschaltbar zur Hard-reset Zeit
|
||||
- Unterschiedliche Frequenzen für CPU und BUS möglich
|
||||
|
||||
-----------------------------------------------------------------
|
||||
Known Limitations
|
||||
-----------------------------------------------------------------
|
||||
- keine MMU
|
||||
- keine Unterstützung für Bus exceptions IBE und DBE
|
||||
- kein externes Coprocessor interface (COP1..3) für z.B. FPU
|
||||
- Befehle für Cop1..3 nicht implementiert:
|
||||
CFCz, CTCz, COPz, MFCz, MTCz, LWCz, SWCz
|
||||
Benutzung dieser Befehle führt zur Exception 'RI' (Reserved Instruction)
|
||||
- nicht alle COP0 Register/Bits vorhanden.
|
||||
|
||||
-----------------------------------------------------------------
|
||||
Known Bugs
|
||||
-----------------------------------------------------------------
|
||||
- es gibt bestimmt noch nicht entdeckte Bugs
|
||||
|
||||
-----------------------------------------------------------------
|
||||
Known Optimizations
|
||||
-----------------------------------------------------------------
|
||||
- Area: Multiplier als technologieabhängiges Primitive instanzieren
|
||||
- Area: Auf Divider verzichten
|
||||
- Area: Auf Multiplier verzichten
|
||||
- Area vs. Speed: Bei Hazards Pipeline-stall statt Forwarding.
|
||||
Durch Stalling geringerer Befehlsdurchsatz dafür weniger Logik.
|
||||
Weniger Logik bedeutet vielleicht wieder auch größere Taktfrequenz.
|
||||
|
||||
-----------------------------------------------------------------
|
||||
Known ToDos
|
||||
-----------------------------------------------------------------
|
||||
- Unterstützung für Bus exceptions IBE und DBE
|
||||
- Externes COP1..3 interface, fehlende COP-Befehle implementieren
|
||||
- Optimierungen evaluieren und ggf. durchführen
|
||||
|
||||
-----------------------------------------------------------------
|
||||
Synthesis results
|
||||
-----------------------------------------------------------------
|
||||
Virtex-4 XC4VSX35-10
|
||||
|
||||
Config: 16Kbyte I/D-Cache
|
||||
|
||||
Number of Slices 2387 15360 15%
|
||||
Number of Slice Flip Flops 1784 30720 5%
|
||||
Number of 4 input LUTs 3962 30720 12%
|
||||
Number of FIFO16/RAMB16s 18 192 9%
|
||||
|
||||
Speed: 110MHz nach Synthesis
|
||||
|
||||
-----------------------------------------------------------------
|
||||
Virtex-1 XCV1000-4
|
||||
|
||||
Config: 4Kbyte I/D-Cache
|
||||
|
||||
Number of Slices 2045 13824 16%
|
||||
Number of Slice Flip Flops 1783 27648 7%
|
||||
Number of 4 input LUTs 3923 27648 15%
|
||||
Number of FIFO16/RAMB16s 20 32 62%
|
||||
|
||||
Speed: 30MHz nach Synthesis
|
||||
|
||||
-----------------------------------------------------------------
|
||||
Performance bei 100MHz
|
||||
- GCC ohne Small-data section
|
||||
- MIPS Rev. 9
|
||||
-----------------------------------------------------------------
|
||||
I/D-Cache Dhrystone-2.1 RipeMD-160 Whetstone Stanford Queens(12x12)
|
||||
1k 32 DMIPS 5 Mbit/s 345 kwhets/s 47/767 2,135s
|
||||
2k 51 DMIPS 5 Mbit/s 534 kwhets/s 38/561 2,134s
|
||||
4k 72 DMIPS 5 Mbit/s 623 kwhets/s 36/259 2,121s
|
||||
8k 98 DMIPS 10 Mbit/s 1149 kwhets/s 31/228 1,938s
|
||||
16k 115 DMIPS 17 Mbit/s 1234 kwhets/s 23/225 1,938s
|
||||
32k 115 DMIPS 17 Mbit/s 1285 kwhets/s 24/218 1,938s
|
||||
64k 115 DMIPS 17 Mbit/s 1285 kwhets/s 20/221 1,938s
|
||||
|
||||
-----------------------------------------------------------------
|
||||
Performance bei 100MHz
|
||||
- GCC mit Small-data section
|
||||
- MIPS Rev. 9
|
||||
-----------------------------------------------------------------
|
||||
I/D-Cache Dhrystone-2.1 RipeMD-160 Whetstone Stanford Queens(12x12)
|
||||
16k 117 DMIPS 17 Mbit/s 1236 kwhets/s 24/230 1,811s
|
||||
|
||||
-----------------------------------------------------------------
|
||||
Performance bei 100MHz
|
||||
- GCC mit Small-data section
|
||||
- MIPS Rev. 10
|
||||
-----------------------------------------------------------------
|
||||
I/D-Cache Dhrystone-2.1 RipeMD-160 Whetstone Stanford Queens(12x12)
|
||||
16k 120 DMIPS 17 Mbit/s 1242 kwhets/s 25/219 1,803s
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,46 @@
|
||||
# ---------------------------------------------------------------
|
||||
# 1. Binutils bauen und installieren
|
||||
# ---------------------------------------------------------------
|
||||
> tar -xzf binutils-2.19.tar.gz
|
||||
> mkdir binutils-2.19_build
|
||||
> cd binutils-2.19_build
|
||||
|
||||
> ../binutils-2.19/configure --target=mipsel-elf --prefix=/usr/local
|
||||
> make
|
||||
> make install
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
# 2. GCC bootstrapping
|
||||
# ---------------------------------------------------------------
|
||||
> tar -xzf gcc-4.3.2.tar.gz
|
||||
> mkdir gcc-4.3.2_build
|
||||
> cd gcc-4.3.2_build
|
||||
> ../gcc-4.3.2/configure --target=mipsel-elf --prefix=/usr/local --enable-languages="c,c++" --without-headers --with-newlib --with-float=soft --disable-multilib
|
||||
> CFLAGS_FOR_TARGET="-mno-gpopt" make all-gcc
|
||||
> make info-gcc
|
||||
> make install-gcc
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
# 3. Newlib bauen und installieren
|
||||
# ---------------------------------------------------------------
|
||||
> tar -xzf newlib-1.16.0.tar.gz
|
||||
! Bug in newlib-1.16.0/newlib/libc/machine/mips/strlen.c.
|
||||
Newlib von Hand patchen (32-bit MIPS targets):
|
||||
"lbu $3,0($4)\n"
|
||||
"nop\n" <= nop einfügen
|
||||
"bnez $3,1b\n"
|
||||
|
||||
> mkdir newlib-1.16.0_build
|
||||
> cd newlib-1.16.0_build
|
||||
> ../newlib-1.16.0/configure --target=mipsel-elf --prefix=/usr/local --with-float=soft --disable-multilib
|
||||
> TARGET_CFLAGS="-mno-gpopt" make all
|
||||
> make install
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
# 4. GCC bauen und installieren
|
||||
# ---------------------------------------------------------------
|
||||
> cd gcc-4.3.2_build
|
||||
> ../gcc-4.3.2/configure --target=mipsel-elf --prefix=/usr/local --enable-languages="c,c++" --disable-shared --with-newlib --with-float=soft --disable-multilib
|
||||
> CFLAGS_FOR_TARGET="-mno-gpopt" make all
|
||||
> make info
|
||||
> make install
|
||||
@@ -0,0 +1,151 @@
|
||||
#!/bin/sh
|
||||
TARGET=mipsel-elf
|
||||
PREFIX=/usr/local
|
||||
|
||||
SRC_BINUTILS=binutils-2.19
|
||||
SRC_GCC=gcc-4.3.3
|
||||
SRC_NEWLIB=newlib-1.16.0
|
||||
SRC_GMP=gmp-4.2.4
|
||||
SRC_MPFR=mpfr-2.4.0
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
# 1. Binutils bauen und installieren
|
||||
# ---------------------------------------------------------------
|
||||
if [ ! -e $SRC_BINUTILS.tar.bz2 ]; then
|
||||
echo Downloading $SRC_BINUTILS
|
||||
wget ftp://ftp-stud.fht-esslingen.de/pub/Mirrors/ftp.gnu.org/binutils/$SRC_BINUTILS.tar.bz2 || exit 1
|
||||
else
|
||||
echo Skipped downloading $SRC_BINUTILS
|
||||
fi
|
||||
|
||||
if [ ! -e ./$SRC_BINUTILS ]; then
|
||||
echo Unpacking $SRC_BINUTILS
|
||||
tar -xjf $SRC_BINUTILS.tar.bz2 || exit 1
|
||||
else
|
||||
echo Skipped unpacking $SRC_BINUTILS
|
||||
fi
|
||||
|
||||
if [ ! -e ./$SRC_BINUTILS-build ]; then
|
||||
echo Building $SRC_BINUTILS
|
||||
mkdir -p $SRC_BINUTILS-build
|
||||
cd $SRC_BINUTILS-build
|
||||
../$SRC_BINUTILS/configure --target=$TARGET --prefix=$PREFIX || exit 1
|
||||
make || exit 1
|
||||
make install || exit 1
|
||||
cd ..
|
||||
else
|
||||
echo $SRC_BINUTILS is already built.
|
||||
fi
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
# 2. GMP bauen und installieren
|
||||
# ---------------------------------------------------------------
|
||||
if [ ! -e $SRC_GMP.tar.bz2 ]; then
|
||||
echo Downloading $SRC_GMP
|
||||
wget http://ftp.sunet.se/pub/gnu/gmp/$SRC_GMP.tar.bz2 || exit 1
|
||||
else
|
||||
echo Skipped downloading $SRC_GMP
|
||||
fi
|
||||
|
||||
if [ ! -e ./$SRC_GMP ]; then
|
||||
echo Unpacking $SRC_GMP
|
||||
tar -xjf $SRC_GMP.tar.bz2 || exit 1
|
||||
else
|
||||
echo Skipped unpacking $SRC_GMP
|
||||
fi
|
||||
|
||||
if [ ! -e ./$SRC_GMP-build ]; then
|
||||
echo Building $SRC_GMP
|
||||
mkdir -p $SRC_GMP-build
|
||||
cd $SRC_GMP-build
|
||||
../$SRC_GMP/configure --prefix=$PREFIX || exit 1
|
||||
make || exit 1
|
||||
make check || exit 1
|
||||
make install || exit 1
|
||||
cd ..
|
||||
else
|
||||
echo $SRC_GMP is already built.
|
||||
fi
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
# 3. MPFR bauen und installieren
|
||||
# ---------------------------------------------------------------
|
||||
if [ ! -e $SRC_MPFR.tar.bz2 ]; then
|
||||
echo Downloading $SRC_MPFR
|
||||
wget http://www.mpfr.org/mpfr-current/$SRC_MPFR.tar.bz2 || exit 1
|
||||
else
|
||||
echo Skipped downloading $SRC_MPFR
|
||||
fi
|
||||
|
||||
if [ ! -e ./$SRC_MPFR ]; then
|
||||
echo Unpacking $SRC_MPFR
|
||||
tar -xjf $SRC_MPFR.tar.bz2 || exit 1
|
||||
else
|
||||
echo Skipped unpacking $SRC_MPFR
|
||||
fi
|
||||
|
||||
if [ ! -e ./$SRC_MPFR-build ]; then
|
||||
echo Building $SRC_MPFR
|
||||
mkdir -p $SRC_MPFR-build
|
||||
cd $SRC_MPFR-build
|
||||
../$SRC_MPFR/configure --prefix=$PREFIX || exit 1
|
||||
make || exit 1
|
||||
make check || exit 1
|
||||
make install || exit 1
|
||||
cd ..
|
||||
else
|
||||
echo $SRC_MPFR is already built.
|
||||
fi
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
# 4. GCC & newlib bauen und installieren
|
||||
# ---------------------------------------------------------------
|
||||
if [ ! -e $SRC_NEWLIB.tar.gz ]; then
|
||||
echo Downloading $SRC_NEWLIB
|
||||
wget ftp://sources.redhat.com/pub/newlib/$SRC_NEWLIB.tar.gz || exit 1
|
||||
else
|
||||
echo Skipped downloading $SRC_NEWLIB
|
||||
fi
|
||||
|
||||
if [ ! -e ./$SRC_NEWLIB ]; then
|
||||
echo Unpacking $SRC_NEWLIB
|
||||
tar -xzf $SRC_NEWLIB.tar.gz || exit 1
|
||||
if [ -e $SRC_NEWLIB-jens.patch ]; then
|
||||
echo Patching $SRC_NEWLIB
|
||||
patch -p0 < $SRC_NEWLIB-jens.patch || exit 1
|
||||
fi
|
||||
else
|
||||
echo Skipped unpacking $SRC_NEWLIB
|
||||
fi
|
||||
|
||||
if [ ! -e $SRC_GCC.tar.bz2 ]; then
|
||||
echo Downloading $SRC_GCC
|
||||
wget ftp://ftp-stud.fht-esslingen.de/pub/Mirrors/ftp.gnu.org/gcc/$SRC_GCC/$SRC_GCC.tar.bz2 || exit 1
|
||||
else
|
||||
echo Skipped downloading $SRC_GCC
|
||||
fi
|
||||
|
||||
if [ ! -e ./$SRC_GCC ]; then
|
||||
echo Unpacking $SRC_GCC
|
||||
tar -xjf $SRC_GCC.tar.bz2 || exit 1
|
||||
cd ./$SRC_GCC
|
||||
ln -sf ../$SRC_NEWLIB/newlib/ .
|
||||
cd ..
|
||||
else
|
||||
echo Skipped unpacking $SRC_GCC
|
||||
fi
|
||||
|
||||
if [ ! -e ./$SRC_GCC-build ]; then
|
||||
echo Building $SRC_GCC
|
||||
mkdir -p $SRC_GCC-build
|
||||
cd $SRC_GCC-build
|
||||
../$SRC_GCC/configure --target=$TARGET --prefix=$PREFIX --with-float=soft --with-newlib --verbose --enable-languages="c,c++" || exit 1
|
||||
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PREFIX/lib make all || exit 1
|
||||
make info || exit 1
|
||||
make install || exit 1
|
||||
cd ..
|
||||
echo $PREFIX/lib >/etc/ld.so.conf.d/local.conf
|
||||
ldconfig
|
||||
else
|
||||
echo $SRC_GCC is already built.
|
||||
fi
|
||||
@@ -0,0 +1,11 @@
|
||||
diff -Naur newlib-1.16.0/newlib/libc/machine/mips/strlen.c newlib-1.16.0-fixed/newlib/libc/machine/mips/strlen.c
|
||||
--- newlib-1.16.0/newlib/libc/machine/mips/strlen.c 2002-03-14 03:41:43.000000000 +0100
|
||||
+++ newlib-1.16.0-fixed/newlib/libc/machine/mips/strlen.c 2009-02-14 15:52:58.000000000 +0100
|
||||
@@ -60,6 +60,7 @@
|
||||
" addiu $2,$4,1\n"
|
||||
"\n"
|
||||
"1: lbu $3,0($4)\n"
|
||||
+ " nop\n"
|
||||
" bnez $3,1b\n"
|
||||
" addiu $4,$4,1\n"
|
||||
"\n"
|
||||
@@ -0,0 +1,11 @@
|
||||
diff -Naur newlib-1.17.0/newlib/libc/machine/mips/strlen.c newlib-1.17.0-fixed/newlib/libc/machine/mips/strlen.c
|
||||
--- newlib-1.17.0/newlib/libc/machine/mips/strlen.c 2002-03-14 03:41:43.000000000 +0100
|
||||
+++ newlib-1.17.0-fixed/newlib/libc/machine/mips/strlen.c 2009-02-14 15:45:19.000000000 +0100
|
||||
@@ -60,6 +60,7 @@
|
||||
" addiu $2,$4,1\n"
|
||||
"\n"
|
||||
"1: lbu $3,0($4)\n"
|
||||
+ " nop\n"
|
||||
" bnez $3,1b\n"
|
||||
" addiu $4,$4,1\n"
|
||||
"\n"
|
||||
Binary file not shown.
@@ -0,0 +1,42 @@
|
||||
vlib work
|
||||
vcom -explicit -93 "../src/dpram_2w2r.vhd"
|
||||
vcom -explicit -93 "../src/dpram_1w1r.vhd"
|
||||
vcom -explicit -93 "../src/fifo_ctrl_pkg.vhd"
|
||||
vcom -explicit -93 "../src/gray_counter.vhd"
|
||||
vcom -explicit -93 "../src/fifo_sync_ctrl.vhd"
|
||||
vcom -explicit -93 "../src/fifo_sync.vhd"
|
||||
vcom -explicit -93 "../src/fifo_async_ctrl.vhd"
|
||||
vcom -explicit -93 "../src/fifo_async.vhd"
|
||||
vcom -explicit -93 "../src/bbfifo_16x8.vhd"
|
||||
vcom -explicit -93 "../src/kcuart_rx.vhd"
|
||||
vcom -explicit -93 "../src/kcuart_tx.vhd"
|
||||
vcom -explicit -93 "../src/uart_rx.vhd"
|
||||
vcom -explicit -93 "../src/uart_tx.vhd"
|
||||
vcom -explicit -93 "../src/uart_wb.vhd"
|
||||
vcom -explicit -93 "../src/gpio_wb.vhd"
|
||||
vcom -explicit -93 "../src/async_types.vhd"
|
||||
vcom -explicit -93 "../src/async_port_wb.vhd"
|
||||
vcom -explicit -93 "../src/async_defs.vhd"
|
||||
vcom -explicit -93 "../src/bootloader.ROM.vhd"
|
||||
vcom -explicit -93 "../src/rom_wb.vhd"
|
||||
vcom -explicit -93 "../src/mips_types.vhd"
|
||||
vcom -explicit -93 "../src/mips_instr.vhd"
|
||||
vcom -explicit -93 "../src/mips_reg.vhd"
|
||||
vcom -explicit -93 "../src/mips_shifter.vhd"
|
||||
vcom -explicit -93 "../src/mips_alu.vhd"
|
||||
vcom -explicit -93 "../src/mips_muldiv.vhd"
|
||||
vcom -explicit -93 "../src/mips_cop.vhd"
|
||||
vcom -explicit -93 "../src/mips_icache.vhd"
|
||||
vcom -explicit -93 "../src/mips_dcache.vhd"
|
||||
vcom -explicit -93 "../src/mips_biu.vhd"
|
||||
vcom -explicit -93 "../src/mips_bcu.vhd"
|
||||
vcom -explicit -93 "../src/mips_pipeline.vhd"
|
||||
vcom -explicit -93 "../src/mips_top.vhd"
|
||||
vcom -explicit -93 "../src/mips_sys.vhd"
|
||||
vcom -explicit -93 "../src/tb_mips_sys.vhd"
|
||||
vsim -t 1ps -lib work tb_mips_sys
|
||||
do {tb_mips_sys.wdo}
|
||||
view wave
|
||||
view structure
|
||||
view signals
|
||||
run 3000us
|
||||
@@ -0,0 +1,45 @@
|
||||
onerror {resume}
|
||||
quietly WaveActivateNextPane {} 0
|
||||
add wave -noupdate -divider {MIPS top}
|
||||
add wave -noupdate -format Literal /tb_mips_sys/debug
|
||||
add wave -noupdate -format Logic /tb_mips_sys/rst
|
||||
add wave -noupdate -format Logic /tb_mips_sys/clk
|
||||
add wave -noupdate -divider Flash
|
||||
add wave -noupdate -format Logic /tb_mips_sys/clk
|
||||
add wave -noupdate -format Logic /tb_mips_sys/flash_cs_n
|
||||
add wave -noupdate -format Logic /tb_mips_sys/flash_oe_n
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_sys/flash_a
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_sys/flash_d
|
||||
add wave -noupdate -divider SRAM
|
||||
add wave -noupdate -format Logic /tb_mips_sys/clk
|
||||
add wave -noupdate -format Logic /tb_mips_sys/sram_cs_n
|
||||
add wave -noupdate -format Literal /tb_mips_sys/sram_wr_n
|
||||
add wave -noupdate -format Logic /tb_mips_sys/sram_oe_n
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_sys/sram_a
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_sys/sram_d
|
||||
add wave -noupdate -divider GPIO
|
||||
add wave -noupdate -format Logic /tb_mips_sys/clk
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_sys/gpo0
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_sys/gpo1
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_sys/gpi0
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_sys/gpi1
|
||||
add wave -noupdate -divider UART
|
||||
add wave -noupdate -format Logic /tb_mips_sys/clk
|
||||
add wave -noupdate -format Logic /tb_mips_sys/rx
|
||||
add wave -noupdate -format Logic /tb_mips_sys/tx
|
||||
TreeUpdate [SetDefaultTree]
|
||||
WaveRestoreCursors {{Cursor 1} {1165707237 ps} 0}
|
||||
configure wave -namecolwidth 150
|
||||
configure wave -valuecolwidth 100
|
||||
configure wave -justifyvalue left
|
||||
configure wave -signalnamewidth 1
|
||||
configure wave -snapdistance 10
|
||||
configure wave -datasetprefix 0
|
||||
configure wave -rowmargin 4
|
||||
configure wave -childrowmargin 2
|
||||
configure wave -gridoffset 0
|
||||
configure wave -gridperiod 100
|
||||
configure wave -griddelta 40
|
||||
configure wave -timeline 1
|
||||
update
|
||||
WaveRestoreZoom {0 ps} {3150 us}
|
||||
@@ -0,0 +1,68 @@
|
||||
-------------------------------------------------------------------------
|
||||
-- Project: MIPS System controller
|
||||
-- This file:
|
||||
--
|
||||
-- Copyright (C) 2008 J. Ahrensfeld
|
||||
--
|
||||
-- This program is free software: you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation, either version 3 of the License, or
|
||||
-- (at your option) any later version.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
--
|
||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||
--
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
library IEEE;
|
||||
USE IEEE.STD_LOGIC_1164.ALL;
|
||||
USE IEEE.NUMERIC_STD.ALL;
|
||||
|
||||
use work.async_types.all;
|
||||
|
||||
package async_defs is
|
||||
|
||||
constant ts_flash : async_timespec_t :=
|
||||
(
|
||||
T_leadin => 00.0,
|
||||
T_pulse_rd => 120.0,
|
||||
T_pulse_wr => 70.0,
|
||||
T_leadout => 00.0,
|
||||
T_release => 40.0,
|
||||
T_pulse_rst => 80.0,
|
||||
T_pulse_page_rd => 30.0,
|
||||
can_page_rd => true,
|
||||
nbits_page_rd => 4,
|
||||
pol_cs => '0',
|
||||
pol_oe => '0',
|
||||
pol_we => '0',
|
||||
pol_be => '0',
|
||||
pol_rst => '0'
|
||||
);
|
||||
|
||||
constant ts_sram : async_timespec_t :=
|
||||
(
|
||||
T_leadin => 00.0,
|
||||
T_pulse_rd => 10.0,
|
||||
T_pulse_wr => 10.0,
|
||||
T_leadout => 00.0,
|
||||
T_release => 00.0,
|
||||
T_pulse_rst => 80.0,
|
||||
T_pulse_page_rd => 20.0,
|
||||
can_page_rd => false,
|
||||
nbits_page_rd => 5,
|
||||
pol_cs => '0',
|
||||
pol_oe => '0',
|
||||
pol_we => '0',
|
||||
pol_be => '0',
|
||||
pol_rst => '0'
|
||||
);
|
||||
|
||||
end async_defs;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,12 @@
|
||||
VHDL/lib/CPUs/MIPS/src/core/dcache.vhd
|
||||
VHDL/lib/CPUs/MIPS/src/core/mips_dcache.vhd
|
||||
VHDL/lib/CPUs/MIPS/src/core/icache.vhd
|
||||
VHDL/lib/CPUs/MIPS/src/core/mips_icache.vhd
|
||||
VHDL/lib/CPUs/MIPS/src/core/mips_biu.vhd
|
||||
|
||||
VHDL/lib/CPUs/MIPS/src/core/mips_bui.vhd
|
||||
VHDL/lib/CPUs/MIPS/src/core/mips_biu.vhd
|
||||
VHDL/lib/CPUs/MIPS/src/core/mips_dcache.vhd
|
||||
|
||||
VHDL/lib/CPUs/MIPS/src/core/mips_icache.vhd
|
||||
|
||||
@@ -0,0 +1,531 @@
|
||||
--------------------------------------------------------------------------
|
||||
-- Project: JIPS, a portable 32-bit RISC CPU written in VHDL
|
||||
-- This file: JIPS top file
|
||||
--
|
||||
-- Copyright (C) 2008 J. Ahrensfeld
|
||||
--
|
||||
-- This program is free software: you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation, either version 3 of the License, or
|
||||
-- (at your option) any later version.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
--
|
||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||
--
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
LIBRARY IEEE;
|
||||
USE IEEE.STD_LOGIC_1164.ALL;
|
||||
USE IEEE.NUMERIC_STD.ALL;
|
||||
|
||||
library work;
|
||||
use work.mips_types.all;
|
||||
|
||||
ENTITY dcache IS
|
||||
Generic
|
||||
(
|
||||
cache_size : natural := 2048; -- words
|
||||
line_size : natural := 8 -- words
|
||||
);
|
||||
Port
|
||||
(
|
||||
RST_I : in STD_LOGIC;
|
||||
CLK_I : in STD_LOGIC;
|
||||
ACK_I : in STD_LOGIC;
|
||||
SRDY_I : in STD_LOGIC;
|
||||
MRDY_O : out STD_LOGIC;
|
||||
ADDR_O : out word_t;
|
||||
DAT_I : in word_t;
|
||||
STB_O : out STD_LOGIC;
|
||||
CYC_O : out STD_LOGIC;
|
||||
ctrl : in cache_ctrl_t;
|
||||
cpu_en : in STD_LOGIC;
|
||||
cpu_we : in STD_LOGIC;
|
||||
cpu_be : in unsigned(3 downto 0);
|
||||
cpu_addr : in word_t;
|
||||
cpu_din : in word_t;
|
||||
cpu_dout : out word_t;
|
||||
cpu_busy : out STD_LOGIC
|
||||
);
|
||||
END dcache;
|
||||
|
||||
ARCHITECTURE behavior OF dcache IS
|
||||
|
||||
COMPONENT dpram_1w1r
|
||||
GENERIC
|
||||
(
|
||||
addr_width : integer := 3;
|
||||
data_width : integer := 8
|
||||
);
|
||||
PORT (
|
||||
clka : in STD_LOGIC;
|
||||
clkb : in STD_LOGIC;
|
||||
en_a : in STD_LOGIC;
|
||||
en_b : in STD_LOGIC;
|
||||
we_a : in STD_LOGIC;
|
||||
addr_a : in unsigned (addr_width-1 downto 0);
|
||||
addr_b : in unsigned (addr_width-1 downto 0);
|
||||
din_a : in unsigned (data_width-1 downto 0);
|
||||
dout_b : out unsigned (data_width-1 downto 0)
|
||||
);
|
||||
END COMPONENT;
|
||||
|
||||
COMPONENT dpram_2w2r is
|
||||
GENERIC
|
||||
(
|
||||
addr_width : integer := 3;
|
||||
data_width : integer := 8
|
||||
);
|
||||
PORT
|
||||
(
|
||||
clk_a : in STD_LOGIC;
|
||||
clk_b : in STD_LOGIC;
|
||||
en_a : in STD_LOGIC;
|
||||
en_b : in STD_LOGIC;
|
||||
we_a : in STD_LOGIC;
|
||||
we_b : in STD_LOGIC;
|
||||
addr_a : in unsigned (addr_width-1 downto 0);
|
||||
addr_b : in unsigned (addr_width-1 downto 0);
|
||||
din_a : in unsigned (data_width-1 downto 0);
|
||||
din_b : in unsigned (data_width-1 downto 0);
|
||||
dout_a : out unsigned (data_width-1 downto 0);
|
||||
dout_b : out unsigned (data_width-1 downto 0)
|
||||
);
|
||||
END COMPONENT;
|
||||
|
||||
constant addr_width : natural := 32;
|
||||
constant word_index_width : natural := lg2(line_size);
|
||||
constant cache_index_width : natural := lg2(cache_size) - word_index_width;
|
||||
constant tag_width : natural := addr_width - word_index_width - cache_index_width - 2;
|
||||
constant tag_parity_width : natural := 3;
|
||||
constant tag_ram_data_width : natural := 1 + tag_parity_width + tag_width;
|
||||
constant tag_ram_addr_width : natural := cache_index_width;
|
||||
|
||||
subtype tag_ram_data_t is unsigned (tag_ram_data_width-1 downto 0);
|
||||
|
||||
type dcache_entry_t is record
|
||||
valid : std_logic;
|
||||
tv_p : unsigned(tag_parity_width-1 downto 0);
|
||||
tag : unsigned(tag_width-1 downto 0);
|
||||
end record;
|
||||
|
||||
function to_dcache_entry(x : tag_ram_data_t) return dcache_entry_t is
|
||||
variable result : dcache_entry_t;
|
||||
begin
|
||||
result.valid := x(0);
|
||||
result.tv_p := x(3 downto 1);
|
||||
result.tag := x(tag_width+3 downto 4);
|
||||
|
||||
return result;
|
||||
end to_dcache_entry;
|
||||
|
||||
function to_tag_ram_data(x : dcache_entry_t) return tag_ram_data_t is
|
||||
variable result : tag_ram_data_t;
|
||||
begin
|
||||
result(0) := x.valid;
|
||||
result(3 downto 1) := x.tv_p;
|
||||
result(tag_width+3 downto 4) := x.tag;
|
||||
|
||||
return result;
|
||||
end to_tag_ram_data;
|
||||
|
||||
type cache_state_t is (init, ready, invalidate, flush, mem_request, mem_access, mem_data, rd_cache);
|
||||
signal s, sn : cache_state_t;
|
||||
|
||||
signal cache_req : std_logic;
|
||||
signal cache_ack : std_logic;
|
||||
signal cache_busy : std_logic;
|
||||
signal cache_hit : std_logic;
|
||||
signal tag_match : std_logic;
|
||||
signal cache_hit_inv : std_logic;
|
||||
signal tag_match_inv : std_logic;
|
||||
|
||||
signal request_addr : unsigned(addr_width-1 downto 0);
|
||||
signal fill_addr : unsigned(addr_width-1 downto 0);
|
||||
|
||||
signal cache_index_inv : unsigned(cache_index_width-1 downto 0);
|
||||
signal tag_inv : unsigned(tag_width-1 downto 0);
|
||||
signal tag_reg_inv : unsigned(tag_width-1 downto 0);
|
||||
|
||||
signal cache_entry_in : dcache_entry_t;
|
||||
signal cache_entry_out : dcache_entry_t;
|
||||
signal cache_entry_out_inv : dcache_entry_t;
|
||||
signal cpu_data_ram_addr : unsigned(lg2(cache_size)-1 downto 0);
|
||||
signal cpu_data_ram_dout : word_t;
|
||||
signal cpu_data_reg : word_t;
|
||||
signal cpu_be_reg : unsigned(3 downto 0);
|
||||
signal cpu_we_reg : std_logic;
|
||||
signal ctrl_data_ram_addr : unsigned(lg2(cache_size)-1 downto 0);
|
||||
signal ctrl_data_ram_we : unsigned(3 downto 0);
|
||||
signal cpu_data_ram_we : unsigned(3 downto 0);
|
||||
signal cpu_we2 : std_logic;
|
||||
|
||||
signal tag_ram_addr_rd : unsigned(cache_index_width-1 downto 0);
|
||||
signal tag_ram_dout : tag_ram_data_t;
|
||||
signal tag_ram_dout_inv : tag_ram_data_t;
|
||||
signal tag_ram_addr_wr : unsigned(cache_index_width-1 downto 0);
|
||||
signal tag_ram_din : tag_ram_data_t;
|
||||
signal tag_ram_we : std_logic;
|
||||
|
||||
signal fill_count : natural range 0 to 2**word_index_width-1;
|
||||
signal fill_count_en : std_logic;
|
||||
signal fill_count_rdy : std_logic;
|
||||
signal flush_count : natural range 0 to 2**cache_index_width-1;
|
||||
signal flush_count_rst : std_logic;
|
||||
signal flush_count_en : std_logic;
|
||||
signal flush_count_rdy : std_logic;
|
||||
signal request_count : natural range 0 to 2**word_index_width-1;
|
||||
signal request_count_en : std_logic;
|
||||
signal request_count_rdy : std_logic;
|
||||
signal was_miss : std_logic;
|
||||
signal invalidate_all : std_logic;
|
||||
signal invalidate_ack : std_logic;
|
||||
signal invalidate_en : std_logic;
|
||||
signal invalidate_req : std_logic;
|
||||
signal cpu_hit_we : std_logic;
|
||||
signal instant_raw : std_logic;
|
||||
signal hit_cache_index : unsigned(cache_index_width-1 downto 0);
|
||||
|
||||
alias cpu_word_index is cpu_addr(word_index_width+1 downto 2);
|
||||
alias cpu_cache_index is cpu_addr(cache_index_width+word_index_width+1 downto word_index_width+2);
|
||||
alias cpu_tag is cpu_addr(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2);
|
||||
|
||||
alias fill_word_index is fill_addr(word_index_width+1 downto 2);
|
||||
alias fill_cache_index is fill_addr(cache_index_width+word_index_width+1 downto word_index_width+2);
|
||||
alias fill_tag is fill_addr(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2);
|
||||
|
||||
alias req_word_index is request_addr(word_index_width+1 downto 2);
|
||||
alias req_cache_index is request_addr(cache_index_width+word_index_width+1 downto word_index_width+2);
|
||||
alias req_tag is request_addr(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2);
|
||||
|
||||
begin
|
||||
|
||||
cache_index_inv <= ctrl.inv_addr(cache_index_width+word_index_width+1 downto word_index_width+2);
|
||||
tag_inv <= ctrl.inv_addr(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2);
|
||||
|
||||
cpu_hit_we <= cpu_we2 and cache_hit;
|
||||
|
||||
fill_address_register:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if fill_count_en = '1' then
|
||||
if ACK_I = '1' then
|
||||
fill_word_index <= fill_word_index + 1;
|
||||
end if;
|
||||
elsif cache_busy = '0' then
|
||||
fill_addr <= cpu_addr(addr_width-1 downto 2) & "00";
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
request_address_register:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if request_count_en = '1'then
|
||||
if SRDY_I = '1' then
|
||||
req_word_index <= req_word_index + 1;
|
||||
end if;
|
||||
elsif cache_busy = '0' then
|
||||
request_addr <= cpu_addr(addr_width-1 downto 2) & "00";
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
cpu_request_register:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if RST_I = '1' then
|
||||
cpu_we_reg <= '0';
|
||||
cache_req <= '0';
|
||||
elsif cpu_en = '1' then
|
||||
if cache_busy = '0' then
|
||||
cpu_we2 <= cpu_we;
|
||||
cache_req <= '1';
|
||||
cpu_data_reg <= cpu_din;
|
||||
cpu_be_reg <= cpu_be;
|
||||
cpu_we_reg <= cpu_we;
|
||||
if cpu_we = '1' then
|
||||
hit_cache_index <= cpu_cache_index;
|
||||
end if;
|
||||
end if;
|
||||
elsif cache_ack = '1' then
|
||||
cache_req <= '0';
|
||||
cpu_we2 <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
instant_raw_logic:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
instant_raw <= '0';
|
||||
if cpu_word_index = fill_word_index and cpu_cache_index = hit_cache_index then
|
||||
instant_raw <= cpu_hit_we and cpu_en and not cpu_we;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
inst_tag_ram : dpram_2w2r
|
||||
GENERIC MAP
|
||||
(
|
||||
addr_width => tag_ram_addr_width,
|
||||
data_width => tag_ram_data_width
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
clk_a => CLK_I,
|
||||
clk_b => CLK_I,
|
||||
en_a => '1',
|
||||
en_b => '1',
|
||||
we_a => tag_ram_we,
|
||||
we_b => '0',
|
||||
addr_a => tag_ram_addr_wr,
|
||||
addr_b => tag_ram_addr_rd,
|
||||
din_a => tag_ram_din,
|
||||
din_b => tag_ram_din,
|
||||
dout_a => tag_ram_dout_inv,
|
||||
dout_b => tag_ram_dout
|
||||
);
|
||||
|
||||
gen_data_ram:
|
||||
for i in 0 to 3 generate
|
||||
begin
|
||||
|
||||
inst_data_ram : dpram_2w2r
|
||||
GENERIC MAP
|
||||
(
|
||||
addr_width => lg2(cache_size),
|
||||
data_width => word_t'length/4
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
clk_a => CLK_I,
|
||||
clk_b => CLK_I,
|
||||
en_a => '1',
|
||||
en_b => '1',
|
||||
we_a => cpu_data_ram_we(i),
|
||||
we_b => ctrl_data_ram_we(i),
|
||||
addr_a => ctrl_data_ram_addr,
|
||||
addr_b => cpu_data_ram_addr,
|
||||
din_a => cpu_data_reg(8*(i+1)-1 downto 8*i),
|
||||
din_b => DAT_I(8*(i+1)-1 downto 8*i),
|
||||
dout_a => open,
|
||||
dout_b => cpu_data_ram_dout(8*(i+1)-1 downto 8*i)
|
||||
);
|
||||
end generate;
|
||||
|
||||
|
||||
|
||||
cache_invalidate_request:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if RST_I = '1' or ctrl.inv_all = '1' or ctrl.inv_at = '1' then
|
||||
invalidate_req <= '1';
|
||||
invalidate_all <= ctrl.inv_all or RST_I;
|
||||
tag_reg_inv <= tag_inv;
|
||||
elsif invalidate_ack = '1' then
|
||||
invalidate_req <= '0';
|
||||
invalidate_all <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
cache_state_next:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if RST_I = '1' then
|
||||
s <= init;
|
||||
else
|
||||
s <= sn;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
MRDY_O <= fill_count_en;
|
||||
ADDR_O <= request_addr;
|
||||
|
||||
cpu_busy <= cache_busy;
|
||||
cpu_dout <= cpu_data_ram_dout;
|
||||
|
||||
tag_match <= '1' when fill_tag = cache_entry_out.tag else '0';
|
||||
cache_hit <= tag_match and cache_entry_out.valid;
|
||||
tag_match_inv <= '1' when tag_reg_inv = cache_entry_out_inv.tag else '0';
|
||||
cache_hit_inv <= tag_match_inv and cache_entry_out_inv.valid;
|
||||
tag_ram_din <= to_tag_ram_data(cache_entry_in);
|
||||
tag_ram_addr_wr <= to_unsigned(flush_count, cache_index_width) when invalidate_en = '1' else fill_cache_index;
|
||||
tag_ram_addr_rd <= cpu_cache_index when (was_miss = '0' and instant_raw = '0') else fill_cache_index;
|
||||
|
||||
cache_entry_out <= to_dcache_entry(tag_ram_dout);
|
||||
cache_entry_out_inv <= to_dcache_entry(tag_ram_dout_inv);
|
||||
|
||||
cpu_data_ram_addr <= (cpu_cache_index & cpu_word_index) when (was_miss = '0' and instant_raw = '0' and fill_count_en = '0') else (fill_cache_index & fill_word_index);
|
||||
ctrl_data_ram_addr <= fill_cache_index & fill_word_index;
|
||||
ctrl_data_ram_we <= (others => fill_count_en and ACK_I);
|
||||
cpu_data_ram_we <= cpu_be_reg when (cpu_hit_we = '1') else (others => '0');
|
||||
|
||||
cache_state:
|
||||
process(s, cache_req, instant_raw, cache_hit, cache_hit_inv, flush_count_rdy, fill_count_rdy, request_count_rdy, fill_tag, SRDY_I, cpu_we_reg, invalidate_req, invalidate_all)
|
||||
begin
|
||||
cache_busy <= cache_req;
|
||||
cache_ack <= '0';
|
||||
tag_ram_we <= '0';
|
||||
flush_count_en <= '0';
|
||||
flush_count_rst <= '0';
|
||||
invalidate_en <= '0';
|
||||
request_count_en <= '0';
|
||||
fill_count_en <= '0';
|
||||
CYC_O <= '0';
|
||||
STB_O <= '0';
|
||||
was_miss <= '0';
|
||||
invalidate_ack <= '0';
|
||||
|
||||
cache_entry_in.tv_p <= (others => '0');
|
||||
cache_entry_in.tag <= fill_tag;
|
||||
cache_entry_in.valid <= '0';
|
||||
sn <= s;
|
||||
|
||||
case s is
|
||||
when init =>
|
||||
sn <= ready;
|
||||
when ready =>
|
||||
if invalidate_req = '1' then
|
||||
sn <= invalidate;
|
||||
invalidate_en <= '1';
|
||||
else
|
||||
if cache_req = '1' then
|
||||
if cache_hit = '0' and cpu_we_reg = '0' then
|
||||
sn <= mem_request;
|
||||
CYC_O <= '1';
|
||||
else
|
||||
cache_busy <= instant_raw;
|
||||
cache_ack <= not instant_raw;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
when invalidate =>
|
||||
sn <= rd_cache;
|
||||
invalidate_en <= '1';
|
||||
invalidate_ack <= '1';
|
||||
if invalidate_all = '1' then
|
||||
sn <= flush;
|
||||
flush_count_rst <= '1';
|
||||
elsif cache_hit_inv = '1' then
|
||||
tag_ram_we <= '1';
|
||||
cache_entry_in.valid <= '0';
|
||||
cache_entry_in.tag <= (others => '0');
|
||||
sn <= rd_cache;
|
||||
end if;
|
||||
|
||||
when flush =>
|
||||
flush_count_en <= '1';
|
||||
invalidate_en <= '1';
|
||||
tag_ram_we <= '1';
|
||||
cache_entry_in.valid <= '0';
|
||||
cache_entry_in.tag <= (others => '0');
|
||||
if flush_count_rdy = '1' then
|
||||
tag_ram_we <= '0';
|
||||
sn <= rd_cache;
|
||||
end if;
|
||||
when mem_request =>
|
||||
CYC_O <= '1';
|
||||
if SRDY_I = '1' then
|
||||
sn <= mem_access;
|
||||
end if;
|
||||
when mem_access =>
|
||||
fill_count_en <= '1';
|
||||
request_count_en <= '1';
|
||||
CYC_O <= '1';
|
||||
STB_O <= '1';
|
||||
if request_count_rdy = '1' then
|
||||
STB_O <= '0';
|
||||
sn <= mem_data;
|
||||
end if;
|
||||
when mem_data =>
|
||||
CYC_O <= '1';
|
||||
fill_count_en <= '1';
|
||||
if fill_count_rdy = '1' then
|
||||
tag_ram_we <= '1';
|
||||
cache_entry_in.valid <= '1';
|
||||
sn <= rd_cache;
|
||||
end if;
|
||||
when rd_cache =>
|
||||
was_miss <= '1';
|
||||
sn <= ready;
|
||||
|
||||
when others =>
|
||||
sn <= ready;
|
||||
end case;
|
||||
|
||||
end process;
|
||||
|
||||
flush_counter:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if ctrl.inv_at = '1' then
|
||||
flush_count <= to_integer(cache_index_inv);
|
||||
elsif flush_count_rst = '1' then
|
||||
flush_count_rdy <= '0';
|
||||
flush_count <= 2**cache_index_width-1;
|
||||
elsif flush_count_en = '1' then
|
||||
if flush_count /= 0 then
|
||||
flush_count <= flush_count - 1;
|
||||
else
|
||||
flush_count_rdy <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
request_counter:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if request_count_en = '0' then
|
||||
request_count_rdy <= '0';
|
||||
request_count <= 2**word_index_width-1;
|
||||
else
|
||||
if SRDY_I = '1' then
|
||||
if request_count /= 0 then
|
||||
request_count <= request_count - 1;
|
||||
else
|
||||
request_count_rdy <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
fill_counter:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if fill_count_en = '0' then
|
||||
fill_count_rdy <= '0';
|
||||
fill_count <= 2**word_index_width-1;
|
||||
else
|
||||
if ACK_I = '1' then
|
||||
if fill_count /= 0 then
|
||||
fill_count <= fill_count - 1;
|
||||
else
|
||||
fill_count_rdy <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end behavior;
|
||||
@@ -0,0 +1,488 @@
|
||||
--------------------------------------------------------------------------
|
||||
-- Project: JIPS, a portable 32-bit RISC CPU written in VHDL
|
||||
-- This file: JIPS top file
|
||||
--
|
||||
-- Copyright (C) 2008 J. Ahrensfeld
|
||||
--
|
||||
-- This program is free software: you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation, either version 3 of the License, or
|
||||
-- (at your option) any later version.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
--
|
||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||
--
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
LIBRARY IEEE;
|
||||
USE IEEE.STD_LOGIC_1164.ALL;
|
||||
USE IEEE.NUMERIC_STD.ALL;
|
||||
|
||||
library work;
|
||||
use work.mips_types.all;
|
||||
|
||||
ENTITY icache IS
|
||||
Generic
|
||||
(
|
||||
cache_size : natural := 2048; -- words
|
||||
line_size : natural := 8 -- words
|
||||
);
|
||||
Port
|
||||
(
|
||||
RST_I : in STD_LOGIC;
|
||||
CLK_I : in STD_LOGIC;
|
||||
ACK_I : in STD_LOGIC;
|
||||
SRDY_I : in STD_LOGIC;
|
||||
MRDY_O : out STD_LOGIC;
|
||||
ADDR_O : out word_t;
|
||||
DAT_I : in word_t;
|
||||
STB_O : out STD_LOGIC;
|
||||
CYC_O : out STD_LOGIC;
|
||||
ctrl : in cache_ctrl_t;
|
||||
cpu_en : in STD_LOGIC;
|
||||
cpu_addr : in word_t;
|
||||
cpu_dout : out word_t;
|
||||
cpu_busy : out STD_LOGIC
|
||||
);
|
||||
END icache;
|
||||
|
||||
ARCHITECTURE behavior OF icache IS
|
||||
|
||||
COMPONENT dpram_1w1r
|
||||
GENERIC
|
||||
(
|
||||
addr_width : integer := 3;
|
||||
data_width : integer := 8
|
||||
);
|
||||
PORT (
|
||||
clka : in STD_LOGIC;
|
||||
clkb : in STD_LOGIC;
|
||||
en_a : in STD_LOGIC;
|
||||
en_b : in STD_LOGIC;
|
||||
we_a : in STD_LOGIC;
|
||||
addr_a : in unsigned (addr_width-1 downto 0);
|
||||
addr_b : in unsigned (addr_width-1 downto 0);
|
||||
din_a : in unsigned (data_width-1 downto 0);
|
||||
dout_b : out unsigned (data_width-1 downto 0)
|
||||
);
|
||||
END COMPONENT;
|
||||
|
||||
COMPONENT dpram_2w2r is
|
||||
GENERIC
|
||||
(
|
||||
addr_width : integer := 3;
|
||||
data_width : integer := 8
|
||||
);
|
||||
PORT
|
||||
(
|
||||
clk_a : in STD_LOGIC;
|
||||
clk_b : in STD_LOGIC;
|
||||
en_a : in STD_LOGIC;
|
||||
en_b : in STD_LOGIC;
|
||||
we_a : in STD_LOGIC;
|
||||
we_b : in STD_LOGIC;
|
||||
addr_a : in unsigned (addr_width-1 downto 0);
|
||||
addr_b : in unsigned (addr_width-1 downto 0);
|
||||
din_a : in unsigned (data_width-1 downto 0);
|
||||
din_b : in unsigned (data_width-1 downto 0);
|
||||
dout_a : out unsigned (data_width-1 downto 0);
|
||||
dout_b : out unsigned (data_width-1 downto 0)
|
||||
);
|
||||
END COMPONENT;
|
||||
|
||||
constant addr_width : natural := 32;
|
||||
constant word_index_width : natural := lg2(line_size);
|
||||
constant cache_index_width : natural := lg2(cache_size) - word_index_width;
|
||||
constant tag_width : natural := addr_width - word_index_width - cache_index_width - 2;
|
||||
constant tag_parity_width : natural := 3;
|
||||
constant tag_ram_data_width : natural := 1 + tag_parity_width + tag_width;
|
||||
constant tag_ram_addr_width : natural := cache_index_width;
|
||||
|
||||
subtype tag_ram_data_t is unsigned (tag_ram_data_width-1 downto 0);
|
||||
|
||||
type icache_entry_t is record
|
||||
valid : std_logic;
|
||||
tv_p : unsigned(tag_parity_width-1 downto 0);
|
||||
tag : unsigned(tag_width-1 downto 0);
|
||||
end record;
|
||||
|
||||
function to_icache_entry(x : tag_ram_data_t) return icache_entry_t is
|
||||
variable result : icache_entry_t;
|
||||
begin
|
||||
result.valid := x(0);
|
||||
result.tv_p := x(3 downto 1);
|
||||
result.tag := x(tag_width+3 downto 4);
|
||||
|
||||
return result;
|
||||
end to_icache_entry;
|
||||
|
||||
function to_tag_ram_data(x : icache_entry_t) return tag_ram_data_t is
|
||||
variable result : tag_ram_data_t;
|
||||
begin
|
||||
result(0) := x.valid;
|
||||
result(3 downto 1) := x.tv_p;
|
||||
result(tag_width+3 downto 4) := x.tag;
|
||||
|
||||
return result;
|
||||
end to_tag_ram_data;
|
||||
|
||||
type cache_state_t is (init, ready, invalidate, flush, mem_request, mem_access, mem_data, rd_cache, upd_cache);
|
||||
signal s, sn : cache_state_t;
|
||||
|
||||
signal cache_req : std_logic;
|
||||
signal cache_ack : std_logic;
|
||||
signal cache_busy : std_logic;
|
||||
signal cache_miss : std_logic;
|
||||
signal tag_match : std_logic;
|
||||
signal cache_miss_inv : std_logic;
|
||||
signal tag_match_inv : std_logic;
|
||||
signal request_addr : unsigned(addr_width-1 downto 0);
|
||||
signal fill_addr : unsigned(addr_width-1 downto 0);
|
||||
|
||||
signal cache_index_inv : unsigned(cache_index_width-1 downto 0);
|
||||
signal tag_inv : unsigned(tag_width-1 downto 0);
|
||||
signal tag_reg_inv : unsigned(tag_width-1 downto 0);
|
||||
|
||||
signal cache_entry_in : icache_entry_t;
|
||||
signal cache_entry_out : icache_entry_t;
|
||||
signal cache_entry_out_inv : icache_entry_t;
|
||||
signal data_ram_addr_rd : unsigned(lg2(cache_size)-1 downto 0);
|
||||
signal data_ram_data_rd : word_t;
|
||||
signal data_ram_addr_wr : unsigned(lg2(cache_size)-1 downto 0);
|
||||
signal data_ram_data_wr : word_t;
|
||||
signal data_ram_we : std_logic;
|
||||
|
||||
signal tag_ram_addr_rd : unsigned(cache_index_width-1 downto 0);
|
||||
signal tag_ram_data_rd : tag_ram_data_t;
|
||||
signal tag_ram_data_rd_inv : tag_ram_data_t;
|
||||
signal tag_ram_addr_wr : unsigned(cache_index_width-1 downto 0);
|
||||
signal tag_ram_data_wr : tag_ram_data_t;
|
||||
signal tag_ram_we : std_logic;
|
||||
|
||||
signal fill_count : natural range 0 to 2**word_index_width-1;
|
||||
signal fill_count_en : std_logic;
|
||||
signal fill_count_rdy : std_logic;
|
||||
signal flush_count : natural range 0 to 2**cache_index_width-1;
|
||||
signal flush_count_rst : std_logic;
|
||||
signal flush_count_en : std_logic;
|
||||
signal flush_count_rdy : std_logic;
|
||||
signal request_count : natural range 0 to 2**word_index_width-1;
|
||||
signal request_count_en : std_logic;
|
||||
signal request_count_rdy : std_logic;
|
||||
signal ram_read_en : std_logic;
|
||||
signal was_miss : std_logic;
|
||||
signal invalidate_all : std_logic;
|
||||
signal invalidate_ack : std_logic;
|
||||
signal invalidate_en : std_logic;
|
||||
signal invalidate_req : std_logic;
|
||||
|
||||
alias cpu_word_index is cpu_addr(word_index_width+1 downto 2);
|
||||
alias cpu_cache_index is cpu_addr(cache_index_width+word_index_width+1 downto word_index_width+2);
|
||||
alias cpu_tag is cpu_addr(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2);
|
||||
|
||||
alias fill_word_index is fill_addr(word_index_width+1 downto 2);
|
||||
alias fill_cache_index is fill_addr(cache_index_width+word_index_width+1 downto word_index_width+2);
|
||||
alias fill_tag is fill_addr(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2);
|
||||
|
||||
alias req_word_index is request_addr(word_index_width+1 downto 2);
|
||||
alias req_cache_index is request_addr(cache_index_width+word_index_width+1 downto word_index_width+2);
|
||||
alias req_tag is request_addr(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2);
|
||||
|
||||
begin
|
||||
|
||||
ram_read_en <= cpu_en or was_miss;
|
||||
cache_index_inv <= ctrl.inv_addr(cache_index_width+word_index_width+1 downto word_index_width+2);
|
||||
tag_inv <= ctrl.inv_addr(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2);
|
||||
|
||||
|
||||
fill_address_register:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if fill_count_en = '1' then
|
||||
if ACK_I = '1' then
|
||||
fill_word_index <= fill_word_index + 1;
|
||||
end if;
|
||||
elsif cache_busy = '0' then
|
||||
fill_addr <= cpu_addr(addr_width-1 downto 2) & "00";
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
request_address_register:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if request_count_en = '1'then
|
||||
if SRDY_I = '1' then
|
||||
req_word_index <= req_word_index + 1;
|
||||
end if;
|
||||
elsif cache_busy = '0' then
|
||||
request_addr <= cpu_addr(addr_width-1 downto 2) & "00";
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
cpu_request_register:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if RST_I = '1' then
|
||||
cache_req <= '0';
|
||||
elsif cpu_en = '1' then
|
||||
if cache_busy = '0' then
|
||||
cache_req <= '1';
|
||||
end if;
|
||||
elsif cache_ack = '1' then
|
||||
cache_req <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
cache_invalidate_request:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if RST_I = '1' or ctrl.inv_all = '1' or ctrl.inv_at = '1' then
|
||||
invalidate_req <= '1';
|
||||
invalidate_all <= ctrl.inv_all or RST_I;
|
||||
tag_reg_inv <= tag_inv;
|
||||
elsif invalidate_ack = '1' then
|
||||
invalidate_req <= '0';
|
||||
invalidate_all <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
inst_tag_ram : dpram_2w2r
|
||||
GENERIC MAP
|
||||
(
|
||||
addr_width => tag_ram_addr_width,
|
||||
data_width => tag_ram_data_width
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
clk_a => CLK_I,
|
||||
clk_b => CLK_I,
|
||||
en_a => '1',
|
||||
en_b => ram_read_en,
|
||||
we_a => tag_ram_we,
|
||||
we_b => '0',
|
||||
addr_a => tag_ram_addr_wr,
|
||||
addr_b => tag_ram_addr_rd,
|
||||
din_a => tag_ram_data_wr,
|
||||
din_b => tag_ram_data_wr,
|
||||
dout_a => tag_ram_data_rd_inv,
|
||||
dout_b => tag_ram_data_rd
|
||||
);
|
||||
|
||||
inst_data_ram : dpram_1w1r
|
||||
GENERIC MAP
|
||||
(
|
||||
addr_width => lg2(cache_size),
|
||||
data_width => word_t'length
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
clka => CLK_I,
|
||||
clkb => CLK_I,
|
||||
en_a => '1',
|
||||
en_b => ram_read_en,
|
||||
we_a => data_ram_we,
|
||||
addr_a => data_ram_addr_wr,
|
||||
addr_b => data_ram_addr_rd,
|
||||
din_a => data_ram_data_wr,
|
||||
dout_b => data_ram_data_rd
|
||||
);
|
||||
|
||||
cache_state_next:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if RST_I = '1' then
|
||||
s <= init;
|
||||
else
|
||||
s <= sn;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
MRDY_O <= fill_count_en;
|
||||
ADDR_O <= fill_tag & fill_cache_index & req_word_index & "00";
|
||||
|
||||
cpu_busy <= cache_busy;
|
||||
cpu_dout <= data_ram_data_rd;
|
||||
|
||||
cache_entry_out <= to_icache_entry(tag_ram_data_rd);
|
||||
tag_match <= '1' when fill_tag = cache_entry_out.tag else '0';
|
||||
cache_miss <= not (tag_match and cache_entry_out.valid);
|
||||
|
||||
cache_entry_out_inv <= to_icache_entry(tag_ram_data_rd_inv);
|
||||
tag_match_inv <= '1' when tag_reg_inv = cache_entry_out_inv.tag else '0';
|
||||
cache_miss_inv <= not (tag_match_inv and cache_entry_out_inv.valid);
|
||||
|
||||
tag_ram_data_wr <= to_tag_ram_data(cache_entry_in);
|
||||
tag_ram_addr_wr <= to_unsigned(flush_count, cache_index_width) when invalidate_en = '1' else fill_cache_index;
|
||||
tag_ram_addr_rd <= cpu_cache_index when was_miss = '0' else fill_cache_index;
|
||||
data_ram_addr_rd <= (cpu_cache_index & cpu_word_index) when was_miss = '0' else (fill_cache_index & fill_word_index);
|
||||
data_ram_addr_wr <= fill_cache_index & fill_word_index;
|
||||
data_ram_data_wr <= DAT_I;
|
||||
data_ram_we <= fill_count_en and ACK_I;
|
||||
|
||||
cache_state:
|
||||
process(s, cache_req, cache_miss, cache_miss_inv, flush_count_rdy, fill_count_rdy, request_count_rdy, fill_tag, SRDY_I, invalidate_req, invalidate_all)
|
||||
begin
|
||||
cache_busy <= cache_req;
|
||||
cache_ack <= '0';
|
||||
tag_ram_we <= '0';
|
||||
flush_count_en <= '0';
|
||||
flush_count_rst <= '0';
|
||||
invalidate_en <= '0';
|
||||
request_count_en <= '0';
|
||||
fill_count_en <= '0';
|
||||
CYC_O <= '0';
|
||||
STB_O <= '0';
|
||||
was_miss <= '0';
|
||||
invalidate_ack <= '0';
|
||||
|
||||
cache_entry_in.tv_p <= (others => '0');
|
||||
cache_entry_in.tag <= fill_tag;
|
||||
cache_entry_in.valid <= '0';
|
||||
sn <= s;
|
||||
|
||||
case s is
|
||||
when init =>
|
||||
sn <= ready;
|
||||
when ready =>
|
||||
if invalidate_req = '1' then
|
||||
sn <= invalidate;
|
||||
invalidate_en <= '1';
|
||||
elsif cache_req = '1' then
|
||||
if cache_miss = '1' then
|
||||
sn <= mem_request;
|
||||
CYC_O <= '1';
|
||||
else
|
||||
cache_busy <= '0';
|
||||
cache_ack <= '1';
|
||||
end if;
|
||||
end if;
|
||||
when invalidate =>
|
||||
sn <= rd_cache;
|
||||
invalidate_en <= '1';
|
||||
invalidate_ack <= '1';
|
||||
if invalidate_all = '1' then
|
||||
sn <= flush;
|
||||
flush_count_rst <= '1';
|
||||
elsif cache_miss_inv = '0' then
|
||||
tag_ram_we <= '1';
|
||||
cache_entry_in.valid <= '0';
|
||||
cache_entry_in.tag <= (others => '0');
|
||||
sn <= rd_cache;
|
||||
end if;
|
||||
|
||||
when flush =>
|
||||
flush_count_en <= '1';
|
||||
invalidate_en <= '1';
|
||||
tag_ram_we <= '1';
|
||||
cache_entry_in.valid <= '0';
|
||||
cache_entry_in.tag <= (others => '0');
|
||||
if flush_count_rdy = '1' then
|
||||
tag_ram_we <= '0';
|
||||
sn <= rd_cache;
|
||||
end if;
|
||||
when mem_request =>
|
||||
CYC_O <= '1';
|
||||
if SRDY_I = '1' then
|
||||
sn <= mem_access;
|
||||
end if;
|
||||
when mem_access =>
|
||||
request_count_en <= '1';
|
||||
fill_count_en <= '1';
|
||||
CYC_O <= '1';
|
||||
STB_O <= '1';
|
||||
if request_count_rdy = '1' then
|
||||
STB_O <= '0';
|
||||
sn <= mem_data;
|
||||
end if;
|
||||
when mem_data =>
|
||||
CYC_O <= '1';
|
||||
fill_count_en <= '1';
|
||||
if fill_count_rdy = '1' then
|
||||
tag_ram_we <= '1';
|
||||
cache_entry_in.valid <= '1';
|
||||
sn <= rd_cache;
|
||||
end if;
|
||||
when rd_cache =>
|
||||
was_miss <= '1';
|
||||
sn <= ready;
|
||||
when others =>
|
||||
sn <= ready;
|
||||
end case;
|
||||
|
||||
end process;
|
||||
|
||||
flush_counter:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if ctrl.inv_at = '1' then
|
||||
flush_count <= to_integer(cache_index_inv);
|
||||
elsif flush_count_rst = '1' then
|
||||
flush_count_rdy <= '0';
|
||||
flush_count <= 2**cache_index_width-1;
|
||||
elsif flush_count_en = '1' then
|
||||
if flush_count /= 0 then
|
||||
flush_count <= flush_count - 1;
|
||||
else
|
||||
flush_count_rdy <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
request_counter:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if request_count_en = '0' then
|
||||
request_count_rdy <= '0';
|
||||
request_count <= 2**word_index_width-1;
|
||||
else
|
||||
if SRDY_I = '1' then
|
||||
if request_count /= 0 then
|
||||
request_count <= request_count - 1;
|
||||
else
|
||||
request_count_rdy <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
fill_counter:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if fill_count_en = '0' then
|
||||
fill_count_rdy <= '0';
|
||||
fill_count <= 2**word_index_width-1;
|
||||
else
|
||||
if ACK_I = '1' then
|
||||
if fill_count /= 0 then
|
||||
fill_count <= fill_count - 1;
|
||||
else
|
||||
fill_count_rdy <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end behavior;
|
||||
@@ -0,0 +1,184 @@
|
||||
--------------------------------------------------------------------------
|
||||
-- Project: JIPS, a portable 32-bit RISC CPU written in VHDL
|
||||
-- This file: The arithmetic logic unit
|
||||
--
|
||||
-- Copyright (C) 2008 J. Ahrensfeld
|
||||
--
|
||||
-- This program is free software: you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation, either version 3 of the License, or
|
||||
-- (at your option) any later version.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
--
|
||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||
--
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.numeric_std.ALL;
|
||||
|
||||
use work.mips_types.all;
|
||||
|
||||
entity alu is
|
||||
Generic
|
||||
(
|
||||
data_width : integer := 8
|
||||
);
|
||||
Port
|
||||
(
|
||||
op1_in : in unsigned (data_width-1 downto 0);
|
||||
op2_in : in unsigned (data_width-1 downto 0);
|
||||
op2_shifted : in unsigned (data_width-1 downto 0);
|
||||
ctrl : in alu_ctrl_t;
|
||||
result : out unsigned (data_width-1 downto 0);
|
||||
flags : out alu_flags_t
|
||||
);
|
||||
end alu;
|
||||
|
||||
architecture Behavioral of alu is
|
||||
|
||||
signal sum_res : unsigned (data_width-1 downto 0);
|
||||
signal and_res : unsigned (data_width-1 downto 0);
|
||||
signal xor_res : unsigned (data_width-1 downto 0);
|
||||
signal nor_res : unsigned (data_width-1 downto 0);
|
||||
signal or_res : unsigned (data_width-1 downto 0);
|
||||
signal eq, sa, sb, sr, c, z : STD_LOGIC;
|
||||
signal lts, ltu : STD_LOGIC;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
begin
|
||||
|
||||
eq <= '1' when op1_in = op2_in else '0' after 3 ns;
|
||||
sa <= op1_in(op1_in'left);
|
||||
sb <= op2_in(op2_in'left);
|
||||
sr <= sum_res(sum_res'left);
|
||||
z <= '1' when op1_in = (data_width-1 downto 0 => '0') else '0' after 2 ns;
|
||||
|
||||
flags.uvf <= (not ctrl.add) and ((sa and (not sb) and (not sr)) or ((not sa) and sb and sr));
|
||||
flags.ovf <= ctrl.add and ((sa and sb and (not sr)) or ((not sa) and (not sb) and sr));
|
||||
-- lts <= (not eq) and (((not c) and sa and sb) or (((not sr) and sa) or (sa and (not sb)) or (sr and (not sb))));
|
||||
lts <= not eq and ((not c and sa) or (not sb and sa) or (not sb and sr));
|
||||
|
||||
ltu <= (not eq) and (not c);
|
||||
flags.lts <= lts;
|
||||
flags.ltu <= ltu;
|
||||
flags.c <= c;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
proc_op_and:
|
||||
process(op1_in, op2_in)
|
||||
variable x1, x2 : unsigned (data_width-1 downto 0);
|
||||
begin
|
||||
x1 := op1_in;
|
||||
x2 := op2_in;
|
||||
|
||||
and_res <= (x1 and x2) after 1 ns;
|
||||
|
||||
end process;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
proc_proc_xor:
|
||||
process(op1_in, op2_in)
|
||||
variable x1, x2 : unsigned (data_width-1 downto 0);
|
||||
begin
|
||||
x1 := op1_in;
|
||||
x2 := op2_in;
|
||||
|
||||
xor_res <= (x1 xor x2) after 2 ns;
|
||||
|
||||
end process;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
proc_proc_nor:
|
||||
process(op1_in, op2_in)
|
||||
variable x1, x2 : unsigned (data_width-1 downto 0);
|
||||
begin
|
||||
x1 := op1_in;
|
||||
x2 := op2_in;
|
||||
|
||||
nor_res <= (x1 nor x2) after 1 ns;
|
||||
|
||||
end process;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
proc_proc_or:
|
||||
process(op1_in, op2_in)
|
||||
variable x1, x2 : unsigned (data_width-1 downto 0);
|
||||
begin
|
||||
x1 := op1_in;
|
||||
x2 := op2_in;
|
||||
|
||||
or_res <= (x1 or x2) after 1 ns;
|
||||
|
||||
end process;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
proc_alu_out:
|
||||
process(ctrl, sum_res, and_res, xor_res, nor_res, or_res, op2_shifted, lts, ltu)
|
||||
begin
|
||||
|
||||
result <= sum_res;
|
||||
|
||||
case ctrl.outsel is
|
||||
|
||||
when alu_adder =>
|
||||
result <= sum_res;
|
||||
|
||||
when alu_and =>
|
||||
result <= and_res;
|
||||
|
||||
when alu_xor =>
|
||||
result <= xor_res;
|
||||
|
||||
when alu_nor =>
|
||||
result <= nor_res;
|
||||
|
||||
when alu_or =>
|
||||
result <= or_res;
|
||||
|
||||
when alu_shift2 =>
|
||||
result <= op2_shifted;
|
||||
|
||||
when alu_ltu =>
|
||||
result <= (data_width-1 downto 1 => '0') & ltu;
|
||||
|
||||
when alu_lts =>
|
||||
result <= (data_width-1 downto 1 => '0') & lts;
|
||||
|
||||
when others => null;
|
||||
|
||||
end case;
|
||||
|
||||
end process;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
alu_addsub:
|
||||
process(op1_in, op2_in, ctrl)
|
||||
variable sum : unsigned(data_width+1 downto 0);
|
||||
variable op1, op2 : unsigned(data_width+1 downto 0);
|
||||
begin
|
||||
|
||||
op1 := '0' & op1_in & not ctrl.add;
|
||||
if (ctrl.add = '1') then
|
||||
op2 := '0' & op2_in & '0';
|
||||
else
|
||||
op2 := '0' & not op2_in & '1';
|
||||
end if;
|
||||
sum := op1 + op2;
|
||||
|
||||
-- Form sum + carry
|
||||
sum_res <= unsigned(sum(data_width downto 1)) after 4 ns;
|
||||
c <= sum(sum'left) after 4 ns;
|
||||
|
||||
end process;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
end Behavioral;
|
||||
@@ -0,0 +1,52 @@
|
||||
--------------------------------------------------------------------------
|
||||
-- Project: JIPS, a portable 32-bit RISC CPU written in VHDL
|
||||
-- This file: The arithmetic logic unit
|
||||
--
|
||||
-- Copyright (C) 2008 J. Ahrensfeld
|
||||
--
|
||||
-- This program is free software: you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation, either version 3 of the License, or
|
||||
-- (at your option) any later version.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
--
|
||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||
--
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.numeric_std.ALL;
|
||||
|
||||
use work.mips_types.all;
|
||||
|
||||
entity bcu is
|
||||
Generic
|
||||
(
|
||||
data_width : integer := 8
|
||||
);
|
||||
Port
|
||||
(
|
||||
op1_in : in unsigned (data_width-1 downto 0);
|
||||
op2_in : in unsigned (data_width-1 downto 0);
|
||||
flags : out bcu_flags_t
|
||||
);
|
||||
end bcu;
|
||||
|
||||
architecture Behavioral of bcu is
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
begin
|
||||
|
||||
flags.eq <= '1' when op1_in = op2_in else '0' after 3 ns;
|
||||
flags.ltz <= op1_in(op1_in'left) after 1 ns;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
end Behavioral;
|
||||
@@ -0,0 +1,552 @@
|
||||
--------------------------------------------------------------------------
|
||||
-- Project: JIPS, a portable 32-bit RISC CPU written in VHDL
|
||||
-- This file: JIPS top file
|
||||
--
|
||||
-- Copyright (C) 2008 J. Ahrensfeld
|
||||
--
|
||||
-- This program is free software: you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation, either version 3 of the License, or
|
||||
-- (at your option) any later version.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
--
|
||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||
--
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.numeric_std.ALL;
|
||||
|
||||
library work;
|
||||
use work.mips_types.all;
|
||||
|
||||
entity biu is
|
||||
Generic
|
||||
(
|
||||
icache_size : natural := 2048; -- words
|
||||
icache_line : natural := 8; -- words
|
||||
dcache_size : natural := 2048; -- words
|
||||
dcache_line : natural := 8 -- words
|
||||
);
|
||||
Port
|
||||
(
|
||||
RST_I : in STD_LOGIC;
|
||||
CLK_I : in STD_LOGIC;
|
||||
ACK_I : in STD_LOGIC;
|
||||
SRDY_I : in STD_LOGIC;
|
||||
ADDR_O : out unsigned(31 downto 0);
|
||||
DAT_I : in unsigned(31 downto 0);
|
||||
DAT_O : out unsigned(31 downto 0);
|
||||
WE_O : out STD_LOGIC;
|
||||
SEL_O : out unsigned(3 downto 0);
|
||||
CYC_O : out STD_LOGIC;
|
||||
STB_O : out STD_LOGIC;
|
||||
MRDY_O : out STD_LOGIC;
|
||||
cop0_ctrl_in : in cop0_ctrl_out_t;
|
||||
cpu_clk : in STD_LOGIC;
|
||||
cpu_imem_err : out STD_LOGIC;
|
||||
cpu_imem_rdy : out STD_LOGIC;
|
||||
cpu_imem_en : in STD_LOGIC;
|
||||
cpu_imem_addr : in word_t;
|
||||
cpu_imem_din : out word_t;
|
||||
cpu_dmem_err : out STD_LOGIC;
|
||||
cpu_dmem_rdy : out STD_LOGIC;
|
||||
cpu_dmem_en : in STD_LOGIC;
|
||||
cpu_dmem_we : in STD_LOGIC;
|
||||
cpu_dmem_be : in unsigned(3 downto 0);
|
||||
cpu_dmem_dout : in word_t;
|
||||
cpu_dmem_din : out word_t;
|
||||
cpu_dmem_addr : in word_t
|
||||
);
|
||||
end biu;
|
||||
|
||||
architecture behavior of biu is
|
||||
|
||||
COMPONENT icache
|
||||
GENERIC
|
||||
(
|
||||
cache_size : natural; -- words
|
||||
line_size : natural -- words
|
||||
);
|
||||
PORT
|
||||
(
|
||||
RST_I : in STD_LOGIC;
|
||||
CLK_I : in STD_LOGIC;
|
||||
ACK_I : in STD_LOGIC;
|
||||
SRDY_I : in STD_LOGIC;
|
||||
MRDY_O : out STD_LOGIC;
|
||||
ADDR_O : out word_t;
|
||||
DAT_I : in word_t;
|
||||
STB_O : out STD_LOGIC;
|
||||
CYC_O : out STD_LOGIC;
|
||||
ctrl : in cache_ctrl_t;
|
||||
cpu_en : in STD_LOGIC;
|
||||
cpu_addr : in word_t;
|
||||
cpu_dout : out word_t;
|
||||
cpu_busy : out STD_LOGIC
|
||||
);
|
||||
END COMPONENT;
|
||||
|
||||
COMPONENT dcache
|
||||
GENERIC
|
||||
(
|
||||
cache_size : natural; -- words
|
||||
line_size : natural -- words
|
||||
);
|
||||
PORT
|
||||
(
|
||||
RST_I : in STD_LOGIC;
|
||||
CLK_I : in STD_LOGIC;
|
||||
ACK_I : in STD_LOGIC;
|
||||
SRDY_I : in STD_LOGIC;
|
||||
MRDY_O : out STD_LOGIC;
|
||||
ADDR_O : out word_t;
|
||||
DAT_I : in word_t;
|
||||
STB_O : out STD_LOGIC;
|
||||
CYC_O : out STD_LOGIC;
|
||||
ctrl : in cache_ctrl_t;
|
||||
cpu_en : in STD_LOGIC;
|
||||
cpu_we : in STD_LOGIC;
|
||||
cpu_be : in unsigned(3 downto 0);
|
||||
cpu_addr : in word_t;
|
||||
cpu_din : in word_t;
|
||||
cpu_dout : out word_t;
|
||||
cpu_busy : out STD_LOGIC
|
||||
);
|
||||
END COMPONENT;
|
||||
|
||||
type bus_state_t is (init, ready, icache_bus_access, dcache_bus_access, write_bus, read_bus, read_finish);
|
||||
|
||||
signal s, sn : bus_state_t;
|
||||
signal bus_idle : std_logic;
|
||||
signal busy : std_logic;
|
||||
signal dmem_be : unsigned(3 downto 0);
|
||||
signal dcache_dout : word_t;
|
||||
signal dcache_mem_gnt : std_logic;
|
||||
signal icache_mem_gnt : std_logic;
|
||||
signal dmem_mem_wr_gnt : std_logic;
|
||||
signal dmem_mem_rd_gnt : std_logic;
|
||||
signal dcache_busy : std_logic;
|
||||
signal icache_busy : std_logic;
|
||||
signal CYC_O_icache : std_logic;
|
||||
signal CYC_O_dcache : std_logic;
|
||||
signal CYC_O_dmem_rd : std_logic;
|
||||
signal CYC_O_dmem_wr : std_logic;
|
||||
signal SRDY_I_icache : std_logic;
|
||||
signal SRDY_I_dcache : std_logic;
|
||||
signal MRDY_O_icache : std_logic;
|
||||
signal MRDY_O_dcache : std_logic;
|
||||
signal ADDR_O_icache : word_t;
|
||||
signal ADDR_O_dcache : word_t;
|
||||
signal ADDR_O_dmem_rd : word_t;
|
||||
signal ADDR_O_dmem_wr : word_t;
|
||||
signal STB_O_icache : std_logic;
|
||||
signal STB_O_dcache : std_logic;
|
||||
signal STB_O_dmem_rd : std_logic;
|
||||
signal STB_O_dmem_wr : std_logic;
|
||||
signal DAT_I_dmem_rd : word_t;
|
||||
signal DAT_O_dmem_wr : word_t;
|
||||
signal SEL_O_dmem_wr : unsigned(3 downto 0);
|
||||
signal SEL_O_dmem_rd : unsigned(3 downto 0);
|
||||
signal dcached : std_logic;
|
||||
signal dcache_en2 : std_logic;
|
||||
signal dcache_en : std_logic;
|
||||
signal uncached_access : std_logic;
|
||||
signal ACK : std_logic;
|
||||
signal DAT : unsigned(31 downto 0);
|
||||
|
||||
type timeout_cnt_t is range 0 to 1E5-1;
|
||||
signal bus_timeout_cnt : timeout_cnt_t;
|
||||
signal bus_timeout : std_logic;
|
||||
|
||||
signal bout_fifo_din : unsigned(68 downto 0);
|
||||
signal bout_fifo_dout : unsigned(68 downto 0);
|
||||
signal bout_fifo_re : std_logic;
|
||||
signal bout_fifo_we : std_logic;
|
||||
signal bout_fifo_full : std_logic;
|
||||
signal bout_fifo_empty : std_logic;
|
||||
signal bout_rdy : std_logic;
|
||||
|
||||
signal bin_fifo_din : unsigned(31 downto 0);
|
||||
signal bin_fifo_dout : unsigned(31 downto 0);
|
||||
signal bin_fifo_re : std_logic;
|
||||
signal bin_fifo_we : std_logic;
|
||||
signal bin_fifo_full : std_logic;
|
||||
signal bin_fifo_empty : std_logic;
|
||||
|
||||
alias bout_fifo_addr_in is bout_fifo_din(31 downto 0);
|
||||
alias bout_fifo_data_in is bout_fifo_din(63 downto 32);
|
||||
alias bout_fifo_sel_in is bout_fifo_din(67 downto 64);
|
||||
alias bout_fifo_we_in is bout_fifo_din(68);
|
||||
alias bout_fifo_addr_out is bout_fifo_dout(31 downto 0);
|
||||
alias bout_fifo_data_out is bout_fifo_dout(63 downto 32);
|
||||
alias bout_fifo_sel_out is bout_fifo_dout(67 downto 64);
|
||||
alias bout_fifo_we_out is bout_fifo_dout(68);
|
||||
|
||||
signal write_fifo_din : unsigned(67 downto 0);
|
||||
signal write_fifo_dout : unsigned(67 downto 0);
|
||||
signal write_fifo_re : std_logic;
|
||||
signal write_fifo_we : std_logic;
|
||||
signal write_fifo_full : std_logic;
|
||||
signal write_fifo_empty : std_logic;
|
||||
|
||||
alias write_fifo_addr_in is write_fifo_din(31 downto 0);
|
||||
alias write_fifo_data_in is write_fifo_din(63 downto 32);
|
||||
alias write_fifo_sel_in is write_fifo_din(67 downto 64);
|
||||
alias write_fifo_addr_out is write_fifo_dout(31 downto 0);
|
||||
alias write_fifo_data_out is write_fifo_dout(63 downto 32);
|
||||
alias write_fifo_sel_out is write_fifo_dout(67 downto 64);
|
||||
|
||||
signal read_cycle : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
read_cyc_register:
|
||||
process(cpu_clk)
|
||||
begin
|
||||
if rising_edge(cpu_clk) then
|
||||
if RST_I = '1' then
|
||||
read_cycle <= '0';
|
||||
else
|
||||
read_cycle <= (dmem_mem_rd_gnt and CYC_O_dmem_rd)
|
||||
or (dcache_mem_gnt and CYC_O_dcache)
|
||||
or (icache_mem_gnt and CYC_O_icache);
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
MRDY_O <= not bin_fifo_full;
|
||||
CYC_O <= not bout_fifo_empty or read_cycle;
|
||||
STB_O <= not bout_fifo_empty;
|
||||
ADDR_O <= bout_fifo_addr_out;
|
||||
DAT_O <= bout_fifo_data_out;
|
||||
SEL_O <= bout_fifo_sel_out;
|
||||
WE_O <= bout_fifo_we_out;
|
||||
|
||||
cpu_imem_rdy <= not icache_busy after 4.5 ns;
|
||||
busy <= CYC_O_dmem_rd or dcache_busy or (write_fifo_full);
|
||||
cpu_dmem_rdy <= not busy after 4.5 ns;
|
||||
|
||||
inst_icache : icache
|
||||
GENERIC MAP
|
||||
(
|
||||
cache_size => icache_size, -- words
|
||||
line_size => icache_line -- words
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
CLK_I => cpu_clk,
|
||||
RST_I => RST_I,
|
||||
STB_O => STB_O_icache,
|
||||
CYC_O => CYC_O_icache,
|
||||
ADDR_O => ADDR_O_icache,
|
||||
MRDY_O => MRDY_O_icache,
|
||||
DAT_I => DAT,
|
||||
ACK_I => ACK,
|
||||
SRDY_I => SRDY_I_icache,
|
||||
ctrl => cop0_ctrl_in.icache,
|
||||
cpu_en => cpu_imem_en,
|
||||
cpu_addr => cpu_imem_addr,
|
||||
cpu_dout => cpu_imem_din,
|
||||
cpu_busy => icache_busy
|
||||
);
|
||||
|
||||
SRDY_I_icache <= bout_rdy and icache_mem_gnt;
|
||||
|
||||
inst_dcache : dcache
|
||||
GENERIC MAP
|
||||
(
|
||||
cache_size => dcache_size, -- words
|
||||
line_size => dcache_line -- words
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
CLK_I => cpu_clk,
|
||||
RST_I => RST_I,
|
||||
CYC_O => CYC_O_dcache,
|
||||
STB_O => STB_O_dcache,
|
||||
ADDR_O => ADDR_O_dcache,
|
||||
MRDY_O => MRDY_O_dcache,
|
||||
DAT_I => DAT,
|
||||
ACK_I => ACK,
|
||||
SRDY_I => SRDY_I_dcache,
|
||||
ctrl => cop0_ctrl_in.dcache,
|
||||
cpu_en => dcache_en,
|
||||
cpu_we => cpu_dmem_we,
|
||||
cpu_be => cpu_dmem_be,
|
||||
cpu_addr => cpu_dmem_addr,
|
||||
cpu_din => cpu_dmem_dout,
|
||||
cpu_dout => dcache_dout,
|
||||
cpu_busy => dcache_busy
|
||||
);
|
||||
|
||||
SRDY_I_dcache <= bout_rdy and dcache_mem_gnt;
|
||||
|
||||
dcached <= '1' when cpu_dmem_addr(31 downto 29) /= "101" else '0';
|
||||
cpu_dmem_din <= dcache_dout when uncached_access = '0' else DAT_I_dmem_rd;
|
||||
dcache_en <= dcached and cpu_dmem_en and dcache_en2; -- or write_fifo_full);
|
||||
|
||||
-- Instantiate synchronous FIFO
|
||||
inst_bin_fifo: entity work.fifo_async
|
||||
GENERIC MAP
|
||||
(
|
||||
addr_width => 4,
|
||||
data_width => 32,
|
||||
do_last_read_update => true
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
rst => RST_I,
|
||||
clk_w => CLK_I,
|
||||
clk_r => cpu_clk,
|
||||
we => bin_fifo_we,
|
||||
re => bin_fifo_re,
|
||||
fifo_full => bin_fifo_full,
|
||||
fifo_empty => bin_fifo_empty,
|
||||
fifo_afull => open,
|
||||
fifo_aempty => open,
|
||||
data_w => bin_fifo_din,
|
||||
data_r => bin_fifo_dout
|
||||
);
|
||||
|
||||
bin_fifo_din <= DAT_I;
|
||||
DAT <= bin_fifo_dout;
|
||||
ACK <= not bin_fifo_empty;
|
||||
bin_fifo_we <= ACK_I;
|
||||
bin_fifo_re <= dmem_mem_rd_gnt or MRDY_O_icache or MRDY_O_dcache;
|
||||
|
||||
-- Instantiate synchronous FIFO
|
||||
inst_bout_fifo: entity work.fifo_async
|
||||
GENERIC MAP
|
||||
(
|
||||
addr_width => 4,
|
||||
data_width => 69,
|
||||
do_last_read_update => false
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
rst => RST_I,
|
||||
clk_w => cpu_clk,
|
||||
clk_r => CLK_I,
|
||||
we => bout_fifo_we,
|
||||
re => bout_fifo_re,
|
||||
fifo_full => bout_fifo_full,
|
||||
fifo_empty => bout_fifo_empty,
|
||||
fifo_afull => open,
|
||||
fifo_aempty => open,
|
||||
data_w => bout_fifo_din,
|
||||
data_r => bout_fifo_dout
|
||||
);
|
||||
bout_rdy <= not bout_fifo_full;
|
||||
bout_fifo_re <= SRDY_I and not bin_fifo_full;
|
||||
|
||||
bout_fifo_we <= STB_O_dmem_wr or STB_O_dmem_rd or STB_O_dcache or STB_O_icache;
|
||||
|
||||
bout_fifo_data_in <= DAT_O_dmem_wr when dmem_mem_wr_gnt = '1' else (others => '-');
|
||||
|
||||
bout_fifo_addr_in <= ADDR_O_dmem_wr when dmem_mem_wr_gnt = '1' else
|
||||
ADDR_O_dmem_rd when dmem_mem_rd_gnt = '1' else
|
||||
ADDR_O_dcache when dcache_mem_gnt = '1' else
|
||||
ADDR_O_icache when icache_mem_gnt = '1' else (others => '-');
|
||||
|
||||
bout_fifo_sel_in <= SEL_O_dmem_wr when dmem_mem_wr_gnt = '1' else
|
||||
SEL_O_dmem_rd when dmem_mem_rd_gnt = '1' else (others => '1');
|
||||
|
||||
bout_fifo_we_in <= '1' when dmem_mem_wr_gnt = '1' else '0';
|
||||
|
||||
-- Instantiate synchronous FIFO
|
||||
inst_write_fifo: entity work.fifo_sync
|
||||
GENERIC MAP
|
||||
(
|
||||
addr_width => 4,
|
||||
data_width => 68,
|
||||
do_last_read_update => true
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
rst => RST_I,
|
||||
clk => cpu_clk,
|
||||
we => write_fifo_we,
|
||||
re => write_fifo_re,
|
||||
fifo_full => write_fifo_full,
|
||||
fifo_empty => write_fifo_empty,
|
||||
fifo_afull => open,
|
||||
fifo_aempty => open,
|
||||
data_w => write_fifo_din,
|
||||
data_r => write_fifo_dout
|
||||
);
|
||||
|
||||
CYC_O_dmem_wr <= not write_fifo_empty;
|
||||
DAT_O_dmem_wr <= write_fifo_data_out;
|
||||
ADDR_O_dmem_wr <= write_fifo_addr_out;
|
||||
SEL_O_dmem_wr <= write_fifo_sel_out;
|
||||
|
||||
write_fifo_data_in <= cpu_dmem_dout;
|
||||
write_fifo_addr_in <= cpu_dmem_addr;
|
||||
write_fifo_sel_in <= cpu_dmem_be;
|
||||
write_fifo_re <= STB_O_dmem_wr;
|
||||
write_fifo_we <= cpu_dmem_en and not busy and cpu_dmem_we;
|
||||
|
||||
dmem_rd_flags:
|
||||
process(cpu_clk)
|
||||
begin
|
||||
if rising_edge(cpu_clk) then
|
||||
uncached_access <= '0';
|
||||
if RST_I = '1' then
|
||||
CYC_O_dmem_rd <= '0';
|
||||
dcache_en2 <= '1';
|
||||
else
|
||||
if ACK = '1' and dmem_mem_rd_gnt = '1' then
|
||||
uncached_access <= '1';
|
||||
CYC_O_dmem_rd <= '0';
|
||||
dcache_en2 <= '1';
|
||||
end if;
|
||||
if cpu_dmem_en = '1' and busy = '0' and cpu_dmem_we = '0' then
|
||||
if dcached = '0' then
|
||||
CYC_O_dmem_rd <= '1';
|
||||
dcache_en2 <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
dmem_rd_data:
|
||||
process(cpu_clk)
|
||||
begin
|
||||
if rising_edge(cpu_clk) then
|
||||
if RST_I = '1' then
|
||||
DAT_I_dmem_rd <= (others => '0');
|
||||
elsif ACK = '1' and CYC_O_dmem_rd = '1' then
|
||||
DAT_I_dmem_rd <= DAT;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
dmem_rd_regs:
|
||||
process(cpu_clk)
|
||||
begin
|
||||
if rising_edge(cpu_clk) then
|
||||
if cpu_dmem_en = '1' and busy = '0' then
|
||||
ADDR_O_dmem_rd <= cpu_dmem_addr;
|
||||
SEL_O_dmem_rd <= cpu_dmem_be;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
bus_state_next:
|
||||
process(cpu_clk)
|
||||
begin
|
||||
if rising_edge(cpu_clk) then
|
||||
if RST_I = '1' then
|
||||
s <= init;
|
||||
else
|
||||
s <= sn;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
bus_state:
|
||||
process(s, CYC_O_icache, CYC_O_dcache, CYC_O_dmem_wr, CYC_O_dmem_rd, bout_rdy, ACK)
|
||||
begin
|
||||
|
||||
icache_mem_gnt <= '0';
|
||||
dcache_mem_gnt <= '0';
|
||||
dmem_mem_rd_gnt <= '0';
|
||||
dmem_mem_wr_gnt <= '0';
|
||||
STB_O_dmem_rd <= '0';
|
||||
STB_O_dmem_wr <= '0';
|
||||
bus_idle <= '0';
|
||||
sn <= s;
|
||||
case s is
|
||||
when init =>
|
||||
sn <= ready;
|
||||
when ready =>
|
||||
bus_idle <= '1';
|
||||
if CYC_O_dmem_wr = '1' then
|
||||
sn <= write_bus;
|
||||
elsif CYC_O_dmem_rd = '1' then
|
||||
sn <= read_bus;
|
||||
elsif CYC_O_icache = '1' then
|
||||
sn <= icache_bus_access;
|
||||
elsif CYC_O_dcache = '1' then
|
||||
sn <= dcache_bus_access;
|
||||
end if;
|
||||
when icache_bus_access =>
|
||||
icache_mem_gnt <= '1';
|
||||
if CYC_O_icache = '0' then
|
||||
sn <= ready;
|
||||
end if;
|
||||
when dcache_bus_access =>
|
||||
dcache_mem_gnt <= '1';
|
||||
if CYC_O_dcache = '0' then
|
||||
sn <= ready;
|
||||
end if;
|
||||
when write_bus =>
|
||||
dmem_mem_wr_gnt <= '1';
|
||||
if CYC_O_dmem_wr = '1' then
|
||||
if bout_rdy = '1' then
|
||||
STB_O_dmem_wr <= '1';
|
||||
end if;
|
||||
else
|
||||
sn <= ready;
|
||||
end if;
|
||||
when read_bus =>
|
||||
dmem_mem_rd_gnt <= '1';
|
||||
if bout_rdy = '1' then
|
||||
STB_O_dmem_rd <= '1';
|
||||
sn <= read_finish;
|
||||
end if;
|
||||
when read_finish =>
|
||||
dmem_mem_rd_gnt <= '1';
|
||||
if ACK = '1' then
|
||||
sn <= ready;
|
||||
end if;
|
||||
when others =>
|
||||
sn <= ready;
|
||||
end case;
|
||||
|
||||
end process;
|
||||
|
||||
bus_timeout_counter:
|
||||
process(cpu_clk)
|
||||
begin
|
||||
if rising_edge(cpu_clk) then
|
||||
if bus_idle = '0' then
|
||||
if bus_timeout_cnt /= 0 then
|
||||
bus_timeout_cnt <= bus_timeout_cnt - 1;
|
||||
else
|
||||
bus_timeout <= '1';
|
||||
end if;
|
||||
else
|
||||
bus_timeout_cnt <= timeout_cnt_t'high;
|
||||
bus_timeout <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
bus_err:
|
||||
process(cpu_clk)
|
||||
begin
|
||||
if rising_edge(cpu_clk) then
|
||||
if RST_I = '1' then
|
||||
cpu_imem_err <= '0';
|
||||
cpu_dmem_err <= '0';
|
||||
elsif bus_timeout = '1' then
|
||||
cpu_imem_err <= icache_mem_gnt;
|
||||
cpu_dmem_err <= dcache_mem_gnt or dmem_mem_wr_gnt or dmem_mem_rd_gnt;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
end behavior;
|
||||
@@ -0,0 +1,546 @@
|
||||
--------------------------------------------------------------------------
|
||||
-- Project: JIPS, a portable 32-bit RISC CPU written in VHDL
|
||||
-- This file: The arithmetic logic unit
|
||||
--
|
||||
-- Copyright (C) 2008 J. Ahrensfeld
|
||||
--
|
||||
-- This program is free software: you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation, either version 3 of the License, or
|
||||
-- (at your option) any later version.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
--
|
||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||
--
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.numeric_std.ALL;
|
||||
|
||||
use work.mips_types.all;
|
||||
use work.mips_instr.all;
|
||||
|
||||
entity cop is
|
||||
Generic
|
||||
(
|
||||
icache_size : natural := 2048; -- words
|
||||
icache_line : natural := 8; -- words
|
||||
dcache_size : natural := 2048; -- words
|
||||
dcache_line : natural := 8 -- words
|
||||
);
|
||||
Port
|
||||
(
|
||||
rst : in STD_LOGIC;
|
||||
clk : in STD_LOGIC;
|
||||
eb : in STD_LOGIC;
|
||||
int : in unsigned(5 downto 0);
|
||||
nmi : in STD_LOGIC;
|
||||
ir_en : in STD_LOGIC;
|
||||
ir : in word_t;
|
||||
ctrl_in : in cop0_ctrl_in_t;
|
||||
ctrl_out : out cop0_ctrl_out_t;
|
||||
din : in word_t;
|
||||
dout : out word_t
|
||||
);
|
||||
end cop;
|
||||
|
||||
architecture Behavioral of cop is
|
||||
|
||||
signal epc : word_t;
|
||||
signal cause : word_t;
|
||||
signal status : word_t;
|
||||
signal imem_addr : word_t;
|
||||
signal imem_addr_we : STD_LOGIC;
|
||||
signal BadVAddr : word_t;
|
||||
signal exc_code : unsigned(4 downto 0);
|
||||
signal test_reg : word_t;
|
||||
signal test_reg_we : STD_LOGIC;
|
||||
signal stat_reg_we : STD_LOGIC;
|
||||
signal eflags_reg_we : STD_LOGIC;
|
||||
signal epc_reg_we : STD_LOGIC;
|
||||
signal code_reg_we : STD_LOGIC;
|
||||
signal ip_reg_we : STD_LOGIC;
|
||||
signal bd : STD_LOGIC;
|
||||
signal sw_int : unsigned(1 downto 0);
|
||||
signal ip : unsigned(7 downto 0);
|
||||
signal im : unsigned(7 downto 0);
|
||||
signal status_save : STD_LOGIC;
|
||||
signal status_rest : STD_LOGIC;
|
||||
signal eflags : exc_flags_t;
|
||||
signal EB_reg : STD_LOGIC;
|
||||
signal icache_info : unsigned(7 downto 0);
|
||||
signal dcache_info : unsigned(7 downto 0);
|
||||
signal reg_rptr : reg_ptr_t;
|
||||
signal reg_wptr : reg_ptr_t;
|
||||
signal inject_exc : STD_LOGIC;
|
||||
signal latch_vect_en : STD_LOGIC;
|
||||
signal int_nmi : STD_LOGIC;
|
||||
signal nmi_asserted : std_logic;
|
||||
|
||||
type cop_pipe_t is record
|
||||
opc : opcode_t;
|
||||
RFE : std_logic;
|
||||
CO : std_logic;
|
||||
reg_ptr : reg_ptr_t;
|
||||
rs : reg_ptr_t;
|
||||
rd : reg_ptr_t;
|
||||
rt : reg_ptr_t;
|
||||
func : func_t;
|
||||
we : std_logic;
|
||||
re : std_logic;
|
||||
cs : std_logic;
|
||||
end record;
|
||||
|
||||
signal cop_pipe_ID : cop_pipe_t;
|
||||
signal cop_pipe_EX : cop_pipe_t;
|
||||
|
||||
function eval_int(ip : unsigned) return STD_LOGIC is
|
||||
variable result : STD_LOGIC;
|
||||
begin
|
||||
result := '0';
|
||||
for i in ip'range loop
|
||||
result := result or ip(i);
|
||||
end loop;
|
||||
|
||||
return result;
|
||||
end eval_int;
|
||||
|
||||
type exc_state_t is (exc_idle, exc_pipe_flush, exc_commit, exc_inject, exc_enter, exc_leave, exc_left);
|
||||
signal exc_state, exc_staten : exc_state_t;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
begin
|
||||
|
||||
icache_info <= "00" & to_unsigned(lg2(icache_line), 3) & to_unsigned(lg2(icache_size)-8, 3);
|
||||
dcache_info <= "00" & to_unsigned(lg2(dcache_line), 3) & to_unsigned(lg2(dcache_size)-8, 3);
|
||||
cop_pipe_ID.cs <= ir_en;
|
||||
cop_pipe_ID.opc <= extract_opc(ir);
|
||||
cop_pipe_ID.rs <= extract_rs(ir);
|
||||
cop_pipe_ID.rd <= extract_rd(ir);
|
||||
cop_pipe_ID.rt <= extract_rt(ir);
|
||||
cop_pipe_ID.func <= extract_func(ir);
|
||||
cop_pipe_ID.CO <= ir(25);
|
||||
cop_pipe_ID.re <= cop_pipe_ID.cs when (cop_pipe_ID.opc = "111000" or (cop_pipe_ID.opc = "010000" and cop_pipe_ID.rs = "00000")) else '0';
|
||||
cop_pipe_ID.we <= cop_pipe_ID.cs when (cop_pipe_ID.opc = "110000" or (cop_pipe_ID.opc = "010000" and cop_pipe_ID.rs = "00100")) else '0';
|
||||
cop_pipe_ID.RFE <= cop_pipe_ID.cs when (cop_pipe_ID.CO = '1' and cop_pipe_ID.func = "010000") else '0';
|
||||
ctrl_out.EB <= EB_reg xor (status(25) and status(1));
|
||||
ctrl_out.user_mode <= status(1);
|
||||
ctrl_out.exc_inject <= inject_exc or rst;
|
||||
cop_pipe_ID.reg_ptr <= cop_pipe_ID.rd when cop_pipe_ID.opc = "010000" else cop_pipe_ID.rt;
|
||||
|
||||
im <= status(15 downto 8);
|
||||
cause <= bd & (30 downto 16 => '0') & ip & '0' & exc_code & "00";
|
||||
|
||||
eflags.Ov <= ctrl_in.events.alu_ovf or ctrl_in.events.alu_uvf;
|
||||
eflags.DAdEL <= ctrl_in.events.data_load_err;
|
||||
eflags.DAdES <= ctrl_in.events.data_store_err;
|
||||
eflags.IAdEL <= ctrl_in.events.inst_load_err;
|
||||
eflags.IAdEK <= ctrl_in.events.inst_priv_addr and status(1);
|
||||
eflags.Sys <= ctrl_in.events.syscall;
|
||||
eflags.Bp <= ctrl_in.events.break;
|
||||
eflags.RI <= ctrl_in.events.illegal;
|
||||
eflags.Int <= ctrl_in.events.int;
|
||||
|
||||
-- NMI/RST transition detector
|
||||
proc_nmi_transition:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
int_nmi <= '0';
|
||||
nmi_asserted <= '0';
|
||||
elsif latch_vect_en = '1' then
|
||||
int_nmi <= '0';
|
||||
elsif nmi_asserted = '1' then
|
||||
if nmi = '0' then
|
||||
nmi_asserted <= '0';
|
||||
int_nmi <= '1';
|
||||
end if;
|
||||
elsif nmi = '1' then
|
||||
nmi_asserted <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
|
||||
-- Main exception FSM
|
||||
proc_exc_state:
|
||||
process(exc_state, ctrl_in, cop_pipe_ID)
|
||||
begin
|
||||
|
||||
ctrl_out.exc_commit <= '0';
|
||||
ctrl_out.exc_pending <= '0';
|
||||
ctrl_out.exc_exit <= '0';
|
||||
epc_reg_we <= '0';
|
||||
code_reg_we <= '0';
|
||||
status_save <= '0';
|
||||
status_rest <= '0';
|
||||
inject_exc <= '0';
|
||||
imem_addr_we <= '0';
|
||||
latch_vect_en <= '0';
|
||||
|
||||
exc_staten <= exc_state;
|
||||
|
||||
case exc_state is
|
||||
|
||||
when exc_idle =>
|
||||
if cop_pipe_ID.RFE = '1' then
|
||||
exc_staten <= exc_leave;
|
||||
ctrl_out.exc_exit <= '1';
|
||||
ctrl_out.exc_commit <= '1';
|
||||
elsif ctrl_in.exc_req = '1' then
|
||||
exc_staten <= exc_pipe_flush;
|
||||
imem_addr_we <= '1';
|
||||
end if;
|
||||
|
||||
when exc_pipe_flush =>
|
||||
ctrl_out.exc_pending <= '1';
|
||||
ctrl_out.exc_commit <= '1';
|
||||
if ctrl_in.exc_ack = '1' then
|
||||
exc_staten <= exc_commit;
|
||||
end if;
|
||||
|
||||
when exc_commit =>
|
||||
latch_vect_en <= '1';
|
||||
ctrl_out.exc_pending <= '1';
|
||||
ctrl_out.exc_commit <= '1';
|
||||
if ctrl_in.sdu.ID_stall = '0' then
|
||||
exc_staten <= exc_inject;
|
||||
end if;
|
||||
|
||||
when exc_inject =>
|
||||
ctrl_out.exc_pending <= '1';
|
||||
ctrl_out.exc_commit <= '1';
|
||||
code_reg_we <= '1';
|
||||
status_save <= '1';
|
||||
epc_reg_we <= '1';
|
||||
inject_exc <= '1';
|
||||
exc_staten <= exc_enter;
|
||||
|
||||
when exc_enter =>
|
||||
ctrl_out.exc_pending <= '1';
|
||||
exc_staten <= exc_idle;
|
||||
|
||||
when exc_leave =>
|
||||
exc_staten <= exc_left;
|
||||
status_rest <= '1';
|
||||
ctrl_out.exc_exit <= '1';
|
||||
ctrl_out.exc_commit <= '1';
|
||||
|
||||
when exc_left =>
|
||||
exc_staten <= exc_idle;
|
||||
|
||||
when others =>
|
||||
exc_staten <= exc_idle;
|
||||
|
||||
end case;
|
||||
end process;
|
||||
|
||||
proc_exc_state_next:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
exc_state <= exc_idle;
|
||||
else
|
||||
exc_state <= exc_staten;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- Endian switch sampled at hard reset
|
||||
sample_endian:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
EB_reg <= eb;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- Sample imem_addr for later use
|
||||
exception_last_imem_addr:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if imem_addr_we = '1' then
|
||||
imem_addr <= ctrl_in.imem_addr;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- EPC reg and BD-bit write
|
||||
cop_exception_epc_write:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
bd <= '0';
|
||||
epc <= (others => '0');
|
||||
elsif epc_reg_we = '1' then
|
||||
bd <= '0';
|
||||
epc <= ctrl_in.epc_mem;
|
||||
if ctrl_in.bd_wb = '1' then
|
||||
bd <= '1';
|
||||
epc <= ctrl_in.epc_wb;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- BadVaddr and exception code write
|
||||
cop_exception_map:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
exc_code <= (others => '0');
|
||||
BadVAddr <= (others => '0');
|
||||
elsif code_reg_we = '1' then
|
||||
if eflags.Ov = '1' then
|
||||
exc_code <= "01100";
|
||||
elsif eflags.Sys = '1' then
|
||||
exc_code <= "01000";
|
||||
elsif eflags.Bp = '1' then
|
||||
exc_code <= "01001";
|
||||
elsif eflags.RI = '1' then
|
||||
exc_code <= "01010";
|
||||
elsif eflags.IAdEL = '1' then
|
||||
exc_code <= "00100";
|
||||
BadVAddr <= imem_addr;
|
||||
elsif eflags.IAdEK = '1' then
|
||||
exc_code <= "00100";
|
||||
BadVAddr <= imem_addr;
|
||||
elsif eflags.DAdEL = '1' then
|
||||
exc_code <= "00100";
|
||||
BadVAddr <= ctrl_in.dmem_addr;
|
||||
elsif eflags.DAdES = '1' then
|
||||
exc_code <= "00101";
|
||||
BadVAddr <= ctrl_in.dmem_addr;
|
||||
elsif eflags.Int = '1' then
|
||||
exc_code <= "00000";
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
ctrl_out.icache.inv_addr <= test_reg;
|
||||
ctrl_out.dcache.inv_addr <= test_reg;
|
||||
|
||||
-- Custom I/D-Cache operations: invalidate all/line
|
||||
cop_cache_op:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
ctrl_out.icache.inv_at <= '0';
|
||||
ctrl_out.icache.inv_all <= '0';
|
||||
ctrl_out.dcache.inv_at <= '0';
|
||||
ctrl_out.dcache.inv_all <= '0';
|
||||
if cop_pipe_ID.cs = '1' and cop_pipe_ID.CO = '1' then
|
||||
case cop_pipe_ID.func is
|
||||
when "100000" =>
|
||||
ctrl_out.icache.inv_all <= '1';
|
||||
when "100001" =>
|
||||
ctrl_out.icache.inv_at <= '1';
|
||||
when "100010" =>
|
||||
ctrl_out.dcache.inv_all <= '1';
|
||||
when "100011" =>
|
||||
ctrl_out.dcache.inv_at <= '1';
|
||||
|
||||
when others => null;
|
||||
end case;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- IP register write and signalling Int to pipeline
|
||||
cop_ip_reg_write:
|
||||
process(clk)
|
||||
variable ip_v : unsigned(7 downto 0);
|
||||
variable ipm_v : unsigned(7 downto 0);
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
sw_int <= (others => '0');
|
||||
elsif ctrl_in.sdu.WB_nop = '0' then
|
||||
if ip_reg_we = '1' then
|
||||
sw_int <= din(9 downto 8);
|
||||
end if;
|
||||
end if;
|
||||
ip_v := (int & sw_int);
|
||||
ipm_v := ip_v and im;
|
||||
ip <= ip_v;
|
||||
ctrl_out.int <= (eval_int(ipm_v) and status(0));
|
||||
ctrl_out.NMI <= int_nmi;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- Exception vector dispatch
|
||||
cop_exc_vector:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
ctrl_out.exc_vec <= X"BFC00000";
|
||||
elsif latch_vect_en = '1' then
|
||||
if ctrl_in.events.nmi = '1' then
|
||||
ctrl_out.exc_vec <= X"BFC00000";
|
||||
else
|
||||
ctrl_out.exc_vec <= X"80000080";
|
||||
if status(22) = '1' then
|
||||
ctrl_out.exc_vec <= X"BFC00180";
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- Cop pipeline
|
||||
cop_pipe:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
cop_pipe_EX.cs <= '0';
|
||||
cop_pipe_EX.we <= '0';
|
||||
cop_pipe_EX.re <= '0';
|
||||
elsif ctrl_in.sdu.stall_all = '0' then
|
||||
cop_pipe_EX <= cop_pipe_ID;
|
||||
if cop_pipe_ID.we = '1' then
|
||||
reg_wptr <= cop_pipe_ID.reg_ptr;
|
||||
end if;
|
||||
if cop_pipe_ID.re = '1' then
|
||||
reg_rptr <= cop_pipe_ID.reg_ptr;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- COP Register read
|
||||
cop_register_read:
|
||||
process(reg_rptr, BadVAddr, status, cause, epc, dcache_info, icache_info, test_reg)
|
||||
variable reg : word_t;
|
||||
begin
|
||||
|
||||
case reg_rptr is
|
||||
when "01000" => -- BadVAddr
|
||||
reg := BadVAddr;
|
||||
|
||||
when "01100" => -- Status
|
||||
reg := status;
|
||||
|
||||
when "01101" => -- Cause
|
||||
reg := cause;
|
||||
|
||||
when "01110" => -- EPC (Exception Program Counter)
|
||||
reg := epc;
|
||||
|
||||
when "01111" => -- PRId (Processor Revision Register)
|
||||
reg := dcache_info & icache_info & X"02" & to_unsigned(REVISION ,8);
|
||||
|
||||
when "11111" => -- test_reg
|
||||
reg := test_reg;
|
||||
|
||||
when others =>
|
||||
reg := (others => '-');
|
||||
|
||||
end case;
|
||||
|
||||
dout <= reg after 2 ns;
|
||||
|
||||
end process;
|
||||
|
||||
-- COP Register write strobe generation
|
||||
cop_we_gen:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
test_reg_we <= '0';
|
||||
stat_reg_we <= '0';
|
||||
ip_reg_we <= '0';
|
||||
elsif ctrl_in.sdu.stall_all = '0' then
|
||||
test_reg_we <= '0';
|
||||
stat_reg_we <= '0';
|
||||
ip_reg_we <= '0';
|
||||
if cop_pipe_EX.we = '1' then
|
||||
|
||||
case reg_wptr is
|
||||
|
||||
when "01100" =>
|
||||
stat_reg_we <= '1'; -- not status(1) or status(28);
|
||||
when "01101" =>
|
||||
ip_reg_we <= '1'; -- not status(1) or status(28);
|
||||
when "11111" =>
|
||||
test_reg_we <= '1'; -- not status(1) or status(28);
|
||||
when others => null;
|
||||
|
||||
end case;
|
||||
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- COP Test Register
|
||||
cop_test_reg_write:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
test_reg <= (others => '0');
|
||||
elsif ctrl_in.sdu.WB_nop = '0' then
|
||||
if test_reg_we = '1' then
|
||||
test_reg <= din;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- COP Status Register
|
||||
cop_status_reg_write:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
status <= X"00600000";
|
||||
elsif status_save = '1' then
|
||||
if ctrl_in.events.nmi = '0' then
|
||||
status(5 downto 4) <= status(3 downto 2);
|
||||
status(3 downto 2) <= status(1 downto 0);
|
||||
else
|
||||
status(22) <= '1';
|
||||
end if;
|
||||
status(1 downto 0) <= "00";
|
||||
elsif status_rest = '1' then
|
||||
status(1 downto 0) <= status(3 downto 2);
|
||||
status(3 downto 2) <= status(5 downto 4);
|
||||
elsif ctrl_in.sdu.WB_nop = '0' then
|
||||
if stat_reg_we = '1' then
|
||||
if status(1) = '0' then
|
||||
status(0) <= din(0); -- IEc
|
||||
status(1) <= din(1); -- KUc
|
||||
status(2) <= din(2); -- IEp
|
||||
status(3) <= din(3); -- KUp
|
||||
status(4) <= din(4); -- IEo
|
||||
status(5) <= din(5); -- KUo
|
||||
end if;
|
||||
status(15 downto 8) <= din(15 downto 8); -- IM
|
||||
status(22) <= din(22); -- BEV
|
||||
status(25) <= din(25); -- RE
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
end Behavioral;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,454 @@
|
||||
--------------------------------------------------------------------------
|
||||
-- Project: JIPS, a portable 32-bit RISC CPU written in VHDL
|
||||
-- This file: The arithmetic logic unit
|
||||
--
|
||||
-- Copyright (C) 2007 J. Ahrensfeld
|
||||
--
|
||||
-- This program is free software: you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation, either version 3 of the License, or
|
||||
-- (at your option) any later version.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
--
|
||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||
--
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.numeric_std.ALL;
|
||||
|
||||
use work.mips_types.all;
|
||||
|
||||
entity muldiv is
|
||||
Port
|
||||
(
|
||||
rst : in std_logic;
|
||||
clk : in std_logic;
|
||||
hilo_we : in std_logic;
|
||||
din_hi : in word_t;
|
||||
din_lo : in word_t;
|
||||
mul_divn : in std_logic;
|
||||
start : in std_logic;
|
||||
s_un : in std_logic;
|
||||
hilo_sel : in std_logic;
|
||||
busy : out std_logic;
|
||||
dout : out word_t
|
||||
);
|
||||
end muldiv;
|
||||
|
||||
architecture Behavioral of muldiv is
|
||||
|
||||
subtype pprod_t is unsigned (39 downto 0);
|
||||
subtype prod_t is unsigned (63 downto 0);
|
||||
subtype byte_t is unsigned (7 downto 0);
|
||||
|
||||
type pprod_array_t is array (natural range <>) of pprod_t;
|
||||
type word_array_t is array (natural range <>) of word_t;
|
||||
type byte_array_t is array (natural range <>) of byte_t;
|
||||
|
||||
signal pprod : pprod_array_t(0 to 3);
|
||||
signal sign1 : std_logic;
|
||||
signal sign2 : std_logic;
|
||||
signal s1_r : std_logic;
|
||||
signal s2_r : std_logic;
|
||||
signal sr_r : std_logic;
|
||||
signal cy : unsigned (3 downto 0);
|
||||
signal mul_start : std_logic;
|
||||
signal mul_en : std_logic;
|
||||
signal sum_en : std_logic;
|
||||
signal pre_sum_vld : std_logic;
|
||||
signal pp_reg : unsigned (63 downto 8);
|
||||
signal pre_const : word_array_t(0 to 1);
|
||||
signal result : prod_t;
|
||||
signal add_op1 : unsigned (39 downto 0);
|
||||
signal add_op2 : unsigned (39 downto 0);
|
||||
signal add_res : unsigned (39 downto 0);
|
||||
signal ppadd_op1 : word_array_t(0 to 3);
|
||||
signal ppadd_op2 : word_array_t(0 to 3);
|
||||
signal ppadd_res : word_array_t(0 to 3);
|
||||
signal ppadd_cyi : unsigned (3 downto 0);
|
||||
signal ppadd_cyo : unsigned (3 downto 0);
|
||||
|
||||
signal pp_op1_r : word_t;
|
||||
signal pp_op1 : word_t;
|
||||
signal pp_op2 : word_t;
|
||||
signal pp_op2_r : byte_array_t(0 to 3);
|
||||
signal bsy : std_logic;
|
||||
|
||||
signal div_add_res : unsigned (32 downto 0);
|
||||
signal div_add_op1 : unsigned (32 downto 0);
|
||||
signal div_add_op2 : unsigned (32 downto 0);
|
||||
signal div_add_cyi : std_logic;
|
||||
signal div_qbit : std_logic;
|
||||
signal div_start : std_logic;
|
||||
signal div_en : std_logic;
|
||||
|
||||
signal div_A : unsigned (32 downto 0);
|
||||
signal div_M : unsigned (32 downto 0);
|
||||
signal div_M_n : unsigned (32 downto 0);
|
||||
signal div_Q : word_t;
|
||||
|
||||
type md_state_t is (md_rdy, mul_pre1, mul_pre2, mul_pp, mul_sum, div_process, div_post1, div_post2, div_post3);
|
||||
signal s, sn : md_state_t;
|
||||
signal cycle_cnt : natural range 0 to 31;
|
||||
signal cycle_cnt_preset : natural range 0 to 31;
|
||||
signal cycle_cnt_load : std_logic;
|
||||
signal div_fin_en : unsigned (2 downto 0);
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
begin
|
||||
-- 9A0CD0570B88D78
|
||||
|
||||
busy <= bsy;
|
||||
|
||||
sign1 <= din_hi(din_hi'left) and s_un;
|
||||
sign2 <= din_lo(din_lo'left) and s_un;
|
||||
pp_op1 <= not din_hi when sign1 = '1' else din_hi;
|
||||
pp_op2 <= not din_lo when sign2 = '1' else din_lo;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
md_state:
|
||||
process(s, start, mul_divn, cycle_cnt)
|
||||
begin
|
||||
|
||||
bsy <= '1';
|
||||
cycle_cnt_load <= '0';
|
||||
cycle_cnt_preset <= 7;
|
||||
|
||||
mul_en <= '0';
|
||||
div_en <= '0';
|
||||
sum_en <= '0';
|
||||
pre_sum_vld <= '0';
|
||||
mul_start <= '0';
|
||||
div_start <= '0';
|
||||
div_fin_en <= "000";
|
||||
sn <= s;
|
||||
case s is
|
||||
when md_rdy =>
|
||||
bsy <= '0';
|
||||
if start = '1' then
|
||||
if mul_divn = '1' then
|
||||
sn <= mul_pre1;
|
||||
cycle_cnt_load <= '1';
|
||||
cycle_cnt_preset <= 7;
|
||||
mul_start <= '1';
|
||||
else
|
||||
sn <= div_process;
|
||||
cycle_cnt_load <= '1';
|
||||
cycle_cnt_preset <= 31;
|
||||
div_start <= '1';
|
||||
end if;
|
||||
end if;
|
||||
when mul_pre1 =>
|
||||
pre_sum_vld <= '1';
|
||||
mul_en <= '1';
|
||||
sn <= mul_pre2;
|
||||
when mul_pre2 =>
|
||||
pre_sum_vld <= '1';
|
||||
mul_en <= '1';
|
||||
sn <= mul_pp;
|
||||
when mul_pp =>
|
||||
mul_en <= '1';
|
||||
if cycle_cnt = 0 then
|
||||
cycle_cnt_load <= '1';
|
||||
cycle_cnt_preset <= 3;
|
||||
sn <= mul_sum;
|
||||
end if;
|
||||
when mul_sum =>
|
||||
sum_en <= '1';
|
||||
if cycle_cnt = 0 then
|
||||
bsy <= '0';
|
||||
sn <= md_rdy;
|
||||
end if;
|
||||
when div_process =>
|
||||
div_en <= '1';
|
||||
if cycle_cnt = 0 then
|
||||
sn <= div_post1;
|
||||
end if;
|
||||
when div_post1 =>
|
||||
div_fin_en <= "001";
|
||||
sn <= div_post2;
|
||||
when div_post2 =>
|
||||
div_fin_en <= "010";
|
||||
sn <= div_post3;
|
||||
when div_post3 =>
|
||||
div_fin_en <= "100";
|
||||
sn <= md_rdy;
|
||||
bsy <= '0';
|
||||
when others =>
|
||||
sn <= md_rdy;
|
||||
end case;
|
||||
|
||||
end process;
|
||||
|
||||
md_state_next:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
s <= md_rdy;
|
||||
else
|
||||
s <= sn;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
md_cycle_cnt:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
cycle_cnt <= 0;
|
||||
elsif cycle_cnt_load = '1' then
|
||||
cycle_cnt <= cycle_cnt_preset;
|
||||
elsif cycle_cnt /= 0 then
|
||||
cycle_cnt <= cycle_cnt - 1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
proc_out_reg:
|
||||
process(hilo_sel, result)
|
||||
begin
|
||||
if hilo_sel = '1' then
|
||||
dout <= result(63 downto 32);
|
||||
else
|
||||
dout <= result(31 downto 0);
|
||||
end if;
|
||||
end process;
|
||||
|
||||
proc_in_reg:
|
||||
process(clk)
|
||||
variable pre_cond : unsigned(1 downto 0);
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if mul_start = '1' or div_start = '1' then
|
||||
pp_op1_r <= pp_op1;
|
||||
pre_const(0) <= (others => '0');
|
||||
pre_const(1) <= (others => '0');
|
||||
pre_cond := (din_hi(din_hi'left) and s_un) & (din_lo(din_lo'left) and s_un);
|
||||
s1_r <= pre_cond(1);
|
||||
s2_r <= pre_cond(0);
|
||||
sr_r <= pre_cond(0) xor pre_cond(1);
|
||||
case pre_cond is
|
||||
when "01" =>
|
||||
pre_const(0) <= din_hi;
|
||||
pre_const(1) <= X"FFFF_FFFF";
|
||||
when "10" =>
|
||||
pre_const(0) <= X"0000_0000";
|
||||
pre_const(1) <= X"FFFF_FFFF";
|
||||
when "11" =>
|
||||
pre_const(0) <= not din_hi;
|
||||
pre_const(1) <= X"0000_0001";
|
||||
when others => null;
|
||||
end case;
|
||||
elsif pre_sum_vld = '1' then
|
||||
pre_const(0) <= pre_const(1);
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
proc_mul_sr:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if mul_start = '1' then
|
||||
for i in 0 to 3 loop
|
||||
cy(i) <= '0';
|
||||
pprod(i) <= ppadd_res(i) & X"00";
|
||||
end loop;
|
||||
elsif mul_en = '1' then
|
||||
for i in 0 to 3 loop
|
||||
cy(i) <= ppadd_cyo(i);
|
||||
pprod(i) <= ppadd_res(i) & pprod(i)(8 downto 1);
|
||||
end loop;
|
||||
elsif sum_en = '1' then
|
||||
for i in 1 to 3 loop
|
||||
pprod(i-1) <= pprod(i);
|
||||
end loop;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
gen_mul32x8pp:
|
||||
for i in 0 to 3 generate
|
||||
begin
|
||||
|
||||
pp_adder_mux:
|
||||
process(mul_start, pp_op1, pp_op2, pp_op1_r, pp_op2_r(i), s1_r, sign1, pprod(i), cy(i))
|
||||
variable v2 : unsigned(7 downto 0);
|
||||
begin
|
||||
ppadd_cyi(i) <= '0';
|
||||
ppadd_op1(i) <= (others => '0');
|
||||
if mul_start = '1' then
|
||||
ppadd_op2(i) <= (others => '0');
|
||||
v2 := pp_op2(8*(i+1)-1 downto 8*i);
|
||||
if v2(0) = '1' then
|
||||
ppadd_cyi(i) <= sign1;
|
||||
ppadd_op1(i) <= pp_op1;
|
||||
end if;
|
||||
else
|
||||
ppadd_op2(i) <= cy(i) & pprod(i)(39 downto 9);
|
||||
v2 := pp_op2_r(i);
|
||||
if v2(0) = '1' then
|
||||
ppadd_cyi(i) <= s1_r;
|
||||
ppadd_op1(i) <= pp_op1_r;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
pp_adder:
|
||||
process(ppadd_op1(i), ppadd_op2(i), ppadd_cyi(i))
|
||||
variable sum_pp : unsigned(33 downto 0);
|
||||
begin
|
||||
sum_pp := ('0' & ppadd_op1(i) & ppadd_cyi(i)) + ('0' & ppadd_op2(i) & ppadd_cyi(i));
|
||||
ppadd_res(i) <= sum_pp(sum_pp'left-1 downto 1);
|
||||
ppadd_cyo(i) <= sum_pp(sum_pp'left);
|
||||
end process;
|
||||
|
||||
proc_mul_ctrl:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if mul_start = '1' then
|
||||
pp_op2_r(i) <= '0' & pp_op2(8*(i+1)-1 downto 8*i+1);
|
||||
elsif mul_en = '1' then
|
||||
pp_op2_r(i) <= '0' & pp_op2_r(i)(7 downto 1);
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end generate;
|
||||
|
||||
comb_mul_adder:
|
||||
process(add_op1, add_op2)
|
||||
variable sum_mul : unsigned(39 downto 0);
|
||||
begin
|
||||
sum_mul := (add_op1) + (add_op2);
|
||||
add_res <= sum_mul(sum_mul'left downto 0);
|
||||
end process;
|
||||
|
||||
comb_mul_adder_mux:
|
||||
process(pre_const, pre_sum_vld, pp_reg, pprod, sr_r)
|
||||
variable s_ext : std_logic;
|
||||
begin
|
||||
if pre_sum_vld = '1' then
|
||||
add_op1 <= pp_reg(63 downto 24);
|
||||
add_op2 <= pre_const(0) & X"00";
|
||||
else
|
||||
s_ext := pp_reg(63) and sr_r;
|
||||
add_op1 <= (7 downto 0 => s_ext) & pp_reg(63 downto 32);
|
||||
add_op2 <= pprod(0);
|
||||
end if;
|
||||
end process;
|
||||
|
||||
comb_mul:
|
||||
process(clk)
|
||||
variable tmp : prod_t;
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if mul_start = '1' then
|
||||
pp_reg <= (others => '0');
|
||||
elsif pre_sum_vld = '1' then
|
||||
pp_reg <= add_res & X"0000";
|
||||
elsif sum_en = '1' then
|
||||
tmp := add_res & pp_reg(31 downto 8);
|
||||
pp_reg <= tmp(63 downto 8);
|
||||
result <= tmp;
|
||||
if sr_r = '1' then
|
||||
result <= not tmp;
|
||||
end if;
|
||||
elsif div_fin_en(1) = '1' then
|
||||
result(63 downto 32) <= div_A(31 downto 0);
|
||||
if s1_r = '1' then
|
||||
result(63 downto 32) <= div_add_res(31 downto 0);
|
||||
end if;
|
||||
elsif div_fin_en(2) = '1' then
|
||||
result(31 downto 0) <= div_Q;
|
||||
if sr_r = '1' then
|
||||
result(31 downto 0) <= div_add_res(31 downto 0);
|
||||
end if;
|
||||
elsif hilo_we = '1' then
|
||||
if hilo_sel = '1' then
|
||||
result(63 downto 32) <= din_hi;
|
||||
else
|
||||
result(31 downto 0) <= din_hi;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
div_adder:
|
||||
process(div_add_op1, div_add_op2, div_add_cyi)
|
||||
variable sum_div : unsigned(33 downto 0);
|
||||
begin
|
||||
sum_div := (div_add_op1 & div_add_cyi) + (div_add_op2 & div_add_cyi);
|
||||
div_add_res <= sum_div(sum_div'left downto 1);
|
||||
end process;
|
||||
|
||||
div_adder_mux:
|
||||
process(div_start, div_en, div_fin_en, div_A, div_Q, pp_op1, sign1, s1_r, s2_r, sr_r, div_qbit, div_M, div_M_n)
|
||||
begin
|
||||
|
||||
div_add_cyi <= s2_r xor div_qbit;
|
||||
div_add_op1 <= div_A(31 downto 0) & div_Q(31);
|
||||
div_add_op2 <= (others => '0');
|
||||
if div_start = '1' then
|
||||
div_add_op1 <= '0' & pp_op1;
|
||||
div_add_cyi <= sign1;
|
||||
elsif div_en = '1' then
|
||||
div_add_op2 <= div_M;
|
||||
if div_qbit = '1' then
|
||||
div_add_op2 <= div_M_n;
|
||||
end if;
|
||||
elsif div_fin_en(0) = '1' then
|
||||
div_add_op2 <= div_M;
|
||||
div_add_cyi <= s2_r;
|
||||
div_add_op1 <= '0' & div_A(31 downto 0);
|
||||
elsif div_fin_en(1) = '1' then
|
||||
div_add_cyi <= s1_r;
|
||||
div_add_op1 <= '0' & not div_A(31 downto 0);
|
||||
elsif div_fin_en(2) = '1' then
|
||||
div_add_cyi <= sr_r;
|
||||
div_add_op1 <= '0' & not div_Q;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
divide:
|
||||
process(clk)
|
||||
variable quo : std_logic;
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if div_start = '1' then
|
||||
div_qbit <= '1';
|
||||
div_Q <= div_add_res(31 downto 0);
|
||||
div_A <= (others => '0');
|
||||
if sign2 = '1' then
|
||||
div_M_n <= '1' & din_lo;
|
||||
div_M <= '0' & not din_lo;
|
||||
else
|
||||
div_M_n <= '1' & not din_lo;
|
||||
div_M <= '0' & din_lo;
|
||||
end if;
|
||||
elsif div_en = '1' then
|
||||
div_qbit <= not div_add_res(32);
|
||||
div_A <= div_add_res(32 downto 0);
|
||||
div_Q <= div_Q(30 downto 0) & not div_add_res(32);
|
||||
elsif div_fin_en(0) = '1' then
|
||||
if div_A(32) = '1' then
|
||||
div_A <= '0' & div_add_res(31 downto 0);
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
end Behavioral;
|
||||
@@ -0,0 +1,851 @@
|
||||
--------------------------------------------------------------------------
|
||||
-- Project: JIPS, a portable 32-bit RISC CPU written in VHDL
|
||||
-- This file: The pipeline
|
||||
--
|
||||
-- Copyright (C) 2008 J. Ahrensfeld
|
||||
--
|
||||
-- This program is free software: you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation, either version 3 of the License, or
|
||||
-- (at your option) any later version.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
--
|
||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||
--
|
||||
--------------------------------------------------------------------------
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.numeric_std.ALL;
|
||||
|
||||
library work;
|
||||
use work.mips_types.all;
|
||||
use work.mips_instr.all;
|
||||
|
||||
entity pipeline is
|
||||
Port
|
||||
(
|
||||
rst : in STD_LOGIC;
|
||||
clk : in STD_LOGIC;
|
||||
ce : in STD_LOGIC;
|
||||
imem_err : in STD_LOGIC;
|
||||
imem_rdy : in STD_LOGIC;
|
||||
imem_en : out STD_LOGIC;
|
||||
imem_addr : out word_t;
|
||||
imem_data : in word_t;
|
||||
dmem_err : in STD_LOGIC;
|
||||
dmem_rdy : in STD_LOGIC;
|
||||
dmem_en : out STD_LOGIC;
|
||||
dmem_we : out STD_LOGIC;
|
||||
dmem_be : out unsigned(3 downto 0);
|
||||
dmem_addr : out word_t;
|
||||
dmem_din : in word_t;
|
||||
dmem_dout : out word_t;
|
||||
cop_ir : out word_t;
|
||||
cop_ir_en : out STD_LOGIC;
|
||||
cop_din : in word_t;
|
||||
cop_dout : out word_t;
|
||||
c0_ctrl_out : out cop0_ctrl_in_t;
|
||||
c0_ctrl_in : in cop0_ctrl_out_t
|
||||
|
||||
);
|
||||
end pipeline;
|
||||
|
||||
architecture Behavioral of pipeline is
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
COMPONENT reg_dual is
|
||||
Generic
|
||||
(
|
||||
addr_width : integer := 3;
|
||||
data_width : integer := 8
|
||||
);
|
||||
Port
|
||||
(
|
||||
clk_w : in STD_LOGIC;
|
||||
en : in STD_LOGIC;
|
||||
we : in STD_LOGIC;
|
||||
wptr : in unsigned (addr_width-1 downto 0);
|
||||
din : in unsigned (data_width-1 downto 0);
|
||||
rptr_a : in unsigned (addr_width-1 downto 0);
|
||||
rptr_b : in unsigned (addr_width-1 downto 0);
|
||||
dout_a : out unsigned (data_width-1 downto 0);
|
||||
dout_b : out unsigned (data_width-1 downto 0)
|
||||
);
|
||||
END COMPONENT;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
COMPONENT shifter is
|
||||
Generic
|
||||
(
|
||||
data_width : integer
|
||||
);
|
||||
Port
|
||||
(
|
||||
shift_ctrl : in shift_ctrl_t;
|
||||
din : in unsigned (data_width-1 downto 0);
|
||||
dout : out unsigned (data_width-1 downto 0)
|
||||
);
|
||||
END COMPONENT;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
COMPONENT alu is
|
||||
Generic
|
||||
(
|
||||
data_width : integer
|
||||
);
|
||||
Port
|
||||
(
|
||||
op1_in : in unsigned (data_width-1 downto 0);
|
||||
op2_in : in unsigned (data_width-1 downto 0);
|
||||
op2_shifted : in unsigned (data_width-1 downto 0);
|
||||
ctrl : in alu_ctrl_t;
|
||||
result : out unsigned (data_width-1 downto 0);
|
||||
flags : out alu_flags_t
|
||||
);
|
||||
END COMPONENT;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
COMPONENT bcu is
|
||||
Generic
|
||||
(
|
||||
data_width : integer
|
||||
);
|
||||
Port
|
||||
(
|
||||
op1_in : in unsigned (data_width-1 downto 0);
|
||||
op2_in : in unsigned (data_width-1 downto 0);
|
||||
flags : out bcu_flags_t
|
||||
);
|
||||
END COMPONENT;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
COMPONENT muldiv is
|
||||
Port
|
||||
(
|
||||
rst : in std_logic;
|
||||
clk : in std_logic;
|
||||
hilo_we : in std_logic;
|
||||
din_hi : in word_t;
|
||||
din_lo : in word_t;
|
||||
mul_divn : in std_logic;
|
||||
start : in std_logic;
|
||||
s_un : in std_logic;
|
||||
hilo_sel : in std_logic;
|
||||
busy : out std_logic;
|
||||
dout : out word_t
|
||||
);
|
||||
END COMPONENT;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
signal ID_stage : ID_t;
|
||||
signal EX_stage : EX_t;
|
||||
signal MEM_stage : MEM_t;
|
||||
signal WB_stage : WB_t;
|
||||
signal clk_2, clk_1 : STD_LOGIC;
|
||||
signal hdu : hdu_t;
|
||||
signal sdu : sdu_t;
|
||||
signal reg_a : word_t;
|
||||
signal reg_b : word_t;
|
||||
signal branch_ce : STD_LOGIC;
|
||||
signal cpu_run : STD_LOGIC;
|
||||
signal alu_result : word_t;
|
||||
signal mul_result : word_t;
|
||||
signal mul_busy : STD_LOGIC;
|
||||
signal EX_events_instr : event_t;
|
||||
signal EX_events_alu : event_t;
|
||||
signal EX_events_mem : event_t;
|
||||
signal EX_events : event_t;
|
||||
signal MEM_events : event_t;
|
||||
signal bcu_op_a : word_t;
|
||||
signal bcu_op_b : word_t;
|
||||
signal bcu_flags : bcu_flags_t;
|
||||
signal vaddr : word_t;
|
||||
signal dmem_src : word_t;
|
||||
signal stage_rst : unsigned(3 downto 0);
|
||||
signal pipe_rst : STD_LOGIC;
|
||||
|
||||
signal pc : pc_t;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
begin
|
||||
|
||||
clk_1 <= clk;
|
||||
clk_2 <= not clk;
|
||||
cpu_run <= ce;
|
||||
|
||||
-- Stall Detection Unit ---------------------------------------------------
|
||||
sdu.ID_nop <= sdu.imem_dep or c0_ctrl_in.exc_pending or ID_stage.exc or EX_stage.exc or MEM_stage.exc;
|
||||
sdu.EX_nop <= sdu.mul_dep or ID_stage.nop or ID_stage.exc;
|
||||
sdu.MEM_nop <= EX_stage.nop or EX_stage.exc;
|
||||
sdu.WB_nop <= sdu.dmem_dep or MEM_stage.nop;
|
||||
|
||||
sdu.stall_all <= sdu.dmem_dep;
|
||||
sdu.ID_stall <= sdu.stall_all or sdu.imem_dep or sdu.mul_dep or c0_ctrl_in.exc_exit;
|
||||
sdu.EX_stall <= sdu.stall_all;
|
||||
sdu.MEM_stall <= sdu.stall_all;
|
||||
sdu.WB_stall <= '0';
|
||||
|
||||
sdu.mul_dep <= ID_stage.ctrl.mul_access and (EX_stage.ctrl.mul_start or mul_busy);
|
||||
sdu.imem_dep <= not imem_rdy;
|
||||
sdu.dmem_dep <= not dmem_rdy and MEM_stage.ctrl.dmem_en;
|
||||
---------------------------------------------------------------------------
|
||||
imem_en <= cpu_run and not (sdu.mul_dep or sdu.dmem_dep or c0_ctrl_in.exc_commit);
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
-- Coprocessor assignments
|
||||
--------------------------------------------------------------------------
|
||||
c0_ctrl_out.bd_wb <= WB_stage.bd;
|
||||
c0_ctrl_out.epc_mem <= MEM_stage.pcn;
|
||||
c0_ctrl_out.epc_wb <= MEM_stage.epc;
|
||||
c0_ctrl_out.imem_addr <= EX_stage.epc;
|
||||
c0_ctrl_out.dmem_addr <= MEM_stage.va;
|
||||
c0_ctrl_out.sdu <= sdu;
|
||||
c0_ctrl_out.events <= WB_stage.events;
|
||||
c0_ctrl_out.exc_req <= MEM_stage.exc;
|
||||
c0_ctrl_out.exc_ack <= WB_stage.exc;
|
||||
cop_ir <= ID_stage.IR;
|
||||
cop_ir_en <= ID_stage.ctrl.cop_instr_en;
|
||||
cop_dout <= dmem_din when MEM_stage.ctrl.dmem_en = '1' else MEM_stage.ex_result;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
-- Muldiv
|
||||
--------------------------------------------------------------------------
|
||||
inst_muldiv: muldiv
|
||||
PORT MAP
|
||||
(
|
||||
rst => rst,
|
||||
clk => clk,
|
||||
hilo_we => EX_stage.ctrl.mul_hilo_we,
|
||||
din_hi => EX_stage.reg_a,
|
||||
din_lo => EX_stage.reg_b,
|
||||
mul_divn => EX_stage.ctrl.mul_mul_divn,
|
||||
start => EX_stage.ctrl.mul_start,
|
||||
s_un => EX_stage.ctrl.mul_s_un,
|
||||
hilo_sel => EX_stage.ctrl.mul_hilo_sel,
|
||||
busy => mul_busy,
|
||||
dout => mul_result
|
||||
);
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
-- IF stage
|
||||
--------------------------------------------------------------------------
|
||||
imem_addr <= pc.curr;
|
||||
|
||||
pipe_rst <= stage_rst(0);
|
||||
|
||||
proc_stage_reset:
|
||||
process(clk_1)
|
||||
begin
|
||||
if rising_edge(clk_1) then
|
||||
if rst = '1' then
|
||||
stage_rst <= (others => '1');
|
||||
else
|
||||
stage_rst <= stage_rst(stage_rst'left-1 downto 0) & '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
proc_stage_pc:
|
||||
process(pc)
|
||||
begin
|
||||
if pc.branch_take = '1' then
|
||||
pc.curr <= pc.pc_branch after 2 ns;
|
||||
else
|
||||
pc.curr <= pc.nxt after 2 ns;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
proc_stage_pc_branch:
|
||||
process(clk_1)
|
||||
begin
|
||||
if rising_edge(clk_1) then
|
||||
if sdu.ID_stall = '0' then
|
||||
pc.pc_branch <= pc.curr + ID_stage.bimm18;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
proc_stage_branch_ce:
|
||||
process(clk_1)
|
||||
begin
|
||||
if rising_edge(clk_1) then
|
||||
if pipe_rst = '1' then
|
||||
branch_ce <= '1';
|
||||
else
|
||||
branch_ce <= c0_ctrl_in.exc_pending;
|
||||
if sdu.ID_stall = '0' and c0_ctrl_in.exc_inject = '0' then
|
||||
branch_ce <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
proc_stage_pc_next:
|
||||
process(clk_1)
|
||||
begin
|
||||
if rising_edge(clk_1) then
|
||||
if c0_ctrl_in.exc_inject = '1' then
|
||||
pc.nxt <= c0_ctrl_in.exc_vec;
|
||||
elsif sdu.ID_stall = '0' then
|
||||
pc.last <= pc.curr;
|
||||
if ID_stage.ctrl.jump = '1' then
|
||||
pc.nxt <= ID_stage.jimm32;
|
||||
elsif ID_stage.ctrl.jump_long = '1' then
|
||||
pc.nxt <= ID_stage.reg_a;
|
||||
else
|
||||
pc.nxt <= pc.curr + 4;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
proc_stage_branch:
|
||||
process(clk_2)
|
||||
begin
|
||||
if rising_edge(clk_2) and branch_ce = '1' then
|
||||
pc.branch_take <= '0';
|
||||
if EX_stage.ctrl.branch = '1' then
|
||||
|
||||
case EX_stage.ctrl.bc_src is
|
||||
|
||||
when bc_eq_ne =>
|
||||
pc.branch_take <= EX_stage.ctrl.bc_not xor bcu_flags.eq;
|
||||
|
||||
when bc_lez_gtz =>
|
||||
pc.branch_take <= EX_stage.ctrl.bc_not xor (bcu_flags.eq or bcu_flags.ltz);
|
||||
|
||||
when bc_ltz_gez =>
|
||||
pc.branch_take <= EX_stage.ctrl.bc_not xor bcu_flags.ltz;
|
||||
|
||||
when others => null;
|
||||
end case;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
-- ID stage
|
||||
--------------------------------------------------------------------------
|
||||
ID_stage.IR <= to_01(imem_data);
|
||||
ID_stage.pcn <= pc.curr;
|
||||
ID_stage.op <= decode_op(ID_stage.IR);
|
||||
ID_stage.jimm32 <= extract_jimm32(ID_stage.IR, ID_stage.pcn);
|
||||
ID_stage.bimm18 <= extract_bimm18(ID_stage.IR, ID_stage.pcn);
|
||||
ID_stage.shamt <= extract_shamt(ID_stage.IR);
|
||||
ID_stage.reg_a_rptr <= extract_rs(ID_stage.IR);
|
||||
ID_stage.reg_b_rptr <= extract_rt(ID_stage.IR);
|
||||
ID_stage.ctrl <= opcode_ctrl_lines(ID_stage.IR) when sdu.ID_nop = '0' else ctrl_lines_default;
|
||||
ID_stage.reg_write <= ID_stage.ctrl.reg_write;
|
||||
ID_stage.epc <= pc.last;
|
||||
ID_stage.exc <= event_is_active(ID_stage.events); -- Todo: works
|
||||
ID_stage.nop <= sdu.ID_nop;
|
||||
|
||||
proc_ID_except:
|
||||
process(ID_stage, c0_ctrl_in, pc)
|
||||
begin
|
||||
ID_stage.events <= events_clr;
|
||||
ID_stage.events.inst_load_err <= not c0_ctrl_in.exc_pending and (pc.nxt(1) or pc.nxt(0));
|
||||
ID_stage.events.inst_priv_addr <= not c0_ctrl_in.exc_pending and (pc.nxt(word_t'left) and c0_ctrl_in.user_mode);
|
||||
end process;
|
||||
|
||||
proc_stage_hdu:
|
||||
process(ID_stage, EX_stage, MEM_stage, WB_stage)
|
||||
variable read_a, read_b : boolean;
|
||||
variable raw_a_EX, raw_a_MEM, raw_a_WB : boolean;
|
||||
variable raw_b_EX, raw_b_MEM, raw_b_WB : boolean;
|
||||
variable reg_ptr_a : reg_ptr_t;
|
||||
variable reg_ptr_b : reg_ptr_t;
|
||||
begin
|
||||
|
||||
reg_ptr_a := ID_stage.reg_a_rptr;
|
||||
reg_ptr_b := ID_stage.reg_b_rptr;
|
||||
raw_a_EX := reg_ptr_a = EX_stage.reg_wptr and EX_stage.wreg_we = '1';
|
||||
raw_a_MEM := reg_ptr_a = MEM_stage.reg_wptr and MEM_stage.wreg_we = '1';
|
||||
raw_a_WB := reg_ptr_a = WB_stage.reg_wptr and WB_stage.wreg_we = '1';
|
||||
raw_b_EX := reg_ptr_b = EX_stage.reg_wptr and EX_stage.wreg_we = '1';
|
||||
raw_b_MEM := reg_ptr_b = MEM_stage.reg_wptr and MEM_stage.wreg_we = '1';
|
||||
raw_b_WB := reg_ptr_b = WB_stage.reg_wptr and WB_stage.wreg_we = '1';
|
||||
|
||||
hdu.alu_fwd_a_ex <= raw_a_EX after 1 ns;
|
||||
hdu.alu_fwd_a_mem <= raw_a_MEM after 1 ns;
|
||||
hdu.alu_fwd_a_wb <= raw_a_WB after 1 ns;
|
||||
hdu.alu_fwd_b_ex <= raw_b_EX after 1 ns;
|
||||
hdu.alu_fwd_b_mem <= raw_b_MEM after 1 ns;
|
||||
hdu.alu_fwd_b_wb <= raw_b_WB after 1 ns;
|
||||
|
||||
end process;
|
||||
|
||||
proc_stage_fwd_a:
|
||||
process(reg_a, hdu, EX_stage, MEM_stage, WB_stage)
|
||||
variable data : word_t;
|
||||
begin
|
||||
data := reg_a;
|
||||
if hdu.alu_fwd_a_ex then
|
||||
data := EX_stage.result;
|
||||
elsif hdu.alu_fwd_a_mem then
|
||||
data := MEM_stage.data;
|
||||
elsif hdu.alu_fwd_a_wb then
|
||||
data := WB_stage.data;
|
||||
end if;
|
||||
ID_stage.reg_a <= to_01(data) after 2 ns;
|
||||
end process;
|
||||
|
||||
proc_stage_fwd_b:
|
||||
process(reg_b, hdu, EX_stage, MEM_stage, WB_stage)
|
||||
variable data : word_t;
|
||||
begin
|
||||
data := reg_b;
|
||||
if hdu.alu_fwd_b_ex then
|
||||
data := EX_stage.result;
|
||||
elsif hdu.alu_fwd_b_mem then
|
||||
data := MEM_stage.data;
|
||||
elsif hdu.alu_fwd_b_wb then
|
||||
data := WB_stage.data;
|
||||
end if;
|
||||
ID_stage.reg_b <= to_01(data) after 2 ns;
|
||||
end process;
|
||||
|
||||
proc_imm_mux:
|
||||
process(ID_stage)
|
||||
variable data : word_t;
|
||||
begin
|
||||
data := extract_uimm16(ID_stage.IR);
|
||||
|
||||
case ID_stage.ctrl.imm_src is
|
||||
|
||||
when src_imm32 =>
|
||||
data := extract_simm32(ID_stage.IR);
|
||||
|
||||
when src_imm16 =>
|
||||
data := extract_uimm16(ID_stage.IR);
|
||||
|
||||
when src_imm16_high =>
|
||||
data := ID_stage.IR(word_t'length/2-1 downto 0) & (word_t'length/2-1 downto 0 => '0');
|
||||
|
||||
when others => null;
|
||||
|
||||
end case;
|
||||
|
||||
ID_stage.imm <= data after 2 ns;
|
||||
|
||||
end process;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
inst_reg_dual: reg_dual
|
||||
GENERIC MAP
|
||||
(
|
||||
addr_width => reg_ptr_t'length,
|
||||
data_width => word_t'length
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
clk_w => clk_1,
|
||||
we => WB_stage.wreg_we,
|
||||
en => '1',
|
||||
wptr => WB_stage.reg_wptr,
|
||||
din => WB_stage.data,
|
||||
rptr_a => ID_stage.reg_a_rptr,
|
||||
rptr_b => ID_stage.reg_b_rptr,
|
||||
dout_a => reg_a,
|
||||
dout_b => reg_b
|
||||
);
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
-- EX stage
|
||||
--------------------------------------------------------------------------
|
||||
EX_stage.reg_a_rptr <= extract_rs(EX_stage.IR);
|
||||
EX_stage.reg_b_rptr <= extract_rt(EX_stage.IR);
|
||||
EX_stage.result <= alu_result when EX_stage.ctrl.mul_access = '0' else mul_result;
|
||||
|
||||
proc_stage_ID_EX_1:
|
||||
process(clk_1)
|
||||
begin
|
||||
if rising_edge(clk_1) then
|
||||
if stage_rst(1) = '1' then
|
||||
EX_stage.op <= NOP;
|
||||
EX_stage.IR <= (others => '0');
|
||||
EX_stage.ctrl <= ctrl_lines_default;
|
||||
EX_stage.reg_write <= '0';
|
||||
EX_stage.epc <= (others => '0');
|
||||
EX_stage.pcn <= (others => '0');
|
||||
EX_stage.events_in <= events_clr;
|
||||
elsif sdu.EX_stall = '0' then
|
||||
EX_stage.reg_a <= ID_stage.reg_a;
|
||||
EX_stage.reg_b <= ID_stage.reg_b;
|
||||
EX_stage.events_in <= ID_stage.events;
|
||||
EX_stage.op <= ID_stage.op;
|
||||
EX_stage.ctrl <= ID_stage.ctrl;
|
||||
EX_stage.reg_write <= ID_stage.reg_write;
|
||||
EX_stage.nop <= sdu.EX_nop;
|
||||
EX_stage.IR <= ID_stage.IR;
|
||||
EX_stage.pcn <= ID_stage.pcn;
|
||||
EX_stage.epc <= ID_stage.epc;
|
||||
if sdu.EX_nop = '1' then
|
||||
EX_stage.op <= NOP;
|
||||
EX_stage.IR <= (others => '0');
|
||||
EX_stage.ctrl <= ctrl_lines_default;
|
||||
EX_stage.reg_write <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
proc_stage_EX_instr_except:
|
||||
process(EX_stage)
|
||||
begin
|
||||
EX_events_instr <= events_clr;
|
||||
EX_events_instr.illegal <= EX_stage.ctrl.exc_illegal;
|
||||
EX_events_instr.break <= EX_stage.ctrl.exc_break;
|
||||
EX_events_instr.syscall <= EX_stage.ctrl.exc_syscall;
|
||||
end process;
|
||||
|
||||
proc_stage_EX_alu_except:
|
||||
process(EX_stage)
|
||||
begin
|
||||
EX_events_alu <= events_clr;
|
||||
if EX_stage.ctrl.alu_exc_en = '1' then
|
||||
if EX_stage.alu_flags.ovf = '1' then
|
||||
EX_events_alu.alu_ovf <= '1';
|
||||
end if;
|
||||
if EX_stage.alu_flags.uvf = '1' then
|
||||
EX_events_alu.alu_uvf <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
vaddr <= ID_stage.reg_a + extract_simm32(ID_stage.IR);
|
||||
|
||||
proc_stage_EX_mem_except:
|
||||
process(clk_1)
|
||||
begin
|
||||
if rising_edge(clk_1) then
|
||||
if pipe_rst = '1' then
|
||||
dmem_en <= '0';
|
||||
elsif sdu.EX_stall = '0' then
|
||||
EX_events_mem <= events_clr;
|
||||
dmem_en <= '0';
|
||||
if ID_stage.ctrl.dmem_en = '1' then
|
||||
dmem_en <= '1';
|
||||
if ID_stage.ctrl.except_en = '1' then
|
||||
if ID_stage.ctrl.word2_en = '1' then
|
||||
if vaddr(0) = '1' then
|
||||
EX_events_mem.data_load_err <= not ID_stage.ctrl.dmem_we;
|
||||
EX_events_mem.data_store_err <= ID_stage.ctrl.dmem_we;
|
||||
dmem_en <= '0';
|
||||
end if;
|
||||
elsif vaddr(1 downto 0) /= "00" then
|
||||
EX_events_mem.data_load_err <= not ID_stage.ctrl.dmem_we;
|
||||
EX_events_mem.data_store_err <= ID_stage.ctrl.dmem_we;
|
||||
dmem_en <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
proc_stage_DMEM_ADDR:
|
||||
process(clk_1)
|
||||
begin
|
||||
if rising_edge(clk_1) then
|
||||
if sdu.EX_stall = '0' then
|
||||
EX_stage.va <= vaddr;
|
||||
if c0_ctrl_in.EB = '1' then
|
||||
if ID_stage.ctrl.word2_en = '0' then
|
||||
EX_stage.pa_off <= not vaddr(1 downto 0);
|
||||
else
|
||||
EX_stage.pa_off <= not vaddr(1) & vaddr(0);
|
||||
end if;
|
||||
else
|
||||
EX_stage.pa_off <= vaddr(1 downto 0);
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
dmem_src <= cop_din when EX_stage.ctrl.cop_instr_en = '1' else EX_stage.reg_b;
|
||||
dmem_be <= store_be(EX_stage.pa_off, EX_stage.ctrl.dmem_en, EX_stage.ctrl.word2_en, EX_stage.ctrl.word4_en, EX_stage.ctrl.align_left, EX_stage.ctrl.shift_byp) after 1 ns;
|
||||
dmem_we <= EX_stage.ctrl.dmem_we;
|
||||
dmem_dout <= store_shift(dmem_src, EX_stage.pa_off, EX_stage.ctrl.shift_offset, EX_stage.ctrl.shift_byp) after 1ns;
|
||||
dmem_addr <= EX_stage.va;
|
||||
EX_stage.events <= EX_events_instr or EX_events_mem or EX_events_alu or EX_stage.events_in;
|
||||
EX_stage.exc <= event_is_active(EX_stage.events);
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
proc_wptr_mux:
|
||||
process(EX_stage)
|
||||
variable opclass : opcode_t;
|
||||
variable reg_wptr : reg_ptr_t;
|
||||
begin
|
||||
|
||||
opclass := extract_opc(EX_stage.IR);
|
||||
case opclass is
|
||||
when "000000" =>
|
||||
reg_wptr := extract_rd(EX_stage.IR);
|
||||
when others =>
|
||||
reg_wptr := extract_rt(EX_stage.IR);
|
||||
end case;
|
||||
|
||||
EX_stage.wreg_we <= EX_stage.reg_write after 1 ns;
|
||||
if reg_wptr = "00000" then
|
||||
EX_stage.wreg_we <= '0' after 1 ns;
|
||||
end if;
|
||||
|
||||
EX_stage.reg_wptr <= reg_wptr after 1 ns;
|
||||
case EX_stage.ctrl.wptr_srcsel is
|
||||
when wptr_src_imm =>
|
||||
EX_stage.reg_wptr <= reg_wptr after 1 ns;
|
||||
|
||||
when wptr_src_const =>
|
||||
EX_stage.reg_wptr <= to_unsigned(31, reg_ptr_t'length) after 1 ns;
|
||||
EX_stage.wreg_we <= '1' after 1 ns;
|
||||
|
||||
when others => null;
|
||||
end case;
|
||||
|
||||
end process;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
proc_stage_bcu_op:
|
||||
process(clk_1)
|
||||
begin
|
||||
if rising_edge(clk_1) and sdu.EX_stall = '0' then
|
||||
bcu_op_a <= ID_stage.reg_a;
|
||||
bcu_op_b <= ID_stage.reg_b;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
EX_stage.alu_op1 <= EX_stage.reg_a;
|
||||
|
||||
alu_op2_mux:
|
||||
process(clk_1)
|
||||
variable data : word_t;
|
||||
begin
|
||||
|
||||
if rising_edge(clk_1) and sdu.EX_stall = '0' then
|
||||
data := ID_stage.reg_b;
|
||||
|
||||
case ID_stage.ctrl.alu.op2_src is
|
||||
|
||||
when alu_src_reg =>
|
||||
data := ID_stage.reg_b;
|
||||
|
||||
when alu_src_imm =>
|
||||
data := ID_stage.imm;
|
||||
|
||||
when others => null;
|
||||
|
||||
end case;
|
||||
|
||||
EX_stage.alu_op2 <= data;
|
||||
end if;
|
||||
|
||||
end process;
|
||||
|
||||
shifter_sa_mux:
|
||||
process(clk_1)
|
||||
variable data : shamt_t;
|
||||
variable data_inv : shamt_t;
|
||||
|
||||
begin
|
||||
if rising_edge(clk_1) and sdu.EX_stall = '0' then
|
||||
data := ID_stage.reg_a(4 downto 0);
|
||||
case ID_stage.ctrl.shamt2_srcsel is
|
||||
|
||||
when sa_src_reg =>
|
||||
data := ID_stage.reg_a(4 downto 0);
|
||||
|
||||
when sa_src_imm =>
|
||||
data := ID_stage.shamt;
|
||||
|
||||
when others => null;
|
||||
|
||||
end case;
|
||||
data_inv := not data + 1;
|
||||
if ID_stage.ctrl.alu.shift_right = '0' then
|
||||
EX_stage.shift_ctrl.shamt_rnd <= data_inv after 2 ns;
|
||||
else
|
||||
EX_stage.shift_ctrl.shamt_rnd <= data after 2 ns;
|
||||
end if;
|
||||
EX_stage.shift_ctrl.shamt_nrm <= data after 1 ns;
|
||||
EX_stage.shift_ctrl.shift_right <= ID_stage.ctrl.alu.shift_right;
|
||||
EX_stage.shift_ctrl.shift_arith <= ID_stage.ctrl.alu.shift_arith;
|
||||
end if;
|
||||
|
||||
end process;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
inst_shifter: shifter
|
||||
GENERIC MAP
|
||||
(
|
||||
data_width => word_t'length
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
shift_ctrl => EX_stage.shift_ctrl,
|
||||
din => EX_stage.reg_b,
|
||||
dout => EX_stage.alu_op2_s
|
||||
);
|
||||
|
||||
inst_alu: alu
|
||||
GENERIC MAP
|
||||
(
|
||||
data_width => word_t'length
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
op1_in => EX_stage.alu_op1,
|
||||
op2_in => EX_stage.alu_op2,
|
||||
op2_shifted => EX_stage.alu_op2_s,
|
||||
ctrl => EX_stage.ctrl.alu,
|
||||
result => alu_result,
|
||||
flags => EX_stage.alu_flags
|
||||
);
|
||||
|
||||
inst_bcu: bcu
|
||||
GENERIC MAP
|
||||
(
|
||||
data_width => word_t'length
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
op1_in => bcu_op_a,
|
||||
op2_in => bcu_op_b,
|
||||
flags => bcu_flags
|
||||
);
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
-- MEM stage
|
||||
--------------------------------------------------------------------------
|
||||
proc_stage_MEM_n:
|
||||
process(clk_1)
|
||||
begin
|
||||
if rising_edge(clk_1) then
|
||||
if stage_rst(2) = '1' then
|
||||
MEM_stage.op <= NOP;
|
||||
MEM_stage.wreg_we <= '0';
|
||||
MEM_stage.ctrl <= ctrl_lines_default;
|
||||
MEM_stage.pa_off <= (others => '0');
|
||||
MEM_stage.events_in <= events_clr;
|
||||
elsif sdu.MEM_stall = '0' then
|
||||
MEM_stage.events_in <= EX_stage.events;
|
||||
MEM_stage.op <= EX_stage.op;
|
||||
MEM_stage.wreg_we <= EX_stage.wreg_we;
|
||||
MEM_stage.ctrl <= EX_stage.ctrl;
|
||||
if EX_stage.ctrl.dmem_en = '1' then
|
||||
MEM_stage.va <= EX_stage.va;
|
||||
end if;
|
||||
MEM_stage.pa_off <= EX_stage.pa_off;
|
||||
MEM_stage.reg_wptr <= EX_stage.reg_wptr;
|
||||
MEM_stage.nop <= sdu.MEM_nop;
|
||||
if MEM_stage.reg_wptr = EX_stage.reg_wptr then
|
||||
if (EX_stage.ctrl.dmem_en and MEM_stage.ctrl.dmem_en) = '1' then
|
||||
MEM_stage.ex_result <= MEM_stage.data;
|
||||
end if;
|
||||
else
|
||||
MEM_stage.ex_result <= EX_stage.reg_b;
|
||||
end if;
|
||||
if EX_stage.ctrl.cop_instr_en = '1' then
|
||||
if EX_stage.ctrl.cop_read = '1' then
|
||||
MEM_stage.ex_result <= cop_din;
|
||||
end if;
|
||||
elsif EX_stage.ctrl.dmem_en = '0' then
|
||||
MEM_stage.ex_result <= EX_stage.result;
|
||||
end if;
|
||||
if sdu.MEM_nop = '1' then
|
||||
MEM_stage.op <= NOP;
|
||||
MEM_stage.wreg_we <= '0';
|
||||
MEM_stage.ctrl <= ctrl_lines_default;
|
||||
else
|
||||
MEM_stage.pcn <= EX_stage.pcn;
|
||||
MEM_stage.epc <= EX_stage.epc;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
proc_stage_MEM_mux:
|
||||
process(MEM_stage, dmem_din)
|
||||
variable temp1 : word_t;
|
||||
variable temp2 : word_t;
|
||||
variable data : word_t;
|
||||
variable be : unsigned(3 downto 0);
|
||||
begin
|
||||
data := MEM_stage.ex_result;
|
||||
if MEM_stage.ctrl.reg_link = '1' then
|
||||
data := MEM_stage.epc + 8;
|
||||
elsif MEM_stage.ctrl.dmem_en = '1' then
|
||||
temp1 := load_shift(dmem_din, MEM_stage.pa_off, MEM_stage.ctrl.shift_offset, MEM_stage.ctrl.shift_byp);
|
||||
temp2 := load_sign_ext(temp1, MEM_stage.ctrl.sign_ext_byp, MEM_stage.ctrl.load_signed, MEM_stage.ctrl.word2_en, MEM_stage.ctrl.word4_en);
|
||||
be := load_be(MEM_stage.pa_off, MEM_stage.ctrl.align_left, MEM_stage.ctrl.byte_en_byp);
|
||||
if be(0) = '1' then
|
||||
data(7 downto 0) := temp2(7 downto 0);
|
||||
end if;
|
||||
if be(1) = '1' then
|
||||
data(15 downto 8) := temp2(15 downto 8);
|
||||
end if;
|
||||
if be(2) = '1' then
|
||||
data(23 downto 16) := temp2(23 downto 16);
|
||||
end if;
|
||||
if be(3) = '1' then
|
||||
data(31 downto 24) := temp2(31 downto 24);
|
||||
end if;
|
||||
end if;
|
||||
MEM_stage.data <= data after 1 ns;
|
||||
|
||||
end process;
|
||||
|
||||
proc_stage_MEM_except:
|
||||
process(MEM_stage, c0_ctrl_in)
|
||||
begin
|
||||
MEM_stage.events <= MEM_stage.events_in;
|
||||
MEM_stage.events.Int <= c0_ctrl_in.int;
|
||||
MEM_stage.events.NMI <= c0_ctrl_in.NMI;
|
||||
end process;
|
||||
|
||||
MEM_stage.exc <= event_is_active(MEM_stage.events);
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
-- WB stage
|
||||
--------------------------------------------------------------------------
|
||||
proc_stage_WB_p:
|
||||
process(clk_1)
|
||||
begin
|
||||
if rising_edge(clk_1) then
|
||||
if stage_rst(3) = '1' then
|
||||
WB_stage.op <= NOP;
|
||||
WB_stage.wreg_we <= '1';
|
||||
WB_stage.reg_wptr <= (others => '0');
|
||||
WB_stage.data <= (others => '0');
|
||||
WB_stage.events <= events_clr;
|
||||
elsif sdu.WB_stall = '0' then
|
||||
WB_stage.op <= MEM_stage.op;
|
||||
WB_stage.wreg_we <= MEM_stage.wreg_we;
|
||||
WB_stage.reg_wptr <= MEM_stage.reg_wptr;
|
||||
WB_stage.data <= MEM_stage.data;
|
||||
WB_stage.exc <= '0';
|
||||
if sdu.stall_all = '0' then
|
||||
WB_stage.exc <= MEM_stage.exc;
|
||||
if MEM_stage.exc = '1' then
|
||||
WB_stage.events <= MEM_stage.events;
|
||||
end if;
|
||||
end if;
|
||||
WB_stage.nop <= sdu.WB_nop;
|
||||
if sdu.WB_nop = '1' then
|
||||
WB_stage.op <= NOP;
|
||||
WB_stage.wreg_we <= '0';
|
||||
else
|
||||
WB_stage.bd <= MEM_stage.ctrl.branch or MEM_stage.ctrl.jump or MEM_stage.ctrl.jump_long; -- Todo: works
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
end Behavioral;
|
||||
@@ -0,0 +1,72 @@
|
||||
--------------------------------------------------------------------------
|
||||
-- Project: JIPS, a portable 32-bit RISC CPU written in VHDL
|
||||
-- This file: On-Chip work registers
|
||||
--
|
||||
-- Copyright (C) 2008 J. Ahrensfeld
|
||||
--
|
||||
-- This program is free software: you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation, either version 3 of the License, or
|
||||
-- (at your option) any later version.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
--
|
||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||
--
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.numeric_std.ALL;
|
||||
|
||||
use work.mips_types.all;
|
||||
|
||||
entity reg_dual is
|
||||
Generic
|
||||
(
|
||||
addr_width : integer := 3;
|
||||
data_width : integer := 8
|
||||
);
|
||||
Port (
|
||||
clk_w : in STD_LOGIC;
|
||||
we : in STD_LOGIC;
|
||||
en : in STD_LOGIC;
|
||||
wptr : in unsigned (addr_width-1 downto 0);
|
||||
din : in unsigned (data_width-1 downto 0);
|
||||
rptr_a : in unsigned (addr_width-1 downto 0);
|
||||
rptr_b : in unsigned (addr_width-1 downto 0);
|
||||
dout_a : out unsigned (data_width-1 downto 0);
|
||||
dout_b : out unsigned (data_width-1 downto 0)
|
||||
);
|
||||
end reg_dual;
|
||||
|
||||
architecture Behavioral of reg_dual is
|
||||
|
||||
constant depth : integer := 2**addr_width;
|
||||
type mem_t is array (0 to depth-1) of unsigned (data_width-1 downto 0);
|
||||
|
||||
signal reg_mem : mem_t;
|
||||
|
||||
begin
|
||||
|
||||
reg_in:
|
||||
process(clk_w)
|
||||
begin
|
||||
if rising_edge(clk_w) then
|
||||
if we = '1' and en = '1' then
|
||||
reg_mem(to_integer(wptr)) <= din;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
dout_a <= reg_mem(to_integer(rptr_a)) after 2 ns;
|
||||
dout_b <= reg_mem(to_integer(rptr_b)) after 2 ns;
|
||||
|
||||
end Behavioral;
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
--------------------------------------------------------------------------
|
||||
-- Project: JIPS, a portable 32-bit RISC CPU written in VHDL
|
||||
-- This file: The shifter unit
|
||||
--
|
||||
-- Copyright (C) 2008 J. Ahrensfeld
|
||||
--
|
||||
-- This program is free software: you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation, either version 3 of the License, or
|
||||
-- (at your option) any later version.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
--
|
||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||
--
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.numeric_std.ALL;
|
||||
|
||||
use work.mips_types.all;
|
||||
|
||||
entity shifter is
|
||||
Generic
|
||||
(
|
||||
data_width : integer := 8
|
||||
);
|
||||
Port
|
||||
(
|
||||
shift_ctrl : in shift_ctrl_t;
|
||||
din : in unsigned (data_width-1 downto 0);
|
||||
dout : out unsigned (data_width-1 downto 0)
|
||||
);
|
||||
end shifter;
|
||||
|
||||
architecture Behavioral of shifter is
|
||||
|
||||
subtype word_t is unsigned(data_width-1 downto 0);
|
||||
type word_array_t is array (0 to 5) of word_t;
|
||||
|
||||
signal rot_data : word_array_t;
|
||||
signal sa_rnd : unsigned (4 downto 0);
|
||||
signal fill : std_logic;
|
||||
|
||||
type fill_mask_rom_t is array (0 to 2*data_width-1) of unsigned(data_width-1 downto 0);
|
||||
--------------------------------------------------------------------------
|
||||
function gen_fill_mask_rom(data_width : natural) return fill_mask_rom_t is
|
||||
variable result : fill_mask_rom_t;
|
||||
begin
|
||||
result(0) := (data_width-1 downto 0 => '0');
|
||||
for i in 1 to data_width-1 loop
|
||||
result(i) := (data_width-1-i downto 0 => '0') & (i-1 downto 0 => '1');
|
||||
end loop;
|
||||
result(data_width) := (data_width-1 downto 0 => '0');
|
||||
for i in 1 to data_width-1 loop
|
||||
result(data_width+i) := (i-1 downto 0 => '1') & (data_width-1-i downto 0 => '0');
|
||||
end loop;
|
||||
return result;
|
||||
|
||||
end gen_fill_mask_rom;
|
||||
|
||||
function rot_stage(x : unsigned; en : std_logic; stage_num : natural) return unsigned is
|
||||
variable result : unsigned(x'range);
|
||||
constant sa : natural := 2**stage_num;
|
||||
begin
|
||||
if en = '1' then
|
||||
result := x(sa-1 downto 0) & x(x'left downto sa);
|
||||
else
|
||||
result := x;
|
||||
end if;
|
||||
return result;
|
||||
|
||||
end rot_stage;
|
||||
|
||||
constant fill_mask_rom : fill_mask_rom_t := gen_fill_mask_rom(data_width);
|
||||
signal fill_mask : unsigned(data_width-1 downto 0);
|
||||
signal fill_mask_addr : unsigned(5 downto 0);
|
||||
signal dout_filled : unsigned (data_width-1 downto 0);
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
begin
|
||||
|
||||
rot_data(0) <= din;
|
||||
|
||||
gen_rotate_right:
|
||||
for stage in 0 to 4 generate
|
||||
begin
|
||||
rot_data(stage+1) <= rot_stage(rot_data(stage), sa_rnd(stage), stage);
|
||||
end generate;
|
||||
|
||||
sa_rnd <= shift_ctrl.shamt_rnd;
|
||||
fill <= shift_ctrl.shift_arith and din(data_width-1);
|
||||
fill_mask_addr <= shift_ctrl.shift_right & shift_ctrl.shamt_nrm;
|
||||
fill_mask <= fill_mask_rom(to_integer(fill_mask_addr));
|
||||
|
||||
proc_fill_neu:
|
||||
process(fill_mask, fill, rot_data(5))
|
||||
begin
|
||||
if fill = '1' then
|
||||
dout_filled <= rot_data(5) or fill_mask;
|
||||
else
|
||||
dout_filled <= rot_data(5) and not fill_mask;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
dout <= dout_filled after 5 ns;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
end Behavioral;
|
||||
|
||||
@@ -0,0 +1,308 @@
|
||||
--------------------------------------------------------------------------
|
||||
-- Project: JIPS, a portable 32-bit RISC CPU written in VHDL
|
||||
-- This file: JIPS top file
|
||||
--
|
||||
-- Copyright (C) 2008 J. Ahrensfeld
|
||||
--
|
||||
-- This program is free software: you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation, either version 3 of the License, or
|
||||
-- (at your option) any later version.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
--
|
||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||
--
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.numeric_std.ALL;
|
||||
|
||||
library work;
|
||||
use work.mips_types.all;
|
||||
|
||||
entity mips_top is
|
||||
Generic
|
||||
(
|
||||
icache_size : natural := 8192; -- words
|
||||
icache_line : natural := 8; -- words
|
||||
dcache_size : natural := 4096; -- words
|
||||
dcache_line : natural := 8 -- words
|
||||
);
|
||||
Port
|
||||
(
|
||||
debug : out unsigned(1 downto 0);
|
||||
eb : in STD_LOGIC;
|
||||
nmi : in STD_LOGIC;
|
||||
cpu_clk : in STD_LOGIC;
|
||||
RST_I : in STD_LOGIC;
|
||||
CLK_I : in STD_LOGIC;
|
||||
ACK_I : in STD_LOGIC;
|
||||
SRDY_I : in STD_LOGIC;
|
||||
ADDR_O : out unsigned(31 downto 0);
|
||||
DAT_I : in unsigned(31 downto 0);
|
||||
DAT_O : out unsigned(31 downto 0);
|
||||
WE_O : out STD_LOGIC;
|
||||
SEL_O : out unsigned(3 downto 0);
|
||||
CYC_O : out STD_LOGIC;
|
||||
STB_O : out STD_LOGIC;
|
||||
MRDY_O : out STD_LOGIC;
|
||||
INT : in unsigned (5 downto 0)
|
||||
);
|
||||
|
||||
end mips_top;
|
||||
|
||||
architecture rtl of mips_top is
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
-- Pipeline
|
||||
--------------------------------------------------------------------------
|
||||
COMPONENT pipeline is
|
||||
Port
|
||||
(
|
||||
rst : in STD_LOGIC;
|
||||
clk : in STD_LOGIC;
|
||||
ce : in STD_LOGIC;
|
||||
imem_err : in STD_LOGIC;
|
||||
imem_rdy : in STD_LOGIC;
|
||||
imem_en : out STD_LOGIC;
|
||||
imem_addr : out word_t;
|
||||
imem_data : in word_t;
|
||||
dmem_err : in STD_LOGIC;
|
||||
dmem_rdy : in STD_LOGIC;
|
||||
dmem_en : out STD_LOGIC;
|
||||
dmem_we : out STD_LOGIC;
|
||||
dmem_be : out unsigned(3 downto 0);
|
||||
dmem_addr : out word_t;
|
||||
dmem_din : in word_t;
|
||||
dmem_dout : out word_t;
|
||||
cop_ir : out word_t;
|
||||
cop_ir_en : out STD_LOGIC;
|
||||
cop_din : in word_t;
|
||||
cop_dout : out word_t;
|
||||
c0_ctrl_out : out cop0_ctrl_in_t;
|
||||
c0_ctrl_in : in cop0_ctrl_out_t
|
||||
);
|
||||
END COMPONENT;
|
||||
signal imem_err : std_logic;
|
||||
signal imem_rdy : std_logic;
|
||||
signal imem_en : std_logic;
|
||||
signal imem_addr : word_t;
|
||||
signal imem_din : word_t;
|
||||
signal dmem_err : std_logic;
|
||||
signal dmem_rdy : std_logic;
|
||||
signal dmem_en : std_logic;
|
||||
signal dmem_we : std_logic;
|
||||
signal dmem_addr : word_t;
|
||||
signal dmem_dout : word_t;
|
||||
signal dmem_din : word_t;
|
||||
signal dmem_be : unsigned(3 downto 0);
|
||||
|
||||
signal biu_rst : STD_LOGIC;
|
||||
signal cpu_rst : STD_LOGIC;
|
||||
signal cpu_run : STD_LOGIC;
|
||||
|
||||
signal pipe_cop_ir : word_t;
|
||||
signal pipe_cop_ir_en : STD_LOGIC;
|
||||
signal pipe_cop_din : word_t;
|
||||
signal pipe_cop_dout : word_t;
|
||||
signal pipe_c0_ctrl_out : cop0_ctrl_in_t;
|
||||
signal pipe_c0_ctrl_in : cop0_ctrl_out_t;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
-- Coprocessor
|
||||
--------------------------------------------------------------------------
|
||||
COMPONENT cop is
|
||||
GENERIC
|
||||
(
|
||||
icache_size : natural;
|
||||
icache_line : natural;
|
||||
dcache_size : natural;
|
||||
dcache_line : natural
|
||||
);
|
||||
Port
|
||||
(
|
||||
rst : in STD_LOGIC;
|
||||
clk : in STD_LOGIC;
|
||||
nmi : in STD_LOGIC;
|
||||
eb : in STD_LOGIC;
|
||||
int : in unsigned (5 downto 0);
|
||||
ir_en : in STD_LOGIC;
|
||||
ir : in word_t;
|
||||
ctrl_in : in cop0_ctrl_in_t;
|
||||
ctrl_out : out cop0_ctrl_out_t;
|
||||
din : in word_t;
|
||||
dout : out word_t
|
||||
);
|
||||
END COMPONENT;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
-- Bus Interface Unit
|
||||
--------------------------------------------------------------------------
|
||||
COMPONENT biu
|
||||
GENERIC
|
||||
(
|
||||
icache_size : natural;
|
||||
icache_line : natural;
|
||||
dcache_size : natural;
|
||||
dcache_line : natural
|
||||
);
|
||||
PORT
|
||||
(
|
||||
RST_I : in STD_LOGIC;
|
||||
CLK_I : in STD_LOGIC;
|
||||
ACK_I : in STD_LOGIC;
|
||||
SRDY_I : in STD_LOGIC;
|
||||
ADDR_O : out unsigned(31 downto 0);
|
||||
DAT_I : in unsigned(31 downto 0);
|
||||
DAT_O : out unsigned(31 downto 0);
|
||||
WE_O : out STD_LOGIC;
|
||||
SEL_O : out unsigned(3 downto 0);
|
||||
CYC_O : out STD_LOGIC;
|
||||
STB_O : out STD_LOGIC;
|
||||
MRDY_O : out STD_LOGIC;
|
||||
cop0_ctrl_in : in cop0_ctrl_out_t;
|
||||
cpu_clk : in STD_LOGIC;
|
||||
cpu_imem_err : out STD_LOGIC;
|
||||
cpu_imem_rdy : out STD_LOGIC;
|
||||
cpu_imem_en : in STD_LOGIC;
|
||||
cpu_imem_addr : in word_t;
|
||||
cpu_imem_din : out word_t;
|
||||
cpu_dmem_err : out STD_LOGIC;
|
||||
cpu_dmem_rdy : out STD_LOGIC;
|
||||
cpu_dmem_en : in STD_LOGIC;
|
||||
cpu_dmem_we : in STD_LOGIC;
|
||||
cpu_dmem_be : in unsigned(3 downto 0);
|
||||
cpu_dmem_dout : in word_t;
|
||||
cpu_dmem_din : out word_t;
|
||||
cpu_dmem_addr : in word_t
|
||||
);
|
||||
END COMPONENT;
|
||||
|
||||
begin
|
||||
|
||||
-------------------------------------------------------------------
|
||||
debug(0) <= imem_err;
|
||||
debug(1) <= dmem_err;
|
||||
|
||||
process(CLK_I)
|
||||
variable reset_delay : unsigned (31 downto 0);
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if RST_I = '1' then
|
||||
reset_delay := (others => '0');
|
||||
biu_rst <= '1';
|
||||
cpu_rst <= '1';
|
||||
cpu_run <= '0';
|
||||
else
|
||||
reset_delay := reset_delay(reset_delay'left-1 downto 0) & '1';
|
||||
if reset_delay(20) = '1' then
|
||||
biu_rst <= '0';
|
||||
end if;
|
||||
if reset_delay(31) = '1' then
|
||||
cpu_rst <= '0';
|
||||
end if;
|
||||
if reset_delay(16) = '1' then
|
||||
cpu_run <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
inst_pipeline: pipeline
|
||||
PORT MAP
|
||||
(
|
||||
rst => cpu_rst,
|
||||
clk => cpu_clk,
|
||||
ce => cpu_run,
|
||||
imem_err => imem_err,
|
||||
imem_rdy => imem_rdy,
|
||||
imem_en => imem_en,
|
||||
imem_addr => imem_addr,
|
||||
imem_data => imem_din,
|
||||
dmem_err => dmem_err,
|
||||
dmem_rdy => dmem_rdy,
|
||||
dmem_en => dmem_en,
|
||||
dmem_we => dmem_we,
|
||||
dmem_be => dmem_be,
|
||||
dmem_addr => dmem_addr,
|
||||
dmem_din => dmem_din,
|
||||
dmem_dout => dmem_dout,
|
||||
cop_ir => pipe_cop_ir,
|
||||
cop_ir_en => pipe_cop_ir_en,
|
||||
cop_din => pipe_cop_din,
|
||||
cop_dout => pipe_cop_dout,
|
||||
c0_ctrl_out => pipe_c0_ctrl_out,
|
||||
c0_ctrl_in => pipe_c0_ctrl_in
|
||||
);
|
||||
|
||||
inst_cop: cop
|
||||
GENERIC MAP
|
||||
(
|
||||
icache_size => icache_size, -- words
|
||||
icache_line => icache_line, -- words
|
||||
dcache_size => dcache_size, -- words
|
||||
dcache_line => dcache_line -- words
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
rst => cpu_rst,
|
||||
clk => cpu_clk,
|
||||
nmi => nmi,
|
||||
eb => eb,
|
||||
int => INT,
|
||||
ir_en => pipe_cop_ir_en,
|
||||
ir => pipe_cop_ir,
|
||||
ctrl_in => pipe_c0_ctrl_out,
|
||||
ctrl_out => pipe_c0_ctrl_in,
|
||||
dout => pipe_cop_din,
|
||||
din => pipe_cop_dout
|
||||
);
|
||||
|
||||
inst_biu: biu
|
||||
GENERIC MAP
|
||||
(
|
||||
icache_size => icache_size, -- words
|
||||
icache_line => icache_line, -- words
|
||||
dcache_size => dcache_size, -- words
|
||||
dcache_line => dcache_line -- words
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
RST_I => biu_rst,
|
||||
CLK_I => CLK_I,
|
||||
ACK_I => ACK_I,
|
||||
SRDY_I => SRDY_I,
|
||||
ADDR_O => ADDR_O,
|
||||
DAT_I => DAT_I,
|
||||
DAT_O => DAT_O,
|
||||
WE_O => WE_O,
|
||||
SEL_O => SEL_O,
|
||||
CYC_O => CYC_O,
|
||||
STB_O => STB_O,
|
||||
MRDY_O => MRDY_O,
|
||||
cop0_ctrl_in => pipe_c0_ctrl_in,
|
||||
cpu_clk => cpu_clk,
|
||||
cpu_imem_err => imem_err,
|
||||
cpu_imem_rdy => imem_rdy,
|
||||
cpu_imem_en => imem_en,
|
||||
cpu_imem_addr => imem_addr,
|
||||
cpu_imem_din => imem_din,
|
||||
cpu_dmem_err => dmem_err,
|
||||
cpu_dmem_rdy => dmem_rdy,
|
||||
cpu_dmem_en => dmem_en,
|
||||
cpu_dmem_we => dmem_we,
|
||||
cpu_dmem_be => dmem_be,
|
||||
cpu_dmem_addr => dmem_addr,
|
||||
cpu_dmem_din => dmem_din,
|
||||
cpu_dmem_dout => dmem_dout
|
||||
);
|
||||
|
||||
end rtl;
|
||||
@@ -0,0 +1,670 @@
|
||||
--------------------------------------------------------------------------
|
||||
-- Project: JIPS, a portable 32-bit RISC CPU written in VHDL
|
||||
-- This file: Types, constants and functions for JIPS
|
||||
--
|
||||
-- Copyright (C) 2008 J. Ahrensfeld
|
||||
--
|
||||
-- This program is free software: you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation, either version 3 of the License, or
|
||||
-- (at your option) any later version.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
--
|
||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||
--
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.NUMERIC_STD.ALL;
|
||||
use IEEE.MATH_REAL.ALL;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
package mips_types is
|
||||
|
||||
-- Revision of the CPU
|
||||
constant REVISION : integer := 13;
|
||||
constant WORD_WIDTH : integer := 32;
|
||||
|
||||
--Types
|
||||
subtype instr_name_t is string(1 to 12);
|
||||
type instr_name_array_t is array (0 to 63) of instr_name_t;
|
||||
subtype opcode_t is unsigned (5 downto 0);
|
||||
subtype word_t is unsigned (WORD_WIDTH-1 downto 0);
|
||||
subtype reg_ptr_t is unsigned (4 downto 0);
|
||||
subtype shamt_t is unsigned(4 downto 0);
|
||||
subtype sa_t is natural range 0 to 63;
|
||||
subtype func_t is unsigned(5 downto 0);
|
||||
|
||||
type op_t is
|
||||
(
|
||||
reserved,
|
||||
nop,
|
||||
op_sll,
|
||||
op_srl,
|
||||
op_sra,
|
||||
op_sllv,
|
||||
op_srlv,
|
||||
op_srav,
|
||||
op_jr,
|
||||
op_jalr,
|
||||
op_syscall,
|
||||
op_break,
|
||||
op_mfhi,
|
||||
op_mthi,
|
||||
op_mflo,
|
||||
op_mtlo,
|
||||
op_mult,
|
||||
op_multu,
|
||||
op_div,
|
||||
op_divu,
|
||||
op_add,
|
||||
op_addu,
|
||||
op_sub,
|
||||
op_subu,
|
||||
op_and,
|
||||
op_or,
|
||||
op_xor,
|
||||
op_nor,
|
||||
op_slt,
|
||||
op_sltu,
|
||||
op_bltz,
|
||||
op_bgez,
|
||||
op_bltzal,
|
||||
op_bgezal,
|
||||
op_j,
|
||||
op_jal,
|
||||
op_beq,
|
||||
op_bne,
|
||||
op_blez,
|
||||
op_bgtz,
|
||||
op_addi,
|
||||
op_addiu,
|
||||
op_slti,
|
||||
op_sltiu,
|
||||
op_andi,
|
||||
op_ori,
|
||||
op_xori,
|
||||
op_lui,
|
||||
op_lb,
|
||||
op_lh,
|
||||
op_lwl,
|
||||
op_lw,
|
||||
op_lbu,
|
||||
op_lhu,
|
||||
op_lwr,
|
||||
op_sb,
|
||||
op_sh,
|
||||
op_swl,
|
||||
op_sw,
|
||||
op_swr,
|
||||
op_cop0,
|
||||
op_cop1,
|
||||
op_cop2,
|
||||
op_cop3,
|
||||
op_mfc0,
|
||||
op_cfc0,
|
||||
op_mtc0,
|
||||
op_ctc0,
|
||||
op_bcf0,
|
||||
op_bct0,
|
||||
op_mfc1,
|
||||
op_cfc1,
|
||||
op_mtc1,
|
||||
op_ctc1,
|
||||
op_bcf1,
|
||||
op_bct1,
|
||||
op_mfc2,
|
||||
op_cfc2,
|
||||
op_mtc2,
|
||||
op_ctc2,
|
||||
op_bcf2,
|
||||
op_bct2,
|
||||
op_mfc3,
|
||||
op_cfc3,
|
||||
op_mtc3,
|
||||
op_ctc3,
|
||||
op_bcf3,
|
||||
op_bct3,
|
||||
op_lwc0,
|
||||
op_lwc1,
|
||||
op_lwc2,
|
||||
op_lwc3,
|
||||
op_swc0,
|
||||
op_swc1,
|
||||
op_swc2,
|
||||
op_swc3
|
||||
);
|
||||
|
||||
attribute ENUM_ENCODING : string;
|
||||
|
||||
type imm_src_t is (src_imm32, src_imm16, src_imm16_high);
|
||||
type sa_src_t is (sa_src_reg, sa_src_imm);
|
||||
type alu_src1_t is (alu_src_reg);
|
||||
type alu_src2_t is (alu_src_reg, alu_src_imm);
|
||||
type bc_src_t is (bc_eq_ne, bc_lez_gtz, bc_ltz_gez);
|
||||
type shift_opsel_t is (shift_sll, shift_srl, shift_sra);
|
||||
type wptr_src_t is (wptr_src_imm, wptr_src_const);
|
||||
|
||||
-- attribute ENUM_ENCODING of itype_t: type is "ONE-HOT";
|
||||
|
||||
type pc_t is record
|
||||
curr : word_t;
|
||||
last : word_t;
|
||||
nxt : word_t;
|
||||
pc_branch : word_t;
|
||||
branch_take : std_logic;
|
||||
end record;
|
||||
|
||||
type alu_outsel_t is
|
||||
(
|
||||
alu_adder,
|
||||
alu_shift2,
|
||||
alu_and,
|
||||
alu_or,
|
||||
alu_xor,
|
||||
alu_nor,
|
||||
alu_ltu,
|
||||
alu_lts
|
||||
);
|
||||
|
||||
type sdu_t is record
|
||||
imem_dep : STD_LOGIC;
|
||||
dmem_dep : STD_LOGIC;
|
||||
mul_dep : STD_LOGIC;
|
||||
ID_nop : STD_LOGIC;
|
||||
EX_nop : STD_LOGIC;
|
||||
MEM_nop : STD_LOGIC;
|
||||
WB_nop : STD_LOGIC;
|
||||
ID_stall : STD_LOGIC;
|
||||
EX_stall : STD_LOGIC;
|
||||
MEM_stall : STD_LOGIC;
|
||||
WB_stall : STD_LOGIC;
|
||||
stall_all : STD_LOGIC;
|
||||
end record;
|
||||
|
||||
type hdu_t is record
|
||||
alu_fwd_a_ex : boolean;
|
||||
alu_fwd_a_mem : boolean;
|
||||
alu_fwd_a_wb : boolean;
|
||||
alu_fwd_b_ex : boolean;
|
||||
alu_fwd_b_mem : boolean;
|
||||
alu_fwd_b_wb : boolean;
|
||||
end record;
|
||||
|
||||
type alu_flags_t is record
|
||||
c : STD_LOGIC;
|
||||
uvf : STD_LOGIC;
|
||||
ovf : STD_LOGIC;
|
||||
ltu : STD_LOGIC;
|
||||
lts : STD_LOGIC;
|
||||
end record;
|
||||
|
||||
type bcu_flags_t is record
|
||||
eq : STD_LOGIC;
|
||||
ltz : STD_LOGIC;
|
||||
end record;
|
||||
|
||||
type event_t is record
|
||||
NMI : STD_LOGIC;
|
||||
Int : STD_LOGIC;
|
||||
data_load_err : STD_LOGIC;
|
||||
data_store_err : STD_LOGIC;
|
||||
inst_load_err : STD_LOGIC;
|
||||
inst_priv_addr : STD_LOGIC;
|
||||
alu_ovf : STD_LOGIC;
|
||||
alu_uvf : STD_LOGIC;
|
||||
syscall : STD_LOGIC;
|
||||
break : STD_LOGIC;
|
||||
illegal : STD_LOGIC;
|
||||
end record;
|
||||
|
||||
type exc_flags_t is record
|
||||
Int : STD_LOGIC;
|
||||
DAdEL : STD_LOGIC;
|
||||
DAdES : STD_LOGIC;
|
||||
IAdEL : STD_LOGIC;
|
||||
IAdEK : STD_LOGIC;
|
||||
Ov : STD_LOGIC;
|
||||
Sys : STD_LOGIC;
|
||||
Bp : STD_LOGIC;
|
||||
RI : STD_LOGIC;
|
||||
IBE : STD_LOGIC;
|
||||
DBE : STD_LOGIC;
|
||||
end record;
|
||||
|
||||
type except_t is record
|
||||
act : STD_LOGIC;
|
||||
epc : word_t;
|
||||
cause : word_t;
|
||||
end record;
|
||||
|
||||
type cache_ctrl_t is record
|
||||
inv_addr : word_t;
|
||||
inv_at : STD_LOGIC;
|
||||
inv_all : STD_LOGIC;
|
||||
end record;
|
||||
|
||||
type cop0_ctrl_in_t is record
|
||||
sdu : sdu_t;
|
||||
events : event_t;
|
||||
bd_wb : STD_LOGIC;
|
||||
epc_mem : word_t;
|
||||
epc_wb : word_t;
|
||||
imem_addr : word_t;
|
||||
dmem_addr : word_t;
|
||||
exc_req : STD_LOGIC;
|
||||
exc_ack : STD_LOGIC;
|
||||
end record;
|
||||
|
||||
type cop0_ctrl_out_t is record
|
||||
EB : STD_LOGIC;
|
||||
exc_inject : STD_LOGIC;
|
||||
exc_commit : STD_LOGIC;
|
||||
exc_pending : STD_LOGIC;
|
||||
exc_exit : STD_LOGIC;
|
||||
user_mode : STD_LOGIC;
|
||||
NMI : STD_LOGIC;
|
||||
int : STD_LOGIC;
|
||||
exc_vec : word_t;
|
||||
icache : cache_ctrl_t;
|
||||
dcache : cache_ctrl_t;
|
||||
end record;
|
||||
|
||||
type alu_ctrl_t is record
|
||||
outsel : alu_outsel_t;
|
||||
add : STD_LOGIC;
|
||||
shift_right : STD_LOGIC;
|
||||
shift_arith : STD_LOGIC;
|
||||
op1_src : alu_src1_t;
|
||||
op2_src : alu_src2_t;
|
||||
end record;
|
||||
|
||||
type shift_ctrl_t is record
|
||||
shamt_nrm : shamt_t;
|
||||
shamt_rnd : shamt_t;
|
||||
shift_right : STD_LOGIC;
|
||||
shift_arith : STD_LOGIC;
|
||||
end record;
|
||||
|
||||
type ctrl_lines_t is record
|
||||
branch : STD_LOGIC;
|
||||
jump_long : STD_LOGIC;
|
||||
jump : STD_LOGIC;
|
||||
bc_not : STD_LOGIC;
|
||||
bc_src : bc_src_t;
|
||||
imm_src : imm_src_t;
|
||||
alu : alu_ctrl_t;
|
||||
reg_write : STD_LOGIC;
|
||||
reg_link : STD_LOGIC;
|
||||
dmem_we : STD_LOGIC;
|
||||
dmem_en : STD_LOGIC;
|
||||
shamt2_srcsel : sa_src_t;
|
||||
wptr_srcsel : wptr_src_t;
|
||||
cop_instr_en : STD_LOGIC;
|
||||
cop_read : STD_LOGIC;
|
||||
shift_offset : unsigned(1 downto 0);
|
||||
shift_byp : STD_LOGIC;
|
||||
byte_en_byp : STD_LOGIC;
|
||||
sign_ext_byp : STD_LOGIC;
|
||||
word4_en : STD_LOGIC;
|
||||
word2_en : STD_LOGIC;
|
||||
align_left : STD_LOGIC;
|
||||
load_signed : STD_LOGIC;
|
||||
mul_access : STD_LOGIC;
|
||||
mul_hilo_we : STD_LOGIC;
|
||||
mul_mul_divn : STD_LOGIC;
|
||||
mul_start : STD_LOGIC;
|
||||
mul_s_un : STD_LOGIC;
|
||||
mul_hilo_sel : STD_LOGIC;
|
||||
exc_break : STD_LOGIC;
|
||||
exc_syscall : STD_LOGIC;
|
||||
exc_illegal : STD_LOGIC;
|
||||
except_en : STD_LOGIC;
|
||||
alu_exc_en : STD_LOGIC;
|
||||
end record;
|
||||
|
||||
type ID_t is record
|
||||
nop : STD_LOGIC;
|
||||
exc : std_logic;
|
||||
IR : word_t;
|
||||
op : op_t;
|
||||
pcn : word_t;
|
||||
epc : word_t;
|
||||
jimm32 : word_t;
|
||||
bimm18 : word_t;
|
||||
imm : word_t;
|
||||
shamt : shamt_t;
|
||||
ctrl : ctrl_lines_t;
|
||||
reg_write : STD_LOGIC;
|
||||
reg_a_rptr : reg_ptr_t;
|
||||
reg_b_rptr : reg_ptr_t;
|
||||
reg_a : word_t;
|
||||
reg_b : word_t;
|
||||
events : event_t;
|
||||
end record;
|
||||
|
||||
type EX_t is record
|
||||
nop : STD_LOGIC;
|
||||
exc : std_logic;
|
||||
IR : word_t;
|
||||
op : op_t;
|
||||
pcn : word_t;
|
||||
epc : word_t;
|
||||
reg_a : word_t;
|
||||
reg_b : word_t;
|
||||
ctrl : ctrl_lines_t;
|
||||
shift_ctrl : shift_ctrl_t;
|
||||
alu_op1 : word_t;
|
||||
alu_op2 : word_t;
|
||||
alu_op2_s : word_t;
|
||||
alu_flags : alu_flags_t;
|
||||
result : word_t;
|
||||
reg_write : STD_LOGIC;
|
||||
wreg_we : STD_LOGIC;
|
||||
reg_wptr : reg_ptr_t;
|
||||
reg_a_rptr : reg_ptr_t;
|
||||
reg_b_rptr : reg_ptr_t;
|
||||
va : word_t;
|
||||
pa_off : unsigned(1 downto 0);
|
||||
events_in : event_t;
|
||||
events : event_t;
|
||||
end record;
|
||||
|
||||
type MEM_t is record
|
||||
nop : STD_LOGIC;
|
||||
exc : std_logic;
|
||||
op : op_t;
|
||||
pcn : word_t;
|
||||
epc : word_t;
|
||||
ctrl : ctrl_lines_t;
|
||||
ex_result : word_t;
|
||||
reg_wptr : reg_ptr_t;
|
||||
wreg_we : STD_LOGIC;
|
||||
data : word_t;
|
||||
va : word_t;
|
||||
pa_off : unsigned(1 downto 0);
|
||||
events_in : event_t;
|
||||
events : event_t;
|
||||
end record;
|
||||
|
||||
type WB_t is record
|
||||
nop : STD_LOGIC;
|
||||
exc : std_logic;
|
||||
events : event_t;
|
||||
op : op_t;
|
||||
reg_wptr : reg_ptr_t;
|
||||
wreg_we : STD_LOGIC;
|
||||
data : word_t;
|
||||
bd : STD_LOGIC;
|
||||
end record;
|
||||
|
||||
|
||||
type rom_special_t is array (0 to 2**func_t'length-1) of ctrl_lines_t;
|
||||
type rom_regimm_t is array (0 to 2**reg_ptr_t'length-1) of ctrl_lines_t;
|
||||
type rom_opcode_t is array (0 to 2**opcode_t'length-1) of ctrl_lines_t;
|
||||
|
||||
function store_shift(x : word_t; va, shift_off : unsigned(1 downto 0); bypass : std_logic) return word_t;
|
||||
function store_be(va : unsigned(1 downto 0); be_src, word2_en, word4_en, align_left, bypass : std_logic) return unsigned;
|
||||
function load_shift(x : word_t; va, shift_off : unsigned(1 downto 0); bypass : std_logic) return word_t;
|
||||
function load_be(va : unsigned(1 downto 0); align_left, bypass : std_logic) return unsigned;
|
||||
function load_sign_ext(x : word_t; bypass, signed, word2_en, word4_en : std_logic) return word_t;
|
||||
function events_clr return event_t;
|
||||
function event_is_active(e : event_t) return std_logic;
|
||||
function "or" (a, b : event_t) return event_t;
|
||||
|
||||
function lg2(x : natural) return natural;
|
||||
function po2(x : natural) return natural;
|
||||
|
||||
end mips_types;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
package body mips_types is
|
||||
|
||||
function store_shift(x : word_t; va, shift_off : unsigned(1 downto 0); bypass : std_logic) return word_t is
|
||||
variable stage1 : word_t;
|
||||
variable result : word_t;
|
||||
variable sa : unsigned(1 downto 0);
|
||||
begin
|
||||
|
||||
if bypass = '1' then
|
||||
sa := "00";
|
||||
else
|
||||
sa := va + shift_off;
|
||||
end if;
|
||||
|
||||
stage1 := x;
|
||||
if sa(0) = '1' then
|
||||
stage1 := x(23 downto 0) & x(31 downto 24);
|
||||
end if;
|
||||
result := stage1;
|
||||
if sa(1) = '1' then
|
||||
result := stage1(15 downto 0) & stage1(31 downto 16);
|
||||
end if;
|
||||
|
||||
return result;
|
||||
end store_shift;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
function store_be(va : unsigned(1 downto 0); be_src, word2_en, word4_en, align_left, bypass : std_logic) return unsigned is
|
||||
variable result : unsigned(3 downto 0);
|
||||
begin
|
||||
result := (3 downto 0 => be_src);
|
||||
if bypass = '0' then
|
||||
if word2_en = '1' then
|
||||
case va is
|
||||
when "00" =>
|
||||
result := "00" & be_src & be_src;
|
||||
when "10" =>
|
||||
result := be_src & be_src & "00";
|
||||
when others => null;
|
||||
end case;
|
||||
elsif word4_en = '1' then
|
||||
case va is
|
||||
when "00" =>
|
||||
result := "000" & be_src;
|
||||
when "01" =>
|
||||
result := "00" & be_src & '0';
|
||||
when "10" =>
|
||||
result := '0' & be_src & "00";
|
||||
when "11" =>
|
||||
result := be_src & "000";
|
||||
when others => null;
|
||||
end case;
|
||||
elsif align_left = '1' then
|
||||
case va is
|
||||
when "00" =>
|
||||
result := be_src & be_src & be_src & be_src;
|
||||
when "01" =>
|
||||
result := be_src & be_src & be_src & '0';
|
||||
when "10" =>
|
||||
result := be_src & be_src & "00";
|
||||
when "11" =>
|
||||
result := be_src & "000";
|
||||
when others => null;
|
||||
end case;
|
||||
else
|
||||
case va is
|
||||
when "00" =>
|
||||
result := "000" & be_src;
|
||||
when "01" =>
|
||||
result := "00" & be_src & be_src;
|
||||
when "10" =>
|
||||
result := '0' & be_src & be_src & be_src;
|
||||
when "11" =>
|
||||
result := be_src & be_src & be_src & be_src;
|
||||
when others => null;
|
||||
end case;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
return result;
|
||||
|
||||
end store_be;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
function load_shift(x : word_t; va, shift_off : unsigned(1 downto 0); bypass : std_logic) return word_t is
|
||||
variable stage1 : word_t;
|
||||
variable result : word_t;
|
||||
variable sa : unsigned(1 downto 0);
|
||||
|
||||
begin
|
||||
if bypass = '1' then
|
||||
sa := "00";
|
||||
else
|
||||
sa := va + shift_off;
|
||||
end if;
|
||||
|
||||
stage1 := x;
|
||||
if sa(0) = '1' then
|
||||
stage1 := x(7 downto 0) & x(31 downto 8);
|
||||
end if;
|
||||
result := stage1;
|
||||
if sa(1) = '1' then
|
||||
result := stage1(15 downto 0) & stage1(31 downto 16);
|
||||
end if;
|
||||
|
||||
return result;
|
||||
end load_shift;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
function load_be(va : unsigned(1 downto 0); align_left, bypass : std_logic) return unsigned is
|
||||
variable result : unsigned(3 downto 0);
|
||||
begin
|
||||
result := (3 downto 0 => '1');
|
||||
if bypass = '0' then
|
||||
if align_left = '1' then
|
||||
case va is
|
||||
when "00" =>
|
||||
result := "1000";
|
||||
when "01" =>
|
||||
result := "1100";
|
||||
when "10" =>
|
||||
result := "1110";
|
||||
when "11" =>
|
||||
result := "1111";
|
||||
when others => null;
|
||||
end case;
|
||||
else
|
||||
case va is
|
||||
when "00" =>
|
||||
result := "1111";
|
||||
when "01" =>
|
||||
result := "0111";
|
||||
when "10" =>
|
||||
result := "0011";
|
||||
when "11" =>
|
||||
result := "0001";
|
||||
when others => null;
|
||||
end case;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
return result;
|
||||
|
||||
end load_be;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
function load_sign_ext(x : word_t; bypass, signed, word2_en, word4_en : std_logic) return word_t is
|
||||
variable result : word_t;
|
||||
variable sign : std_logic;
|
||||
|
||||
begin
|
||||
if bypass = '1' then
|
||||
result := x;
|
||||
elsif word2_en = '1' then
|
||||
sign := signed and x(15);
|
||||
result := (31 downto 16 => sign) & x(15 downto 0);
|
||||
else
|
||||
sign := signed and x(7);
|
||||
result := (31 downto 8 => sign) & x(7 downto 0);
|
||||
end if;
|
||||
|
||||
return result;
|
||||
end load_sign_ext;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
function events_clr return event_t is
|
||||
variable result : event_t;
|
||||
begin
|
||||
result.NMI := '0';
|
||||
result.Int := '0';
|
||||
result.data_load_err := '0';
|
||||
result.data_store_err := '0';
|
||||
result.inst_load_err := '0';
|
||||
result.inst_priv_addr := '0';
|
||||
result.alu_ovf := '0';
|
||||
result.alu_uvf := '0';
|
||||
result.syscall := '0';
|
||||
result.break := '0';
|
||||
result.illegal := '0';
|
||||
|
||||
return result;
|
||||
|
||||
end events_clr;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
function event_is_active(e : event_t) return std_logic is
|
||||
variable result : std_logic;
|
||||
begin
|
||||
result := '0';
|
||||
|
||||
result := result or e.NMI;
|
||||
result := result or e.Int;
|
||||
result := result or e.data_load_err;
|
||||
result := result or e.data_store_err;
|
||||
result := result or e.inst_load_err;
|
||||
result := result or e.inst_priv_addr;
|
||||
result := result or e.alu_ovf;
|
||||
result := result or e.alu_uvf;
|
||||
result := result or e.syscall;
|
||||
result := result or e.break;
|
||||
result := result or e.illegal;
|
||||
|
||||
return result;
|
||||
|
||||
end event_is_active;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
function "or" (a, b : event_t) return event_t is
|
||||
variable result : event_t;
|
||||
begin
|
||||
result.NMI := a.NMI or b.NMI;
|
||||
result.Int := a.Int or b.Int;
|
||||
result.data_load_err := a.data_load_err or b.data_load_err;
|
||||
result.data_store_err := a.data_store_err or b.data_store_err;
|
||||
result.inst_load_err := a.inst_load_err or b.inst_load_err;
|
||||
result.inst_priv_addr := a.inst_priv_addr or b.inst_priv_addr;
|
||||
result.alu_ovf := a.alu_ovf or b.alu_ovf;
|
||||
result.alu_uvf := a.alu_uvf or b.alu_uvf;
|
||||
result.syscall := a.syscall or b.syscall;
|
||||
result.break := a.break or b.break;
|
||||
result.illegal := a.illegal or b.illegal;
|
||||
|
||||
return result;
|
||||
|
||||
end "or";
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
function lg2(x : natural) return natural is
|
||||
begin
|
||||
return natural(ceil(log2(real(x))));
|
||||
end lg2;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
function po2(x : natural) return natural is
|
||||
begin
|
||||
|
||||
return 2**lg2(x);
|
||||
end po2;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
end mips_types;
|
||||
|
||||
@@ -0,0 +1,341 @@
|
||||
-------------------------------------------------------------------------
|
||||
-- Project: JIPS, a portable 32-bit RISC CPU written in VHDL
|
||||
-- This file: Testbench for JCPU
|
||||
-- also writes 'opc.lst' for JASM-assembler
|
||||
--
|
||||
-- Copyright (C) 2007 J. Ahrensfeld
|
||||
--
|
||||
-- This program is free software: you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation, either version 3 of the License, or
|
||||
-- (at your option) any later version.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
--
|
||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||
--
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
LIBRARY ieee;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
USE ieee.numeric_std.ALL;
|
||||
|
||||
library work;
|
||||
use work.mips_types.all;
|
||||
use work.mips_instr.all;
|
||||
use work.async_types.all;
|
||||
use work.async_defs.all;
|
||||
|
||||
ENTITY mips_sys IS
|
||||
GENERIC
|
||||
(
|
||||
ICACHE_SIZE : natural := 512; -- words
|
||||
DCACHE_SIZE : natural := 512; -- words
|
||||
SRAM_ADDR_WIDTH : integer := 14;
|
||||
FLASH_ADDR_WIDTH : integer := 14
|
||||
);
|
||||
PORT
|
||||
(
|
||||
eb : in std_logic;
|
||||
nmi : in std_logic;
|
||||
rst : in std_logic;
|
||||
clk : in std_logic;
|
||||
flash_cs_n : out std_logic;
|
||||
flash_oe_n : out std_logic;
|
||||
flash_we_n : out std_logic;
|
||||
flash_be_n : out unsigned(3 downto 0);
|
||||
sram_cs_n : out std_logic;
|
||||
sram_we_n : out std_logic;
|
||||
sram_oe_n : out std_logic;
|
||||
sram_be_n : out unsigned(3 downto 0);
|
||||
sram_a : out unsigned(SRAM_ADDR_WIDTH-1 downto 0);
|
||||
sram_d : inout unsigned(31 downto 0);
|
||||
flash_a : out unsigned(FLASH_ADDR_WIDTH-1 downto 0);
|
||||
flash_d : inout unsigned(31 downto 0);
|
||||
|
||||
gpo0 : out unsigned(31 downto 0);
|
||||
gpo1 : out unsigned(31 downto 0);
|
||||
gpi0 : in unsigned(31 downto 0);
|
||||
gpi1 : in unsigned(31 downto 0);
|
||||
|
||||
rx : in std_logic;
|
||||
tx : out std_logic;
|
||||
|
||||
debug : out unsigned(1 downto 0)
|
||||
);
|
||||
END mips_sys;
|
||||
|
||||
ARCHITECTURE behavior OF mips_sys IS
|
||||
|
||||
-- Master
|
||||
signal ACK_I : STD_LOGIC := '0';
|
||||
signal SRDY_I : STD_LOGIC := '0';
|
||||
signal ADDR_O : unsigned(31 downto 0);
|
||||
signal DAT_I : unsigned(31 downto 0) := (others => '0');
|
||||
signal DAT_O : unsigned(31 downto 0);
|
||||
signal WE_O : STD_LOGIC;
|
||||
signal SEL_O : unsigned(3 downto 0);
|
||||
signal CYC_O : STD_LOGIC;
|
||||
signal STB_O : STD_LOGIC;
|
||||
signal MRDY_O : STD_LOGIC;
|
||||
signal INT : unsigned (5 downto 0) := (others => '0');
|
||||
|
||||
-- Slaves
|
||||
signal CYC_I_rom : std_logic;
|
||||
signal ACK_O_rom : std_logic;
|
||||
signal SRDY_O_rom : std_logic;
|
||||
signal DAT_O_rom : unsigned(31 downto 0);
|
||||
|
||||
signal CYC_I_flash : std_logic;
|
||||
signal ACK_O_flash : std_logic;
|
||||
signal SRDY_O_flash : std_logic;
|
||||
signal DAT_O_flash : unsigned(31 downto 0);
|
||||
|
||||
signal CYC_I_sram : std_logic;
|
||||
signal ACK_O_sram : std_logic;
|
||||
signal SRDY_O_sram : std_logic;
|
||||
signal DAT_O_sram : unsigned(31 downto 0);
|
||||
|
||||
signal CYC_I_gpio : std_logic;
|
||||
signal ACK_O_gpio : std_logic;
|
||||
signal SRDY_O_gpio : std_logic;
|
||||
signal DAT_O_gpio : unsigned(31 downto 0);
|
||||
|
||||
signal CYC_I_uart : std_logic;
|
||||
signal ACK_O_uart : std_logic;
|
||||
signal SRDY_O_uart : std_logic;
|
||||
signal DAT_O_uart : unsigned(31 downto 0);
|
||||
|
||||
signal int_timer : std_logic;
|
||||
signal int_uart : std_logic;
|
||||
|
||||
type mem_area_t is (mem_dead, mem_flash, mem_sram, mem_rom, mem_gpio, mem_uart);
|
||||
signal mem_area : mem_area_t;
|
||||
|
||||
BEGIN
|
||||
|
||||
------------------------------------------------------------------
|
||||
-- Memory mux
|
||||
------------------------------------------------------------------
|
||||
mem_mux:
|
||||
process(ADDR_O)
|
||||
begin
|
||||
mem_area <= mem_dead;
|
||||
if ADDR_O(31 downto 28) = X"0" then
|
||||
mem_area <= mem_flash;
|
||||
elsif ADDR_O(31 downto 28) = X"A" then
|
||||
if ADDR_O(27 downto 26) = "00" then
|
||||
if ADDR_O(18 downto 16) = "000" then
|
||||
mem_area <= mem_gpio;
|
||||
elsif ADDR_O(18 downto 16) = "001" then
|
||||
mem_area <= mem_uart;
|
||||
end if;
|
||||
elsif ADDR_O(27 downto 26) = "01" then
|
||||
mem_area <= mem_flash;
|
||||
end if;
|
||||
elsif (ADDR_O(31 downto 28) = X"B" and ADDR_O(15) = '0') then
|
||||
mem_area <= mem_rom;
|
||||
elsif (ADDR_O(31 downto 28) = X"8" or ADDR_O(30) = '1') then
|
||||
mem_area <= mem_sram;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
signal_mux:
|
||||
process(mem_area, CYC_O)
|
||||
begin
|
||||
|
||||
CYC_I_uart <= '0';
|
||||
CYC_I_gpio <= '0';
|
||||
CYC_I_flash <= '0';
|
||||
CYC_I_rom <= '0';
|
||||
CYC_I_sram <= '0';
|
||||
|
||||
case mem_area is
|
||||
|
||||
when mem_gpio =>
|
||||
CYC_I_gpio <= CYC_O;
|
||||
|
||||
when mem_uart =>
|
||||
CYC_I_uart <= CYC_O;
|
||||
|
||||
when mem_flash =>
|
||||
CYC_I_flash <= CYC_O;
|
||||
|
||||
when mem_rom =>
|
||||
CYC_I_rom <= CYC_O;
|
||||
|
||||
when mem_sram =>
|
||||
CYC_I_sram <= CYC_O;
|
||||
|
||||
when others => null;
|
||||
|
||||
end case;
|
||||
|
||||
end process;
|
||||
|
||||
SRDY_I <= SRDY_O_flash or SRDY_O_sram or SRDY_O_rom or SRDY_O_uart or SRDY_O_gpio;
|
||||
ACK_I <= ACK_O_flash or ACK_O_sram or ACK_O_rom or ACK_O_uart or ACK_O_gpio;
|
||||
DAT_I <= DAT_O_sram when CYC_I_sram = '1' else
|
||||
DAT_O_rom when CYC_I_rom = '1' else
|
||||
DAT_O_flash when CYC_I_flash = '1' else
|
||||
DAT_O_uart when CYC_I_uart = '1' else
|
||||
DAT_O_gpio when CYC_I_gpio = '1' else X"DEADBEEF";
|
||||
|
||||
|
||||
------------------------------------------------------------------
|
||||
inst_mips_top: entity work.mips_top
|
||||
GENERIC MAP
|
||||
(
|
||||
icache_size => ICACHE_SIZE, -- words
|
||||
dcache_size => DCACHE_SIZE -- words
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
debug => debug,
|
||||
nmi => nmi,
|
||||
eb => eb,
|
||||
cpu_clk => clk,
|
||||
RST_I => rst,
|
||||
CLK_I => clk,
|
||||
ACK_I => ACK_I,
|
||||
SRDY_I => SRDY_I,
|
||||
ADDR_O => ADDR_O,
|
||||
DAT_I => DAT_I,
|
||||
DAT_O => DAT_O,
|
||||
WE_O => WE_O,
|
||||
SEL_O => SEL_O,
|
||||
CYC_O => CYC_O,
|
||||
STB_O => STB_O,
|
||||
MRDY_O => MRDY_O,
|
||||
INT => INT
|
||||
);
|
||||
INT(1) <= int_uart;
|
||||
INT(5) <= int_timer;
|
||||
|
||||
inst_rom : entity work.rom_wb
|
||||
PORT MAP
|
||||
(
|
||||
CLK_I => clk,
|
||||
RST_I => rst,
|
||||
CYC_I => CYC_I_rom,
|
||||
STB_I => STB_O,
|
||||
ACK_O => ACK_O_rom,
|
||||
MRDY_I => MRDY_O,
|
||||
SRDY_O => SRDY_O_rom,
|
||||
ADDR_I => ADDR_O,
|
||||
DAT_O => DAT_O_rom
|
||||
);
|
||||
|
||||
inst_gpio : entity work.gpio_wb
|
||||
PORT MAP
|
||||
(
|
||||
CLK_I => clk,
|
||||
RST_I => rst,
|
||||
CYC_I => CYC_I_gpio,
|
||||
STB_I => STB_O,
|
||||
SEL_I => SEL_O,
|
||||
WE_I => WE_O,
|
||||
ACK_O => ACK_O_gpio,
|
||||
SRDY_O => SRDY_O_gpio,
|
||||
MRDY_I => MRDY_O,
|
||||
ADDR_I => ADDR_O,
|
||||
DAT_I => DAT_O,
|
||||
DAT_O => DAT_O_gpio,
|
||||
INT_TIM_O => int_timer,
|
||||
sys_gpo0 => gpo0,
|
||||
sys_gpo1 => gpo1,
|
||||
sys_gpi0 => gpi0,
|
||||
sys_gpi1 => gpi1
|
||||
);
|
||||
|
||||
inst_flash_port : entity work.async_port_wb
|
||||
GENERIC MAP
|
||||
(
|
||||
addr_width => FLASH_ADDR_WIDTH,
|
||||
data_width => 32,
|
||||
byte_sel_width => 4,
|
||||
async_timespec => ts_flash
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
CLK_I => clk,
|
||||
RST_I => rst,
|
||||
CYC_I => CYC_I_flash,
|
||||
STB_I => STB_O,
|
||||
WE_I => WE_O,
|
||||
ACK_O => ACK_O_flash,
|
||||
SRDY_O => SRDY_O_flash,
|
||||
MRDY_I => MRDY_O,
|
||||
SEL_I => SEL_O,
|
||||
ADDR_I => ADDR_O,
|
||||
DAT_I => DAT_O,
|
||||
DAT_O => DAT_O_flash,
|
||||
page_mode_en => '0',
|
||||
async_a => flash_a,
|
||||
async_d => flash_d,
|
||||
async_cs => flash_cs_n,
|
||||
async_wr => flash_we_n,
|
||||
async_rd => flash_oe_n,
|
||||
async_be => flash_be_n,
|
||||
async_rst => open
|
||||
);
|
||||
|
||||
inst_sram_port : entity work.async_port_wb
|
||||
GENERIC MAP
|
||||
(
|
||||
addr_width => SRAM_ADDR_WIDTH,
|
||||
data_width => 32,
|
||||
byte_sel_width => 4,
|
||||
async_timespec => ts_sram
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
CLK_I => clk,
|
||||
RST_I => rst,
|
||||
CYC_I => CYC_I_sram,
|
||||
STB_I => STB_O,
|
||||
WE_I => WE_O,
|
||||
ACK_O => ACK_O_sram,
|
||||
SRDY_O => SRDY_O_sram,
|
||||
MRDY_I => MRDY_O,
|
||||
SEL_I => SEL_O,
|
||||
ADDR_I => ADDR_O,
|
||||
DAT_I => DAT_O,
|
||||
DAT_O => DAT_O_sram,
|
||||
page_mode_en => '0',
|
||||
async_a => sram_a,
|
||||
async_d => sram_d,
|
||||
async_cs => sram_cs_n,
|
||||
async_wr => sram_we_n,
|
||||
async_rd => sram_oe_n,
|
||||
async_be => sram_be_n,
|
||||
async_rst => open
|
||||
);
|
||||
|
||||
inst_uart : entity work.uart_wb
|
||||
PORT MAP
|
||||
(
|
||||
CLK_I => clk,
|
||||
RST_I => rst,
|
||||
CYC_I => CYC_I_uart,
|
||||
STB_I => STB_O,
|
||||
SEL_I => SEL_O,
|
||||
WE_I => WE_O,
|
||||
ACK_O => ACK_O_uart,
|
||||
SRDY_O => SRDY_O_uart,
|
||||
MRDY_I => MRDY_O,
|
||||
ADDR_I => ADDR_O,
|
||||
DAT_I => DAT_O,
|
||||
DAT_O => DAT_O_uart,
|
||||
INT_O => int_uart,
|
||||
ser_rx => rx,
|
||||
ser_tx => tx
|
||||
);
|
||||
|
||||
END;
|
||||
@@ -0,0 +1,233 @@
|
||||
-------------------------------------------------------------------------
|
||||
-- Project: JIPS, a portable 32-bit RISC CPU written in VHDL
|
||||
-- This file: Testbench for JCPU
|
||||
-- also writes 'opc.lst' for JASM-assembler
|
||||
--
|
||||
-- Copyright (C) 2007 J. Ahrensfeld
|
||||
--
|
||||
-- This program is free software: you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation, either version 3 of the License, or
|
||||
-- (at your option) any later version.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
--
|
||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||
--
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
LIBRARY ieee;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
USE ieee.numeric_std.ALL;
|
||||
|
||||
library work;
|
||||
use work.mips_types.all;
|
||||
use work.mips_instr.all;
|
||||
use work.async_types.all;
|
||||
use work.async_defs.all;
|
||||
|
||||
ENTITY tb_mips_sys IS
|
||||
END tb_mips_sys;
|
||||
|
||||
ARCHITECTURE behavior OF tb_mips_sys IS
|
||||
|
||||
constant CLK_PERIOD : time := 10 ns;
|
||||
constant ICACHE_SIZE : natural := 512; -- words
|
||||
constant DCACHE_SIZE : natural := 512; -- words
|
||||
constant SRAM_ADDR_WIDTH : integer := 17; -- bits
|
||||
constant FLASH_ADDR_WIDTH : integer := 17; -- bits
|
||||
|
||||
signal debug : unsigned(1 downto 0);
|
||||
|
||||
-- Master
|
||||
signal nmi : STD_LOGIC := '0';
|
||||
signal rst : STD_LOGIC := '1';
|
||||
signal clk : STD_LOGIC := '0';
|
||||
signal eb : STD_LOGIC := '1';
|
||||
|
||||
signal flash_cs_n : std_logic;
|
||||
signal flash_we_n : std_logic;
|
||||
signal flash_oe_n : std_logic;
|
||||
signal flash_be_n : unsigned(3 downto 0);
|
||||
signal sram_cs_n : std_logic;
|
||||
signal sram_be_n : unsigned(3 downto 0);
|
||||
signal sram_wr_n : std_logic;
|
||||
signal sram_oe_n : std_logic;
|
||||
signal sram_a : unsigned(SRAM_ADDR_WIDTH-1 downto 0);
|
||||
signal sram_d : unsigned(31 downto 0);
|
||||
signal flash_a : unsigned(FLASH_ADDR_WIDTH-1 downto 0);
|
||||
signal flash_d : unsigned(31 downto 0);
|
||||
|
||||
signal gpo0 : unsigned(31 downto 0);
|
||||
signal gpo1 : unsigned(31 downto 0);
|
||||
signal gpi0 : unsigned(31 downto 0) := (others => '0');
|
||||
signal gpi1 : unsigned(31 downto 0) := (others => '0');
|
||||
|
||||
signal int_timer : std_logic;
|
||||
signal int_uart : std_logic;
|
||||
signal rx : std_logic := '1';
|
||||
signal tx : std_logic;
|
||||
|
||||
type word_array_t is array (natural range <>) of unsigned(31 downto 0);
|
||||
signal sram_data : word_array_t(0 to 2**SRAM_ADDR_WIDTH-1);
|
||||
signal flash_data : word_array_t(0 to 2**FLASH_ADDR_WIDTH-1);
|
||||
|
||||
BEGIN
|
||||
|
||||
------------------------------------------------------------------
|
||||
CLK_GEN: process
|
||||
begin
|
||||
wait for CLK_PERIOD/2;
|
||||
clk <= not clk;
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
uut : entity work.mips_sys
|
||||
GENERIC MAP
|
||||
(
|
||||
ICACHE_SIZE => ICACHE_SIZE, -- words
|
||||
DCACHE_SIZE => DCACHE_SIZE, -- words
|
||||
SRAM_ADDR_WIDTH => SRAM_ADDR_WIDTH,
|
||||
FLASH_ADDR_WIDTH => FLASH_ADDR_WIDTH
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
eb => eb,
|
||||
nmi => nmi,
|
||||
rst => rst,
|
||||
clk => clk,
|
||||
flash_cs_n => flash_cs_n,
|
||||
flash_oe_n => flash_oe_n,
|
||||
flash_we_n => flash_we_n,
|
||||
flash_be_n => flash_be_n,
|
||||
sram_cs_n => sram_cs_n,
|
||||
sram_we_n => sram_wr_n,
|
||||
sram_oe_n => sram_oe_n,
|
||||
sram_be_n => sram_be_n,
|
||||
sram_a => sram_a,
|
||||
sram_d => sram_d,
|
||||
flash_a => flash_a,
|
||||
flash_d => flash_d,
|
||||
|
||||
gpo0 => gpo0,
|
||||
gpo1 => gpo1,
|
||||
gpi0 => gpi0,
|
||||
gpi1 => gpi1,
|
||||
|
||||
rx => rx,
|
||||
tx => tx,
|
||||
|
||||
debug => debug
|
||||
);
|
||||
|
||||
------------------------------------------------------------------
|
||||
SRAM_READ:
|
||||
process(sram_a, sram_cs_n, sram_oe_n, sram_be_n)
|
||||
begin
|
||||
sram_d <= (others => 'Z') after 10 ns;
|
||||
if sram_oe_n = '0' then
|
||||
if sram_cs_n = '0' then
|
||||
if sram_be_n(0) = '0' then
|
||||
sram_d(7 downto 0) <= sram_data(to_integer(sram_a(SRAM_ADDR_WIDTH-1 downto 2)))(7 downto 0) after 10 ns;
|
||||
end if;
|
||||
if sram_be_n(1) = '0' then
|
||||
sram_d(15 downto 8) <= sram_data(to_integer(sram_a(SRAM_ADDR_WIDTH-1 downto 2)))(15 downto 8) after 10 ns;
|
||||
end if;
|
||||
if sram_be_n(2) = '0' then
|
||||
sram_d(23 downto 16) <= sram_data(to_integer(sram_a(SRAM_ADDR_WIDTH-1 downto 2)))(23 downto 16) after 10 ns;
|
||||
end if;
|
||||
if sram_be_n(3) = '0' then
|
||||
sram_d(31 downto 24) <= sram_data(to_integer(sram_a(SRAM_ADDR_WIDTH-1 downto 2)))(31 downto 24) after 10 ns;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
SRAM_WRITE:
|
||||
process(sram_wr_n)
|
||||
begin
|
||||
if rising_edge(sram_wr_n) then
|
||||
if sram_cs_n = '0' then
|
||||
if sram_be_n(0) = '0' then
|
||||
sram_data(to_integer(sram_a(SRAM_ADDR_WIDTH-1 downto 2)))(7 downto 0) <= sram_d(7 downto 0);
|
||||
end if;
|
||||
if sram_be_n(1) = '0' then
|
||||
sram_data(to_integer(sram_a(SRAM_ADDR_WIDTH-1 downto 2)))(15 downto 8) <= sram_d(15 downto 8);
|
||||
end if;
|
||||
if sram_be_n(2) = '0' then
|
||||
sram_data(to_integer(sram_a(SRAM_ADDR_WIDTH-1 downto 2)))(23 downto 16) <= sram_d(23 downto 16);
|
||||
end if;
|
||||
if sram_be_n(3) = '0' then
|
||||
sram_data(to_integer(sram_a(SRAM_ADDR_WIDTH-1 downto 2)))(31 downto 24) <= sram_d(31 downto 24);
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
FLASH_READ:
|
||||
process(rst, flash_cs_n, flash_oe_n, flash_a)
|
||||
type file_t is file of integer;
|
||||
file load_flash : file_t open read_mode is "hello.flash.bin";
|
||||
variable instr : integer;
|
||||
variable index : natural;
|
||||
variable temp : signed(31 downto 0);
|
||||
constant tpd : time := 25 ns;
|
||||
begin
|
||||
if rst = '1' then
|
||||
index := 0;
|
||||
while not endfile(load_flash) loop
|
||||
read(load_flash, instr);
|
||||
temp := to_signed(instr, word_t'length);
|
||||
flash_data(index) <= unsigned(temp);
|
||||
index := index + 1;
|
||||
end loop;
|
||||
else
|
||||
flash_d <= (others => 'Z') after tpd;
|
||||
index := to_integer(flash_a(FLASH_ADDR_WIDTH-1 downto 2));
|
||||
if flash_oe_n = '0' then
|
||||
if flash_cs_n = '0' then
|
||||
if flash_be_n(0) = '0' then
|
||||
flash_d(7 downto 0) <= flash_data(index)(7 downto 0) after tpd;
|
||||
end if;
|
||||
if flash_be_n(1) = '0' then
|
||||
flash_d(15 downto 8) <= flash_data(index)(15 downto 8) after tpd;
|
||||
end if;
|
||||
if flash_be_n(2) = '0' then
|
||||
flash_d(23 downto 16) <= flash_data(index)(23 downto 16) after tpd;
|
||||
end if;
|
||||
if flash_be_n(3) = '0' then
|
||||
flash_d(31 downto 24) <= flash_data(index)(31 downto 24) after tpd;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
STIMULUS: process
|
||||
|
||||
begin
|
||||
|
||||
|
||||
wait for 3*CLK_PERIOD;
|
||||
wait until rising_edge(clk);
|
||||
rst <= '0';
|
||||
wait for 778254*CLK_PERIOD;
|
||||
wait until rising_edge(clk);
|
||||
nmi <= '0';
|
||||
wait for 3000*CLK_PERIOD;
|
||||
wait until rising_edge(clk);
|
||||
nmi <= '0';
|
||||
|
||||
wait;
|
||||
|
||||
end process;
|
||||
|
||||
END;
|
||||
@@ -0,0 +1,20 @@
|
||||
CFLAGS=-O2
|
||||
CC=gcc
|
||||
PREFIX=/usr/local
|
||||
all: romgen ramgen flashgen
|
||||
|
||||
romgen: ./src/romgen.c
|
||||
$(CC) $(CFLAGS) ./src/romgen.c -lm -o ./romgen
|
||||
|
||||
ramgen: ./src/ramgen.c
|
||||
$(CC) $(CFLAGS) ./src/ramgen.c -lm -o ./ramgen
|
||||
|
||||
flashgen: ./src/flashgen.c
|
||||
$(CC) $(CFLAGS) ./src/flashgen.c -lm -o ./flashgen
|
||||
|
||||
install:
|
||||
cp romgen $(PREFIX)/bin
|
||||
cp ramgen $(PREFIX)/bin
|
||||
cp flashgen $(PREFIX)/bin
|
||||
clean:
|
||||
rm -rf romgen* ramgen* flashgen*
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,140 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#define INT8 char
|
||||
#define INT16 short
|
||||
#define INT32 long
|
||||
#define UINT8 unsigned char
|
||||
#define UINT16 unsigned short
|
||||
#define UINT32 unsigned long
|
||||
#define INT int
|
||||
#define UINT unsigned int
|
||||
#define FLOAT32 float
|
||||
#define FLOAT64 double
|
||||
|
||||
#define SDRAM_BASE 0x40000000
|
||||
#define FLASH_OFFSET 0x00000000
|
||||
|
||||
#define MAGIC_EB 0x4A464931 // "JFI1" in big-endian;
|
||||
#define MAGIC_EL 0x3149464A // "JFI1" in little-endian;
|
||||
|
||||
UINT32 conv_endian32(UINT32 src)
|
||||
{
|
||||
UINT32 dst;
|
||||
|
||||
dst = (0xFF000000 & (src << 24))
|
||||
| (0x00FF0000 & (src << 8))
|
||||
| (0x0000FF00 & (src >> 8))
|
||||
| (0x000000FF & (src >> 24));
|
||||
|
||||
return dst;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------
|
||||
typedef struct _sflash_img_hdr_t
|
||||
{
|
||||
UINT32 magic;
|
||||
UINT32 target_addr;
|
||||
UINT32 img_offset;
|
||||
UINT32 img_size;
|
||||
UINT32 hdr_next;
|
||||
UINT8 img_name[128];
|
||||
UINT8 res[108];
|
||||
|
||||
} flash_img_hdr_t;
|
||||
|
||||
// --------------------------------------------------------------
|
||||
void basename(char *pSrc, char *pDst)
|
||||
{
|
||||
int i, size;
|
||||
|
||||
size = strlen(pSrc);
|
||||
|
||||
while(pSrc[size] != '.')
|
||||
size--;
|
||||
|
||||
for (i=0; i < size; i++)
|
||||
pDst[i] = pSrc[i];
|
||||
|
||||
pDst[i] = 0;
|
||||
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *pFilenameIn;
|
||||
char name_flash[1024];
|
||||
char name_prj[1024];
|
||||
char *pBuf;
|
||||
UINT32 *pBuf32;
|
||||
flash_img_hdr_t img_hdr = {0};
|
||||
|
||||
FILE *pFile;
|
||||
int filesize;
|
||||
long start, end;
|
||||
int i;
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
fprintf(stderr, "Usage: flashgen <input file> [-{EL|EB}]\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
pFilenameIn = argv[1];
|
||||
pFile = fopen(pFilenameIn, "rb");
|
||||
if (!pFile)
|
||||
{
|
||||
fprintf(stderr, "Error opening file %s\n", pFilenameIn);
|
||||
return 1;
|
||||
}
|
||||
|
||||
basename(pFilenameIn, name_prj);
|
||||
sprintf(name_flash, "%s.flash.bin", name_prj);
|
||||
|
||||
// determine filesize
|
||||
fseek(pFile, 0, SEEK_SET);
|
||||
start = ftell(pFile);
|
||||
fseek(pFile, 0, SEEK_END);
|
||||
end = ftell(pFile);
|
||||
fseek(pFile, 0, SEEK_SET);
|
||||
filesize = (end-start);
|
||||
|
||||
pBuf = (char*)malloc(filesize);
|
||||
fread(pBuf, 1, filesize, pFile);
|
||||
|
||||
fclose(pFile);
|
||||
|
||||
pFile = fopen(name_flash, "wb");
|
||||
if (!pFile)
|
||||
{
|
||||
fprintf(stderr, "Error opening file %s\n", name_flash);
|
||||
return 1;
|
||||
}
|
||||
|
||||
img_hdr.magic = MAGIC_EL;
|
||||
img_hdr.target_addr = SDRAM_BASE;
|
||||
img_hdr.img_size = filesize;
|
||||
img_hdr.img_offset = FLASH_OFFSET + sizeof(flash_img_hdr_t);
|
||||
img_hdr.hdr_next = FLASH_OFFSET;
|
||||
|
||||
if (argc == 3)
|
||||
{
|
||||
if ((argv[2][0] == '-') && (toupper(argv[2][1]) == 'E') && (toupper(argv[2][2]) == 'B'))
|
||||
{
|
||||
img_hdr.magic = MAGIC_EB;
|
||||
pBuf32 = (UINT32*)pBuf;
|
||||
for (i=0; i < filesize/4; i ++)
|
||||
pBuf32[i] = conv_endian32(pBuf32[i]);
|
||||
}
|
||||
}
|
||||
fwrite(&img_hdr, sizeof(flash_img_hdr_t), 1, pFile);
|
||||
fwrite(pBuf, 1, filesize, pFile);
|
||||
|
||||
fclose(pFile);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,385 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#define ARCH_NAME "data"
|
||||
#define ENT_NAME "ram"
|
||||
#define JTAG_ADDR_WIDTH 16
|
||||
|
||||
// --------------------------------------------------------------
|
||||
void basename(char *pSrc, char *pDst)
|
||||
{
|
||||
int i, size;
|
||||
|
||||
size = strlen(pSrc);
|
||||
|
||||
while(pSrc[size] != '.')
|
||||
size--;
|
||||
|
||||
for (i=0; i < size; i++)
|
||||
pDst[i] = pSrc[i];
|
||||
|
||||
pDst[i] = 0;
|
||||
|
||||
}
|
||||
|
||||
int SaveRAM(char *pFilenameIn, char *pFilenameOut, char *pArchName, char *pEntName, int nbits_addr, int nbits_data)
|
||||
{
|
||||
FILE *pFileIn, *pFileOut;
|
||||
long start, end;
|
||||
int i, word, filesize, romsize;
|
||||
|
||||
pFileIn = fopen(pFilenameIn, "rb");
|
||||
if (!pFileIn)
|
||||
{
|
||||
fprintf(stderr, "Error opening file %s\n", pFilenameIn);
|
||||
return 1;
|
||||
}
|
||||
|
||||
pFileOut = fopen(pFilenameOut, "wb");
|
||||
if (!pFileOut)
|
||||
{
|
||||
fprintf(stderr, "Error opening file %s\n", pFilenameOut);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fseek(pFileIn, 0, SEEK_SET);
|
||||
start = ftell(pFileIn);
|
||||
fseek(pFileIn, 0, SEEK_END);
|
||||
end = ftell(pFileIn);
|
||||
fseek(pFileIn, 0, SEEK_SET);
|
||||
|
||||
filesize = (end-start);
|
||||
romsize = (int)pow(2, nbits_addr+2);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Header
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
fprintf(pFileOut, "LIBRARY IEEE;\n");
|
||||
fprintf(pFileOut, "USE IEEE.STD_LOGIC_1164.ALL;\n");
|
||||
fprintf(pFileOut, "USE IEEE.NUMERIC_STD.ALL;\n");
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
fprintf(pFileOut, "ENTITY %s IS\n", ENT_NAME);
|
||||
fprintf(pFileOut, "\tPort\n");
|
||||
fprintf(pFileOut, "\t(\n");
|
||||
fprintf(pFileOut, "\t\tclk\t\t: in STD_LOGIC;\n");
|
||||
fprintf(pFileOut, "\t\tce\t\t: in STD_LOGIC;\n");
|
||||
fprintf(pFileOut, "\t\twe\t\t: in unsigned(%d downto 0);\n", nbits_data/8-1);
|
||||
fprintf(pFileOut, "\t\taddr\t\t: in unsigned(%d downto 0);\n", nbits_data-1);
|
||||
fprintf(pFileOut, "\t\tdin\t\t: in unsigned(%d downto 0);\n", nbits_data-1);
|
||||
fprintf(pFileOut, "\t\tdout\t\t: out unsigned(%d downto 0)\n", nbits_data-1);
|
||||
fprintf(pFileOut, "\t);\n");
|
||||
fprintf(pFileOut, "END %s;\n", ENT_NAME);
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
|
||||
fprintf(pFileOut, "ARCHITECTURE %s OF %s IS\n", ARCH_NAME, ENT_NAME);
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
fprintf(pFileOut, "\tconstant depth : natural := %d;\n", romsize/4);
|
||||
fprintf(pFileOut, "\tsubtype word_t is unsigned(%d downto 0);\n", nbits_data-1);
|
||||
fprintf(pFileOut, "\ttype word_array_t is array (0 to %d) of word_t;\n", romsize/4-1);
|
||||
|
||||
fprintf(pFileOut, "\tsignal sram : word_array_t :=\n");
|
||||
fprintf(pFileOut, "\t(\n");
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// ROM part
|
||||
// -------------------------------------------------------------------------
|
||||
for (i=0; i < filesize; i += sizeof(int))
|
||||
{
|
||||
fread(&word, 1, sizeof(int), pFileIn);
|
||||
fprintf(pFileOut, "\t\tX\"%8.8X\"", word);
|
||||
if (i < (romsize-sizeof(int)))
|
||||
fprintf(pFileOut, ", -- %8.8X\n", i);
|
||||
else
|
||||
fprintf(pFileOut, " -- %8.8X\n", i);
|
||||
}
|
||||
word = 0;
|
||||
for (; i < romsize; i += sizeof(int))
|
||||
{
|
||||
fprintf(pFileOut, "\t\tX\"%8.8X\"", word);
|
||||
if (i < (romsize-sizeof(int)))
|
||||
fprintf(pFileOut, ", -- %8.8X\n", i);
|
||||
else
|
||||
fprintf(pFileOut, " -- %8.8X\n", i);
|
||||
}
|
||||
fprintf(pFileOut, "\t);\n");
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Trailer
|
||||
// -------------------------------------------------------------------------
|
||||
fprintf(pFileOut, "begin\n", ARCH_NAME);
|
||||
fprintf(pFileOut, "\n");
|
||||
fprintf(pFileOut, "RAM_RW:\n", ARCH_NAME);
|
||||
fprintf(pFileOut, "\tprocess(clk)\n");
|
||||
fprintf(pFileOut, "\tvariable index : natural range 0 to depth-1;\n");
|
||||
fprintf(pFileOut, "\tbegin\n");
|
||||
fprintf(pFileOut, "\t\tif rising_edge(clk) and ce = '1' then\n");
|
||||
fprintf(pFileOut, "\t\t\tindex := to_integer(addr(%d downto 2));\n", nbits_addr+1);
|
||||
fprintf(pFileOut, "\t\t\tif we(0) = '1' then\n");
|
||||
fprintf(pFileOut, "\t\t\t\tsram(index)(7 downto 0)\t\t<= din(7 downto 0);\n");
|
||||
fprintf(pFileOut, "\t\t\tend if;\n");
|
||||
fprintf(pFileOut, "\t\t\tif we(1) = '1' then\n");
|
||||
fprintf(pFileOut, "\t\t\t\tsram(index)(15 downto 8)\t<= din(15 downto 8);\n");
|
||||
fprintf(pFileOut, "\t\t\tend if;\n");
|
||||
fprintf(pFileOut, "\t\t\tif we(2) = '1' then\n");
|
||||
fprintf(pFileOut, "\t\t\t\tsram(index)(23 downto 16)\t<= din(23 downto 16);\n");
|
||||
fprintf(pFileOut, "\t\t\tend if;\n");
|
||||
fprintf(pFileOut, "\t\t\tif we(3) = '1' then\n");
|
||||
fprintf(pFileOut, "\t\t\t\tsram(index)(31 downto 24)\t\t<= din(31 downto 24);\n");
|
||||
fprintf(pFileOut, "\t\t\tend if;\n");
|
||||
fprintf(pFileOut, "\t\t\tdout <= sram(index);\n");
|
||||
fprintf(pFileOut, "\t\tend if;\n");
|
||||
fprintf(pFileOut, "\tend process;\n");
|
||||
fprintf(pFileOut, "\n");
|
||||
fprintf(pFileOut, "end %s;\n", ARCH_NAME);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SaveRAM_V4LD(char *pFilenameIn, char *pFilenameOut, char *pArchName, char *pEntName, int nbits_addr, int nbits_data)
|
||||
{
|
||||
FILE *pFileIn, *pFileOut;
|
||||
long start, end;
|
||||
int i, word, filesize, romsize;
|
||||
|
||||
char tpl[] = {"--------------------------------------------------------------------------\n-- Virtex-4: JTAG Loader\n--------------------------------------------------------------------------\n\ti00_BUFG : BUFG\n\tport map\n\t(\n\t\tO => bs_clk1,\n I => bs_clk0\n\t);\n\t\n\ti01_BUFG : BUFG\n\tport map\n\t(\n\t\tO => bs_update1,\n I => bs_update0\n\t);\n\n\tBSCAN_VIRTEX4_inst1 : BSCAN_VIRTEX4 \n\tgeneric map\n\t(\n\t\tJTAG_CHAIN => 1 -- Value to set BSCAN site of device. Possible values: (1,2,3 or 4)\n\t)\n\tport map \n\t(\n\t\tCAPTURE => bs_capture, -- CAPTURE output from TAP controller\n\t\tDRCK => bs_clk0, -- Data register output for USER functions\n\t\tRESET => bs_rst, -- Reset output from TAP controller\n\t\tSEL => bs_sel, -- USER active output\n\t\tSHIFT => bs_shift, -- SHIFT output from TAP controller\n\t\tTDI => bs_tdi, -- TDI output from TAP controller\n\t\tUPDATE => bs_update0, -- UPDATE output from TAP controller\n\t\tTDO => bs_tdo -- Data input for USER function\n\t);\n\n\tjtag_ld_addr <= user_regi(user_regi'left downto jtag_ld_dout'length);\n\tjtag_ld_din <= user_regi(jtag_ld_dout'length-1 downto 0);\n\tjtag_ld_clk <= bs_update1;\n\tjtag_ld_we <= bs_sel;\n\t\nsipo:\n\tprocess (bs_rst, bs_clk1, bs_tdi, bs_shift)\n\tbegin\n\t\tif bs_rst = '1' then\n\t\t\tuser_regi <= (others => '0');\n\t\telsif rising_edge(bs_clk1) then\n\t\t\tif bs_shift = '1' then\n\t\t\t\tuser_regi <= bs_tdi & user_regi(user_regi'left downto 1);\n\t\t\tend if;\n\t\tend if;\n\tend process;\t\n\npiso:\n\tprocess (bs_rst, bs_clk1, bs_shift, user_rego)\n\tbegin\n\t\tbs_tdo <= user_rego(0);\n\t\tif bs_rst = '1' then\n\t\t\tuser_rego <= (others => '0');\n\t\telsif rising_edge(bs_clk1) then\n\t\t\tif bs_shift = '1' then\n\t\t\t\tuser_rego <= user_rego(0) & user_rego(user_rego'left downto 1);\n\t\t\telse\n\t\t\t\tuser_rego <= (user_rego'left downto jtag_ld_dout'length => '0') & jtag_ld_dout;\t\n\t\n\t\t\tend if;\n\t\tend if;\n\tend process;\n\n"};
|
||||
|
||||
pFileIn = fopen(pFilenameIn, "rb");
|
||||
if (!pFileIn)
|
||||
{
|
||||
fprintf(stderr, "Error opening file %s\n", pFilenameIn);
|
||||
return 1;
|
||||
}
|
||||
|
||||
pFileOut = fopen(pFilenameOut, "wb");
|
||||
if (!pFileOut)
|
||||
{
|
||||
fprintf(stderr, "Error opening file %s\n", pFilenameOut);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fseek(pFileIn, 0, SEEK_SET);
|
||||
start = ftell(pFileIn);
|
||||
fseek(pFileIn, 0, SEEK_END);
|
||||
end = ftell(pFileIn);
|
||||
fseek(pFileIn, 0, SEEK_SET);
|
||||
|
||||
filesize = (end-start);
|
||||
romsize = (int)pow(2, nbits_addr+2);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Header
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
fprintf(pFileOut, "LIBRARY IEEE;\n");
|
||||
fprintf(pFileOut, "USE IEEE.STD_LOGIC_1164.ALL;\n");
|
||||
fprintf(pFileOut, "USE IEEE.NUMERIC_STD.ALL;\n");
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
fprintf(pFileOut, "library UNISIM;\n");
|
||||
fprintf(pFileOut, "use UNISIM.VComponents.all;\n");
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
fprintf(pFileOut, "ENTITY %s IS\n", ENT_NAME);
|
||||
fprintf(pFileOut, "\tPort\n");
|
||||
fprintf(pFileOut, "\t(\n");
|
||||
fprintf(pFileOut, "\t\tclk\t\t: in STD_LOGIC;\n");
|
||||
fprintf(pFileOut, "\t\tce\t\t: in STD_LOGIC;\n");
|
||||
fprintf(pFileOut, "\t\taddr\t\t: in unsigned(%d downto 0);\n", nbits_data-1);
|
||||
fprintf(pFileOut, "\t\tdout\t\t: out unsigned(%d downto 0)\n", nbits_data-1);
|
||||
fprintf(pFileOut, "\t);\n");
|
||||
fprintf(pFileOut, "END %s;\n", ENT_NAME);
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
|
||||
fprintf(pFileOut, "ARCHITECTURE %s OF %s IS\n", ARCH_NAME, ENT_NAME);
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
fprintf(pFileOut, "\tsubtype word_t is unsigned(%d downto 0);\n", nbits_data-1);
|
||||
fprintf(pFileOut, "\ttype word_array_t is array (0 to %d) of word_t;\n", romsize/4-1);
|
||||
|
||||
fprintf(pFileOut, "\tsignal jtag_ld_clk\t\t: STD_LOGIC;\n");
|
||||
fprintf(pFileOut, "\tsignal jtag_ld_we\t\t: STD_LOGIC;\n");
|
||||
fprintf(pFileOut, "\tsignal jtag_ld_addr\t\t: unsigned (%d downto 0);\n", JTAG_ADDR_WIDTH-1);
|
||||
fprintf(pFileOut, "\tsignal jtag_ld_dout\t\t: unsigned (%d downto 0);\n", nbits_data-1);
|
||||
fprintf(pFileOut, "\tsignal jtag_ld_din\t\t: unsigned (%d downto 0);\n", nbits_data-1);
|
||||
fprintf(pFileOut, "\tsignal bs_rst, bs_sel, bs_shift, bs_tdi, bs_tdo : std_logic;\n");
|
||||
fprintf(pFileOut, "\tsignal bs_capture, bs_clk0, bs_clk1, bs_update0, bs_update1 : std_logic;\n");
|
||||
fprintf(pFileOut, "\tsignal user_regi, user_rego : unsigned (%d downto 0);\n", 31 + JTAG_ADDR_WIDTH);
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
fprintf(pFileOut, "\tsignal word_array : word_array_t :=\n");
|
||||
fprintf(pFileOut, "\t(\n");
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// ROM part
|
||||
// -------------------------------------------------------------------------
|
||||
for (i=0; i < filesize; i += sizeof(int))
|
||||
{
|
||||
fread(&word, 1, sizeof(int), pFileIn);
|
||||
fprintf(pFileOut, "\t\tX\"%8.8X\"", word);
|
||||
if (i < (romsize-sizeof(int)))
|
||||
fprintf(pFileOut, ", -- %8.8X\n", i);
|
||||
else
|
||||
fprintf(pFileOut, " -- %8.8X\n", i);
|
||||
}
|
||||
word = 0;
|
||||
for (; i < romsize; i += sizeof(int))
|
||||
{
|
||||
fprintf(pFileOut, "\t\tX\"%8.8X\"", word);
|
||||
if (i < (romsize-sizeof(int)))
|
||||
fprintf(pFileOut, ", -- %8.8X\n", i);
|
||||
else
|
||||
fprintf(pFileOut, " -- %8.8X\n", i);
|
||||
}
|
||||
fprintf(pFileOut, "\t);\n");
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
fprintf(pFileOut, "begin\n", ARCH_NAME);
|
||||
|
||||
fprintf(pFileOut, "\n");
|
||||
fprintf(pFileOut, "PROM_READ:\n", ARCH_NAME);
|
||||
fprintf(pFileOut, "\tprocess(clk)\n");
|
||||
fprintf(pFileOut, "\tbegin\n");
|
||||
fprintf(pFileOut, "\t\tif rising_edge(clk) and ce = '1' then\n");
|
||||
fprintf(pFileOut, "\t\t\tdout <= word_array(to_integer(addr(%d downto 2)));\n", nbits_addr+1);
|
||||
fprintf(pFileOut, "\t\tend if;\n");
|
||||
fprintf(pFileOut, "\tend process;\n");
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Trailer
|
||||
// -------------------------------------------------------------------------
|
||||
fprintf(pFileOut, "\n");
|
||||
fputs(tpl, pFileOut);
|
||||
|
||||
fprintf(pFileOut, "PROM_WRITE:\n", ARCH_NAME);
|
||||
fprintf(pFileOut, "\tprocess(jtag_ld_clk, jtag_ld_we)\n");
|
||||
fprintf(pFileOut, "\tbegin\n");
|
||||
fprintf(pFileOut, "\t\tif rising_edge(jtag_ld_clk) then\n");
|
||||
fprintf(pFileOut, "\t\t\tif jtag_ld_we = '1' then\n");
|
||||
fprintf(pFileOut, "\t\t\t\tword_array(to_integer(jtag_ld_addr(%d downto 0))) <= jtag_ld_din;\n", nbits_addr-1);
|
||||
fprintf(pFileOut, "\t\t\telse\n");
|
||||
fprintf(pFileOut, "\t\t\t\tjtag_ld_dout <= word_array(to_integer(jtag_ld_addr(%d downto 0)));\n", nbits_addr-1);
|
||||
fprintf(pFileOut, "\t\t\tend if;\n");
|
||||
fprintf(pFileOut, "\t\tend if;\n");
|
||||
fprintf(pFileOut, "\tend process;\n");
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
fprintf(pFileOut, "end %s;\n", ARCH_NAME);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SaveRAM_TCL(char *pFilenameIn, char *pFilenameOut, char *pArchName, char *pEntName, int nbits_addr, int nbits_data)
|
||||
{
|
||||
FILE *pFileIn, *pFileOut;
|
||||
long start, end;
|
||||
int i, word, word_addr, filesize, romsize;
|
||||
char binstr_addr[33];
|
||||
char binstr_data[33];
|
||||
|
||||
char tpl[] = {"# ---------------------------------------------------------------------\n# For Chipscope 9.1\n# ---------------------------------------------------------------------\n# Source JTAG/TCL frame work\ncd $env(CHIPSCOPE)\\\\bin\\\\nt\nsource csejtag.tcl\n\nnamespace import ::chipscope::*\n\n# Platform USB Cable\nset PLATFORM_USB_CABLE_ARGS [list \"port=USB2\" \"frequency=6000000\"]\n# frequency=\"24000000 | 12000000 | 6000000 | 3000000 | 1500000 | 750000\"\n\n# Create session\nset handle [::chipscope::csejtag_session create 0]\n\n# Open JTAG and lock\nset open_result [::chipscope::csejtag_target open $handle $CSEJTAG_TARGET_PLATFORMUSB 0 $PLATFORM_USB_CABLE_ARGS]\nset lock_result [::chipscope::csejtag_target lock $handle 1000]\n\nset devlist [::chipscope::csejtag_tap autodetect_chain $handle $CSEJTAG_SCAN_DEFAULT]\n\n# Get Device ID\nset devtype \"Virtex-4SX\"\nset devid 2\nset irlength [::chipscope::csejtag_tap get_irlength $handle $devid]\nset idcode [::chipscope::csejtag_tap get_device_idcode $handle $devid]\n\nset CSE_OP $CSEJTAG_SHIFT_READWRITE\nset CSE_ES $CSEJTAG_RUN_TEST_IDLE\n\n# Write Program\n"};
|
||||
|
||||
pFileIn = fopen(pFilenameIn, "rb");
|
||||
if (!pFileIn)
|
||||
{
|
||||
fprintf(stderr, "Error opening file %s\n", pFilenameIn);
|
||||
return 1;
|
||||
}
|
||||
|
||||
pFileOut = fopen(pFilenameOut, "wb");
|
||||
if (!pFileOut)
|
||||
{
|
||||
fprintf(stderr, "Error opening file %s\n", pFilenameOut);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fseek(pFileIn, 0, SEEK_SET);
|
||||
start = ftell(pFileIn);
|
||||
fseek(pFileIn, 0, SEEK_END);
|
||||
end = ftell(pFileIn);
|
||||
fseek(pFileIn, 0, SEEK_SET);
|
||||
|
||||
filesize = (end-start);
|
||||
romsize = (int)pow(2, nbits_addr+2);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Header
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
fputs(tpl, pFileOut);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// ROM part
|
||||
// -------------------------------------------------------------------------
|
||||
fprintf(pFileOut, "# Assembled from %s\n", pFilenameIn);
|
||||
fprintf(pFileOut, "# ---------------------------------------------------------------\n");
|
||||
fprintf(pFileOut, "# Shift the USER2 Instruction (b1111000011) into the Instruction Register of FPGA\n");
|
||||
fprintf(pFileOut, "# User 2\n");
|
||||
fprintf(pFileOut, "set result [::chipscope::csejtag_tap shift_device_ir $handle $devid $CSE_OP $CSE_ES 0 $irlength \"3C3\"]\n\n");
|
||||
|
||||
word_addr = 0;
|
||||
for (i=0; i < filesize; i += sizeof(int))
|
||||
{
|
||||
fread(&word, 1, sizeof(int), pFileIn);
|
||||
fprintf(pFileOut, "::chipscope::csejtag_tap shift_device_dr $handle $devid $CSE_OP $CSE_ES 0 %d \"%4.4X%8.8X\"\n", nbits_data + JTAG_ADDR_WIDTH, word_addr, word);
|
||||
word_addr++;
|
||||
}
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Trailer
|
||||
// -------------------------------------------------------------------------
|
||||
fprintf(pFileOut, "::chipscope::csejtag_target unlock $handle\n");
|
||||
fprintf(pFileOut, "::chipscope::csejtag_target close $handle\n");
|
||||
fprintf(pFileOut, "::chipscope::csejtag_session destroy $handle\n");
|
||||
fprintf(pFileOut, "exit\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *pFilenameIn;
|
||||
char name_prj[1024];
|
||||
char name_rom_tcl[1024];
|
||||
char name_rom[1024];
|
||||
char name_rom_v4ld[1024];
|
||||
|
||||
FILE *pFileIn;
|
||||
int filesize, romsize, nbits_addr, nbits_data;
|
||||
long start, end;
|
||||
int word, i;
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
fprintf(stderr, "Usage: ramgen <input file> <num. word address bits>\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
pFilenameIn = argv[1];
|
||||
if (argc == 3)
|
||||
nbits_addr = atoi(argv[2]);
|
||||
|
||||
|
||||
basename(pFilenameIn, name_prj);
|
||||
sprintf(name_rom, "%s.vhd", name_prj);
|
||||
sprintf(name_rom_v4ld, "%s_ld.vhd", name_prj);
|
||||
sprintf(name_rom_tcl, "%s.tcl", name_prj);
|
||||
|
||||
SaveRAM(pFilenameIn, name_rom, ARCH_NAME, ENT_NAME, nbits_addr, 32);
|
||||
// SaveROM_V4LD(pFilenameIn, name_rom_v4ld, ARCH_NAME, ENT_NAME, nbits_addr, 32);
|
||||
SaveRAM_TCL(pFilenameIn, name_rom_tcl, ARCH_NAME, ENT_NAME, nbits_addr, 32);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,428 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#define INT8 char
|
||||
#define INT16 short
|
||||
#define INT32 long
|
||||
#define UINT8 unsigned char
|
||||
#define UINT16 unsigned short
|
||||
#define UINT32 unsigned long
|
||||
#define INT int
|
||||
#define UINT unsigned int
|
||||
#define FLOAT32 float
|
||||
#define FLOAT64 double
|
||||
|
||||
#define ARCH_NAME "data"
|
||||
#define ENT_NAME "rom"
|
||||
#define JTAG_ADDR_WIDTH 16
|
||||
|
||||
UINT32 g_endianess_EB;
|
||||
|
||||
// --------------------------------------------------------------
|
||||
UINT32 conv_endian32(UINT32 src)
|
||||
{
|
||||
UINT32 dst;
|
||||
|
||||
dst = (0xFF000000 & (src << 24))
|
||||
| (0x00FF0000 & (src << 8))
|
||||
| (0x0000FF00 & (src >> 8))
|
||||
| (0x000000FF & (src >> 24));
|
||||
|
||||
return dst;
|
||||
};
|
||||
|
||||
UINT32 to_big_endian32(UINT32 src)
|
||||
{
|
||||
#ifndef NATIVE_IS_BIG_ENDIAN
|
||||
return conv_endian32(src);
|
||||
#else
|
||||
return src;
|
||||
#endif
|
||||
}
|
||||
|
||||
UINT32 from_big_endian32(UINT32 src)
|
||||
{
|
||||
#ifndef NATIVE_IS_BIG_ENDIAN
|
||||
return conv_endian32(src);
|
||||
#else
|
||||
return src;
|
||||
#endif
|
||||
}
|
||||
|
||||
void basename(char *pSrc, char *pDst)
|
||||
{
|
||||
int i, size;
|
||||
|
||||
size = strlen(pSrc);
|
||||
|
||||
while(pSrc[size] != '.')
|
||||
size--;
|
||||
|
||||
for (i=0; i < size; i++)
|
||||
pDst[i] = pSrc[i];
|
||||
|
||||
pDst[i] = 0;
|
||||
|
||||
}
|
||||
|
||||
int SaveROM(char *pFilenameIn, char *pFilenameOut, char *pArchName, char *pEntName, int nbits_addr, int nbits_data)
|
||||
{
|
||||
FILE *pFileIn, *pFileOut;
|
||||
long start, end;
|
||||
int i, word, filesize, romsize;
|
||||
|
||||
pFileIn = fopen(pFilenameIn, "rb");
|
||||
if (!pFileIn)
|
||||
{
|
||||
fprintf(stderr, "Error opening file %s\n", pFilenameIn);
|
||||
return 1;
|
||||
}
|
||||
|
||||
pFileOut = fopen(pFilenameOut, "wb");
|
||||
if (!pFileOut)
|
||||
{
|
||||
fprintf(stderr, "Error opening file %s\n", pFilenameOut);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fseek(pFileIn, 0, SEEK_SET);
|
||||
start = ftell(pFileIn);
|
||||
fseek(pFileIn, 0, SEEK_END);
|
||||
end = ftell(pFileIn);
|
||||
fseek(pFileIn, 0, SEEK_SET);
|
||||
|
||||
filesize = (end-start);
|
||||
romsize = (int)pow(2, nbits_addr+2);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Header
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
fprintf(pFileOut, "LIBRARY IEEE;\n");
|
||||
fprintf(pFileOut, "USE IEEE.STD_LOGIC_1164.ALL;\n");
|
||||
fprintf(pFileOut, "USE IEEE.NUMERIC_STD.ALL;\n");
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
fprintf(pFileOut, "ENTITY %s IS\n", ENT_NAME);
|
||||
fprintf(pFileOut, "\tPort\n");
|
||||
fprintf(pFileOut, "\t(\n");
|
||||
fprintf(pFileOut, "\t\tclk\t\t: in STD_LOGIC;\n");
|
||||
fprintf(pFileOut, "\t\tce\t\t: in STD_LOGIC;\n");
|
||||
fprintf(pFileOut, "\t\taddr\t\t: in unsigned(%d downto 0);\n", nbits_data-1);
|
||||
fprintf(pFileOut, "\t\tdout\t\t: out unsigned(%d downto 0)\n", nbits_data-1);
|
||||
fprintf(pFileOut, "\t);\n");
|
||||
fprintf(pFileOut, "END %s;\n", ENT_NAME);
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
|
||||
fprintf(pFileOut, "ARCHITECTURE %s OF %s IS\n", ARCH_NAME, ENT_NAME);
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
fprintf(pFileOut, "\tsubtype word_t is unsigned(%d downto 0);\n", nbits_data-1);
|
||||
fprintf(pFileOut, "\ttype word_array_t is array (0 to %d) of word_t;\n", romsize/4-1);
|
||||
|
||||
fprintf(pFileOut, "\tconstant word_array : word_array_t :=\n");
|
||||
fprintf(pFileOut, "\t(\n");
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// ROM part
|
||||
// -------------------------------------------------------------------------
|
||||
for (i=0; i < filesize; i += sizeof(int))
|
||||
{
|
||||
fread(&word, 1, sizeof(int), pFileIn);
|
||||
if (g_endianess_EB)
|
||||
fprintf(pFileOut, "\t\tX\"%8.8X\"", to_big_endian32(word));
|
||||
else
|
||||
fprintf(pFileOut, "\t\tX\"%8.8X\"", word);
|
||||
|
||||
if (i < (romsize-sizeof(int)))
|
||||
fprintf(pFileOut, ", -- %8.8X\n", i);
|
||||
else
|
||||
fprintf(pFileOut, " -- %8.8X\n", i);
|
||||
}
|
||||
word = 0;
|
||||
for (; i < romsize; i += sizeof(int))
|
||||
{
|
||||
fprintf(pFileOut, "\t\tX\"%8.8X\"", word);
|
||||
if (i < (romsize-sizeof(int)))
|
||||
fprintf(pFileOut, ", -- %8.8X\n", i);
|
||||
else
|
||||
fprintf(pFileOut, " -- %8.8X\n", i);
|
||||
}
|
||||
fprintf(pFileOut, "\t);\n");
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Trailer
|
||||
// -------------------------------------------------------------------------
|
||||
fprintf(pFileOut, "begin\n", ARCH_NAME);
|
||||
fprintf(pFileOut, "\n");
|
||||
fprintf(pFileOut, "PROM_READ:\n", ARCH_NAME);
|
||||
fprintf(pFileOut, "\tprocess(clk)\n");
|
||||
fprintf(pFileOut, "\tbegin\n");
|
||||
fprintf(pFileOut, "\t\tif rising_edge(clk) and ce = '1' then\n");
|
||||
fprintf(pFileOut, "\t\t\tdout <= word_array(to_integer(addr(%d downto 2)));\n", nbits_addr+1);
|
||||
fprintf(pFileOut, "\t\tend if;\n");
|
||||
fprintf(pFileOut, "\tend process;\n");
|
||||
fprintf(pFileOut, "\n");
|
||||
fprintf(pFileOut, "end %s;\n", ARCH_NAME);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SaveROM_V4LD(char *pFilenameIn, char *pFilenameOut, char *pArchName, char *pEntName, int nbits_addr, int nbits_data)
|
||||
{
|
||||
FILE *pFileIn, *pFileOut;
|
||||
long start, end;
|
||||
int i, word, filesize, romsize;
|
||||
|
||||
char tpl[] = {"--------------------------------------------------------------------------\n-- Virtex-4: JTAG Loader\n--------------------------------------------------------------------------\n\ti00_BUFG : BUFG\n\tport map\n\t(\n\t\tO => bs_clk1,\n I => bs_clk0\n\t);\n\t\n\ti01_BUFG : BUFG\n\tport map\n\t(\n\t\tO => bs_update1,\n I => bs_update0\n\t);\n\n\tBSCAN_VIRTEX4_inst1 : BSCAN_VIRTEX4 \n\tgeneric map\n\t(\n\t\tJTAG_CHAIN => 1 -- Value to set BSCAN site of device. Possible values: (1,2,3 or 4)\n\t)\n\tport map \n\t(\n\t\tCAPTURE => bs_capture, -- CAPTURE output from TAP controller\n\t\tDRCK => bs_clk0, -- Data register output for USER functions\n\t\tRESET => bs_rst, -- Reset output from TAP controller\n\t\tSEL => bs_sel, -- USER active output\n\t\tSHIFT => bs_shift, -- SHIFT output from TAP controller\n\t\tTDI => bs_tdi, -- TDI output from TAP controller\n\t\tUPDATE => bs_update0, -- UPDATE output from TAP controller\n\t\tTDO => bs_tdo -- Data input for USER function\n\t);\n\n\tjtag_ld_addr <= user_regi(user_regi'left downto jtag_ld_dout'length);\n\tjtag_ld_din <= user_regi(jtag_ld_dout'length-1 downto 0);\n\tjtag_ld_clk <= bs_update1;\n\tjtag_ld_we <= bs_sel;\n\t\nsipo:\n\tprocess (bs_rst, bs_clk1, bs_tdi, bs_shift)\n\tbegin\n\t\tif bs_rst = '1' then\n\t\t\tuser_regi <= (others => '0');\n\t\telsif rising_edge(bs_clk1) then\n\t\t\tif bs_shift = '1' then\n\t\t\t\tuser_regi <= bs_tdi & user_regi(user_regi'left downto 1);\n\t\t\tend if;\n\t\tend if;\n\tend process;\t\n\npiso:\n\tprocess (bs_rst, bs_clk1, bs_shift, user_rego)\n\tbegin\n\t\tbs_tdo <= user_rego(0);\n\t\tif bs_rst = '1' then\n\t\t\tuser_rego <= (others => '0');\n\t\telsif rising_edge(bs_clk1) then\n\t\t\tif bs_shift = '1' then\n\t\t\t\tuser_rego <= user_rego(0) & user_rego(user_rego'left downto 1);\n\t\t\telse\n\t\t\t\tuser_rego <= (user_rego'left downto jtag_ld_dout'length => '0') & jtag_ld_dout;\t\n\t\n\t\t\tend if;\n\t\tend if;\n\tend process;\n\n"};
|
||||
|
||||
pFileIn = fopen(pFilenameIn, "rb");
|
||||
if (!pFileIn)
|
||||
{
|
||||
fprintf(stderr, "Error opening file %s\n", pFilenameIn);
|
||||
return 1;
|
||||
}
|
||||
|
||||
pFileOut = fopen(pFilenameOut, "wb");
|
||||
if (!pFileOut)
|
||||
{
|
||||
fprintf(stderr, "Error opening file %s\n", pFilenameOut);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fseek(pFileIn, 0, SEEK_SET);
|
||||
start = ftell(pFileIn);
|
||||
fseek(pFileIn, 0, SEEK_END);
|
||||
end = ftell(pFileIn);
|
||||
fseek(pFileIn, 0, SEEK_SET);
|
||||
|
||||
filesize = (end-start);
|
||||
romsize = (int)pow(2, nbits_addr+2);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Header
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
fprintf(pFileOut, "LIBRARY IEEE;\n");
|
||||
fprintf(pFileOut, "USE IEEE.STD_LOGIC_1164.ALL;\n");
|
||||
fprintf(pFileOut, "USE IEEE.NUMERIC_STD.ALL;\n");
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
fprintf(pFileOut, "library UNISIM;\n");
|
||||
fprintf(pFileOut, "use UNISIM.VComponents.all;\n");
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
fprintf(pFileOut, "ENTITY %s IS\n", ENT_NAME);
|
||||
fprintf(pFileOut, "\tPort\n");
|
||||
fprintf(pFileOut, "\t(\n");
|
||||
fprintf(pFileOut, "\t\tclk\t\t: in STD_LOGIC;\n");
|
||||
fprintf(pFileOut, "\t\tce\t\t: in STD_LOGIC;\n");
|
||||
fprintf(pFileOut, "\t\taddr\t\t: in unsigned(%d downto 0);\n", nbits_data-1);
|
||||
fprintf(pFileOut, "\t\tdout\t\t: out unsigned(%d downto 0)\n", nbits_data-1);
|
||||
fprintf(pFileOut, "\t);\n");
|
||||
fprintf(pFileOut, "END %s;\n", ENT_NAME);
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
|
||||
fprintf(pFileOut, "ARCHITECTURE %s OF %s IS\n", ARCH_NAME, ENT_NAME);
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
fprintf(pFileOut, "\tsubtype word_t is unsigned(%d downto 0);\n", nbits_data-1);
|
||||
fprintf(pFileOut, "\ttype word_array_t is array (0 to %d) of word_t;\n", romsize/4-1);
|
||||
|
||||
fprintf(pFileOut, "\tsignal jtag_ld_clk\t\t: STD_LOGIC;\n");
|
||||
fprintf(pFileOut, "\tsignal jtag_ld_we\t\t: STD_LOGIC;\n");
|
||||
fprintf(pFileOut, "\tsignal jtag_ld_addr\t\t: unsigned (%d downto 0);\n", JTAG_ADDR_WIDTH-1);
|
||||
fprintf(pFileOut, "\tsignal jtag_ld_dout\t\t: unsigned (%d downto 0);\n", nbits_data-1);
|
||||
fprintf(pFileOut, "\tsignal jtag_ld_din\t\t: unsigned (%d downto 0);\n", nbits_data-1);
|
||||
fprintf(pFileOut, "\tsignal bs_rst, bs_sel, bs_shift, bs_tdi, bs_tdo : std_logic;\n");
|
||||
fprintf(pFileOut, "\tsignal bs_capture, bs_clk0, bs_clk1, bs_update0, bs_update1 : std_logic;\n");
|
||||
fprintf(pFileOut, "\tsignal user_regi, user_rego : unsigned (%d downto 0);\n", 31 + JTAG_ADDR_WIDTH);
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
fprintf(pFileOut, "\tsignal word_array : word_array_t :=\n");
|
||||
fprintf(pFileOut, "\t(\n");
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// ROM part
|
||||
// -------------------------------------------------------------------------
|
||||
for (i=0; i < filesize; i += sizeof(int))
|
||||
{
|
||||
fread(&word, 1, sizeof(int), pFileIn);
|
||||
if (g_endianess_EB)
|
||||
fprintf(pFileOut, "\t\tX\"%8.8X\"", to_big_endian32(word));
|
||||
else
|
||||
fprintf(pFileOut, "\t\tX\"%8.8X\"", word);
|
||||
|
||||
if (i < (romsize-sizeof(int)))
|
||||
fprintf(pFileOut, ", -- %8.8X\n", i);
|
||||
else
|
||||
fprintf(pFileOut, " -- %8.8X\n", i);
|
||||
}
|
||||
word = 0;
|
||||
for (; i < romsize; i += sizeof(int))
|
||||
{
|
||||
fprintf(pFileOut, "\t\tX\"%8.8X\"", word);
|
||||
if (i < (romsize-sizeof(int)))
|
||||
fprintf(pFileOut, ", -- %8.8X\n", i);
|
||||
else
|
||||
fprintf(pFileOut, " -- %8.8X\n", i);
|
||||
}
|
||||
fprintf(pFileOut, "\t);\n");
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
fprintf(pFileOut, "begin\n", ARCH_NAME);
|
||||
|
||||
fprintf(pFileOut, "\n");
|
||||
fprintf(pFileOut, "PROM_READ:\n", ARCH_NAME);
|
||||
fprintf(pFileOut, "\tprocess(clk)\n");
|
||||
fprintf(pFileOut, "\tbegin\n");
|
||||
fprintf(pFileOut, "\t\tif rising_edge(clk) and ce = '1' then\n");
|
||||
fprintf(pFileOut, "\t\t\tdout <= word_array(to_integer(addr(%d downto 2)));\n", nbits_addr+1);
|
||||
fprintf(pFileOut, "\t\tend if;\n");
|
||||
fprintf(pFileOut, "\tend process;\n");
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Trailer
|
||||
// -------------------------------------------------------------------------
|
||||
fprintf(pFileOut, "\n");
|
||||
fputs(tpl, pFileOut);
|
||||
|
||||
fprintf(pFileOut, "PROM_WRITE:\n", ARCH_NAME);
|
||||
fprintf(pFileOut, "\tprocess(jtag_ld_clk, jtag_ld_we)\n");
|
||||
fprintf(pFileOut, "\tbegin\n");
|
||||
fprintf(pFileOut, "\t\tif rising_edge(jtag_ld_clk) then\n");
|
||||
fprintf(pFileOut, "\t\t\tif jtag_ld_we = '1' then\n");
|
||||
fprintf(pFileOut, "\t\t\t\tword_array(to_integer(jtag_ld_addr(%d downto 0))) <= jtag_ld_din;\n", nbits_addr-1);
|
||||
fprintf(pFileOut, "\t\t\telse\n");
|
||||
fprintf(pFileOut, "\t\t\t\tjtag_ld_dout <= word_array(to_integer(jtag_ld_addr(%d downto 0)));\n", nbits_addr-1);
|
||||
fprintf(pFileOut, "\t\t\tend if;\n");
|
||||
fprintf(pFileOut, "\t\tend if;\n");
|
||||
fprintf(pFileOut, "\tend process;\n");
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
fprintf(pFileOut, "end %s;\n", ARCH_NAME);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SaveROM_TCL(char *pFilenameIn, char *pFilenameOut, char *pArchName, char *pEntName, int nbits_addr, int nbits_data)
|
||||
{
|
||||
FILE *pFileIn, *pFileOut;
|
||||
long start, end;
|
||||
int i, word, word_addr, filesize, romsize;
|
||||
char binstr_addr[33];
|
||||
char binstr_data[33];
|
||||
|
||||
char tpl[] =
|
||||
{"# ---------------------------------------------------------------------\n# For Chipscope 10.1\n# ---------------------------------------------------------------------\n# Source JTAG/TCL frame work\nsource $env(CS_PATH)\\\\csejtag.tcl\n\nnamespace import ::chipscope::*\n\n# Platform USB Cable\n# Create session\nset handle [::chipscope::csejtag_session create 0]\n\n# Open JTAG and lock\nset open_result [::chipscope::csejtag_target open $handle $CSEJTAG_TARGET_PLATFORMUSB 0 \"port=USB2\" \"frequency=6000000\"]\n# frequency=\"24000000 | 12000000 | 6000000 | 3000000 | 1500000 | 750000\"\n\nset lock_result [::chipscope::csejtag_target lock $handle 1000]\n\nset devlist [::chipscope::csejtag_tap autodetect_chain $handle $CSEJTAG_SCAN_DEFAULT]\n\n# Get Device ID\nset devtype \"Virtex-4SX\"\nset devid 2\nset irlength [::chipscope::csejtag_tap get_irlength $handle $devid]\nset idcode [::chipscope::csejtag_tap get_device_idcode $handle $devid]\n\nset CSE_OP $CSEJTAG_SHIFT_READWRITE\nset CSE_ES $CSEJTAG_RUN_TEST_IDLE\n\n# Write Program\n"};
|
||||
|
||||
pFileIn = fopen(pFilenameIn, "rb");
|
||||
if (!pFileIn)
|
||||
{
|
||||
fprintf(stderr, "Error opening file %s\n", pFilenameIn);
|
||||
return 1;
|
||||
}
|
||||
|
||||
pFileOut = fopen(pFilenameOut, "wb");
|
||||
if (!pFileOut)
|
||||
{
|
||||
fprintf(stderr, "Error opening file %s\n", pFilenameOut);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fseek(pFileIn, 0, SEEK_SET);
|
||||
start = ftell(pFileIn);
|
||||
fseek(pFileIn, 0, SEEK_END);
|
||||
end = ftell(pFileIn);
|
||||
fseek(pFileIn, 0, SEEK_SET);
|
||||
|
||||
filesize = (end-start);
|
||||
romsize = (int)pow(2, nbits_addr+2);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Header
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
fputs(tpl, pFileOut);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// ROM part
|
||||
// -------------------------------------------------------------------------
|
||||
fprintf(pFileOut, "# Assembled from %s\n", pFilenameIn);
|
||||
fprintf(pFileOut, "# ---------------------------------------------------------------\n");
|
||||
fprintf(pFileOut, "# Shift the USER1 Instruction (b1111000010) into the Instruction Register of FPGA\n");
|
||||
fprintf(pFileOut, "# User 1\n");
|
||||
fprintf(pFileOut, "set result [::chipscope::csejtag_tap shift_device_ir $handle $devid $CSE_OP $CSE_ES 0 $irlength \"3C2\"]\n\n");
|
||||
|
||||
word_addr = 0;
|
||||
for (i=0; i < filesize; i += sizeof(int))
|
||||
{
|
||||
fread(&word, 1, sizeof(int), pFileIn);
|
||||
if (g_endianess_EB)
|
||||
fprintf(pFileOut, "::chipscope::csejtag_tap shift_device_dr $handle $devid $CSE_OP $CSE_ES 0 %d \"%4.4X%8.8X\"\n", nbits_data + JTAG_ADDR_WIDTH, word_addr, to_big_endian32(word));
|
||||
else
|
||||
fprintf(pFileOut, "::chipscope::csejtag_tap shift_device_dr $handle $devid $CSE_OP $CSE_ES 0 %d \"%4.4X%8.8X\"\n", nbits_data + JTAG_ADDR_WIDTH, word_addr, word);
|
||||
word_addr++;
|
||||
}
|
||||
fprintf(pFileOut, "\n");
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Trailer
|
||||
// -------------------------------------------------------------------------
|
||||
fprintf(pFileOut, "::chipscope::csejtag_target unlock $handle\n");
|
||||
fprintf(pFileOut, "::chipscope::csejtag_target close $handle\n");
|
||||
fprintf(pFileOut, "::chipscope::csejtag_session destroy $handle\n");
|
||||
fprintf(pFileOut, "exit\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *pFilenameIn;
|
||||
char name_prj[1024];
|
||||
char name_rom[1024];
|
||||
char name_rom_v4ld[1024];
|
||||
char name_rom_tcl[1024];
|
||||
|
||||
FILE *pFileIn;
|
||||
int filesize, romsize, nbits_addr, nbits_data;
|
||||
long start, end;
|
||||
int word, i;
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
fprintf(stderr, "Usage: romgen <input file> <num. word address bits> [-{EL|EB}]\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
pFilenameIn = argv[1];
|
||||
nbits_addr = atoi(argv[2]);
|
||||
|
||||
g_endianess_EB = 0;
|
||||
if (argc == 4)
|
||||
{
|
||||
if ((argv[3][0] == '-') && (toupper(argv[3][1]) == 'E') && (toupper(argv[3][2]) == 'B'))
|
||||
g_endianess_EB = 1;
|
||||
}
|
||||
|
||||
basename(pFilenameIn, name_prj);
|
||||
sprintf(name_rom, "%s.vhd", name_prj);
|
||||
sprintf(name_rom_v4ld, "%s_ld.vhd", name_prj);
|
||||
sprintf(name_rom_tcl, "%s.tcl", name_prj);
|
||||
|
||||
SaveROM(pFilenameIn, name_rom, ARCH_NAME, ENT_NAME, nbits_addr, 32);
|
||||
SaveROM_V4LD(pFilenameIn, name_rom_v4ld, ARCH_NAME, ENT_NAME, nbits_addr, 32);
|
||||
SaveROM_TCL(pFilenameIn, name_rom_tcl, ARCH_NAME, ENT_NAME, nbits_addr, 32);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
VHDL/lib/FIFO/src/async_fifo_ctrl.vhd
|
||||
VHDL/lib/FIFO/src/fifo_async_ctrl.vhd
|
||||
VHDL/lib/FIFO/src/fifo_async_ctrl.vhd
|
||||
|
||||
VHDL/lib/FIFO/src/fifo_sync_ctrl.vhd
|
||||
|
||||
VHDL/lib/FIFO/src/sync_fifo_ctrl.vhd
|
||||
VHDL/lib/FIFO/src/fifo_sync_ctrl.vhd
|
||||
@@ -0,0 +1,248 @@
|
||||
-------------------------------------------------------------------------
|
||||
-- Project: FIFO, generic FIFOs written in VHDL
|
||||
-- Release 1
|
||||
--
|
||||
-- Copyright (C) 2007 J. Ahrensfeld
|
||||
--
|
||||
-- This library is free software; you can redistribute it and/or
|
||||
-- modify it under the terms of the GNU Lesser General Public
|
||||
-- License as published by the Free Software Foundation; either
|
||||
-- version 2.1 of the License, or (at your option) any later version.
|
||||
--
|
||||
-- This library is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
-- Lesser General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU Lesser General Public
|
||||
-- License along with this library; if not, write to the Free Software
|
||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
--
|
||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||
--
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.numeric_std.ALL;
|
||||
|
||||
LIBRARY WORK;
|
||||
USE WORK.FIFO_CTRL_PKG.ALL;
|
||||
|
||||
entity fifo_async_ctrl is
|
||||
Generic
|
||||
(
|
||||
addr_width : integer := 3;
|
||||
almost_full_thresh : integer := 6;
|
||||
almost_empty_thresh : integer := 2
|
||||
);
|
||||
Port
|
||||
(
|
||||
rst : in STD_LOGIC;
|
||||
clk_w : in STD_LOGIC;
|
||||
clk_r : in STD_LOGIC;
|
||||
winc : in STD_LOGIC;
|
||||
rinc : in STD_LOGIC;
|
||||
ptr_w : out unsigned (addr_width-1 downto 0);
|
||||
ptr_r : out unsigned (addr_width-1 downto 0);
|
||||
fifo_pre_full : out STD_LOGIC;
|
||||
fifo_pre_empty : out STD_LOGIC;
|
||||
fifo_full : out STD_LOGIC;
|
||||
fifo_empty : out STD_LOGIC;
|
||||
fifo_afull : out STD_LOGIC;
|
||||
fifo_aempty : out STD_LOGIC
|
||||
);
|
||||
end fifo_async_ctrl;
|
||||
|
||||
architecture Behavioral of fifo_async_ctrl is
|
||||
|
||||
signal gcnt_w : unsigned (addr_width downto 0);
|
||||
signal gcnt2_w : unsigned (addr_width downto 0);
|
||||
signal bcnt2_aw : unsigned (addr_width downto 0);
|
||||
signal bcnt_w : unsigned (addr_width downto 0);
|
||||
signal gnxt_w : unsigned (addr_width downto 0);
|
||||
signal bnxt_w : unsigned (addr_width downto 0);
|
||||
signal gcnt_r : unsigned (addr_width downto 0);
|
||||
signal gcnt2_r : unsigned (addr_width downto 0);
|
||||
signal bcnt2_ar : unsigned (addr_width downto 0);
|
||||
signal bcnt_r : unsigned (addr_width downto 0);
|
||||
signal gnxt_r : unsigned (addr_width downto 0);
|
||||
signal bnxt_r : unsigned (addr_width downto 0);
|
||||
|
||||
signal pre_empty, pre_full : std_logic;
|
||||
signal full, empty : std_logic;
|
||||
|
||||
-- synthesis translate_off
|
||||
signal diffw : signed (addr_width downto 0);
|
||||
signal diffr : signed (addr_width downto 0);
|
||||
-- synthesis translate_on
|
||||
|
||||
begin
|
||||
|
||||
ptr_w <= bcnt_w(addr_width-1 downto 0);
|
||||
ptr_r <= bnxt_r(addr_width-1 downto 0);
|
||||
fifo_full <= full;
|
||||
fifo_empty <= empty;
|
||||
fifo_pre_full <= pre_full;
|
||||
fifo_pre_empty <= pre_empty;
|
||||
|
||||
proc_write_inhibit:
|
||||
process(rst, clk_w)
|
||||
begin
|
||||
if rst = '1' then
|
||||
full <= '0';
|
||||
elsif rising_edge(clk_w) then
|
||||
full <= pre_full;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
proc_read_inhibit:
|
||||
process(rst, clk_r)
|
||||
begin
|
||||
if rst = '1' then
|
||||
empty <= '1';
|
||||
elsif rising_edge(clk_r) then
|
||||
empty <= pre_empty;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
proc_sync_grptr:
|
||||
process(clk_w)
|
||||
variable p1, p2 : unsigned (addr_width downto 0);
|
||||
begin
|
||||
if rising_edge(clk_w) then
|
||||
gcnt2_r <= p2;
|
||||
p2 := p1;
|
||||
p1 := gcnt_r;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
proc_ptr_gwptr:
|
||||
process(clk_r)
|
||||
variable p1, p2 : unsigned (addr_width downto 0);
|
||||
begin
|
||||
if rising_edge(clk_r) then
|
||||
gcnt2_w <= p2;
|
||||
p2 := p1;
|
||||
p1 := gcnt_w;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
proc_status_full:
|
||||
process(gnxt_w, gcnt2_r)
|
||||
begin
|
||||
if (gnxt_w = (not gcnt2_r(gcnt2_r'left downto gcnt2_r'left-1) & gcnt2_r(gcnt2_r'left-2 downto 0))) then
|
||||
pre_full <= '1';
|
||||
else
|
||||
pre_full <= '0';
|
||||
end if;
|
||||
end process;
|
||||
|
||||
proc_status_empty:
|
||||
process(gnxt_r, gcnt2_w)
|
||||
begin
|
||||
if (gnxt_r = gcnt2_w) then
|
||||
pre_empty <= '1';
|
||||
else
|
||||
pre_empty <= '0';
|
||||
end if;
|
||||
end process;
|
||||
|
||||
proc_sync_arptr:
|
||||
process(clk_w)
|
||||
variable p1, p2 : unsigned (addr_width downto 0);
|
||||
begin
|
||||
if rising_edge(clk_w) then
|
||||
bcnt2_ar <= p2;
|
||||
p2 := p1;
|
||||
p1 := bcnt_r;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
proc_ptr_awptr:
|
||||
process(clk_r)
|
||||
variable p1, p2 : unsigned (addr_width downto 0);
|
||||
begin
|
||||
if rising_edge(clk_r) then
|
||||
bcnt2_aw <= p2;
|
||||
p2 := p1;
|
||||
p1 := bcnt_w;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
proc_status_almost_full:
|
||||
process(rst, clk_w)
|
||||
variable diff : unsigned (addr_width downto 0);
|
||||
begin
|
||||
-- synthesis translate_off
|
||||
diffw <= signed(diff);
|
||||
-- synthesis translate_on
|
||||
if rst = '1' then
|
||||
fifo_afull <= '0';
|
||||
diff := (others => '0');
|
||||
elsif rising_edge(clk_w) then
|
||||
if diff >= almost_full_thresh-1 then
|
||||
fifo_afull <= '1';
|
||||
else
|
||||
fifo_afull <= '0';
|
||||
end if;
|
||||
diff := unsigned(abs(signed(bnxt_w) - signed(bcnt2_ar)));
|
||||
end if;
|
||||
end process;
|
||||
|
||||
proc_status_almost_empty:
|
||||
process(rst, clk_r)
|
||||
variable diff : unsigned (addr_width downto 0);
|
||||
begin
|
||||
-- synthesis translate_off
|
||||
diffr <= signed(diff);
|
||||
-- synthesis translate_on
|
||||
if rst = '1' then
|
||||
fifo_aempty <= '1';
|
||||
diff := (others => '0');
|
||||
elsif rising_edge(clk_r) then
|
||||
if diff <= almost_empty_thresh+1 then
|
||||
fifo_aempty <= '1';
|
||||
else
|
||||
fifo_aempty <= '0';
|
||||
end if;
|
||||
diff := unsigned(abs(signed(bcnt2_aw) - signed(bnxt_r)));
|
||||
end if;
|
||||
end process;
|
||||
|
||||
inst_gray_counter_w : entity work.gray_counter
|
||||
generic map
|
||||
(
|
||||
width => addr_width+1,
|
||||
init_value => 0
|
||||
)
|
||||
port map
|
||||
(
|
||||
rst => rst,
|
||||
clk => clk_w,
|
||||
ce => winc,
|
||||
bcnt => bcnt_w,
|
||||
bnxt => bnxt_w,
|
||||
gcnt => gcnt_w,
|
||||
gnxt => gnxt_w
|
||||
);
|
||||
|
||||
inst_gray_counter_r : entity work.gray_counter
|
||||
generic map
|
||||
(
|
||||
width => addr_width+1,
|
||||
init_value => 0
|
||||
)
|
||||
port map
|
||||
(
|
||||
rst => rst,
|
||||
clk => clk_r,
|
||||
ce => rinc,
|
||||
bcnt => bcnt_r,
|
||||
bnxt => bnxt_r,
|
||||
gcnt => gcnt_r,
|
||||
gnxt => gnxt_r
|
||||
);
|
||||
|
||||
end Behavioral;
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
-------------------------------------------------------------------------
|
||||
-- Project: FIFO, generic FIFOs written in VHDL
|
||||
-- Release 1
|
||||
--
|
||||
-- Copyright (C) 2007 J. Ahrensfeld
|
||||
--
|
||||
-- This library is free software; you can redistribute it and/or
|
||||
-- modify it under the terms of the GNU Lesser General Public
|
||||
-- License as published by the Free Software Foundation; either
|
||||
-- version 2.1 of the License, or (at your option) any later version.
|
||||
--
|
||||
-- This library is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
-- Lesser General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU Lesser General Public
|
||||
-- License along with this library; if not, write to the Free Software
|
||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
--
|
||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||
--
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
LIBRARY IEEE;
|
||||
USE IEEE.STD_LOGIC_1164.ALL;
|
||||
USE IEEE.NUMERIC_STD.ALL;
|
||||
|
||||
use work.fifo_ctrl_pkg.all;
|
||||
|
||||
entity fifo_async is
|
||||
Generic
|
||||
(
|
||||
addr_width : natural := 4;
|
||||
data_width : natural := 8;
|
||||
almost_full_thresh : integer := 12;
|
||||
almost_empty_thresh : integer := 4;
|
||||
allow_full_writes : boolean := false;
|
||||
allow_empty_reads : boolean := false;
|
||||
do_last_read_update : boolean := true
|
||||
);
|
||||
Port
|
||||
(
|
||||
rst : in STD_LOGIC;
|
||||
clk_w : in STD_LOGIC;
|
||||
clk_r : in STD_LOGIC;
|
||||
we : in STD_LOGIC;
|
||||
re : in STD_LOGIC;
|
||||
fifo_full : out STD_LOGIC;
|
||||
fifo_empty : out STD_LOGIC;
|
||||
fifo_afull : out STD_LOGIC;
|
||||
fifo_aempty : out STD_LOGIC;
|
||||
data_w : in unsigned (data_width-1 downto 0);
|
||||
data_r : out unsigned (data_width-1 downto 0)
|
||||
);
|
||||
end fifo_async;
|
||||
|
||||
architecture Behavioral of fifo_async is
|
||||
|
||||
signal mem_wr_en : STD_LOGIC;
|
||||
signal mem_rd_en : STD_LOGIC;
|
||||
signal ptr_w : unsigned (addr_width-1 downto 0);
|
||||
signal ptr_r : unsigned (addr_width-1 downto 0);
|
||||
signal full : std_logic;
|
||||
signal empty : std_logic;
|
||||
signal pre_full : STD_LOGIC;
|
||||
signal pre_empty : STD_LOGIC;
|
||||
signal rinc : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
fifo_full <= full;
|
||||
fifo_empty <= empty;
|
||||
|
||||
mem_wr_en <= (we and not full) when allow_full_writes = false else we;
|
||||
rinc <= (re and not empty) when allow_empty_reads = false else re;
|
||||
mem_rd_en <= not pre_empty when do_last_read_update = false else '1';
|
||||
|
||||
|
||||
inst_fifo_async_ctrl: entity work.fifo_async_ctrl
|
||||
GENERIC MAP
|
||||
(
|
||||
addr_width => addr_width,
|
||||
almost_full_thresh => almost_full_thresh,
|
||||
almost_empty_thresh => almost_empty_thresh
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
rst => rst,
|
||||
clk_w => clk_w,
|
||||
clk_r => clk_r,
|
||||
winc => mem_wr_en,
|
||||
rinc => rinc,
|
||||
ptr_w => ptr_w,
|
||||
ptr_r => ptr_r,
|
||||
fifo_full => full,
|
||||
fifo_empty => empty,
|
||||
fifo_pre_full => pre_full,
|
||||
fifo_pre_empty => pre_empty,
|
||||
fifo_afull => fifo_afull,
|
||||
fifo_aempty => fifo_aempty
|
||||
|
||||
);
|
||||
|
||||
inst_dpram_1w1r: entity work.dpram_1w1r
|
||||
GENERIC MAP
|
||||
(
|
||||
addr_width => addr_width,
|
||||
data_width => data_width
|
||||
)
|
||||
PORT MAP(
|
||||
clka => clk_w,
|
||||
clkb => clk_r,
|
||||
en_a => '1',
|
||||
en_b => mem_rd_en,
|
||||
we_a => mem_wr_en,
|
||||
addr_a => ptr_w,
|
||||
addr_b => ptr_r,
|
||||
din_a => data_w,
|
||||
dout_b => data_r
|
||||
);
|
||||
|
||||
end Behavioral;
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
-------------------------------------------------------------------------
|
||||
-- Project: FIFO, generic FIFOs written in VHDL
|
||||
-- Release 1
|
||||
--
|
||||
-- Copyright (C) 2007 J. Ahrensfeld
|
||||
--
|
||||
-- This library is free software; you can redistribute it and/or
|
||||
-- modify it under the terms of the GNU Lesser General Public
|
||||
-- License as published by the Free Software Foundation; either
|
||||
-- version 2.1 of the License, or (at your option) any later version.
|
||||
--
|
||||
-- This library is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
-- Lesser General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU Lesser General Public
|
||||
-- License along with this library; if not, write to the Free Software
|
||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
--
|
||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||
--
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
LIBRARY IEEE;
|
||||
USE IEEE.STD_LOGIC_1164.ALL;
|
||||
USE IEEE.NUMERIC_STD.ALL;
|
||||
|
||||
package fifo_ctrl_pkg is
|
||||
|
||||
-- Constants
|
||||
-- Types
|
||||
|
||||
-- Functions
|
||||
function bin2gray(xb : unsigned) return unsigned;
|
||||
function gray2bin(xg : unsigned) return unsigned;
|
||||
|
||||
end fifo_ctrl_pkg;
|
||||
|
||||
package body fifo_ctrl_pkg is
|
||||
|
||||
function bin2gray(xb : unsigned) return unsigned is
|
||||
variable xg : unsigned(xb'left downto xb'right);
|
||||
begin
|
||||
|
||||
xg(xg'left) := xb(xb'left);
|
||||
for i in 1 to xb'left loop
|
||||
xg(xg'left-i) := xb(xb'left-i+1) xor xb(xb'left-i);
|
||||
end loop;
|
||||
|
||||
return xg;
|
||||
end bin2gray;
|
||||
|
||||
function gray2bin(xg : unsigned) return unsigned is
|
||||
variable xb : unsigned(xg'left downto xg'right);
|
||||
begin
|
||||
|
||||
xb(xb'left) := xg(xg'left);
|
||||
for i in 1 to xg'left loop
|
||||
xb(xb'left-i) := xb(xb'left-i+1) xor xg(xg'left-i);
|
||||
end loop;
|
||||
|
||||
return xb;
|
||||
end gray2bin;
|
||||
|
||||
end fifo_ctrl_pkg;
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
-------------------------------------------------------------------------
|
||||
-- Project: FIFO, generic FIFOs written in VHDL
|
||||
-- Release 1
|
||||
--
|
||||
-- Copyright (C) 2007 J. Ahrensfeld
|
||||
--
|
||||
-- This library is free software; you can redistribute it and/or
|
||||
-- modify it under the terms of the GNU Lesser General Public
|
||||
-- License as published by the Free Software Foundation; either
|
||||
-- version 2.1 of the License, or (at your option) any later version.
|
||||
--
|
||||
-- This library is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
-- Lesser General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU Lesser General Public
|
||||
-- License along with this library; if not, write to the Free Software
|
||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
--
|
||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||
--
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
LIBRARY IEEE;
|
||||
USE IEEE.STD_LOGIC_1164.ALL;
|
||||
USE IEEE.NUMERIC_STD.ALL;
|
||||
|
||||
use work.fifo_ctrl_pkg.all;
|
||||
|
||||
entity fifo_sync is
|
||||
Generic
|
||||
(
|
||||
addr_width : natural := 4;
|
||||
data_width : natural := 8;
|
||||
almost_full_thresh : integer := 12;
|
||||
almost_empty_thresh : integer := 4;
|
||||
allow_full_writes : boolean := false;
|
||||
allow_empty_reads : boolean := false;
|
||||
do_last_read_update : boolean := true
|
||||
|
||||
);
|
||||
Port
|
||||
(
|
||||
rst : in STD_LOGIC;
|
||||
clk : in STD_LOGIC;
|
||||
we : in STD_LOGIC;
|
||||
re : in STD_LOGIC;
|
||||
fifo_full : out STD_LOGIC;
|
||||
fifo_empty : out STD_LOGIC;
|
||||
fifo_afull : out STD_LOGIC;
|
||||
fifo_aempty : out STD_LOGIC;
|
||||
data_w : in unsigned (data_width-1 downto 0);
|
||||
data_r : out unsigned (data_width-1 downto 0)
|
||||
);
|
||||
end fifo_sync;
|
||||
|
||||
architecture Behavioral of fifo_sync is
|
||||
|
||||
signal mem_wr_en : STD_LOGIC;
|
||||
signal mem_rd_en : STD_LOGIC;
|
||||
signal ptr_w : unsigned (addr_width-1 downto 0);
|
||||
signal ptr_r : unsigned (addr_width-1 downto 0);
|
||||
signal full : STD_LOGIC;
|
||||
signal empty : std_logic;
|
||||
signal pre_full : STD_LOGIC;
|
||||
signal pre_empty : STD_LOGIC;
|
||||
signal rinc : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
fifo_full <= full;
|
||||
fifo_empty <= empty;
|
||||
|
||||
mem_wr_en <= (we and not full) when allow_full_writes = false else we;
|
||||
rinc <= (re and not empty) when allow_empty_reads = false else re;
|
||||
mem_rd_en <= not pre_empty when do_last_read_update = false else '1';
|
||||
|
||||
|
||||
inst_fifo_sync_ctrl: entity work.fifo_sync_ctrl
|
||||
GENERIC MAP
|
||||
(
|
||||
addr_width => addr_width,
|
||||
almost_full_thresh => almost_full_thresh,
|
||||
almost_empty_thresh => almost_empty_thresh
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
rst => rst,
|
||||
clk => clk,
|
||||
winc => mem_wr_en,
|
||||
rinc => rinc,
|
||||
ptr_w => ptr_w,
|
||||
ptr_r => ptr_r,
|
||||
fifo_full => full,
|
||||
fifo_empty => empty,
|
||||
fifo_pre_full => pre_full,
|
||||
fifo_pre_empty => pre_empty,
|
||||
fifo_afull => fifo_afull,
|
||||
fifo_aempty => fifo_aempty
|
||||
|
||||
);
|
||||
|
||||
inst_dpram_1w1r: entity work.dpram_1w1r
|
||||
GENERIC MAP
|
||||
(
|
||||
addr_width => addr_width,
|
||||
data_width => data_width
|
||||
)
|
||||
PORT MAP(
|
||||
clka => clk,
|
||||
clkb => clk,
|
||||
en_a => '1',
|
||||
en_b => mem_rd_en,
|
||||
we_a => mem_wr_en,
|
||||
addr_a => ptr_w,
|
||||
addr_b => ptr_r,
|
||||
din_a => data_w,
|
||||
dout_b => data_r
|
||||
);
|
||||
|
||||
end Behavioral;
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
-------------------------------------------------------------------------
|
||||
-- Project: FIFO, generic FIFOs written in VHDL
|
||||
-- Release 1
|
||||
--
|
||||
-- Copyright (C) 2007 J. Ahrensfeld
|
||||
--
|
||||
-- This library is free software; you can redistribute it and/or
|
||||
-- modify it under the terms of the GNU Lesser General Public
|
||||
-- License as published by the Free Software Foundation; either
|
||||
-- version 2.1 of the License, or (at your option) any later version.
|
||||
--
|
||||
-- This library is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
-- Lesser General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU Lesser General Public
|
||||
-- License along with this library; if not, write to the Free Software
|
||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
--
|
||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||
--
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.numeric_std.ALL;
|
||||
|
||||
LIBRARY WORK;
|
||||
USE WORK.FIFO_CTRL_PKG.ALL;
|
||||
|
||||
entity gray_counter is
|
||||
Generic (
|
||||
width : natural := 3;
|
||||
init_value : natural := 0
|
||||
);
|
||||
Port
|
||||
(
|
||||
rst : in STD_LOGIC;
|
||||
clk : in STD_LOGIC;
|
||||
ce : in STD_LOGIC;
|
||||
bcnt : out unsigned (width-1 downto 0);
|
||||
bnxt : out unsigned (width-1 downto 0);
|
||||
gcnt : out unsigned (width-1 downto 0);
|
||||
gnxt : out unsigned (width-1 downto 0)
|
||||
);
|
||||
end gray_counter;
|
||||
|
||||
architecture Behavioral of gray_counter is
|
||||
|
||||
signal cntg : unsigned (width-1 downto 0);
|
||||
signal cntb : unsigned (width-1 downto 0);
|
||||
signal nxtb : unsigned (width-1 downto 0);
|
||||
signal nxtg : unsigned (width-1 downto 0);
|
||||
|
||||
begin
|
||||
|
||||
bnxt <= nxtb;
|
||||
gnxt <= nxtg;
|
||||
bcnt <= cntb;
|
||||
gcnt <= cntg;
|
||||
|
||||
process(rst, clk, ce, cntb, nxtb)
|
||||
begin
|
||||
if rst = '1' then
|
||||
cntb <= to_unsigned(init_value, width);
|
||||
nxtb <= to_unsigned(init_value, width);
|
||||
nxtg <= to_unsigned(init_value, width);
|
||||
cntg <= to_unsigned(init_value, width);
|
||||
else
|
||||
if rising_edge(clk) then
|
||||
cntg <= nxtg;
|
||||
cntb <= nxtb;
|
||||
end if;
|
||||
nxtg <= bin2gray(nxtb);
|
||||
nxtb <= cntb;
|
||||
if ce = '1' then
|
||||
nxtb <= cntb + 1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end Behavioral;
|
||||
|
||||
@@ -0,0 +1,198 @@
|
||||
-------------------------------------------------------------------------
|
||||
-- Project: FIFO, generic FIFOs written in VHDL
|
||||
-- Release 1
|
||||
--
|
||||
-- Copyright (C) 2007 J. Ahrensfeld
|
||||
--
|
||||
-- This library is free software; you can redistribute it and/or
|
||||
-- modify it under the terms of the GNU Lesser General Public
|
||||
-- License as published by the Free Software Foundation; either
|
||||
-- version 2.1 of the License, or (at your option) any later version.
|
||||
--
|
||||
-- This library is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
-- Lesser General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU Lesser General Public
|
||||
-- License along with this library; if not, write to the Free Software
|
||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
--
|
||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||
--
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.numeric_std.ALL;
|
||||
|
||||
entity fifo_sync_ctrl is
|
||||
Generic
|
||||
(
|
||||
addr_width : integer := 3;
|
||||
almost_full_thresh : integer := 6;
|
||||
almost_empty_thresh : integer := 2
|
||||
);
|
||||
Port
|
||||
(
|
||||
rst : in STD_LOGIC;
|
||||
clk : in STD_LOGIC;
|
||||
winc : in STD_LOGIC;
|
||||
rinc : in STD_LOGIC;
|
||||
ptr_w : out unsigned (addr_width-1 downto 0);
|
||||
ptr_r : out unsigned (addr_width-1 downto 0);
|
||||
fifo_pre_full : out STD_LOGIC;
|
||||
fifo_pre_empty : out STD_LOGIC;
|
||||
fifo_full : out STD_LOGIC;
|
||||
fifo_empty : out STD_LOGIC;
|
||||
fifo_afull : out STD_LOGIC;
|
||||
fifo_aempty : out STD_LOGIC
|
||||
);
|
||||
end fifo_sync_ctrl;
|
||||
|
||||
architecture Behavioral of fifo_sync_ctrl is
|
||||
|
||||
signal pW, pW_cnt, pW_next : unsigned (addr_width-1 downto 0);
|
||||
signal pR, pR_cnt, pR_next : unsigned (addr_width-1 downto 0);
|
||||
signal empty, full : std_logic;
|
||||
signal pre_empty, pre_full : std_logic;
|
||||
signal was_write : std_logic;
|
||||
signal diff : unsigned (addr_width downto 0);
|
||||
|
||||
begin
|
||||
|
||||
fifo_full <= full;
|
||||
fifo_empty <= empty;
|
||||
fifo_pre_full <= pre_full;
|
||||
fifo_pre_empty <= pre_empty;
|
||||
|
||||
|
||||
proc_diff_gen:
|
||||
process(rst, clk)
|
||||
begin
|
||||
if rst = '1' then
|
||||
diff <= (others => '0');
|
||||
elsif rising_edge(clk) then
|
||||
if winc = '1' and rinc = '0' then
|
||||
diff <= diff + 1;
|
||||
elsif winc = '0' and rinc = '1' then
|
||||
diff <= diff - 1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
proc_status_almost_full:
|
||||
process(rst, clk)
|
||||
begin
|
||||
if rst = '1' then
|
||||
fifo_afull <= '0';
|
||||
elsif rising_edge(clk) then
|
||||
if diff >= almost_full_thresh-1 then
|
||||
fifo_afull <= '1';
|
||||
else
|
||||
fifo_afull <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
proc_status_almost_empty:
|
||||
process(rst, clk)
|
||||
begin
|
||||
if rst = '1' then
|
||||
fifo_aempty <= '1';
|
||||
elsif rising_edge(clk) then
|
||||
if diff <= almost_empty_thresh+1 then
|
||||
fifo_aempty <= '1';
|
||||
else
|
||||
fifo_aempty <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
proc_full_reg:
|
||||
process(rst, clk)
|
||||
begin
|
||||
if rst = '1' then
|
||||
full <= '0';
|
||||
elsif rising_edge(clk) then
|
||||
full <= pre_full;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
proc_empty_reg:
|
||||
process(rst, clk)
|
||||
begin
|
||||
if rst = '1' then
|
||||
empty <= '1';
|
||||
elsif rising_edge(clk) then
|
||||
empty <= pre_empty;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
proc_status_w:
|
||||
process(was_write, pW_next, pR_next, pW, pR, winc, rinc)
|
||||
begin
|
||||
if (pW_next = pR) and (winc = '1' or was_write = '1') then
|
||||
pre_full <= '1';
|
||||
else
|
||||
pre_full <= '0';
|
||||
end if;
|
||||
if (pR_next = pW) and (rinc = '1' or was_write = '0') then
|
||||
pre_empty <= '1';
|
||||
else
|
||||
pre_empty <= '0';
|
||||
end if;
|
||||
end process;
|
||||
|
||||
proc_flag_write:
|
||||
process(rst, clk)
|
||||
begin
|
||||
if rst = '1' then
|
||||
was_write <= '0';
|
||||
elsif rising_edge(clk) then
|
||||
if winc = '1' then
|
||||
was_write <= '1';
|
||||
elsif rinc = '1' then
|
||||
was_write <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
proc_ptr_w:
|
||||
process(rst, clk, pW, winc)
|
||||
begin
|
||||
if rst = '1' then
|
||||
pW <= to_unsigned(0, addr_width);
|
||||
pW_next <= to_unsigned(0, addr_width);
|
||||
elsif rising_edge(clk) then
|
||||
if winc = '1' then
|
||||
pW <= pW_next;
|
||||
end if;
|
||||
end if;
|
||||
pW_next <= pW;
|
||||
if winc = '1' then
|
||||
pW_next <= pW + 1;
|
||||
end if;
|
||||
ptr_w <= pW;
|
||||
end process;
|
||||
|
||||
proc_ptr_r:
|
||||
process(rst, clk, pR_next, pR, rinc)
|
||||
begin
|
||||
if rst = '1' then
|
||||
pR <= to_unsigned(0, addr_width);
|
||||
pR_next <= to_unsigned(0, addr_width);
|
||||
elsif rising_edge(clk) then
|
||||
if rinc = '1' then
|
||||
pR <= pR_next;
|
||||
end if;
|
||||
end if;
|
||||
pR_next <= pR;
|
||||
if rinc = '1' then
|
||||
pR_next <= pR + 1;
|
||||
end if;
|
||||
ptr_r <= pR_next;
|
||||
end process;
|
||||
|
||||
end Behavioral;
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
VHDL/lib/emac/emac_jb.vhd
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
VHDL/lib/emac/sim/tb_emac_jb.fdo
|
||||
VHDL/lib/emac/sim/tb_serdes.fdo
|
||||
VHDL/lib/emac/sim/tb_emac_jb.wdo
|
||||
VHDL/lib/emac/sim/tb_serdes.wdo
|
||||
VHDL/lib/emac/sim/tb_serdes.fdo
|
||||
|
||||
VHDL/lib/emac/sim/tb_serdes.wdo
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
## NOTE: Do not edit this file.
|
||||
## Autogenerated by ProjNav (creatfdo.tcl) on Thu Jul 06 20:49:07 Westeuropäische Sommerzeit 2006
|
||||
##
|
||||
vlib work
|
||||
vcom -explicit -93 "../../misc/utils_pkg.vhd"
|
||||
vcom -explicit -93 "../src/crc32.vhd"
|
||||
vcom -explicit -93 "../src/tb_crc32.vhd"
|
||||
vsim -t 1ps -lib work tb_crc32
|
||||
view wave
|
||||
do {tb_crc32.wdo}
|
||||
view structure
|
||||
view signals
|
||||
|
||||
run 1 us
|
||||
@@ -1,25 +0,0 @@
|
||||
onerror {resume}
|
||||
quietly WaveActivateNextPane {} 0
|
||||
add wave -noupdate -format Logic /tb_crc32/clk
|
||||
add wave -noupdate -format Logic /tb_crc32/rst
|
||||
add wave -noupdate -format Logic /tb_crc32/din_vld
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_crc32/din
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_crc32/crc32
|
||||
add wave -noupdate -format Logic /tb_crc32/crc32_vld
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_crc32/test_data
|
||||
TreeUpdate [SetDefaultTree]
|
||||
WaveRestoreCursors {{Cursor 1} {667016 ps} 0}
|
||||
configure wave -namecolwidth 150
|
||||
configure wave -valuecolwidth 100
|
||||
configure wave -justifyvalue left
|
||||
configure wave -signalnamewidth 1
|
||||
configure wave -snapdistance 10
|
||||
configure wave -datasetprefix 0
|
||||
configure wave -rowmargin 4
|
||||
configure wave -childrowmargin 2
|
||||
configure wave -gridoffset 0
|
||||
configure wave -gridperiod 100
|
||||
configure wave -griddelta 40
|
||||
configure wave -timeline 1
|
||||
update
|
||||
WaveRestoreZoom {0 ps} {1050 ns}
|
||||
@@ -1,15 +0,0 @@
|
||||
## NOTE: Do not edit this file.
|
||||
## Autogenerated by ProjNav (creatfdo.tcl) on Thu Jul 06 20:49:07 Westeuropäische Sommerzeit 2006
|
||||
##
|
||||
vlib work
|
||||
vcom -explicit -93 "../../misc/utils_pkg.vhd"
|
||||
vcom -explicit -93 "../src/piso.vhd"
|
||||
vcom -explicit -93 "../src/sipo.vhd"
|
||||
vcom -explicit -93 "../src/tb_serdes.vhd"
|
||||
vsim -t 1ps -lib work tb_serdes
|
||||
view wave
|
||||
do {tb_serdes.wdo}
|
||||
view structure
|
||||
view signals
|
||||
|
||||
run 20 us
|
||||
@@ -1,58 +0,0 @@
|
||||
onerror {resume}
|
||||
quietly WaveActivateNextPane {} 0
|
||||
add wave -noupdate -format Logic /tb_serdes/clk
|
||||
add wave -noupdate -format Logic /tb_serdes/rst
|
||||
add wave -noupdate -divider PiSo
|
||||
add wave -noupdate -format Logic /tb_serdes/clk
|
||||
add wave -noupdate -format Logic /tb_serdes/piso_din_vld
|
||||
add wave -noupdate -format Logic /tb_serdes/piso_din_rdy
|
||||
add wave -noupdate -format Literal /tb_serdes/piso_din_be
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_serdes/piso_din
|
||||
add wave -noupdate -format Logic /tb_serdes/piso_dout_vld
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_serdes/piso_dout
|
||||
add wave -noupdate -format Logic /tb_serdes/piso_dout_en
|
||||
add wave -noupdate -divider SiPo
|
||||
add wave -noupdate -format Logic /tb_serdes/clk
|
||||
add wave -noupdate -format Logic /tb_serdes/sipo_enable
|
||||
add wave -noupdate -format Logic /tb_serdes/sipo_rst
|
||||
add wave -noupdate -format Logic /tb_serdes/sipo_din_vld
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_serdes/sipo_din
|
||||
add wave -noupdate -format Logic /tb_serdes/sipo_dout_vld
|
||||
add wave -noupdate -format Logic /tb_serdes/sipo_dout_en
|
||||
add wave -noupdate -format Literal /tb_serdes/sipo_dout_be
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_serdes/sipo_dout
|
||||
add wave -noupdate -divider PiSo
|
||||
add wave -noupdate -format Logic /tb_serdes/clk
|
||||
add wave -noupdate -format Logic /tb_serdes/piso2_din_vld
|
||||
add wave -noupdate -format Logic /tb_serdes/piso2_din_rdy
|
||||
add wave -noupdate -format Literal /tb_serdes/piso2_din_be
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_serdes/piso2_din
|
||||
add wave -noupdate -format Logic /tb_serdes/piso2_dout_vld
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_serdes/piso2_dout
|
||||
add wave -noupdate -format Logic /tb_serdes/piso2_dout_en
|
||||
add wave -noupdate -divider SiPo
|
||||
add wave -noupdate -format Logic /tb_serdes/clk
|
||||
add wave -noupdate -format Logic /tb_serdes/sipo2_enable
|
||||
add wave -noupdate -format Logic /tb_serdes/sipo2_rst
|
||||
add wave -noupdate -format Logic /tb_serdes/sipo2_din_vld
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_serdes/sipo2_din
|
||||
add wave -noupdate -format Logic /tb_serdes/sipo2_dout_vld
|
||||
add wave -noupdate -format Logic /tb_serdes/sipo2_dout_en
|
||||
add wave -noupdate -format Literal /tb_serdes/sipo2_dout_be
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_serdes/sipo2_dout
|
||||
TreeUpdate [SetDefaultTree]
|
||||
WaveRestoreCursors {{Cursor 1} {19757882 ps} 0} {{Cursor 2} {49999912163 ps} 0} {{Cursor 3} {49999529250 ps} 0}
|
||||
configure wave -namecolwidth 150
|
||||
configure wave -valuecolwidth 100
|
||||
configure wave -justifyvalue left
|
||||
configure wave -signalnamewidth 1
|
||||
configure wave -snapdistance 10
|
||||
configure wave -datasetprefix 0
|
||||
configure wave -rowmargin 4
|
||||
configure wave -childrowmargin 2
|
||||
configure wave -gridoffset 0
|
||||
configure wave -gridperiod 100
|
||||
configure wave -griddelta 40
|
||||
configure wave -timeline 1
|
||||
update
|
||||
WaveRestoreZoom {0 ps} {21 us}
|
||||
@@ -1,34 +0,0 @@
|
||||
## NOTE: Do not edit this file.
|
||||
## Autogenerated by ProjNav (creatfdo.tcl) on Thu Jul 06 20:49:07 Westeuropäische Sommerzeit 2006
|
||||
##
|
||||
vlib work
|
||||
vcom -explicit -93 "../../misc/utils_pkg.vhd"
|
||||
vcom -explicit -93 "../../rams/dpram_1w1r2c_ra_sim.vhd"
|
||||
vcom -explicit -93 "../../rams/dpram_2w2r2c_ra_sim.vhd"
|
||||
vcom -explicit -93 "../../rams/dpram_1w1r2c_ro_sim.vhd"
|
||||
vcom -explicit -93 "../../rams/dpram_2w2r2c_ro_sim.vhd"
|
||||
vcom -explicit -93 "../../FIFO/src/fifo_ctrl_pkg.vhd"
|
||||
vcom -explicit -93 "../../FIFO/src/fifo_sync_ctrl.vhd"
|
||||
vcom -explicit -93 "../../FIFO/src/fifo_sync.vhd"
|
||||
vcom -explicit -93 "../../FIFO/src/gray_counter.vhd"
|
||||
vcom -explicit -93 "../../FIFO/src/fifo_async_ctrl.vhd"
|
||||
vcom -explicit -93 "../../FIFO/src/fifo_async.vhd"
|
||||
vcom -explicit -93 "../../JBUS/src/busmaster_types.vhd"
|
||||
vcom -explicit -93 "../../JBUS/src/busmaster_sync.vhd"
|
||||
vcom -explicit -93 "../../JBUS/src/dmac.vhd"
|
||||
vcom -explicit -93 "../src/piso.vhd"
|
||||
vcom -explicit -93 "../src/sipo.vhd"
|
||||
vcom -explicit -93 "../src/crc32.vhd"
|
||||
vcom -explicit -93 "../src/emac_types.vhd"
|
||||
vcom -explicit -93 "../src/emac_rx.vhd"
|
||||
vcom -explicit -93 "../src/emac_tx.vhd"
|
||||
vcom -explicit -93 "../src/emac_top_jb.vhd"
|
||||
vcom -explicit -93 "../src/pkt_gen.vhd"
|
||||
vcom -explicit -93 "../src/tb_emac_top_jb.vhd"
|
||||
vsim -t 1ps -lib work tb_emac_top_jb
|
||||
view wave
|
||||
do {tb_emac_top_jb.wdo}
|
||||
view structure
|
||||
view signals
|
||||
|
||||
run 16000 us
|
||||
@@ -1,236 +0,0 @@
|
||||
onerror {resume}
|
||||
quietly WaveActivateNextPane {} 0
|
||||
add wave -noupdate -divider {Ethernet MAC}
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/clk_i
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/rst_i
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/ram64
|
||||
add wave -noupdate -divider Slave
|
||||
add wave -noupdate -format Logic -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/int_o
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/cyc_i
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/stb_i
|
||||
add wave -noupdate -format Literal /tb_emac_top_jb/inst_emac_top_jb/sel_i
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/we_i
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/ack_o
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/srdy_o
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/mrdy_i
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/addr_i
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/dat_i
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/dat_o
|
||||
add wave -noupdate -divider Master
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/cyc_o
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/stb_o
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/we_o
|
||||
add wave -noupdate -format Literal /tb_emac_top_jb/sel_o
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/ack_i
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/mrdy_o
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/srdy_i
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/addr_o
|
||||
add wave -noupdate -format Literal /tb_emac_top_jb/mdat_i
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/mdat_o
|
||||
add wave -noupdate -divider MII
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/mii_rx_clk
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/mii_rx_dv
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/mii_rx_er
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/mii_rx
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/mii_tx_clk
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/mii_tx_en
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/mii_tx_er
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/mii_tx
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/mii_gtx_clk
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/mii_crs
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/mii_col
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/status_reg
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/size_reg
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/dat_o_reg
|
||||
add wave -noupdate -format Literal /tb_emac_top_jb/emac_action
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/dat_o_cnt_rst
|
||||
add wave -noupdate -format Literal /tb_emac_top_jb/dat_o_cnt
|
||||
add wave -noupdate -format Literal /tb_emac_top_jb/pkt_count
|
||||
add wave -noupdate -divider {Packet generator}
|
||||
add wave -noupdate -format Literal /tb_emac_top_jb/inst_pkt_gen/tx_packets
|
||||
add wave -noupdate -format Literal /tb_emac_top_jb/inst_pkt_gen/tx_bytes
|
||||
add wave -noupdate -format Literal -radix unsigned /tb_emac_top_jb/inst_pkt_gen/pkt_nbytes
|
||||
add wave -noupdate -format Literal -radix unsigned /tb_emac_top_jb/inst_pkt_gen/pkt_nwords
|
||||
add wave -noupdate -format Literal /tb_emac_top_jb/inst_pkt_gen/host_s
|
||||
add wave -noupdate -format Literal -radix hexadecimal -expand /tb_emac_top_jb/inst_pkt_gen/tx_ctrl_in
|
||||
add wave -noupdate -format Literal -radix hexadecimal -expand /tb_emac_top_jb/inst_pkt_gen/tx_ctrl_out
|
||||
add wave -noupdate -format Literal /tb_emac_top_jb/inst_pkt_gen/tx_bytes
|
||||
add wave -noupdate -format Literal /tb_emac_top_jb/inst_pkt_gen/tx_packets
|
||||
add wave -noupdate -format Literal -radix unsigned /tb_emac_top_jb/inst_pkt_gen/fill_size
|
||||
add wave -noupdate -format Literal -radix unsigned /tb_emac_top_jb/inst_pkt_gen/fill_cnt
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_pkt_gen/fill_rdy
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_pkt_gen/fill_set
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_pkt_gen/fill_en
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_pkt_gen/tx_din
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_pkt_gen/tx_din_vld
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/pktgen_tx
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/pktgen_tx_en
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/pktgen_tx_er
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/pktgen_en
|
||||
add wave -noupdate -divider RX-DMA
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/gen_dmac__0/inst_dmac/master_req
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/gen_dmac__0/inst_dmac/master_gnt
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/gen_dmac__0/inst_dmac/dma_start
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/gen_dmac__0/inst_dmac/dma_active
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/gen_dmac__0/inst_dmac/dma_end
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/gen_dmac__0/inst_dmac/req_rdy
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/gen_dmac__0/inst_dmac/req_en
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/gen_dmac__0/inst_dmac/req_rw
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/gen_dmac__0/inst_dmac/req_addr_start
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/gen_dmac__0/inst_dmac/req_num_xfers
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/gen_dmac__0/inst_dmac/req_addr_auto_inc
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/gen_dmac__0/inst_dmac/req_complete
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/gen_dmac__0/inst_dmac/req_complete_ack
|
||||
add wave -noupdate -format Literal /tb_emac_top_jb/inst_emac_top_jb/gen_dmac__0/inst_dmac/s
|
||||
add wave -noupdate -divider RX
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/clk
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/rst
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/dout_re
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/dout
|
||||
add wave -noupdate -format Literal -radix hexadecimal -expand /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/ctrl_in
|
||||
add wave -noupdate -format Literal -radix unsigned -expand /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/ctrl_out
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/mii_rx_clk
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/mii_rx_dv
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/mii_rx_er
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/mii_rx
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/mii_crs
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/mii_col
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/cmd_fifo_din
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/cmd_fifo_dout
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/cmd_fifo_we
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/cmd_fifo_re
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/cmd_fifo_empty
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/cmd_fifo_full
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/host_ptr
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/host_ram_limit
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/host_ram_base
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/commit_en
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/xfer_ram_limit
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/xfer_ram_full
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/xfer_base
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/xfer_ptr
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/ram_en_a
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/ram_we_a
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/ram_addr_a
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/ram_din_a
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/ram_en_b
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/ram_addr_b
|
||||
add wave -noupdate -format Literal -radix unsigned /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/byte_count
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/sipo32_din
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/sipo32_din_vld
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/sipo32_dout
|
||||
add wave -noupdate -format Literal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/sipo32_dout_be
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/sipo32_dout_vld
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/sipo32_dout_en
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/sipo32_en
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/sipo32_rst
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/sipo8_dout
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/sipo8_rst
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/sipo8_dout_vld
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/sipo8_dout_en
|
||||
add wave -noupdate -format Literal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/host_s
|
||||
add wave -noupdate -format Literal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/xfer_s
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/preamble_bsy
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/preamble_ok
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/preamble_rdy
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/mac_chk_rdy
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/mac_chk_ok
|
||||
add wave -noupdate -format Literal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/mac_chk_num_ok
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/mac_chk_addr
|
||||
add wave -noupdate -format Literal -radix unsigned /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/mac_chk_cnt
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/fcs_vld
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/fcs_din_vld
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/fcs
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/fcs_chk_ok
|
||||
add wave -noupdate -divider TX
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/clk
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/rst
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/din_vld
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/din
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/ctrl_in
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/ctrl_out
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/cmd_fifo_din
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/cmd_fifo_dout
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/cmd_fifo_we
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/cmd_fifo_re
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/cmd_fifo_empty
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/cmd_fifo_full
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/fill_pre_rdy
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/fill_bsy
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/fill_set
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/fill_en
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/fill_cnt_en
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/fill_base
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/fill_size
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/fill_cnt
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/fill_ptr
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/fill_remain
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/alloc_ok
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/alloc_req
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/alloc_ack
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/nwords_free
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/alloc_size
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/mem_alloc_en
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/mem_free_en
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/commit_en
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/uncommit_en
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/xfer_bsy
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/xfer_size
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/xfer_ptr
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/xfer_cnt
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/xfer_cnt_en
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/xfer_en
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/xfer_set
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/ram_en_a
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/ram_we_a
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/ram_addr_a
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/ram_din_a
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/ram_en_b
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/ram_addr_b
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/ram_dout_b
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/piso32_din
|
||||
add wave -noupdate -format Literal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/piso32_din_be
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/piso32_din_rdy
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/piso32_din_vld
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/piso32_dout
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/piso32_dout_vld
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/piso32_dout_en
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/mii_fifo_we
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/mii_fifo_re
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/mii_fifo_full
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/mii_fifo_empty
|
||||
add wave -noupdate -format Literal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/mii_fifo_re_dly
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/piso8_din_vld
|
||||
add wave -noupdate -format Literal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/piso8_din
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/piso8_dout_vld
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/piso8_din_rdy
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/piso8_dout
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/fcs_rst
|
||||
add wave -noupdate -format Literal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/fcs_en
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/fcs_din_vld
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/fcs_vld
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/fcs
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/mii_tx_clk
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/mii_tx_en
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/mii_tx_er
|
||||
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/mii_tx
|
||||
add wave -noupdate -format Literal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/host_s
|
||||
add wave -noupdate -format Literal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/xfer_s
|
||||
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/mem_free_req
|
||||
add wave -noupdate -format Literal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/mem_free_ack
|
||||
TreeUpdate [SetDefaultTree]
|
||||
WaveRestoreCursors {{Cursor 1} {15999470765 ps} 0} {{Cursor 2} {49999967706 ps} 0} {{Cursor 3} {42725669958 ps} 0} {{Cursor 4} {10461803096 ps} 0} {{Cursor 5} {10000 ps} 0}
|
||||
configure wave -namecolwidth 150
|
||||
configure wave -valuecolwidth 100
|
||||
configure wave -justifyvalue left
|
||||
configure wave -signalnamewidth 1
|
||||
configure wave -snapdistance 10
|
||||
configure wave -datasetprefix 0
|
||||
configure wave -rowmargin 4
|
||||
configure wave -childrowmargin 2
|
||||
configure wave -gridoffset 0
|
||||
configure wave -gridperiod 100
|
||||
configure wave -griddelta 40
|
||||
configure wave -timeline 1
|
||||
update
|
||||
WaveRestoreZoom {0 ps} {379173 ps}
|
||||
@@ -1,8 +0,0 @@
|
||||
VHDL/lib/emac/emac_jb.vhd
|
||||
VHDL/lib/emac/src/emac_jb.vhd
|
||||
VHDL/lib/emac/src/emac_jb.vhd
|
||||
|
||||
VHDL/lib/emac/src/tb_emac_jb.vhd
|
||||
VHDL/lib/emac/src/tb_serdes.vhd
|
||||
VHDL/lib/emac/src/tb_serdes.vhd
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
LIBRARY IEEE;
|
||||
USE IEEE.STD_LOGIC_1164.ALL;
|
||||
USE IEEE.NUMERIC_STD.ALL;
|
||||
use std.textio.all; -- Imports the standard textio package.
|
||||
|
||||
use work.utils_pkg.all; -- Imports the standard textio package.
|
||||
|
||||
ENTITY crc32 IS
|
||||
Generic
|
||||
(
|
||||
crc32_init : unsigned(31 downto 0) := X"00000000"
|
||||
);
|
||||
Port
|
||||
(
|
||||
rst : in STD_LOGIC;
|
||||
clk : in STD_LOGIC;
|
||||
din_vld : in STD_LOGIC;
|
||||
din : in unsigned(7 downto 0);
|
||||
crc32_vld : out STD_LOGIC;
|
||||
crc32_out : out unsigned(31 downto 0)
|
||||
|
||||
);
|
||||
END crc32;
|
||||
|
||||
ARCHITECTURE behavior OF crc32 IS
|
||||
|
||||
type crc_table_t is array (0 to 15) of unsigned(31 downto 0);
|
||||
|
||||
constant crc_table : crc_table_t :=
|
||||
(
|
||||
X"4DBDF21C", X"500AE278", X"76D3D2D4", X"6B64C2B0",
|
||||
X"3B61B38C", X"26D6A3E8", X"000F9344", X"1DB88320",
|
||||
X"A005713C", X"BDB26158", X"9B6B51F4", X"86DC4190",
|
||||
X"D6D930AC", X"CB6E20C8", X"EDB71064", X"F0000000"
|
||||
);
|
||||
|
||||
signal crc0 : unsigned(31 downto 0);
|
||||
signal crc1 : unsigned(31 downto 0);
|
||||
signal crc2 : unsigned(31 downto 0);
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
begin
|
||||
|
||||
crc1 <= X"0" & crc0(31 downto 4) xor crc_table(to_integer(crc0(3 downto 0) xor din(3 downto 0)));
|
||||
crc2 <= X"0" & crc1(31 downto 4) xor crc_table(to_integer(crc1(3 downto 0) xor din(7 downto 4)));
|
||||
|
||||
crc32_out <= crc0;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
crc0 <= crc32_init;
|
||||
crc32_vld <= '0';
|
||||
elsif din_vld = '1' then
|
||||
crc0 <= crc2;
|
||||
crc32_vld <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
end behavior;
|
||||
@@ -1,561 +0,0 @@
|
||||
LIBRARY IEEE;
|
||||
USE IEEE.STD_LOGIC_1164.ALL;
|
||||
USE IEEE.NUMERIC_STD.ALL;
|
||||
use std.textio.all; -- Imports the standard textio package.
|
||||
|
||||
use work.emac_types.all;
|
||||
use work.utils_pkg.all;
|
||||
|
||||
ENTITY emac_rx IS
|
||||
Generic
|
||||
(
|
||||
f_sysclk : real := 100.0;
|
||||
RAM_SIZE : natural := 2048
|
||||
);
|
||||
Port
|
||||
(
|
||||
clk : in STD_LOGIC;
|
||||
rst : in STD_LOGIC;
|
||||
dout_re : in STD_LOGIC;
|
||||
dout : out unsigned(31 downto 0);
|
||||
ctrl_in : in rx_ctrl_in_t;
|
||||
ctrl_out : out rx_ctrl_out_t;
|
||||
mii_rx_clk : in STD_LOGIC;
|
||||
mii_rx_dv : in STD_LOGIC;
|
||||
mii_rx_er : in STD_LOGIC;
|
||||
mii_rx : in unsigned(7 downto 0);
|
||||
mii_crs : in STD_LOGIC;
|
||||
mii_col : in STD_LOGIC
|
||||
|
||||
);
|
||||
END emac_rx;
|
||||
|
||||
ARCHITECTURE behavior OF emac_rx IS
|
||||
|
||||
constant RAM_ADDR_WIDTH : natural := NextExpBaseTwo(RAM_SIZE);
|
||||
|
||||
subtype word_ptr_t is unsigned(RAM_ADDR_WIDTH-1 downto 0);
|
||||
|
||||
-- Signals for EMAC connections
|
||||
signal cmd_fifo_din : unsigned(2*word_ptr_t'length+2 downto 0);
|
||||
signal cmd_fifo_dout : unsigned(2*word_ptr_t'length+2 downto 0);
|
||||
signal cmd_fifo_we : std_logic;
|
||||
signal cmd_fifo_re : std_logic;
|
||||
signal cmd_fifo_empty : std_logic;
|
||||
signal cmd_fifo_full : std_logic;
|
||||
|
||||
signal reset_en : std_logic;
|
||||
|
||||
signal host_ptr : word_ptr_t;
|
||||
signal host_ptr_next : word_ptr_t;
|
||||
signal host_ram_limit : word_ptr_t;
|
||||
signal host_ram_base : word_ptr_t;
|
||||
|
||||
signal commit_en : std_logic;
|
||||
|
||||
signal xfer_ram_limit : word_ptr_t;
|
||||
signal xfer_ram_full : std_logic;
|
||||
signal xfer_base : word_ptr_t;
|
||||
signal xfer_ptr : word_ptr_t;
|
||||
signal xfer_en : std_logic;
|
||||
signal xfer_set : std_logic;
|
||||
signal xfer_vld : std_logic;
|
||||
signal xfer_promiscious : std_logic;
|
||||
|
||||
signal ram_en_a : std_logic;
|
||||
signal ram_we_a : std_logic;
|
||||
signal ram_addr_a : word_ptr_t;
|
||||
signal ram_din_a : unsigned(31 downto 0);
|
||||
signal ram_dout_b : unsigned(31 downto 0);
|
||||
signal ram_en_b : std_logic;
|
||||
signal ram_addr_b : word_ptr_t;
|
||||
|
||||
signal sipo32_din : unsigned(7 downto 0);
|
||||
signal sipo32_din_vld : std_logic;
|
||||
signal sipo32_dout : unsigned(31 downto 0);
|
||||
signal sipo32_dout_be : unsigned(3 downto 0);
|
||||
signal sipo32_dout_vld : std_logic;
|
||||
signal sipo32_dout_en : std_logic;
|
||||
signal sipo32_en : std_logic;
|
||||
signal sipo32_rst : std_logic;
|
||||
|
||||
signal sipo8_dout : unsigned(7 downto 0);
|
||||
signal sipo8_rst : std_logic;
|
||||
signal sipo8_dout_vld : std_logic;
|
||||
signal sipo8_dout_en : std_logic;
|
||||
signal sipo8_en : std_logic;
|
||||
|
||||
signal byte_count_rst : std_logic;
|
||||
signal byte_count : word_ptr_t;
|
||||
|
||||
signal reset_pipe : unsigned(31 downto 0);
|
||||
|
||||
signal preamble_en : std_logic;
|
||||
signal preamble_rdy : std_logic;
|
||||
signal preamble_bsy : std_logic;
|
||||
signal preamble_OK : std_logic;
|
||||
|
||||
signal mac_chk_rdy : std_logic;
|
||||
signal mac_chk_BC : std_logic;
|
||||
signal mac_chk_OK : std_logic;
|
||||
signal mac_chk_num_OK : natural range 0 to 6;
|
||||
signal mac_chk_num_BC : natural range 0 to 6;
|
||||
signal mac_chk_cnt : natural range 0 to 5;
|
||||
signal mac_addr : mac_addr_t;
|
||||
signal mac_chk_addr : mac_addr_t;
|
||||
|
||||
signal Gbps_en : std_logic;
|
||||
signal fcs_chk_en : std_logic;
|
||||
signal rx_en : std_logic;
|
||||
|
||||
signal fcs_vld : std_logic;
|
||||
signal fcs_din_vld : std_logic;
|
||||
signal fcs_din : unsigned(7 downto 0);
|
||||
signal fcs : unsigned(31 downto 0);
|
||||
signal fcs_chk_OK : std_logic;
|
||||
|
||||
type host_state_t is (host_init, host_flush, host_idle);
|
||||
signal host_s, host_sn : host_state_t;
|
||||
|
||||
type xfer_state_t is (xfer_init, xfer_idle, xfer_preamble, xfer_setup, xfer_active, xfer_finish, xfer_commit);
|
||||
signal xfer_s, xfer_sn : xfer_state_t;
|
||||
|
||||
alias cmd_mac_ok_in is cmd_fifo_din(cmd_fifo_din'left);
|
||||
alias cmd_bcast_in is cmd_fifo_din(cmd_fifo_din'left-1);
|
||||
alias cmd_pkt_valid_in is cmd_fifo_din(cmd_fifo_din'left-2);
|
||||
alias cmd_nbytes_in is cmd_fifo_din(word_ptr_t'length-1 downto 0);
|
||||
alias cmd_base_in is cmd_fifo_din(2*word_ptr_t'length-1 downto word_ptr_t'length);
|
||||
|
||||
alias cmd_mac_ok_out is cmd_fifo_dout(cmd_fifo_dout'left);
|
||||
alias cmd_bcast_out is cmd_fifo_dout(cmd_fifo_dout'left-1);
|
||||
alias cmd_pkt_valid_out is cmd_fifo_dout(cmd_fifo_dout'left-2);
|
||||
alias cmd_nbytes_out is cmd_fifo_dout(word_ptr_t'length-1 downto 0);
|
||||
alias cmd_base_out is cmd_fifo_dout(2*word_ptr_t'length-1 downto word_ptr_t'length);
|
||||
|
||||
begin
|
||||
|
||||
ctrl_out.rx_size <= resize(cmd_nbytes_out, 16);
|
||||
ctrl_out.pkt_avail <= not cmd_fifo_empty;
|
||||
ctrl_out.pkt_valid <= cmd_pkt_valid_out;
|
||||
ctrl_out.pkt_bcast <= cmd_bcast_out;
|
||||
ctrl_out.pkt_mac_match <= cmd_mac_ok_out;
|
||||
ctrl_out.reset_busy <= reset_en;
|
||||
|
||||
dout <= ram_dout_b;
|
||||
|
||||
ram_en_b <= '1';
|
||||
ram_addr_b <= host_ptr_next;
|
||||
|
||||
ram_en_a <= '1';
|
||||
ram_din_a <= sipo32_dout;
|
||||
ram_addr_a <= xfer_ptr;
|
||||
ram_we_a <= xfer_en and sipo32_dout_vld;
|
||||
|
||||
xfer_vld <= (mac_chk_OK or mac_chk_BC or xfer_promiscious) and (not fcs_chk_en or fcs_chk_OK);
|
||||
cmd_fifo_we <= commit_en and xfer_vld;
|
||||
cmd_fifo_re <= ctrl_in.pkt_free_en;
|
||||
|
||||
cmd_pkt_valid_in <= fcs_chk_OK;
|
||||
cmd_mac_ok_in <= mac_chk_OK;
|
||||
cmd_bcast_in <= mac_chk_BC;
|
||||
cmd_nbytes_in <= byte_count;
|
||||
cmd_base_in <= xfer_base;
|
||||
|
||||
|
||||
reset_en <= reset_pipe(reset_pipe'left);
|
||||
|
||||
------------------------------------------------------------------
|
||||
reset_gen:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' or ctrl_in.reset = '1' then
|
||||
reset_pipe <= (others => '1');
|
||||
else
|
||||
reset_pipe <= reset_pipe(reset_pipe'left-1 downto 0) & '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
-- Fill stuff
|
||||
------------------------------------------------------------------
|
||||
fill_pointer:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if ctrl_in.pkt_req_en = '1' then
|
||||
host_ptr <= cmd_base_out;
|
||||
elsif dout_re = '1' then
|
||||
host_ptr <= host_ptr_next;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
host_ptr_next <= host_ptr + 1 when dout_re = '1' else host_ptr;
|
||||
|
||||
------------------------------------------------------------------
|
||||
-- Transfer stuff
|
||||
------------------------------------------------------------------
|
||||
host2xfer_sync_register:
|
||||
process(mii_rx_clk)
|
||||
begin
|
||||
if rising_edge(mii_rx_clk) then
|
||||
xfer_promiscious <= ctrl_in.promiscious;
|
||||
Gbps_en <= ctrl_in.Gbps_en;
|
||||
fcs_chk_en <= ctrl_in.fcs_chk_en;
|
||||
mac_addr <= ctrl_in.mac_addr;
|
||||
xfer_ram_limit <= host_ram_limit;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
host_limit_register:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
host_ram_base <= xfer_base;
|
||||
if cmd_fifo_empty = '1' then
|
||||
host_ram_limit <= host_ram_base - 1;
|
||||
else
|
||||
host_ram_limit <= cmd_base_out - 1;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
end process;
|
||||
|
||||
xfer_ram_full_detect:
|
||||
process(mii_rx_clk)
|
||||
begin
|
||||
if rising_edge(mii_rx_clk) then
|
||||
if xfer_set = '1' or reset_en = '1' then
|
||||
xfer_ram_full <= '0';
|
||||
elsif xfer_en = '1' and sipo32_dout_vld = '1' then
|
||||
if xfer_ptr = xfer_ram_limit then
|
||||
xfer_ram_full <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
end process;
|
||||
|
||||
xfer_base_logic:
|
||||
process(mii_rx_clk)
|
||||
begin
|
||||
if rising_edge(mii_rx_clk) then
|
||||
if reset_en = '1' then
|
||||
xfer_base <= (others => '0');
|
||||
elsif commit_en = '1' and xfer_vld = '1' then
|
||||
xfer_base <= xfer_ptr;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
xfer_pointer:
|
||||
process(mii_rx_clk)
|
||||
begin
|
||||
if rising_edge(mii_rx_clk) then
|
||||
if xfer_set = '1' then
|
||||
xfer_ptr <= xfer_base;
|
||||
elsif xfer_en = '1' and sipo32_dout_vld = '1' then
|
||||
xfer_ptr <= xfer_ptr + 1;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
byte_counter:
|
||||
process(mii_rx_clk)
|
||||
begin
|
||||
if rising_edge(mii_rx_clk) then
|
||||
if byte_count_rst = '1' then
|
||||
if fcs_chk_en = '0' then
|
||||
byte_count <= to_unsigned(0, RAM_ADDR_WIDTH);
|
||||
else
|
||||
byte_count <= unsigned(to_signed(-4, RAM_ADDR_WIDTH));
|
||||
end if;
|
||||
elsif sipo32_en = '1' and sipo32_din_vld = '1' then
|
||||
byte_count <= byte_count + 1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
preamble_sync_logic:
|
||||
process(mii_rx_clk)
|
||||
begin
|
||||
if rising_edge(mii_rx_clk) then
|
||||
if preamble_en = '0' then
|
||||
preamble_rdy <= '0';
|
||||
preamble_bsy <= '0';
|
||||
preamble_OK <= '0';
|
||||
elsif sipo32_din_vld = '1' then
|
||||
if preamble_bsy = '1' then
|
||||
if sipo32_din = X"D5" then
|
||||
preamble_OK <= '1';
|
||||
end if;
|
||||
end if;
|
||||
if sipo32_din /= X"55" then
|
||||
preamble_bsy <= '0';
|
||||
preamble_rdy <= preamble_bsy;
|
||||
else
|
||||
preamble_bsy <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
mac_check_logic:
|
||||
process(mii_rx_clk)
|
||||
begin
|
||||
if rising_edge(mii_rx_clk) then
|
||||
if byte_count_rst = '1' then
|
||||
mac_chk_rdy <= '0';
|
||||
mac_chk_OK <= '0';
|
||||
mac_chk_BC <= '0';
|
||||
mac_chk_cnt <= 0;
|
||||
mac_chk_num_OK <= 0;
|
||||
mac_chk_num_BC <= 0;
|
||||
mac_chk_addr <= mac_addr;
|
||||
elsif mac_chk_rdy = '1' then
|
||||
if mac_chk_num_OK = 6 then
|
||||
mac_chk_OK <= '1';
|
||||
end if;
|
||||
if mac_chk_num_BC = 6 then
|
||||
mac_chk_BC <= '1';
|
||||
end if;
|
||||
elsif sipo32_din_vld = '1' and sipo32_en = '1' then
|
||||
if sipo32_din = mac_chk_addr(mac_chk_cnt) then
|
||||
mac_chk_num_OK <= mac_chk_num_OK + 1;
|
||||
end if;
|
||||
if sipo32_din = X"FF" then
|
||||
mac_chk_num_BC <= mac_chk_num_BC + 1;
|
||||
end if;
|
||||
if mac_chk_cnt /= 5 then
|
||||
mac_chk_cnt <= mac_chk_cnt + 1;
|
||||
else
|
||||
mac_chk_rdy <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
xfer_state_next:
|
||||
process(mii_rx_clk)
|
||||
begin
|
||||
if rising_edge(mii_rx_clk) then
|
||||
if reset_en = '1' then
|
||||
xfer_s <= xfer_init;
|
||||
else
|
||||
xfer_s <= xfer_sn;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
xfer_state:
|
||||
process(xfer_s, rx_en, sipo32_dout_en, preamble_bsy, preamble_OK, xfer_ram_full)
|
||||
begin
|
||||
|
||||
commit_en <= '0';
|
||||
xfer_set <= '0';
|
||||
xfer_en <= '0';
|
||||
sipo32_rst <= '0';
|
||||
sipo32_en <= '0';
|
||||
byte_count_rst <= '0';
|
||||
preamble_en <= '0';
|
||||
|
||||
xfer_sn <= xfer_s;
|
||||
|
||||
case xfer_s is
|
||||
|
||||
when xfer_init =>
|
||||
sipo32_rst <= '1';
|
||||
if rx_en = '0' then
|
||||
xfer_sn <= xfer_idle;
|
||||
end if;
|
||||
|
||||
when xfer_idle =>
|
||||
preamble_en <= rx_en;
|
||||
if preamble_bsy = '1' then
|
||||
xfer_sn <= xfer_preamble;
|
||||
end if;
|
||||
|
||||
when xfer_preamble =>
|
||||
preamble_en <= rx_en;
|
||||
byte_count_rst <= preamble_bsy;
|
||||
sipo32_en <= rx_en and not preamble_bsy;
|
||||
if preamble_bsy = '0' then
|
||||
xfer_sn <= xfer_init;
|
||||
if preamble_OK = '1' then
|
||||
xfer_sn <= xfer_setup;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
when xfer_setup =>
|
||||
xfer_set <= '1';
|
||||
sipo32_en <= rx_en;
|
||||
xfer_en <= sipo32_dout_en;
|
||||
xfer_sn <= xfer_active;
|
||||
|
||||
when xfer_active =>
|
||||
xfer_en <= sipo32_dout_en;
|
||||
sipo32_en <= rx_en;
|
||||
if xfer_ram_full = '1' then
|
||||
xfer_sn <= xfer_init;
|
||||
elsif rx_en = '0' then
|
||||
xfer_sn <= xfer_finish;
|
||||
end if;
|
||||
|
||||
when xfer_finish =>
|
||||
xfer_en <= sipo32_dout_en;
|
||||
if sipo32_dout_en = '0' then
|
||||
xfer_sn <= xfer_commit;
|
||||
end if;
|
||||
|
||||
when xfer_commit =>
|
||||
commit_en <= '1';
|
||||
xfer_sn <= xfer_init;
|
||||
|
||||
when others =>
|
||||
xfer_sn <= xfer_init;
|
||||
end case;
|
||||
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
-- Instantiate synchronous FIFO
|
||||
inst_cmd_fifo: entity work.fifo_async
|
||||
GENERIC MAP
|
||||
(
|
||||
addr_width => NextExpBaseTwo(RAM_SIZE) - 4, -- RAMSIZE(words)/MIN_PACKET_LEN(words)
|
||||
data_width => cmd_fifo_din'length,
|
||||
do_last_read_update => false
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
rst => reset_en,
|
||||
clk_w => mii_rx_clk,
|
||||
clk_r => clk,
|
||||
we => cmd_fifo_we,
|
||||
re => cmd_fifo_re,
|
||||
fifo_full => cmd_fifo_full,
|
||||
fifo_empty => cmd_fifo_empty,
|
||||
fifo_afull => open,
|
||||
fifo_aempty => open,
|
||||
data_w => cmd_fifo_din,
|
||||
data_r => cmd_fifo_dout
|
||||
);
|
||||
|
||||
inst_ram : entity work.dpram_1w1r2c_ro
|
||||
GENERIC MAP
|
||||
(
|
||||
addr_width => RAM_ADDR_WIDTH,
|
||||
data_width => 32
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
clk_a => mii_rx_clk,
|
||||
clk_b => clk,
|
||||
en_a => ram_en_a,
|
||||
en_b => ram_en_b,
|
||||
we_a => ram_we_a,
|
||||
addr_a => ram_addr_a,
|
||||
addr_b => ram_addr_b,
|
||||
din_a => ram_din_a,
|
||||
dout_b => ram_dout_b
|
||||
);
|
||||
|
||||
inst_sipo32 : entity work.sipo
|
||||
GENERIC MAP
|
||||
(
|
||||
data_width_in => 8,
|
||||
data_width_out => 32,
|
||||
msb_first => true
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
rst => sipo32_rst,
|
||||
clk => mii_rx_clk,
|
||||
din_vld => sipo32_din_vld,
|
||||
din_en => sipo32_en,
|
||||
din => sipo32_din,
|
||||
dout_be => sipo32_dout_be,
|
||||
dout_vld => sipo32_dout_vld,
|
||||
dout => sipo32_dout,
|
||||
dout_en => sipo32_dout_en
|
||||
|
||||
);
|
||||
|
||||
inst_fcs: entity work.crc32
|
||||
GENERIC MAP
|
||||
(
|
||||
crc32_init => X"00000000"
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
rst => byte_count_rst,
|
||||
clk => mii_rx_clk,
|
||||
din_vld => fcs_din_vld,
|
||||
din => fcs_din,
|
||||
crc32_vld => fcs_vld,
|
||||
crc32_out => fcs
|
||||
|
||||
);
|
||||
|
||||
fcs_din <= sipo32_din;
|
||||
fcs_din_vld <= sipo32_en and sipo32_din_vld;
|
||||
|
||||
fcs_chk_register:
|
||||
process(mii_rx_clk)
|
||||
begin
|
||||
if rising_edge(mii_rx_clk) then
|
||||
if fcs_vld = '1' then
|
||||
fcs_chk_OK <= '0';
|
||||
if fcs = X"2144DF1C" then
|
||||
fcs_chk_OK <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
mii_input_register:
|
||||
process(mii_rx_clk)
|
||||
begin
|
||||
if rising_edge(mii_rx_clk) then
|
||||
if Gbps_en = '1' then
|
||||
sipo32_din <= mii_rx;
|
||||
sipo32_din_vld <= not mii_rx_er;
|
||||
rx_en <= mii_rx_dv;
|
||||
else
|
||||
sipo32_din <= sipo8_dout;
|
||||
sipo32_din_vld <= sipo8_dout_vld;
|
||||
rx_en <= sipo8_dout_en;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
inst_sipo_8bit : entity work.sipo
|
||||
GENERIC MAP
|
||||
(
|
||||
data_width_in => 4,
|
||||
data_width_out => 8,
|
||||
msb_first => false
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
rst => sipo8_rst,
|
||||
clk => mii_rx_clk,
|
||||
din_vld => mii_rx_dv,
|
||||
din_en => mii_rx_dv,
|
||||
din => mii_rx(3 downto 0),
|
||||
dout_be => open,
|
||||
dout_vld => sipo8_dout_vld,
|
||||
dout => sipo8_dout,
|
||||
dout_en => sipo8_dout_en
|
||||
|
||||
);
|
||||
|
||||
sipo8_rst <= reset_en or not (mii_rx_dv or sipo8_dout_en);
|
||||
sipo8_en <= not mii_rx_er;
|
||||
|
||||
end behavior;
|
||||
@@ -1,503 +0,0 @@
|
||||
LIBRARY IEEE;
|
||||
USE IEEE.STD_LOGIC_1164.ALL;
|
||||
USE IEEE.NUMERIC_STD.ALL;
|
||||
use std.textio.all; -- Imports the standard textio package.
|
||||
|
||||
use work.emac_types.all;
|
||||
use work.utils_pkg.all;
|
||||
use work.busmaster_types.all;
|
||||
|
||||
ENTITY emac_top_jb IS
|
||||
Generic
|
||||
(
|
||||
f_sysclk : real := 100.0;
|
||||
TX_RAM_SIZE : natural := 2048;
|
||||
RX_RAM_SIZE : natural := 2048
|
||||
);
|
||||
Port
|
||||
(
|
||||
-- JBUS Slave
|
||||
CLK_I : in STD_LOGIC;
|
||||
RST_I : in STD_LOGIC;
|
||||
INT_O : out STD_LOGIC;
|
||||
CYC_I : in STD_LOGIC;
|
||||
STB_I : in STD_LOGIC;
|
||||
SEL_I : in unsigned(3 downto 0);
|
||||
WE_I : in STD_LOGIC;
|
||||
ACK_O : out STD_LOGIC;
|
||||
SRDY_O : out STD_LOGIC;
|
||||
MRDY_I : in STD_LOGIC;
|
||||
ADDR_I : in unsigned(31 downto 0);
|
||||
DAT_I : in unsigned(31 downto 0);
|
||||
DAT_O : out unsigned(31 downto 0);
|
||||
|
||||
-- JBUS Master
|
||||
ACK_I : in std_logic;
|
||||
SRDY_I : in std_logic;
|
||||
MDAT_I : in unsigned(31 downto 0);
|
||||
MDAT_O : out unsigned(31 downto 0);
|
||||
ADDR_O : out unsigned(31 downto 0);
|
||||
SEL_O : out unsigned(3 downto 0);
|
||||
WE_O : out std_logic;
|
||||
CYC_O : out std_logic;
|
||||
STB_O : out std_logic;
|
||||
MRDY_O : out std_logic;
|
||||
|
||||
-- MII
|
||||
mii_rx_clk : in STD_LOGIC;
|
||||
mii_rx_dv : in STD_LOGIC;
|
||||
mii_rx_er : in STD_LOGIC;
|
||||
mii_rx : in unsigned(7 downto 0);
|
||||
mii_tx_clk : in STD_LOGIC;
|
||||
mii_tx_en : out STD_LOGIC;
|
||||
mii_tx_er : out STD_LOGIC;
|
||||
mii_tx : out unsigned(7 downto 0);
|
||||
mii_gtx_clk : out STD_LOGIC;
|
||||
mii_crs : in STD_LOGIC;
|
||||
mii_col : in STD_LOGIC
|
||||
|
||||
);
|
||||
END emac_top_jb;
|
||||
|
||||
ARCHITECTURE behavior OF emac_top_jb IS
|
||||
|
||||
-- Constants
|
||||
constant DMA_NUM_CHANNEL : integer := 2;
|
||||
constant DMA_CH_WRITE : integer := 0;
|
||||
constant DMA_CH_READ : integer := 1;
|
||||
constant DMA_RW_CONF : unsigned(DMA_NUM_CHANNEL-1 downto 0) := "01";
|
||||
|
||||
-- Signals for EMAC connections
|
||||
signal tx_ctrl_in : tx_ctrl_in_t;
|
||||
signal tx_ctrl_out : tx_ctrl_out_t;
|
||||
signal tx_din : unsigned(31 downto 0);
|
||||
signal tx_din_vld : std_logic;
|
||||
|
||||
signal rx_ctrl_in : rx_ctrl_in_t;
|
||||
signal rx_ctrl_out : rx_ctrl_out_t;
|
||||
|
||||
signal rx_dout : unsigned(31 downto 0);
|
||||
signal rx_dout_re : std_logic;
|
||||
|
||||
signal rx_int_en : std_logic;
|
||||
signal tx_int_en : std_logic;
|
||||
signal irq_rx : std_logic;
|
||||
signal irq_tx : std_logic;
|
||||
|
||||
signal ready : std_logic;
|
||||
|
||||
signal read : std_logic;
|
||||
signal write : std_logic;
|
||||
signal rx_read_en_CPU : std_logic;
|
||||
signal rx_req_en_CPU : std_logic;
|
||||
signal rx_free_en_CPU : std_logic;
|
||||
signal tx_write_en_CPU : std_logic;
|
||||
signal reg_read : std_logic;
|
||||
signal reg_write : std_logic;
|
||||
|
||||
signal reg_addr : unsigned(3 downto 0);
|
||||
|
||||
-- DMA Controller
|
||||
signal dma_master_req : unsigned(DMA_NUM_CHANNEL-1 downto 0);
|
||||
signal dma_master_gnt : unsigned(DMA_NUM_CHANNEL-1 downto 0) := (others => '0');
|
||||
signal dma_req_rdy : unsigned(DMA_NUM_CHANNEL-1 downto 0);
|
||||
signal dma_req_en : unsigned(DMA_NUM_CHANNEL-1 downto 0) := (others => '0');
|
||||
signal dma_req_addr_auto_inc : unsigned(DMA_NUM_CHANNEL-1 downto 0);
|
||||
type array32_t is array (0 to DMA_NUM_CHANNEL-1) of unsigned(31 downto 0);
|
||||
signal dma_req_addr : array32_t;
|
||||
signal dma_req_num_xfers : array32_t;
|
||||
|
||||
signal dma_req_complete : unsigned(DMA_NUM_CHANNEL-1 downto 0);
|
||||
signal dma_req_complete_ack : unsigned(DMA_NUM_CHANNEL-1 downto 0) := (others => '0');
|
||||
|
||||
signal dma_start : unsigned(DMA_NUM_CHANNEL-1 downto 0);
|
||||
signal dma_active : unsigned(DMA_NUM_CHANNEL-1 downto 0);
|
||||
signal dma_end : unsigned(DMA_NUM_CHANNEL-1 downto 0);
|
||||
signal dma_bus_cmd_cycle_finished : unsigned(DMA_NUM_CHANNEL-1 downto 0);
|
||||
signal dma_bus_cmd_cycle_en : unsigned(DMA_NUM_CHANNEL-1 downto 0) := (others => '0');
|
||||
signal dma_bus_cmd_rdy : unsigned(DMA_NUM_CHANNEL-1 downto 0);
|
||||
signal dma_bus_cmd_we : unsigned(DMA_NUM_CHANNEL-1 downto 0) := (others => '0');
|
||||
type array_bus_cmd_t is array (0 to DMA_NUM_CHANNEL-1) of bm_cmd_t;
|
||||
signal dma_bus_cmd : array_bus_cmd_t;
|
||||
|
||||
-- Busmaster arbiter
|
||||
signal arb_idx : natural range 0 to DMA_NUM_CHANNEL-1;
|
||||
|
||||
-- BUS Master controller
|
||||
signal bus_din_re : std_logic;
|
||||
signal bus_cmd_cycle_finished : std_logic;
|
||||
signal bus_cmd_cycle_en : std_logic := '0';
|
||||
signal bus_cmd_rdy : std_logic;
|
||||
signal bus_cmd_we : std_logic := '0';
|
||||
signal bus_cmd : bm_cmd_t;
|
||||
signal bus_din_rdy : std_logic;
|
||||
signal bus_din_vld : std_logic := '0';
|
||||
signal bus_din : unsigned(31 downto 0) := (others => '-');
|
||||
signal bus_dout : unsigned(31 downto 0);
|
||||
signal bus_dout_vld : std_logic;
|
||||
signal bus_dout_re : std_logic := '0';
|
||||
|
||||
begin
|
||||
|
||||
mii_gtx_clk <= '0';
|
||||
|
||||
SRDY_O <= CYC_I and ready;
|
||||
read <= STB_I and CYC_I and not WE_I;
|
||||
write <= STB_I and CYC_I and WE_I;
|
||||
rx_read_en_CPU <= read and ADDR_I(15);
|
||||
tx_write_en_CPU <= write and ADDR_I(15);
|
||||
reg_read <= read and not ADDR_I(15);
|
||||
reg_write <= write and not ADDR_I(15);
|
||||
reg_addr <= ADDR_I(5 downto 2);
|
||||
|
||||
ready <= not tx_ctrl_in.pkt_alloc_en;
|
||||
|
||||
tx_din_vld <= tx_write_en_CPU;
|
||||
tx_din <= DAT_I;
|
||||
|
||||
rx_ctrl_in.pkt_free_en <= rx_free_en_CPU or dma_end(0);
|
||||
rx_ctrl_in.pkt_req_en <= rx_req_en_CPU or dma_start(0);
|
||||
|
||||
rx_dout_re <= rx_read_en_CPU or (dma_active(DMA_CH_WRITE) and bus_din_rdy);
|
||||
|
||||
bus_din <= rx_dout;
|
||||
bus_din_vld <= dma_active(DMA_CH_WRITE);
|
||||
dma_master_gnt(0) <= SRDY_I;
|
||||
dma_req_en(0) <= rx_ctrl_out.pkt_avail;
|
||||
dma_req_num_xfers(0) <= X"0000" & "00" & rx_ctrl_out.rx_size(15 downto 2) when rx_ctrl_out.rx_size(1 downto 0) = "00" else X"0000" & "00" & rx_ctrl_out.rx_size(15 downto 2) + 1;
|
||||
dma_req_addr(0) <= X"00000800";
|
||||
dma_req_addr_auto_inc <= "11";
|
||||
|
||||
------------------------------------------------------------------
|
||||
registers_write:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
tx_ctrl_in.pkt_alloc_en <= '0';
|
||||
tx_ctrl_in.pkt_commit_en <= '0';
|
||||
tx_ctrl_in.reset <= '0';
|
||||
rx_free_en_CPU <= '0';
|
||||
rx_req_en_CPU <= '0';
|
||||
rx_ctrl_in.reset <= '0';
|
||||
if RST_I = '1' then
|
||||
rx_int_en <= '0';
|
||||
tx_int_en <= '0';
|
||||
tx_ctrl_in.tx_size <= (others => '0');
|
||||
rx_ctrl_in.mac_addr <= (X"03", X"02", X"01", X"00", X"07", X"06");
|
||||
rx_ctrl_in.promiscious <= '0';
|
||||
tx_ctrl_in.Gbps_en <= '0';
|
||||
rx_ctrl_in.Gbps_en <= '0';
|
||||
tx_ctrl_in.fcs_gen_en <= '0';
|
||||
rx_ctrl_in.fcs_chk_en <= '0';
|
||||
elsif reg_write = '1' then
|
||||
|
||||
-- 0x0000 .. 0x003C
|
||||
case reg_addr is
|
||||
|
||||
-- 0x0000
|
||||
when "0000" =>
|
||||
rx_ctrl_in.reset <= DAT_I(31);
|
||||
rx_ctrl_in.Gbps_en <= DAT_I(30);
|
||||
rx_ctrl_in.fcs_chk_en <= DAT_I(29);
|
||||
rx_ctrl_in.promiscious <= DAT_I(23);
|
||||
rx_req_en_CPU <= DAT_I(17);
|
||||
rx_free_en_CPU <= DAT_I(16);
|
||||
rx_int_en <= DAT_I(4);
|
||||
|
||||
-- 0x0004
|
||||
-- rx_size R/O
|
||||
|
||||
-- 0x0008
|
||||
when "0010" =>
|
||||
tx_ctrl_in.reset <= DAT_I(31);
|
||||
tx_ctrl_in.Gbps_en <= DAT_I(30);
|
||||
tx_ctrl_in.fcs_gen_en <= DAT_I(29);
|
||||
tx_ctrl_in.pkt_alloc_en <= DAT_I(17);
|
||||
tx_ctrl_in.pkt_commit_en <= DAT_I(16);
|
||||
tx_int_en <= DAT_I(4);
|
||||
|
||||
-- 0x000C
|
||||
when "0011" =>
|
||||
tx_ctrl_in.tx_size <= DAT_I(15 downto 0);
|
||||
|
||||
-- 0x0010
|
||||
-- Gap
|
||||
|
||||
-- 0x0014
|
||||
-- Gap
|
||||
|
||||
-- 0x0018
|
||||
when "0110" =>
|
||||
rx_ctrl_in.mac_addr(0) <= DAT_I(31 downto 24);
|
||||
rx_ctrl_in.mac_addr(1) <= DAT_I(23 downto 16);
|
||||
rx_ctrl_in.mac_addr(2) <= DAT_I(15 downto 8);
|
||||
rx_ctrl_in.mac_addr(3) <= DAT_I(7 downto 0);
|
||||
|
||||
-- 0x001C
|
||||
when "0111" =>
|
||||
rx_ctrl_in.mac_addr(4) <= DAT_I(31 downto 24);
|
||||
rx_ctrl_in.mac_addr(5) <= DAT_I(23 downto 16);
|
||||
|
||||
-- 0x0020 .. 0x003C
|
||||
-- Gap
|
||||
when others => null;
|
||||
|
||||
end case;
|
||||
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
registers_read:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
ACK_O <= rx_read_en_CPU;
|
||||
DAT_O <= rx_dout;
|
||||
if reg_read = '1' then
|
||||
|
||||
-- 0x0000 .. 0x003C
|
||||
case reg_addr is
|
||||
|
||||
-- 0x0000
|
||||
when "0000" =>
|
||||
ACK_O <= ready;
|
||||
DAT_O <= (others => '0');
|
||||
DAT_O(31) <= rx_ctrl_out.reset_busy;
|
||||
DAT_O(30) <= rx_ctrl_in.Gbps_en;
|
||||
DAT_O(29) <= rx_ctrl_in.fcs_chk_en;
|
||||
DAT_O(23) <= rx_ctrl_in.promiscious;
|
||||
DAT_O(19) <= rx_ctrl_out.pkt_bcast;
|
||||
DAT_O(18) <= rx_ctrl_out.pkt_mac_match;
|
||||
DAT_O(17) <= rx_ctrl_out.pkt_valid;
|
||||
DAT_O(16) <= rx_ctrl_out.pkt_avail;
|
||||
DAT_O(4) <= rx_int_en;
|
||||
|
||||
-- 0x0004
|
||||
when "0001" =>
|
||||
ACK_O <= '1';
|
||||
DAT_O <= X"0000" & rx_ctrl_out.rx_size;
|
||||
|
||||
-- 0x0008
|
||||
when "0010" =>
|
||||
ACK_O <= ready;
|
||||
DAT_O <= (others => '0');
|
||||
DAT_O(31) <= tx_ctrl_out.reset_busy;
|
||||
DAT_O(30) <= tx_ctrl_in.Gbps_en;
|
||||
DAT_O(29) <= tx_ctrl_in.fcs_gen_en;
|
||||
DAT_O(24) <= tx_ctrl_out.pkt_done;
|
||||
DAT_O(17) <= tx_ctrl_out.pkt_alloc_req;
|
||||
DAT_O(16) <= tx_ctrl_out.pkt_armed;
|
||||
DAT_O(4) <= tx_int_en;
|
||||
|
||||
-- 0x000C
|
||||
when "0011" =>
|
||||
ACK_O <= '1';
|
||||
DAT_O <= X"0000" & tx_ctrl_out.tx_size;
|
||||
|
||||
-- 0x0010
|
||||
-- Gap
|
||||
|
||||
-- 0x0014
|
||||
-- Gap
|
||||
|
||||
-- 0x0018
|
||||
when "0110" =>
|
||||
ACK_O <= '1';
|
||||
DAT_O <= rx_ctrl_in.mac_addr(0) & rx_ctrl_in.mac_addr(1) & rx_ctrl_in.mac_addr(2) & rx_ctrl_in.mac_addr(3);
|
||||
|
||||
-- 0x001C
|
||||
when "0111" =>
|
||||
ACK_O <= '1';
|
||||
DAT_O <= rx_ctrl_in.mac_addr(4) & rx_ctrl_in.mac_addr(5) & X"0000";
|
||||
|
||||
-- 0x0020 .. 0x003C
|
||||
-- Gap
|
||||
when others => null;
|
||||
|
||||
end case;
|
||||
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
irq_register:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
INT_O <= irq_rx or irq_tx;
|
||||
irq_tx <= tx_int_en and tx_ctrl_out.pkt_done;
|
||||
irq_rx <= rx_int_en and rx_ctrl_out.pkt_avail;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
inst_emac_rx : entity work.emac_rx
|
||||
GENERIC MAP
|
||||
(
|
||||
f_sysclk => f_sysclk,
|
||||
RAM_SIZE => RX_RAM_SIZE
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
clk => CLK_I,
|
||||
rst => RST_I,
|
||||
dout_re => rx_dout_re,
|
||||
dout => rx_dout,
|
||||
ctrl_in => rx_ctrl_in,
|
||||
ctrl_out => rx_ctrl_out,
|
||||
mii_rx_clk => mii_rx_clk,
|
||||
mii_rx_dv => mii_rx_dv,
|
||||
mii_rx_er => mii_rx_er,
|
||||
mii_rx => mii_rx,
|
||||
mii_crs => mii_crs,
|
||||
mii_col => mii_col
|
||||
|
||||
);
|
||||
|
||||
|
||||
inst_emac_tx : entity work.emac_tx
|
||||
GENERIC MAP
|
||||
(
|
||||
f_sysclk => f_sysclk,
|
||||
RAM_SIZE => TX_RAM_SIZE
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
clk => CLK_I,
|
||||
rst => RST_I,
|
||||
din_vld => tx_din_vld,
|
||||
din => tx_din,
|
||||
ctrl_in => tx_ctrl_in,
|
||||
ctrl_out => tx_ctrl_out,
|
||||
mii_tx_clk => mii_tx_clk,
|
||||
mii_tx_en => mii_tx_en,
|
||||
mii_tx_er => mii_tx_er,
|
||||
mii_tx => mii_tx
|
||||
|
||||
);
|
||||
|
||||
gen_dmac:
|
||||
for i in 0 to DMA_NUM_CHANNEL-1 generate
|
||||
|
||||
dma_bus_cmd_cycle_finished(i) <= bus_cmd_cycle_finished;
|
||||
dma_bus_cmd_rdy(i) <= bus_cmd_rdy;
|
||||
|
||||
inst_dmac : entity work.dmac
|
||||
Generic map
|
||||
(
|
||||
DATA_WIDTH => 32,
|
||||
XFER_CHUNK_SIZE => 32
|
||||
)
|
||||
Port map
|
||||
(
|
||||
clk => CLK_I,
|
||||
rst => RST_I,
|
||||
|
||||
master_req => dma_master_req(i),
|
||||
master_gnt => dma_master_gnt(i),
|
||||
|
||||
req_rdy => dma_req_rdy(i),
|
||||
req_en => dma_req_en(i),
|
||||
req_rw => DMA_RW_CONF(i),
|
||||
req_addr_auto_inc => dma_req_addr_auto_inc(i),
|
||||
req_addr_start => dma_req_addr(i),
|
||||
req_num_xfers => dma_req_num_xfers(i),
|
||||
|
||||
req_complete => dma_req_complete(i),
|
||||
req_complete_ack => dma_req_complete_ack(i),
|
||||
|
||||
dma_start => dma_start(i),
|
||||
dma_active => dma_active(i),
|
||||
dma_end => dma_end(i),
|
||||
|
||||
-- busmaster control
|
||||
bus_cyc_complete => dma_bus_cmd_cycle_finished(i),
|
||||
bus_cmd_rdy => dma_bus_cmd_rdy(i),
|
||||
bus_cmd_we => dma_bus_cmd_we(i),
|
||||
bus_cmd_cycle_en => dma_bus_cmd_cycle_en(i),
|
||||
|
||||
-- busmaster command
|
||||
bus_cmd_out => dma_bus_cmd(i)
|
||||
);
|
||||
|
||||
end generate;
|
||||
|
||||
inst_busmaster_sync : entity work.busmaster_sync
|
||||
GENERIC MAP
|
||||
(
|
||||
DATA_WIDTH => 32,
|
||||
FIFO_DEPTH => 4
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
-- System signals
|
||||
rst => RST_I,
|
||||
clk => CLK_I,
|
||||
|
||||
cmd_cycle_finished => bus_cmd_cycle_finished,
|
||||
cmd_cycle_en => bus_cmd_cycle_en,
|
||||
|
||||
cmd_rdy => bus_cmd_rdy,
|
||||
cmd_we => bus_cmd_we,
|
||||
cmd_in => bus_cmd,
|
||||
|
||||
din_rdy => bus_din_rdy,
|
||||
din_we => bus_din_vld,
|
||||
din => bus_din,
|
||||
|
||||
dout => bus_dout,
|
||||
dout_vld => bus_dout_vld,
|
||||
dout_re => bus_dout_re,
|
||||
|
||||
-- JBUS Master signals
|
||||
CYC_O => CYC_O,
|
||||
STB_O => STB_O,
|
||||
WE_O => WE_O,
|
||||
SEL_O => SEL_O,
|
||||
ACK_I => ACK_I,
|
||||
SRDY_I => SRDY_I,
|
||||
MRDY_O => MRDY_O,
|
||||
ADDR_O => ADDR_O,
|
||||
MDAT_I => MDAT_I,
|
||||
MDAT_O => MDAT_O
|
||||
);
|
||||
|
||||
arbiter_proc:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if RST_I = '1' then
|
||||
dma_master_gnt <= (others => '0');
|
||||
arb_idx <= 0;
|
||||
elsif dma_master_req(arb_idx) = '0' then
|
||||
if arb_idx /= DMA_NUM_CHANNEL-1 then
|
||||
arb_idx <= arb_idx + 1;
|
||||
else
|
||||
arb_idx <= 0;
|
||||
end if;
|
||||
else
|
||||
dma_master_gnt <= (others => '0');
|
||||
dma_master_gnt(arb_idx) <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
arbiter_mux:
|
||||
process(dma_master_gnt, dma_bus_cmd, dma_bus_cmd_we, dma_bus_cmd_cycle_en)
|
||||
variable v_bus_cmd_we : std_logic;
|
||||
variable v_bus_cmd_cycle_en : std_logic;
|
||||
begin
|
||||
v_bus_cmd_we := '0';
|
||||
v_bus_cmd_cycle_en := '0';
|
||||
for i in 0 to DMA_NUM_CHANNEL-1 loop
|
||||
v_bus_cmd_we := v_bus_cmd_we or dma_bus_cmd_we(i);
|
||||
v_bus_cmd_cycle_en := v_bus_cmd_cycle_en or dma_bus_cmd_cycle_en(i);
|
||||
if dma_master_gnt(i) = '1' then
|
||||
bus_cmd <= dma_bus_cmd(i);
|
||||
end if;
|
||||
end loop;
|
||||
bus_cmd_we <= v_bus_cmd_we;
|
||||
bus_cmd_cycle_en <= v_bus_cmd_cycle_en;
|
||||
end process;
|
||||
|
||||
end behavior;
|
||||
@@ -1,751 +0,0 @@
|
||||
LIBRARY IEEE;
|
||||
USE IEEE.STD_LOGIC_1164.ALL;
|
||||
USE IEEE.NUMERIC_STD.ALL;
|
||||
use std.textio.all; -- Imports the standard textio package.
|
||||
|
||||
use work.emac_types.all;
|
||||
use work.utils_pkg.all;
|
||||
|
||||
ENTITY emac_tx IS
|
||||
Generic
|
||||
(
|
||||
f_sysclk : real := 100.0;
|
||||
RAM_SIZE : natural := 2048
|
||||
);
|
||||
Port
|
||||
(
|
||||
clk : in STD_LOGIC;
|
||||
rst : in STD_LOGIC;
|
||||
din_vld : in STD_LOGIC;
|
||||
din : in unsigned(31 downto 0);
|
||||
ctrl_in : in tx_ctrl_in_t;
|
||||
ctrl_out : out tx_ctrl_out_t;
|
||||
mii_tx_clk : in STD_LOGIC;
|
||||
mii_tx_en : out STD_LOGIC;
|
||||
mii_tx_er : out STD_LOGIC;
|
||||
mii_tx : out unsigned(7 downto 0)
|
||||
|
||||
);
|
||||
END emac_tx;
|
||||
|
||||
ARCHITECTURE behavior OF emac_tx IS
|
||||
|
||||
constant RAM_ADDR_WIDTH : natural := NextExpBaseTwo(RAM_SIZE);
|
||||
|
||||
subtype word_ptr_t is unsigned(RAM_ADDR_WIDTH-1 downto 0);
|
||||
|
||||
signal cmd_fifo_din : unsigned(2*word_ptr_t'length-1 downto 0);
|
||||
signal cmd_fifo_dout : unsigned(2*word_ptr_t'length-1 downto 0);
|
||||
signal cmd_fifo_we : std_logic;
|
||||
signal cmd_fifo_re : std_logic;
|
||||
signal cmd_fifo_empty : std_logic;
|
||||
signal cmd_fifo_full : std_logic;
|
||||
|
||||
signal reset_en : std_logic;
|
||||
|
||||
signal fill_base : word_ptr_t;
|
||||
signal fill_size : word_ptr_t;
|
||||
signal fill_cnt : word_ptr_t;
|
||||
signal fill_ptr : word_ptr_t;
|
||||
signal fill_pre_rdy : std_logic;
|
||||
signal fill_bsy : std_logic;
|
||||
signal fill_remain : unsigned(1 downto 0);
|
||||
signal fill_set : std_logic;
|
||||
signal fill_en : std_logic;
|
||||
signal fill_cnt_en : std_logic;
|
||||
|
||||
signal alloc_OK : std_logic;
|
||||
signal alloc_req : std_logic;
|
||||
signal alloc_ack : std_logic;
|
||||
signal alloc_size : word_ptr_t;
|
||||
signal alloc_remain : unsigned(1 downto 0);
|
||||
|
||||
signal commit_en : std_logic;
|
||||
signal uncommit_en : std_logic;
|
||||
signal mem_alloc_en : std_logic;
|
||||
signal mem_free_en : std_logic;
|
||||
signal nwords_free : word_ptr_t;
|
||||
signal mem_free_req : std_logic;
|
||||
signal mem_free_ack : unsigned(1 downto 0);
|
||||
|
||||
signal xfer_size : word_ptr_t;
|
||||
signal xfer_ptr : word_ptr_t;
|
||||
signal xfer_cnt : word_ptr_t;
|
||||
signal xfer_set : std_logic;
|
||||
signal xfer_en : std_logic;
|
||||
signal xfer_cnt_en : std_logic;
|
||||
signal xfer_bsy : std_logic;
|
||||
signal xfer_free_en : std_logic;
|
||||
|
||||
signal ram_en_a : std_logic;
|
||||
signal ram_we_a : std_logic;
|
||||
signal ram_addr_a : word_ptr_t;
|
||||
signal ram_din_a : unsigned(35 downto 0);
|
||||
signal ram_en_b : std_logic;
|
||||
signal ram_addr_b : word_ptr_t;
|
||||
signal ram_dout_b : unsigned(35 downto 0);
|
||||
|
||||
signal piso32_din : unsigned(31 downto 0);
|
||||
signal piso32_din_be : unsigned(3 downto 0);
|
||||
signal piso32_din_rdy : std_logic;
|
||||
signal piso32_din_vld : std_logic;
|
||||
|
||||
signal piso32_dout : unsigned(7 downto 0);
|
||||
signal piso32_dout_vld : std_logic;
|
||||
signal piso32_dout_en : std_logic;
|
||||
|
||||
signal piso8_dout_vld : std_logic;
|
||||
signal piso8_din_rdy : std_logic;
|
||||
signal piso8_din_vld : std_logic;
|
||||
signal piso8_dout : unsigned(3 downto 0);
|
||||
signal piso8_din : unsigned(7 downto 0);
|
||||
|
||||
signal reset_pipe : unsigned(31 downto 0);
|
||||
signal Gbps_en : std_logic;
|
||||
signal fcs_gen_en : std_logic;
|
||||
|
||||
signal fcs_inject_en : std_logic;
|
||||
signal fcs_rst : std_logic;
|
||||
signal fcs_en : unsigned(7 downto 0);
|
||||
signal fcs_vld : std_logic;
|
||||
signal fcs_din_vld : std_logic;
|
||||
signal fcs : unsigned(31 downto 0);
|
||||
signal fcs_rev_endian : unsigned(31 downto 0);
|
||||
|
||||
signal mii_fifo_we : std_logic;
|
||||
signal mii_fifo_re : std_logic;
|
||||
signal mii_fifo_full : std_logic;
|
||||
signal mii_fifo_empty : std_logic;
|
||||
signal mii_fifo_re_dly : unsigned(23 downto 0);
|
||||
|
||||
signal mii_bsy : std_logic;
|
||||
|
||||
type host_state_t is (host_init, host_idle, host_alloc, host_setup, host_arm, host_fill, host_commit);
|
||||
signal host_s, host_sn : host_state_t;
|
||||
|
||||
type xfer_state_t is (xfer_init, xfer_idle, xfer_start, xfer_preamble0, xfer_preamble1, xfer_active, xfer_crc, xfer_stop, xfer_finish);
|
||||
signal xfer_s, xfer_sn : xfer_state_t;
|
||||
|
||||
type piso_byte_mask_array_t is array (0 to 3) of unsigned (3 downto 0);
|
||||
constant piso_byte_mask_rom : piso_byte_mask_array_t :=
|
||||
(
|
||||
"1111",
|
||||
"1000",
|
||||
"1100",
|
||||
"1110"
|
||||
);
|
||||
|
||||
signal preamble_en : std_logic;
|
||||
signal preamble_addr : natural range 0 to 1;
|
||||
type preamble_t is array (0 to 1) of unsigned(31 downto 0);
|
||||
constant preamble : preamble_t :=
|
||||
(
|
||||
X"55555555",
|
||||
X"555555D5"
|
||||
);
|
||||
|
||||
|
||||
begin
|
||||
|
||||
ctrl_out.pkt_alloc_req <= alloc_req;
|
||||
ctrl_out.pkt_done <= cmd_fifo_empty;
|
||||
ctrl_out.reset_busy <= reset_en;
|
||||
|
||||
ram_en_a <= din_vld;
|
||||
ram_we_a <= fill_bsy;
|
||||
ram_din_a(31 downto 0) <= din;
|
||||
ram_din_a(35 downto 32) <= piso_byte_mask_rom(to_integer(fill_remain)) when fill_pre_rdy = '1' else "1111";
|
||||
ram_addr_a <= fill_ptr;
|
||||
|
||||
piso32_din <= preamble(preamble_addr) when preamble_en = '1' else fcs_rev_endian when fcs_inject_en = '1' else ram_dout_b(31 downto 0);
|
||||
piso32_din_be <= "1111" when (preamble_en = '1' or fcs_inject_en = '1') else ram_dout_b(35 downto 32);
|
||||
|
||||
cmd_fifo_we <= commit_en;
|
||||
cmd_fifo_re <= uncommit_en;
|
||||
cmd_fifo_din <= fill_size & fill_base;
|
||||
ram_en_b <= piso32_din_rdy;
|
||||
ram_addr_b <= xfer_ptr;
|
||||
|
||||
reset_en <= reset_pipe(reset_pipe'left);
|
||||
|
||||
xfer_cnt_en <= xfer_bsy and piso32_din_rdy;
|
||||
fill_cnt_en <= fill_bsy and din_vld;
|
||||
mem_free_en <= not mem_free_ack(0) and mem_free_ack(1);
|
||||
|
||||
fcs_rev_endian <= fcs(7 downto 0) & fcs(15 downto 8) & fcs(23 downto 16) & fcs(31 downto 24);
|
||||
|
||||
------------------------------------------------------------------
|
||||
reset_gen:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' or ctrl_in.reset = '1' then
|
||||
reset_pipe <= (others => '1');
|
||||
else
|
||||
reset_pipe <= reset_pipe(reset_pipe'left-1 downto 0) & '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
host_state_next:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if reset_en = '1' then
|
||||
host_s <= host_init;
|
||||
else
|
||||
host_s <= host_sn;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
host_state:
|
||||
process(host_s, alloc_OK, fill_bsy, ctrl_in.pkt_commit_en, alloc_req, mem_free_ack)
|
||||
begin
|
||||
|
||||
fill_set <= '0';
|
||||
fill_en <= '0';
|
||||
commit_en <= '0';
|
||||
alloc_ack <= '0';
|
||||
mem_alloc_en <= '0';
|
||||
|
||||
host_sn <= host_s;
|
||||
|
||||
case host_s is
|
||||
|
||||
when host_init =>
|
||||
host_sn <= host_idle;
|
||||
|
||||
when host_idle =>
|
||||
if alloc_req = '1' then
|
||||
host_sn <= host_alloc;
|
||||
end if;
|
||||
|
||||
when host_alloc =>
|
||||
if alloc_OK = '1' then
|
||||
host_sn <= host_setup;
|
||||
else
|
||||
host_sn <= host_idle;
|
||||
alloc_ack <= '1';
|
||||
end if;
|
||||
|
||||
when host_setup =>
|
||||
fill_set <= '1';
|
||||
host_sn <= host_arm;
|
||||
|
||||
when host_arm =>
|
||||
fill_en <= '1';
|
||||
alloc_ack <= '1';
|
||||
host_sn <= host_fill;
|
||||
|
||||
when host_fill =>
|
||||
fill_en <= '1';
|
||||
if alloc_req = '1' then
|
||||
host_sn <= host_alloc;
|
||||
elsif ctrl_in.pkt_commit_en = '1' then
|
||||
host_sn <= host_commit;
|
||||
end if;
|
||||
|
||||
when host_commit =>
|
||||
if mem_free_ack = "00" then
|
||||
commit_en <= '1';
|
||||
mem_alloc_en <= '1';
|
||||
host_sn <= host_idle;
|
||||
end if;
|
||||
|
||||
when others =>
|
||||
host_sn <= host_idle;
|
||||
end case;
|
||||
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
-- Allocation stuff
|
||||
------------------------------------------------------------------
|
||||
alloc_request_logic:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if reset_en = '1' then
|
||||
alloc_req <= '0';
|
||||
elsif ctrl_in.pkt_alloc_en = '1' and alloc_req = '0' then
|
||||
alloc_req <= '1';
|
||||
alloc_remain <= ctrl_in.tx_size(1 downto 0);
|
||||
alloc_size <= ctrl_in.tx_size(word_ptr_t'left+2 downto 2);
|
||||
if ctrl_in.tx_size(1 downto 0) /= "00" then
|
||||
alloc_size <= ctrl_in.tx_size(word_ptr_t'left+2 downto 2) + 1;
|
||||
end if;
|
||||
ctrl_out.tx_size <= resize(ctrl_in.tx_size(word_ptr_t'left downto 0), 16);
|
||||
elsif alloc_ack = '1' then
|
||||
alloc_req <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
host_alloc_armed_register:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if reset_en = '1' or commit_en = '1' then
|
||||
ctrl_out.pkt_armed <= '0';
|
||||
elsif alloc_ack = '1' then
|
||||
ctrl_out.pkt_armed <= alloc_OK;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
alloc_eval_logic:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
alloc_OK <= '0';
|
||||
if alloc_size < nwords_free then
|
||||
alloc_OK <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
fill_base_logic:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if reset_en = '1' then
|
||||
fill_base <= (others => '0');
|
||||
elsif commit_en = '1' then
|
||||
fill_base <= fill_ptr;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
mem_free_counter:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if reset_en = '1' then
|
||||
nwords_free <= (others => '1');
|
||||
elsif mem_alloc_en = '1' then
|
||||
nwords_free <= nwords_free - fill_size;
|
||||
elsif mem_free_en = '1' then
|
||||
nwords_free <= nwords_free + xfer_size;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
mem_free_mii:
|
||||
process(mii_tx_clk)
|
||||
begin
|
||||
if rising_edge(mii_tx_clk) then
|
||||
if reset_en = '1' then
|
||||
mem_free_req <= '0';
|
||||
elsif mem_free_ack(0) = '0' then
|
||||
if xfer_free_en = '1' then
|
||||
mem_free_req <= '1';
|
||||
end if;
|
||||
else
|
||||
mem_free_req <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
mem_free_host:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
mem_free_ack(1) <= mem_free_ack(0);
|
||||
if reset_en = '1' then
|
||||
mem_free_ack <= "00";
|
||||
elsif mem_free_req = '1' then
|
||||
if mem_alloc_en = '0' then
|
||||
mem_free_ack(0) <= '1';
|
||||
end if;
|
||||
else
|
||||
mem_free_ack(0) <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
-- Fill stuff
|
||||
------------------------------------------------------------------
|
||||
fill_counter:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if fill_set = '1' then
|
||||
fill_bsy <= '0';
|
||||
fill_pre_rdy <= '0';
|
||||
fill_cnt <= alloc_size;
|
||||
fill_size <= alloc_size;
|
||||
fill_remain <= alloc_remain;
|
||||
elsif fill_en = '1' then
|
||||
fill_bsy <= '1';
|
||||
if fill_cnt_en = '1' or fill_bsy = '0' then
|
||||
if fill_cnt /= 1 then
|
||||
fill_cnt <= fill_cnt - 1;
|
||||
else
|
||||
fill_pre_rdy <= '1';
|
||||
end if;
|
||||
if fill_pre_rdy = '1' then
|
||||
fill_bsy <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
fill_pointer:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if fill_set = '1' then
|
||||
fill_ptr <= fill_base;
|
||||
elsif fill_cnt_en = '1' then
|
||||
fill_ptr <= fill_ptr + 1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
-- Transfer stuff
|
||||
------------------------------------------------------------------
|
||||
host2xfer_sync_register:
|
||||
process(mii_tx_clk)
|
||||
begin
|
||||
if rising_edge(mii_tx_clk) then
|
||||
Gbps_en <= ctrl_in.Gbps_en;
|
||||
fcs_gen_en <= ctrl_in.fcs_gen_en;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
xfer_counter:
|
||||
process(mii_tx_clk)
|
||||
begin
|
||||
if rising_edge(mii_tx_clk) then
|
||||
xfer_bsy <= '0';
|
||||
if xfer_set = '1' then
|
||||
xfer_cnt <= cmd_fifo_dout(cmd_fifo_dout'left downto word_ptr_t'length);
|
||||
xfer_size <= (others => '0');
|
||||
elsif xfer_en = '1' then
|
||||
xfer_bsy <= '1';
|
||||
if xfer_cnt_en = '1' or xfer_bsy = '0' then
|
||||
if xfer_cnt /= 0 then
|
||||
xfer_cnt <= xfer_cnt - 1;
|
||||
xfer_size <= xfer_size + 1;
|
||||
else
|
||||
xfer_bsy <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
xfer_pointer:
|
||||
process(mii_tx_clk)
|
||||
begin
|
||||
if rising_edge(mii_tx_clk) then
|
||||
if xfer_set = '1' then
|
||||
xfer_ptr <= cmd_fifo_dout(xfer_ptr'left downto 0);
|
||||
elsif xfer_en = '1' then
|
||||
if xfer_bsy = '0' or xfer_cnt_en = '1' then
|
||||
xfer_ptr <= xfer_ptr + 1;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
xfer_state_next:
|
||||
process(mii_tx_clk)
|
||||
begin
|
||||
if rising_edge(mii_tx_clk) then
|
||||
if reset_en = '1' then
|
||||
xfer_s <= xfer_init;
|
||||
else
|
||||
xfer_s <= xfer_sn;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
xfer_state:
|
||||
process(xfer_s, mii_bsy, cmd_fifo_empty, piso32_din_rdy, piso32_dout_vld, xfer_bsy, fcs_gen_en)
|
||||
begin
|
||||
|
||||
piso32_din_vld <= '0';
|
||||
preamble_en <= '0';
|
||||
preamble_addr <= 0;
|
||||
xfer_set <= '0';
|
||||
xfer_en <= '0';
|
||||
xfer_free_en <= '0';
|
||||
fcs_rst <= '0';
|
||||
fcs_inject_en <= '0';
|
||||
uncommit_en <= '0';
|
||||
|
||||
xfer_sn <= xfer_s;
|
||||
|
||||
case xfer_s is
|
||||
|
||||
when xfer_init =>
|
||||
xfer_sn <= xfer_idle;
|
||||
|
||||
when xfer_idle =>
|
||||
if cmd_fifo_empty = '0' and mii_bsy = '0' then
|
||||
xfer_sn <= xfer_start;
|
||||
end if;
|
||||
|
||||
when xfer_start =>
|
||||
if cmd_fifo_empty = '0' then
|
||||
xfer_sn <= xfer_preamble0;
|
||||
end if;
|
||||
|
||||
when xfer_preamble0 =>
|
||||
xfer_set <= '1';
|
||||
fcs_rst <= '1';
|
||||
preamble_addr <= 0;
|
||||
preamble_en <= '1';
|
||||
piso32_din_vld <= '1';
|
||||
if piso32_din_rdy = '1' then
|
||||
xfer_sn <= xfer_preamble1;
|
||||
end if;
|
||||
|
||||
when xfer_preamble1 =>
|
||||
preamble_addr <= 1;
|
||||
preamble_en <= '1';
|
||||
piso32_din_vld <= '1';
|
||||
if piso32_din_rdy = '1' then
|
||||
xfer_sn <= xfer_active;
|
||||
xfer_en <= '1';
|
||||
end if;
|
||||
|
||||
when xfer_active =>
|
||||
piso32_din_vld <= xfer_bsy;
|
||||
xfer_en <= '1';
|
||||
if xfer_bsy = '0' then
|
||||
xfer_sn <= xfer_stop;
|
||||
end if;
|
||||
|
||||
when xfer_stop =>
|
||||
if piso32_dout_vld = '0' then
|
||||
xfer_sn <= xfer_finish;
|
||||
if fcs_gen_en = '1' then
|
||||
xfer_sn <= xfer_crc;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
when xfer_crc =>
|
||||
fcs_inject_en <= piso32_din_rdy;
|
||||
piso32_din_vld <= '1';
|
||||
if piso32_din_rdy = '1' then
|
||||
xfer_sn <= xfer_finish;
|
||||
end if;
|
||||
|
||||
when xfer_finish =>
|
||||
uncommit_en <= '1';
|
||||
xfer_free_en <= '1';
|
||||
xfer_sn <= xfer_idle;
|
||||
|
||||
when others =>
|
||||
xfer_sn <= xfer_idle;
|
||||
end case;
|
||||
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
inst_ram : entity work.dpram_1w1r2c_ro
|
||||
GENERIC MAP
|
||||
(
|
||||
addr_width => RAM_ADDR_WIDTH,
|
||||
data_width => ram_din_a'length
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
clk_a => clk,
|
||||
clk_b => mii_tx_clk,
|
||||
en_a => ram_en_a,
|
||||
en_b => ram_en_b,
|
||||
we_a => ram_we_a,
|
||||
addr_a => ram_addr_a,
|
||||
addr_b => ram_addr_b,
|
||||
din_a => ram_din_a,
|
||||
dout_b => ram_dout_b
|
||||
);
|
||||
|
||||
------------------------------------------------------------------
|
||||
-- Instantiate synchronous FIFO
|
||||
inst_cmd_fifo: entity work.fifo_async
|
||||
GENERIC MAP
|
||||
(
|
||||
addr_width => NextExpBaseTwo(RAM_SIZE) - 4, -- RAMSIZE(words)/MIN_PACKET_LEN(words)
|
||||
data_width => cmd_fifo_din'length,
|
||||
do_last_read_update => true
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
rst => reset_en,
|
||||
clk_w => clk,
|
||||
clk_r => mii_tx_clk,
|
||||
we => cmd_fifo_we,
|
||||
re => cmd_fifo_re,
|
||||
fifo_full => cmd_fifo_full,
|
||||
fifo_empty => cmd_fifo_empty,
|
||||
fifo_afull => open,
|
||||
fifo_aempty => open,
|
||||
data_w => cmd_fifo_din,
|
||||
data_r => cmd_fifo_dout
|
||||
);
|
||||
|
||||
------------------------------------------------------------------
|
||||
inst_piso32 : entity work.piso
|
||||
GENERIC MAP
|
||||
(
|
||||
data_width_in => 32,
|
||||
data_width_out => 8,
|
||||
msb_first => true
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
rst => reset_en,
|
||||
clk => mii_tx_clk,
|
||||
din_vld => piso32_din_vld,
|
||||
din_rdy => piso32_din_rdy,
|
||||
din_be => piso32_din_be,
|
||||
din => piso32_din,
|
||||
dout_vld => piso32_dout_vld,
|
||||
dout_en => piso32_dout_en,
|
||||
dout => piso32_dout
|
||||
|
||||
);
|
||||
|
||||
piso32_dout_en <= not mii_fifo_full; --'1' when Gbps_en = '1' else piso8_din_rdy;
|
||||
|
||||
------------------------------------------------------------------
|
||||
fcs_enable_gen:
|
||||
process(mii_tx_clk)
|
||||
begin
|
||||
if rising_edge(mii_tx_clk) then
|
||||
if fcs_rst = '1' then
|
||||
fcs_en <= (others => '0');
|
||||
elsif piso32_dout_vld = '1' then
|
||||
fcs_en <= fcs_en(fcs_en'left-1 downto 0) & '1';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
inst_fcs: entity work.crc32
|
||||
GENERIC MAP
|
||||
(
|
||||
crc32_init => X"00000000"
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
rst => fcs_rst,
|
||||
clk => mii_tx_clk,
|
||||
din_vld => fcs_din_vld,
|
||||
din => piso32_dout,
|
||||
crc32_vld => fcs_vld,
|
||||
crc32_out => fcs
|
||||
|
||||
);
|
||||
|
||||
fcs_din_vld <= fcs_en(fcs_en'left) and piso32_dout_vld and piso32_dout_en;
|
||||
|
||||
------------------------------------------------------------------
|
||||
-- ensures continous MII-data stream and also acts as Inter Frame Gap delay
|
||||
mii_fifo_re_dly_gen:
|
||||
process(mii_tx_clk)
|
||||
begin
|
||||
if rising_edge(mii_tx_clk) then
|
||||
if mii_fifo_empty = '1' then
|
||||
if Gbps_en = '0' then
|
||||
mii_fifo_re_dly <= X"000000"; -- 100 mbps
|
||||
else
|
||||
mii_fifo_re_dly <= X"000FFF"; -- Gigabit
|
||||
end if;
|
||||
else
|
||||
mii_fifo_re_dly <= mii_fifo_re_dly(mii_fifo_re_dly'left-1 downto 0) & not mii_fifo_empty;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
mii_bsy <= mii_fifo_re_dly(mii_fifo_re_dly'left);
|
||||
|
||||
------------------------------------------------------------------
|
||||
-- Instantiate synchronous FIFO
|
||||
inst_mii_fifo: entity work.fifo_sync
|
||||
GENERIC MAP
|
||||
(
|
||||
addr_width => 4,
|
||||
data_width => piso32_dout'length,
|
||||
do_last_read_update => true
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
rst => reset_en,
|
||||
clk => mii_tx_clk,
|
||||
we => mii_fifo_we,
|
||||
re => mii_fifo_re,
|
||||
fifo_full => mii_fifo_full,
|
||||
fifo_empty => mii_fifo_empty,
|
||||
fifo_afull => open,
|
||||
fifo_aempty => open,
|
||||
data_w => piso32_dout,
|
||||
data_r => piso8_din
|
||||
);
|
||||
|
||||
mii_fifo_re <= mii_bsy when Gbps_en = '1' else (piso8_din_rdy and mii_bsy);
|
||||
mii_fifo_we <= piso32_dout_vld;
|
||||
|
||||
------------------------------------------------------------------
|
||||
inst_piso8 : entity work.piso
|
||||
GENERIC MAP
|
||||
(
|
||||
data_width_in => 8,
|
||||
data_width_out => 4,
|
||||
msb_first => false
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
rst => reset_en,
|
||||
clk => mii_tx_clk,
|
||||
din_vld => piso8_din_vld,
|
||||
din_rdy => piso8_din_rdy,
|
||||
din_be => "11",
|
||||
din => piso8_din,
|
||||
dout_vld => piso8_dout_vld,
|
||||
dout_en => '1',
|
||||
dout => piso8_dout
|
||||
|
||||
);
|
||||
|
||||
piso8_din_vld <= not mii_fifo_empty and mii_bsy;
|
||||
|
||||
------------------------------------------------------------------
|
||||
mii_output_register:
|
||||
process(mii_tx_clk)
|
||||
begin
|
||||
if rising_edge(mii_tx_clk) then
|
||||
mii_tx_er <= '0';
|
||||
if Gbps_en = '1' then
|
||||
mii_tx_en <= piso8_din_vld;
|
||||
mii_tx <= piso8_din;
|
||||
else
|
||||
mii_tx_en <= piso8_dout_vld;
|
||||
mii_tx <= "0000" & piso8_dout;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
end behavior;
|
||||
@@ -1,63 +0,0 @@
|
||||
-- Package File Template
|
||||
--
|
||||
-- Purpose: This package defines supplemental types, subtypes,
|
||||
-- constants, and functions
|
||||
|
||||
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.NUMERIC_STD.ALL;
|
||||
use IEEE.MATH_REAL.ALL;
|
||||
|
||||
package emac_types is
|
||||
|
||||
-- Constants
|
||||
type mac_addr_t is array (0 to 5) of unsigned (7 downto 0);
|
||||
|
||||
-- Types
|
||||
type tx_ctrl_in_t is record
|
||||
Gbps_en : std_logic;
|
||||
reset : std_logic;
|
||||
fcs_gen_en : std_logic;
|
||||
tx_size : unsigned(15 downto 0);
|
||||
pkt_commit_en : std_logic;
|
||||
pkt_alloc_en : std_logic;
|
||||
end record;
|
||||
|
||||
type tx_ctrl_out_t is record
|
||||
tx_size : unsigned(15 downto 0);
|
||||
pkt_done : std_logic;
|
||||
pkt_alloc_req : std_logic;
|
||||
pkt_armed : std_logic;
|
||||
reset_busy : std_logic;
|
||||
end record;
|
||||
|
||||
type rx_ctrl_in_t is record
|
||||
Gbps_en : std_logic;
|
||||
reset : std_logic;
|
||||
fcs_chk_en : std_logic;
|
||||
pkt_req_en : std_logic;
|
||||
pkt_free_en : std_logic;
|
||||
mac_addr : mac_addr_t;
|
||||
promiscious : std_logic;
|
||||
end record;
|
||||
|
||||
type rx_ctrl_out_t is record
|
||||
pkt_avail : std_logic;
|
||||
pkt_valid : std_logic;
|
||||
pkt_bcast : std_logic;
|
||||
pkt_mac_match : std_logic;
|
||||
rx_size : unsigned(15 downto 0);
|
||||
reset_busy : std_logic;
|
||||
end record;
|
||||
|
||||
-- Functions
|
||||
|
||||
end emac_types;
|
||||
|
||||
|
||||
package body emac_types is
|
||||
|
||||
end emac_types;
|
||||
|
||||
|
||||
@@ -1,124 +0,0 @@
|
||||
LIBRARY IEEE;
|
||||
USE IEEE.STD_LOGIC_1164.ALL;
|
||||
USE IEEE.NUMERIC_STD.ALL;
|
||||
use std.textio.all; -- Imports the standard textio package.
|
||||
|
||||
use work.utils_pkg.all; -- Imports the standard textio package.
|
||||
|
||||
ENTITY piso IS
|
||||
Generic
|
||||
(
|
||||
data_width_in : natural := 32;
|
||||
data_width_out : natural := 8;
|
||||
msb_first : boolean := false
|
||||
);
|
||||
Port
|
||||
(
|
||||
rst : in STD_LOGIC;
|
||||
clk : in STD_LOGIC;
|
||||
din_vld : in STD_LOGIC;
|
||||
din_rdy : out STD_LOGIC;
|
||||
din_be : in unsigned(data_width_in/data_width_out-1 downto 0);
|
||||
din : in unsigned(data_width_in-1 downto 0);
|
||||
dout_vld : out STD_LOGIC;
|
||||
dout_en : in STD_LOGIC;
|
||||
dout : out unsigned(data_width_out-1 downto 0)
|
||||
|
||||
);
|
||||
END piso;
|
||||
|
||||
ARCHITECTURE behavior OF piso IS
|
||||
|
||||
constant num_shifts : natural := data_width_in/data_width_out;
|
||||
signal pre_fin : STD_LOGIC;
|
||||
signal shift_cnt_pipe : unsigned(num_shifts-1 downto 0);
|
||||
signal shift_pipe : unsigned(data_width_in-1 downto 0);
|
||||
signal vld_pipe : unsigned(num_shifts-1 downto 0);
|
||||
signal din_reg : unsigned(data_width_in-1 downto 0);
|
||||
signal din_be_reg : unsigned(num_shifts-1 downto 0);
|
||||
signal din_reg_empty : STD_LOGIC;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
begin
|
||||
|
||||
pre_fin <= shift_cnt_pipe(shift_cnt_pipe'left-1);
|
||||
din_rdy <= din_reg_empty;
|
||||
dout_vld <= vld_pipe(vld_pipe'left) when msb_first else vld_pipe(0);
|
||||
dout <= shift_pipe(shift_pipe'left downto shift_pipe'left-data_width_out+1) when msb_first
|
||||
else shift_pipe(data_width_out-1 downto 0);
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
din_reg_empty <= '1';
|
||||
elsif din_reg_empty = '1' then
|
||||
if din_vld = '1' then
|
||||
din_reg_empty <= '0';
|
||||
end if;
|
||||
elsif pre_fin = '1' and dout_en = '1' then
|
||||
din_reg_empty <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if din_vld = '1' and din_reg_empty = '1' then
|
||||
din_reg <= din;
|
||||
din_be_reg <= din_be;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
shift_cnt_pipe <= (others => '1');
|
||||
elsif (pre_fin = '1' and dout_en = '1' and din_reg_empty = '0') then
|
||||
shift_cnt_pipe <= (others => '0');
|
||||
elsif dout_en = '1' then
|
||||
shift_cnt_pipe <= shift_cnt_pipe(shift_cnt_pipe'left-1 downto 0) & '1';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if (pre_fin = '1' and dout_en = '1' and din_reg_empty = '0') then
|
||||
shift_pipe <= din_reg;
|
||||
elsif dout_en = '1' then
|
||||
if (msb_first) then
|
||||
shift_pipe <= shift_pipe(shift_pipe'left-data_width_out downto 0) & (data_width_out-1 downto 0 => '0');
|
||||
else
|
||||
shift_pipe <= (data_width_out-1 downto 0 => '0') & shift_pipe(shift_pipe'left downto data_width_out);
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
vld_pipe <= (others => '0');
|
||||
elsif (pre_fin = '1' and dout_en = '1' and din_reg_empty = '0') then
|
||||
vld_pipe <= din_be_reg;
|
||||
elsif dout_en = '1' then
|
||||
if (msb_first) then
|
||||
vld_pipe <= vld_pipe(vld_pipe'left-1 downto 0) & '0';
|
||||
else
|
||||
vld_pipe <= '0' & vld_pipe(vld_pipe'left downto 1);
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
end behavior;
|
||||
@@ -1,230 +0,0 @@
|
||||
LIBRARY IEEE;
|
||||
USE IEEE.STD_LOGIC_1164.ALL;
|
||||
USE IEEE.NUMERIC_STD.ALL;
|
||||
USE IEEE.MATH_REAL.ALL;
|
||||
use std.textio.all; -- Imports the standard textio package.
|
||||
|
||||
use work.emac_types.all;
|
||||
use work.utils_pkg.all;
|
||||
|
||||
ENTITY pkt_gen IS
|
||||
Generic
|
||||
(
|
||||
f_sysclk : real := 100.0;
|
||||
TX_RAM_SIZE : natural := 2048;
|
||||
PKT_SIZE_MIN : natural := 64;
|
||||
PKT_SIZE_MAX : natural := 1518
|
||||
|
||||
);
|
||||
Port
|
||||
(
|
||||
clk : in STD_LOGIC;
|
||||
rst : in STD_LOGIC;
|
||||
en : in STD_LOGIC;
|
||||
gigabit_en : in STD_LOGIC;
|
||||
fcs_gen_en : in STD_LOGIC;
|
||||
mii_tx_clk : in STD_LOGIC;
|
||||
mii_tx_en : out STD_LOGIC;
|
||||
mii_tx_er : out STD_LOGIC;
|
||||
mii_tx : out unsigned(7 downto 0)
|
||||
|
||||
);
|
||||
END pkt_gen;
|
||||
|
||||
ARCHITECTURE behavior OF pkt_gen IS
|
||||
|
||||
subtype word_ptr_t is unsigned(15 downto 0);
|
||||
|
||||
signal pkt_data : unsigned(31 downto 0);
|
||||
signal pkt_nbytes : word_ptr_t := X"0040";
|
||||
signal pkt_nwords : word_ptr_t := X"0010";
|
||||
|
||||
signal fill_size : word_ptr_t;
|
||||
signal fill_cnt : word_ptr_t;
|
||||
signal fill_rdy : std_logic;
|
||||
signal fill_set : std_logic;
|
||||
signal fill_en : std_logic;
|
||||
|
||||
signal tx_packets : natural;
|
||||
signal tx_bytes : natural;
|
||||
|
||||
signal tx_ctrl_in : tx_ctrl_in_t;
|
||||
signal tx_ctrl_out : tx_ctrl_out_t;
|
||||
signal tx_din : unsigned(31 downto 0);
|
||||
signal tx_din_vld : std_logic;
|
||||
|
||||
type host_state_t is (host_init, host_idle, host_alloc, host_setup, host_arm, host_fill, host_commit);
|
||||
signal host_s, host_sn : host_state_t;
|
||||
|
||||
begin
|
||||
|
||||
------------------------------------------------------------------
|
||||
host_state_next:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
host_s <= host_init;
|
||||
else
|
||||
host_s <= host_sn;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
host_state:
|
||||
process(host_s, tx_ctrl_out, pkt_nbytes, fill_rdy, en, gigabit_en, fcs_gen_en)
|
||||
begin
|
||||
|
||||
tx_ctrl_in.pkt_alloc_en <= '0';
|
||||
tx_ctrl_in.pkt_commit_en <= '0';
|
||||
tx_ctrl_in.reset <= '0';
|
||||
tx_ctrl_in.Gbps_en <= gigabit_en;
|
||||
tx_ctrl_in.fcs_gen_en <= fcs_gen_en;
|
||||
tx_ctrl_in.tx_size <= pkt_nbytes;
|
||||
fill_set <= '0';
|
||||
fill_en <= '0';
|
||||
|
||||
host_sn <= host_s;
|
||||
|
||||
case host_s is
|
||||
|
||||
when host_init =>
|
||||
if tx_ctrl_out.reset_busy = '0' then
|
||||
host_sn <= host_idle;
|
||||
end if;
|
||||
|
||||
when host_idle =>
|
||||
if tx_ctrl_out.pkt_alloc_req = '0' and en = '1' then
|
||||
tx_ctrl_in.pkt_alloc_en <= '1';
|
||||
host_sn <= host_alloc;
|
||||
end if;
|
||||
|
||||
when host_alloc =>
|
||||
if tx_ctrl_out.pkt_alloc_req = '0' then
|
||||
if tx_ctrl_out.pkt_armed = '1' then
|
||||
host_sn <= host_setup;
|
||||
else
|
||||
host_sn <= host_idle;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
when host_setup =>
|
||||
fill_set <= '1';
|
||||
host_sn <= host_fill;
|
||||
|
||||
when host_fill =>
|
||||
fill_en <= '1';
|
||||
if fill_rdy = '1' then
|
||||
host_sn <= host_commit;
|
||||
end if;
|
||||
|
||||
when host_commit =>
|
||||
tx_ctrl_in.pkt_commit_en <= '1';
|
||||
host_sn <= host_idle;
|
||||
|
||||
when others =>
|
||||
host_sn <= host_idle;
|
||||
end case;
|
||||
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
pkt_generator:
|
||||
process(clk)
|
||||
variable size : word_ptr_t;
|
||||
variable krand : real;
|
||||
variable seed1 : integer;
|
||||
variable seed2 : integer;
|
||||
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
size := to_unsigned(PKT_SIZE_MIN, word_ptr_t'length);
|
||||
seed1 := 31101970;
|
||||
seed2 := 12586901;
|
||||
tx_packets <= 0;
|
||||
tx_bytes <= 0;
|
||||
elsif tx_ctrl_in.pkt_commit_en = '1' then
|
||||
uniform(seed1, seed2, krand);
|
||||
size := to_unsigned(PKT_SIZE_MIN + natural(real(PKT_SIZE_MAX-PKT_SIZE_MIN)*krand), word_ptr_t'length);
|
||||
tx_packets <= tx_packets + 1;
|
||||
tx_bytes <= tx_bytes + to_integer(pkt_nbytes);
|
||||
end if;
|
||||
pkt_nbytes <= size;
|
||||
if size(1 downto 0) = 0 then
|
||||
pkt_nwords <= "00" & size(word_ptr_t'left downto 2);
|
||||
else
|
||||
pkt_nwords <= "00" & size(word_ptr_t'left downto 2) + 1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
pkt_data_gen:
|
||||
process(clk)
|
||||
variable data : unsigned(7 downto 0);
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
tx_din_vld <= fill_en;
|
||||
if fill_set = '1' then
|
||||
data := X"00";
|
||||
tx_din <= X"03020100";
|
||||
elsif fill_en = '1' then
|
||||
tx_din(7 downto 0) <= data;
|
||||
data := data + 1;
|
||||
tx_din(15 downto 8) <= data;
|
||||
data := data + 1;
|
||||
tx_din(23 downto 16) <= data;
|
||||
data := data + 1;
|
||||
tx_din(31 downto 24) <= data;
|
||||
data := data + 1;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
pkt_data_counter:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if fill_set = '1' then
|
||||
fill_size <= (others => '0');
|
||||
fill_rdy <= '0';
|
||||
fill_cnt <= pkt_nwords;
|
||||
elsif fill_en = '1' then
|
||||
if fill_cnt /= 0 then
|
||||
fill_cnt <= fill_cnt - 1;
|
||||
fill_size <= fill_size + 1;
|
||||
else
|
||||
fill_rdy <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
inst_emac_tx : entity work.emac_tx
|
||||
GENERIC MAP
|
||||
(
|
||||
f_sysclk => f_sysclk,
|
||||
RAM_SIZE => TX_RAM_SIZE
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
clk => clk,
|
||||
rst => rst,
|
||||
din_vld => tx_din_vld,
|
||||
din => tx_din,
|
||||
ctrl_in => tx_ctrl_in,
|
||||
ctrl_out => tx_ctrl_out,
|
||||
mii_tx_clk => mii_tx_clk,
|
||||
mii_tx_en => mii_tx_en,
|
||||
mii_tx_er => mii_tx_er,
|
||||
mii_tx => mii_tx
|
||||
|
||||
);
|
||||
|
||||
|
||||
end behavior;
|
||||
@@ -1,111 +0,0 @@
|
||||
LIBRARY IEEE;
|
||||
USE IEEE.STD_LOGIC_1164.ALL;
|
||||
USE IEEE.NUMERIC_STD.ALL;
|
||||
use std.textio.all; -- Imports the standard textio package.
|
||||
|
||||
use work.utils_pkg.all; -- Imports the standard textio package.
|
||||
|
||||
ENTITY shifter IS
|
||||
Generic
|
||||
(
|
||||
data_width : natural := 32;
|
||||
aggregate_size : natural := 8;
|
||||
do_pipelined : boolean := true
|
||||
);
|
||||
Port
|
||||
(
|
||||
rst : in STD_LOGIC;
|
||||
clk : in STD_LOGIC;
|
||||
sa : in integer;
|
||||
din_vld : in STD_LOGIC;
|
||||
din : in unsigned(data_width-1 downto 0);
|
||||
dout_vld : out STD_LOGIC;
|
||||
dout : out unsigned(data_width-1 downto 0)
|
||||
|
||||
);
|
||||
END shifter;
|
||||
|
||||
ARCHITECTURE behavior OF shifter IS
|
||||
|
||||
constant num_rounds : natural := NextExpBaseTwo(data_width/aggregate_size);
|
||||
subtype sa_rnd_t is signed(num_rounds-1 downto 0);
|
||||
subtype word_t is unsigned(data_width-1 downto 0);
|
||||
type word_array_t is array (0 to num_rounds) of word_t;
|
||||
|
||||
signal rot_data : word_array_t;
|
||||
signal sa_rnd : sa_rnd_t;
|
||||
|
||||
type sa_rnd_array_t is array (0 to num_rounds) of sa_rnd_t;
|
||||
signal sa_rnd_pipe : sa_rnd_array_t;
|
||||
signal dout_vld_pipe : unsigned(0 to num_rounds);
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
function rol_stage(x : unsigned; en : std_logic; stage_num : natural; size : natural) return unsigned is
|
||||
variable result : unsigned(x'range);
|
||||
constant sa : natural := (2**stage_num) * size;
|
||||
begin
|
||||
if en = '1' then
|
||||
result := x(x'left-sa downto 0) & x(x'left downto x'length-sa);
|
||||
else
|
||||
result := x;
|
||||
end if;
|
||||
return result;
|
||||
end rol_stage;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
begin
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
gen_non_pipelined:
|
||||
if do_pipelined = false generate
|
||||
begin
|
||||
|
||||
rot_data(0) <= din;
|
||||
|
||||
gen_rotate_right:
|
||||
for stage in 0 to num_rounds-1 generate
|
||||
begin
|
||||
rot_data(stage+1) <= rol_stage(rot_data(stage), sa_rnd(stage), stage, aggregate_size);
|
||||
end generate;
|
||||
|
||||
sa_rnd <= to_signed(sa, num_rounds);
|
||||
dout <= rot_data(num_rounds);
|
||||
dout_vld <= din_vld;
|
||||
|
||||
end generate;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
gen_pipelined:
|
||||
if do_pipelined = true generate
|
||||
begin
|
||||
|
||||
rot_data(0) <= din;
|
||||
sa_rnd_pipe(0) <= to_signed(sa, num_rounds);
|
||||
dout_vld_pipe(0) <= din_vld;
|
||||
|
||||
gen_rotate_right:
|
||||
for stage in 0 to num_rounds-1 generate
|
||||
begin
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
dout_vld_pipe(stage+1) <= '0';
|
||||
else
|
||||
dout_vld_pipe(stage+1) <= dout_vld_pipe(stage);
|
||||
if dout_vld_pipe(stage) = '1' then
|
||||
sa_rnd_pipe(stage+1) <= sa_rnd_pipe(stage);
|
||||
rot_data(stage+1) <= rol_stage(rot_data(stage), sa_rnd_pipe(stage)(stage), stage, aggregate_size);
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
end generate;
|
||||
|
||||
dout <= rot_data(num_rounds);
|
||||
dout_vld <= dout_vld_pipe(num_rounds);
|
||||
|
||||
end generate;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
end behavior;
|
||||
@@ -1,118 +0,0 @@
|
||||
LIBRARY IEEE;
|
||||
USE IEEE.STD_LOGIC_1164.ALL;
|
||||
USE IEEE.NUMERIC_STD.ALL;
|
||||
use std.textio.all; -- Imports the standard textio package.
|
||||
|
||||
use work.utils_pkg.all; -- Imports the standard textio package.
|
||||
|
||||
ENTITY sipo IS
|
||||
Generic
|
||||
(
|
||||
data_width_in : natural := 8;
|
||||
data_width_out : natural := 32;
|
||||
msb_first : boolean := false
|
||||
);
|
||||
Port
|
||||
(
|
||||
rst : in STD_LOGIC;
|
||||
clk : in STD_LOGIC;
|
||||
din_en : in STD_LOGIC;
|
||||
din_vld : in STD_LOGIC;
|
||||
din : in unsigned(data_width_in-1 downto 0);
|
||||
dout_en : out STD_LOGIC;
|
||||
dout_vld : out STD_LOGIC;
|
||||
dout : out unsigned(data_width_out-1 downto 0);
|
||||
dout_be : out unsigned(data_width_out/data_width_in-1 downto 0)
|
||||
|
||||
);
|
||||
END sipo;
|
||||
|
||||
ARCHITECTURE behavior OF sipo IS
|
||||
|
||||
constant num_shifts : natural := data_width_out/data_width_in;
|
||||
signal pre_fin : STD_LOGIC;
|
||||
signal shift_cnt_pipe : unsigned(num_shifts-1 downto 0);
|
||||
signal shift_pipe : unsigned(data_width_out-1 downto 0);
|
||||
signal out_en : STD_LOGIC;
|
||||
signal out_vld : STD_LOGIC;
|
||||
signal din_vld_r : STD_LOGIC;
|
||||
signal abort : STD_LOGIC;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
begin
|
||||
|
||||
pre_fin <= shift_cnt_pipe(shift_cnt_pipe'left) when msb_first else shift_cnt_pipe(0);
|
||||
dout_en <= out_en;
|
||||
dout_vld <= out_vld;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' or pre_fin = '1' then
|
||||
abort <= '0';
|
||||
elsif din_vld_r = '1' and din_en = '0' then
|
||||
abort <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
din_vld_r <= din_vld and din_en;
|
||||
if rst = '1' then
|
||||
out_en <= '0';
|
||||
elsif out_en = '0' then
|
||||
out_en <= pre_fin and din_en;
|
||||
elsif out_vld = '1' then
|
||||
out_en <= din_en;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
out_vld <= pre_fin;
|
||||
if pre_fin = '1' then
|
||||
dout <= shift_pipe;
|
||||
dout_be <= shift_cnt_pipe;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' or pre_fin = '1' then
|
||||
if (msb_first) then
|
||||
shift_cnt_pipe <= (shift_cnt_pipe'left downto 1 => '0') & (din_en and din_vld);
|
||||
else
|
||||
shift_cnt_pipe <= (din_en and din_vld) & (shift_cnt_pipe'left downto 1 => '0');
|
||||
end if;
|
||||
elsif din_vld = '1' or abort = '1' then
|
||||
if (msb_first) then
|
||||
shift_cnt_pipe <= shift_cnt_pipe(shift_cnt_pipe'left-1 downto 0) & din_en;
|
||||
else
|
||||
shift_cnt_pipe <= din_en & shift_cnt_pipe(shift_cnt_pipe'left downto 1);
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if din_vld = '1' or abort = '1' then
|
||||
if (msb_first) then
|
||||
shift_pipe <= shift_pipe(shift_pipe'left-data_width_in downto 0) & din;
|
||||
else
|
||||
shift_pipe <= din & shift_pipe(shift_pipe'left downto data_width_in);
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
end behavior;
|
||||
@@ -1,106 +0,0 @@
|
||||
-------------------------------------------------------------------------
|
||||
-- Project: JCPU, a portable 8-bit RISC CPU written in VHDL
|
||||
-- This file: testbench for system test using Xilinx ML-402
|
||||
|
||||
-- Copyright (C) 2007 J. Ahrensfeld
|
||||
|
||||
-- This library is free software; you can redistribute it and/or
|
||||
-- modify it under the terms of the GNU Lesser General Public
|
||||
-- License as published by the Free Software Foundation; either
|
||||
-- version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
-- This library is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
-- Lesser General Public License for more details.
|
||||
|
||||
-- You should have received a copy of the GNU Lesser General Public
|
||||
-- License along with this library; if not, write to the Free Software
|
||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
LIBRARY ieee;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
USE ieee.numeric_std.ALL;
|
||||
|
||||
ENTITY tb_crc32 IS
|
||||
END tb_crc32;
|
||||
|
||||
ARCHITECTURE behavior OF tb_crc32 IS
|
||||
|
||||
constant CLK_PERIOD : time := 10 ns;
|
||||
|
||||
signal CLK : std_logic := '1';
|
||||
signal RST : std_logic := '1';
|
||||
|
||||
signal din_vld : std_logic := '0';
|
||||
signal din : unsigned(7 downto 0) := (others => '-');
|
||||
signal crc32 : unsigned(31 downto 0);
|
||||
signal crc32_vld : std_logic;
|
||||
|
||||
|
||||
type byte_array_t is array (0 to 61) of unsigned(7 downto 0);
|
||||
|
||||
signal test_data : byte_array_t :=
|
||||
(
|
||||
X"00", X"0A", X"E6", X"F0", X"05", X"A3", X"00", X"12",
|
||||
X"34", X"56", X"78", X"90", X"08", X"00", X"45", X"00",
|
||||
X"00", X"30", X"B3", X"FE", X"00", X"00", X"80", X"11",
|
||||
X"72", X"BA", X"0A", X"00", X"00", X"03", X"0A", X"00",
|
||||
X"00", X"02", X"04", X"00", X"04", X"00", X"00", X"1C",
|
||||
X"89", X"4D", X"00", X"01", X"02", X"03", X"04", X"05",
|
||||
X"06", X"07", X"08", X"09", X"0A", X"0B", X"0C", X"0D",
|
||||
X"0E", X"0F", X"10", X"11", X"12", X"13"
|
||||
);
|
||||
|
||||
BEGIN
|
||||
|
||||
inst_crc32: entity work.crc32
|
||||
PORT MAP
|
||||
(
|
||||
rst => RST,
|
||||
clk => CLK,
|
||||
din_vld => din_vld,
|
||||
din => din,
|
||||
crc32_vld => crc32_vld,
|
||||
crc32_out => crc32
|
||||
|
||||
);
|
||||
|
||||
|
||||
CLK_GEN: process
|
||||
begin
|
||||
wait for CLK_PERIOD/2;
|
||||
CLK <= not CLK;
|
||||
end process;
|
||||
|
||||
|
||||
-- Master
|
||||
STIMULUS: process
|
||||
|
||||
|
||||
begin
|
||||
|
||||
wait for 6*CLK_PERIOD;
|
||||
RST <= '0';
|
||||
wait for 6*CLK_PERIOD;
|
||||
|
||||
wait until rising_edge(CLK);
|
||||
|
||||
for i in 0 to 61 loop
|
||||
din_vld <= '1';
|
||||
din <= test_data(i);
|
||||
wait until rising_edge(CLK);
|
||||
end loop;
|
||||
|
||||
din <= (others => '-');
|
||||
din_vld <= '0';
|
||||
|
||||
wait;
|
||||
|
||||
end process;
|
||||
|
||||
END;
|
||||
@@ -1,224 +0,0 @@
|
||||
-------------------------------------------------------------------------
|
||||
-- Project: JCPU, a portable 8-bit RISC CPU written in VHDL
|
||||
-- This file: testbench for system test using Xilinx ML-402
|
||||
|
||||
-- Copyright (C) 2007 J. Ahrensfeld
|
||||
|
||||
-- This library is free software; you can redistribute it and/or
|
||||
-- modify it under the terms of the GNU Lesser General Public
|
||||
-- License as published by the Free Software Foundation; either
|
||||
-- version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
-- This library is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
-- Lesser General Public License for more details.
|
||||
|
||||
-- You should have received a copy of the GNU Lesser General Public
|
||||
-- License along with this library; if not, write to the Free Software
|
||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
LIBRARY ieee;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
USE ieee.numeric_std.ALL;
|
||||
|
||||
ENTITY tb_serdes IS
|
||||
END tb_serdes;
|
||||
|
||||
ARCHITECTURE behavior OF tb_serdes IS
|
||||
|
||||
constant CLK_PERIOD : time := 10 ns;
|
||||
|
||||
signal CLK : std_logic := '1';
|
||||
signal RST : std_logic := '1';
|
||||
|
||||
signal piso_din_vld : std_logic := '0';
|
||||
signal piso_din_rdy : std_logic;
|
||||
signal piso_din_be : unsigned(3 downto 0) := (others => '0');
|
||||
signal piso_din : unsigned(31 downto 0) := (others => '-');
|
||||
signal piso_dout_vld : std_logic;
|
||||
signal piso_dout : unsigned(7 downto 0);
|
||||
signal piso_dout_en : std_logic;
|
||||
|
||||
signal piso2_din_vld : std_logic := '0';
|
||||
signal piso2_din_rdy : std_logic;
|
||||
signal piso2_din_be : unsigned(1 downto 0) := (others => '1');
|
||||
signal piso2_din : unsigned(7 downto 0) := (others => '-');
|
||||
signal piso2_dout_vld : std_logic;
|
||||
signal piso2_dout : unsigned(3 downto 0);
|
||||
signal piso2_dout_en : std_logic;
|
||||
|
||||
signal sipo_enable : std_logic := '0';
|
||||
signal sipo_rst : std_logic := '0';
|
||||
signal sipo_din_vld : std_logic := '0';
|
||||
signal sipo_din : unsigned(7 downto 0) := (others => '-');
|
||||
signal sipo_dout_vld : std_logic;
|
||||
signal sipo_dout_en : std_logic;
|
||||
signal sipo_dout_be : unsigned(3 downto 0);
|
||||
signal sipo_dout : unsigned(31 downto 0);
|
||||
|
||||
signal sipo2_enable : std_logic := '0';
|
||||
signal sipo2_rst : std_logic := '0';
|
||||
signal sipo2_din_vld : std_logic := '0';
|
||||
signal sipo2_din : unsigned(3 downto 0) := (others => '-');
|
||||
signal sipo2_dout_vld : std_logic;
|
||||
signal sipo2_dout_en : std_logic;
|
||||
signal sipo2_dout_be : unsigned(1 downto 0);
|
||||
signal sipo2_dout : unsigned(7 downto 0);
|
||||
|
||||
|
||||
BEGIN
|
||||
|
||||
inst_piso : entity work.piso
|
||||
GENERIC MAP
|
||||
(
|
||||
data_width_in => 32,
|
||||
data_width_out => 8,
|
||||
msb_first => true
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
rst => RST,
|
||||
clk => CLK,
|
||||
din_vld => piso_din_vld,
|
||||
din_rdy => piso_din_rdy,
|
||||
din_be => piso_din_be,
|
||||
din => piso_din,
|
||||
dout_vld => piso_dout_vld,
|
||||
dout_en => piso_dout_en,
|
||||
dout => piso_dout
|
||||
|
||||
);
|
||||
|
||||
piso_dout_en <= piso2_din_rdy;
|
||||
|
||||
inst_piso2 : entity work.piso
|
||||
GENERIC MAP
|
||||
(
|
||||
data_width_in => 8,
|
||||
data_width_out => 4,
|
||||
msb_first => true
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
rst => RST,
|
||||
clk => CLK,
|
||||
din_vld => piso2_din_vld,
|
||||
din_rdy => piso2_din_rdy,
|
||||
din_be => piso2_din_be,
|
||||
din => piso2_din,
|
||||
dout_vld => piso2_dout_vld,
|
||||
dout_en => piso2_dout_en,
|
||||
dout => piso2_dout
|
||||
|
||||
);
|
||||
|
||||
piso2_din_vld <= piso_dout_vld;
|
||||
piso2_dout_en <= '1';
|
||||
piso2_din <= piso_dout;
|
||||
|
||||
inst_sipo : entity work.sipo
|
||||
GENERIC MAP
|
||||
(
|
||||
data_width_in => 8,
|
||||
data_width_out => 32,
|
||||
msb_first => true
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
rst => RST,
|
||||
clk => CLK,
|
||||
din_en => sipo_enable,
|
||||
din_vld => sipo_din_vld,
|
||||
din => sipo_din,
|
||||
dout_be => sipo_dout_be,
|
||||
dout_vld => sipo_dout_vld,
|
||||
dout => sipo_dout,
|
||||
dout_en => sipo_dout_en
|
||||
|
||||
);
|
||||
sipo_din <= sipo2_dout;
|
||||
sipo_din_vld <= sipo2_dout_vld;
|
||||
sipo_enable <= sipo2_dout_en;
|
||||
sipo_rst <= RST or not piso2_dout_vld;
|
||||
|
||||
inst_sipo2 : entity work.sipo
|
||||
GENERIC MAP
|
||||
(
|
||||
data_width_in => 4,
|
||||
data_width_out => 8,
|
||||
msb_first => true
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
rst => RST,
|
||||
clk => CLK,
|
||||
din_en => sipo2_enable,
|
||||
din_vld => sipo2_din_vld,
|
||||
din => sipo2_din,
|
||||
dout_be => sipo2_dout_be,
|
||||
dout_vld => sipo2_dout_vld,
|
||||
dout => sipo2_dout,
|
||||
dout_en => sipo2_dout_en
|
||||
|
||||
);
|
||||
sipo2_din <= piso2_dout;
|
||||
sipo2_din_vld <= piso2_dout_vld;
|
||||
sipo2_enable <= sipo2_din_vld;
|
||||
sipo_rst <= RST or not piso2_dout_vld;
|
||||
|
||||
CLK_GEN: process
|
||||
begin
|
||||
wait for CLK_PERIOD/2;
|
||||
CLK <= not CLK;
|
||||
end process;
|
||||
|
||||
|
||||
-- Master
|
||||
STIMULUS: process
|
||||
|
||||
|
||||
begin
|
||||
|
||||
wait for 600*CLK_PERIOD;
|
||||
RST <= '0';
|
||||
wait for 60*CLK_PERIOD;
|
||||
|
||||
for i in 1 to 10 loop
|
||||
|
||||
wait until rising_edge(CLK);
|
||||
piso_din_vld <= '1';
|
||||
piso_din <= X"12345678";
|
||||
piso_din_be <= "1111";
|
||||
wait until rising_edge(CLK) and piso_din_rdy = '1';
|
||||
piso_din <= piso_din + X"12345678";
|
||||
piso_din_be <= "1111";
|
||||
wait until rising_edge(CLK) and piso_din_rdy = '1';
|
||||
piso_din <= piso_din + X"12345678";
|
||||
piso_din_be <= "1111";
|
||||
wait until rising_edge(CLK) and piso_din_rdy = '1';
|
||||
piso_din <= piso_din + X"12345678";
|
||||
piso_din_be <= "1100";
|
||||
wait until rising_edge(CLK) and piso_din_rdy = '1';
|
||||
piso_din <= (others => '-');
|
||||
piso_din_vld <= '0';
|
||||
|
||||
|
||||
wait until rising_edge(CLK) and piso_dout_vld = '0';
|
||||
|
||||
-- wait until rising_edge(CLK);
|
||||
-- wait until rising_edge(CLK) and sipo_dout_vld = '1';
|
||||
--
|
||||
wait for 33*CLK_PERIOD;
|
||||
|
||||
end loop;
|
||||
|
||||
wait;
|
||||
|
||||
end process;
|
||||
|
||||
END;
|
||||
@@ -1,761 +0,0 @@
|
||||
-------------------------------------------------------------------------
|
||||
-- Project: JCPU, a portable 8-bit RISC CPU written in VHDL
|
||||
-- This file: testbench for system test using Xilinx ML-402
|
||||
|
||||
-- Copyright (C) 2007 J. Ahrensfeld
|
||||
|
||||
-- This library is free software; you can redistribute it and/or
|
||||
-- modify it under the terms of the GNU Lesser General Public
|
||||
-- License as published by the Free Software Foundation; either
|
||||
-- version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
-- This library is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
-- Lesser General Public License for more details.
|
||||
|
||||
-- You should have received a copy of the GNU Lesser General Public
|
||||
-- License along with this library; if not, write to the Free Software
|
||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
LIBRARY ieee;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
USE ieee.numeric_std.ALL;
|
||||
|
||||
ENTITY tb_emac_top_jb IS
|
||||
END tb_emac_top_jb;
|
||||
|
||||
ARCHITECTURE behavior OF tb_emac_top_jb IS
|
||||
|
||||
constant CLK_PERIOD : time := 10 ns;
|
||||
constant MII_CLK_PERIOD : time := 37.7 ns;
|
||||
|
||||
signal CLK : std_logic := '1';
|
||||
signal RST : std_logic := '1';
|
||||
|
||||
-- Slave
|
||||
signal CYC_I : std_logic := '0';
|
||||
signal STB_I : std_logic := '0';
|
||||
signal WE_I : std_logic := '0';
|
||||
signal SEL_I : unsigned(3 downto 0) := (others => '1');
|
||||
signal ACK_O : std_logic;
|
||||
signal INT_O : std_logic;
|
||||
signal MRDY_I : std_logic := '0';
|
||||
signal SRDY_O : std_logic;
|
||||
signal ADDR_I : unsigned(31 downto 0) := (others => '-');
|
||||
signal DAT_I : unsigned(31 downto 0) := (others => '-');
|
||||
signal DAT_O : unsigned(31 downto 0) := (others => '-');
|
||||
signal DAT_O_reg : unsigned(31 downto 0) := (others => '-');
|
||||
signal status_reg : unsigned(31 downto 0) := (others => '0');
|
||||
signal size_reg : unsigned(31 downto 0) := (others => '0');
|
||||
|
||||
-- Master
|
||||
signal CYC_O : std_logic;
|
||||
signal STB_O : std_logic;
|
||||
signal WE_O : std_logic;
|
||||
signal SEL_O : unsigned(3 downto 0) := (others => '1');
|
||||
signal ACK_I : std_logic := '0';
|
||||
signal MRDY_O : std_logic := '1';
|
||||
signal SRDY_I : std_logic := '1';
|
||||
signal ADDR_O : unsigned(31 downto 0) := (others => '-');
|
||||
signal MDAT_I : unsigned(31 downto 0) := (others => '-');
|
||||
signal MDAT_O : unsigned(31 downto 0) := (others => '-');
|
||||
|
||||
-- MII signals
|
||||
signal mii_rx_clk_board : std_logic := '1';
|
||||
signal mii_tx_clk_board : std_logic := '1';
|
||||
signal mii_rx_clk : std_logic := '1';
|
||||
signal mii_tx_clk : std_logic := '1';
|
||||
signal mii_rx : unsigned(7 downto 0) := (others => '-');
|
||||
signal mii_tx : unsigned(7 downto 0);
|
||||
signal mii_rx_dv : std_logic := '0';
|
||||
signal mii_rx_er : std_logic := '0';
|
||||
signal mii_tx_en : std_logic;
|
||||
signal mii_tx_er : std_logic;
|
||||
signal mii_crs : std_logic := '0';
|
||||
signal mii_col : std_logic := '0';
|
||||
signal mii_gtx_clk : std_logic;
|
||||
|
||||
signal loop_back_en : std_logic := '0';
|
||||
|
||||
signal pktgen_tx : unsigned(7 downto 0);
|
||||
signal pktgen_tx_en : std_logic;
|
||||
signal pktgen_tx_er : std_logic;
|
||||
signal pktgen_en : std_logic := '0';
|
||||
signal pktgen_gigabit : std_logic := '0';
|
||||
signal pktgen_fcs_en : std_logic := '0';
|
||||
signal dat_o_cnt_en : std_logic := '0';
|
||||
signal dat_o_cnt_rst : std_logic := '1';
|
||||
signal dat_o_cnt : natural;
|
||||
signal pkt_count : natural;
|
||||
|
||||
type emac_action_t is (emac_idle, emac_alloc, emac_write, emac_commit, emac_wait_data, emac_read, emac_free);
|
||||
signal emac_action : emac_action_t;
|
||||
|
||||
constant RX_STATUS_REG_ADDR : unsigned(31 downto 0) := X"0000_0000";
|
||||
constant RX_SIZE_REG_ADDR : unsigned(31 downto 0) := X"0000_0004";
|
||||
constant TX_STATUS_REG_ADDR : unsigned(31 downto 0) := X"0000_0008";
|
||||
constant TX_SIZE_REG_ADDR : unsigned(31 downto 0) := X"0000_000C";
|
||||
constant DATA_REG_ADDR : unsigned(31 downto 0) := X"0000_8000";
|
||||
|
||||
|
||||
-- 64Bit RAM
|
||||
signal MDAT_I_64 : unsigned(63 downto 0) := (others => '-');
|
||||
signal MDAT_O_64 : unsigned(63 downto 0) := (others => '-');
|
||||
|
||||
type ram_t is array (0 to 511) of unsigned(63 downto 0);
|
||||
|
||||
signal ram64 : ram_t;
|
||||
|
||||
|
||||
BEGIN
|
||||
|
||||
MDAT_I <= MDAT_I_64(31 downto 0);
|
||||
MDAT_O_64 <= MDAT_O & MDAT_O;
|
||||
|
||||
process(CLK)
|
||||
variable res: unsigned(63 downto 0);
|
||||
variable ram_data : unsigned(63 downto 0);
|
||||
variable data8: unsigned(7 downto 0);
|
||||
begin
|
||||
if rising_edge(CLK) then
|
||||
if RST = '1' then
|
||||
data8 := X"00";
|
||||
for i in 0 to 255 loop
|
||||
ram_data(7 downto 0) := data8;
|
||||
data8 := data8 + 1;
|
||||
ram_data(15 downto 8) := data8;
|
||||
data8 := data8 + 1;
|
||||
ram_data(23 downto 16) := data8;
|
||||
data8 := data8 + 1;
|
||||
ram_data(31 downto 24) := data8;
|
||||
data8 := data8 + 1;
|
||||
ram_data(39 downto 32) := data8;
|
||||
data8 := data8 + 1;
|
||||
ram_data(47 downto 40) := data8;
|
||||
data8 := data8 + 1;
|
||||
ram_data(55 downto 48) := data8;
|
||||
data8 := data8 + 1;
|
||||
ram_data(63 downto 56) := data8;
|
||||
data8 := data8 + 1;
|
||||
ram64(i) <= ram_data;
|
||||
end loop;
|
||||
else
|
||||
ACK_I <= '0';
|
||||
if (CYC_O and STB_O) = '1' then
|
||||
if WE_O = '0' then
|
||||
ACK_I <= '1';
|
||||
ram_data := ram64(to_integer(ADDR_O(31 downto 3)));
|
||||
if ADDR_O(2) = '0' then
|
||||
res := ram_data;
|
||||
else
|
||||
res := ram_data(31 downto 0) & ram_data(63 downto 32);
|
||||
end if;
|
||||
else -- WE=1
|
||||
ram_data := ram64(to_integer(ADDR_O(31 downto 3)));
|
||||
-- ram_data := (others => '-');
|
||||
if ADDR_O(2) = '0' then
|
||||
if SEL_O = "11111111" then
|
||||
ram64(to_integer(ADDR_O(31 downto 3))) <= MDAT_O_64;
|
||||
elsif SEL_O = "00001111" then
|
||||
ram64(to_integer(ADDR_O(31 downto 3))) <= ram_data(63 downto 32) & MDAT_O_64(31 downto 0);
|
||||
elsif SEL_O = "11110000" then
|
||||
ram64(to_integer(ADDR_O(31 downto 3))) <= MDAT_O_64(63 downto 32) & ram_data(31 downto 0);
|
||||
end if;
|
||||
else
|
||||
if SEL_O = "11111111" then
|
||||
ram64(to_integer(ADDR_O(31 downto 3))) <= MDAT_O_64(31 downto 0) & MDAT_O_64(63 downto 32);
|
||||
elsif SEL_O = "00001111" then
|
||||
ram64(to_integer(ADDR_O(31 downto 3))) <= MDAT_O_64(31 downto 0) & ram_data(31 downto 0);
|
||||
elsif SEL_O = "11110000" then
|
||||
ram64(to_integer(ADDR_O(31 downto 3))) <= ram_data(63 downto 32) & MDAT_O_64(63 downto 32);
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
MDAT_I_64 <= res;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
inst_emac_top_jb : entity work.emac_top_jb
|
||||
GENERIC MAP
|
||||
(
|
||||
f_sysclk => 100.0,
|
||||
RX_RAM_SIZE => 2048,
|
||||
TX_RAM_SIZE => 2048
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
-- JBUS Slave signals
|
||||
CLK_I => CLK,
|
||||
RST_I => RST,
|
||||
INT_O => INT_O,
|
||||
CYC_I => CYC_I,
|
||||
STB_I => STB_I,
|
||||
SEL_I => SEL_I,
|
||||
WE_I => WE_I,
|
||||
ACK_O => ACK_O,
|
||||
SRDY_O => SRDY_O,
|
||||
MRDY_I => MRDY_I,
|
||||
ADDR_I => ADDR_I,
|
||||
DAT_I => DAT_I,
|
||||
DAT_O => DAT_O,
|
||||
|
||||
-- JBUS Master signals
|
||||
CYC_O => CYC_O,
|
||||
STB_O => STB_O,
|
||||
WE_O => WE_O,
|
||||
SEL_O => SEL_O,
|
||||
ACK_I => ACK_I,
|
||||
SRDY_I => SRDY_I,
|
||||
MRDY_O => MRDY_O,
|
||||
ADDR_O => ADDR_O,
|
||||
MDAT_I => MDAT_I,
|
||||
MDAT_O => MDAT_O,
|
||||
|
||||
mii_rx_clk => mii_rx_clk_board,
|
||||
mii_rx_dv => mii_rx_dv,
|
||||
mii_rx_er => mii_rx_er,
|
||||
mii_rx => mii_rx,
|
||||
mii_tx_clk => mii_tx_clk_board,
|
||||
mii_tx_en => mii_tx_en,
|
||||
mii_tx_er => mii_tx_er,
|
||||
mii_tx => mii_tx,
|
||||
mii_gtx_clk => mii_gtx_clk,
|
||||
mii_crs => mii_crs,
|
||||
mii_col => mii_col
|
||||
|
||||
);
|
||||
|
||||
inst_pkt_gen : entity work.pkt_gen
|
||||
GENERIC MAP
|
||||
(
|
||||
f_sysclk => 100.0,
|
||||
PKT_SIZE_MIN => 64,
|
||||
PKT_SIZE_MAX => 1512
|
||||
|
||||
)
|
||||
PORT MAP
|
||||
(
|
||||
clk => CLK,
|
||||
rst => RST,
|
||||
en => pktgen_en,
|
||||
gigabit_en => pktgen_gigabit,
|
||||
fcs_gen_en => pktgen_fcs_en,
|
||||
mii_tx_clk => mii_tx_clk_board,
|
||||
mii_tx_en => pktgen_tx_en,
|
||||
mii_tx_er => pktgen_tx_er,
|
||||
mii_tx => pktgen_tx
|
||||
|
||||
);
|
||||
|
||||
|
||||
CLK_GEN: process
|
||||
begin
|
||||
wait for CLK_PERIOD/2;
|
||||
CLK <= not CLK;
|
||||
end process;
|
||||
|
||||
MII_CLK_GEN: process
|
||||
begin
|
||||
wait for MII_CLK_PERIOD/2;
|
||||
mii_rx_clk <= not mii_rx_clk;
|
||||
mii_tx_clk <= not mii_tx_clk;
|
||||
end process;
|
||||
|
||||
mii_rx_clk_board <= mii_rx_clk;
|
||||
mii_tx_clk_board <= mii_tx_clk;
|
||||
|
||||
DAT_O_register:
|
||||
process(CLK)
|
||||
begin
|
||||
if rising_edge(CLK) then
|
||||
if ACK_O = '1' then
|
||||
DAT_O_reg <= DAT_O;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
DAT_O_count_register:
|
||||
process(CLK)
|
||||
begin
|
||||
if rising_edge(CLK) then
|
||||
if dat_o_cnt_rst = '1' then
|
||||
dat_o_cnt <= 0;
|
||||
elsif ACK_O = '1' and dat_o_cnt_en = '1' then
|
||||
dat_o_cnt <= dat_o_cnt + 1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
mii_rx <= mii_tx when loop_back_en = '1' else pktgen_tx;
|
||||
mii_rx_dv <= mii_tx_en when loop_back_en = '1' else pktgen_tx_en;
|
||||
mii_rx_er <= mii_tx_er when loop_back_en = '1' else pktgen_tx_er;
|
||||
mii_crs <= '0';
|
||||
mii_col <= '0';
|
||||
|
||||
-- Master
|
||||
STIMULUS: process
|
||||
|
||||
procedure emac_tx_reset_100mbps is
|
||||
begin
|
||||
|
||||
CYC_I <= '1';
|
||||
wait until rising_edge(CLK) and SRDY_O = '1';
|
||||
DAT_I <= X"A000_0000";
|
||||
STB_I <= '1';
|
||||
WE_I <= '1';
|
||||
ADDR_I <= TX_STATUS_REG_ADDR;
|
||||
wait until rising_edge(CLK) and SRDY_O = '1';
|
||||
STB_I <= '0';
|
||||
WE_I <= '0';
|
||||
|
||||
end procedure emac_tx_reset_100mbps;
|
||||
|
||||
procedure emac_rx_reset_100mbps is
|
||||
begin
|
||||
|
||||
CYC_I <= '1';
|
||||
wait until rising_edge(CLK) and SRDY_O = '1';
|
||||
DAT_I <= X"A000_0000";
|
||||
STB_I <= '1';
|
||||
WE_I <= '1';
|
||||
ADDR_I <= RX_STATUS_REG_ADDR;
|
||||
wait until rising_edge(CLK) and SRDY_O = '1';
|
||||
STB_I <= '0';
|
||||
WE_I <= '0';
|
||||
|
||||
end procedure emac_rx_reset_100mbps;
|
||||
|
||||
procedure emac_tx_reset_1000mbps is
|
||||
begin
|
||||
|
||||
CYC_I <= '1';
|
||||
wait until rising_edge(CLK) and SRDY_O = '1';
|
||||
DAT_I <= X"E000_0000";
|
||||
STB_I <= '1';
|
||||
WE_I <= '1';
|
||||
ADDR_I <= TX_STATUS_REG_ADDR;
|
||||
wait until rising_edge(CLK) and SRDY_O = '1';
|
||||
STB_I <= '0';
|
||||
WE_I <= '0';
|
||||
|
||||
end procedure emac_tx_reset_1000mbps;
|
||||
|
||||
procedure emac_rx_reset_1000mbps is
|
||||
begin
|
||||
|
||||
CYC_I <= '1';
|
||||
wait until rising_edge(CLK) and SRDY_O = '1';
|
||||
DAT_I <= X"E000_0000";
|
||||
STB_I <= '1';
|
||||
WE_I <= '1';
|
||||
ADDR_I <= RX_STATUS_REG_ADDR;
|
||||
wait until rising_edge(CLK) and SRDY_O = '1';
|
||||
STB_I <= '0';
|
||||
WE_I <= '0';
|
||||
|
||||
end procedure emac_rx_reset_1000mbps;
|
||||
|
||||
procedure emac_alloc (size : natural) is
|
||||
begin
|
||||
|
||||
-- TX-ALLOCATION
|
||||
-- set TX-size
|
||||
emac_action <= emac_alloc;
|
||||
CYC_I <= '1';
|
||||
wait until rising_edge(CLK) and SRDY_O = '1';
|
||||
DAT_I <= to_unsigned(size, 32);
|
||||
STB_I <= '1';
|
||||
WE_I <= '1';
|
||||
ADDR_I <= TX_SIZE_REG_ADDR;
|
||||
|
||||
check_alloc_ok:
|
||||
while(true) loop
|
||||
|
||||
-- set alloc request
|
||||
wait until rising_edge(CLK) and SRDY_O = '1';
|
||||
WE_I <= '0';
|
||||
STB_I <= '1';
|
||||
ADDR_I <= TX_STATUS_REG_ADDR;
|
||||
wait until rising_edge(CLK) and SRDY_O = '1';
|
||||
STB_I <= '0';
|
||||
wait until rising_edge(CLK) and ACK_O = '1';
|
||||
status_reg <= DAT_O;
|
||||
wait until rising_edge(CLK) and SRDY_O = '1';
|
||||
DAT_I <= X"0002_0000" or (not X"0001_0000" and status_reg);
|
||||
STB_I <= '1';
|
||||
WE_I <= '1';
|
||||
ADDR_I <= TX_STATUS_REG_ADDR;
|
||||
|
||||
check_bsy:
|
||||
while (true) loop
|
||||
wait until rising_edge(CLK) and SRDY_O = '1';
|
||||
WE_I <= '0';
|
||||
STB_I <= '1';
|
||||
ADDR_I <= TX_STATUS_REG_ADDR;
|
||||
wait until rising_edge(CLK) and SRDY_O = '1';
|
||||
STB_I <= '0';
|
||||
wait until rising_edge(CLK) and ACK_O = '1';
|
||||
status_reg <= DAT_O;
|
||||
wait until rising_edge(CLK);
|
||||
if status_reg(17) = '0' then
|
||||
exit check_bsy;
|
||||
end if;
|
||||
end loop;
|
||||
if status_reg(16) = '1' then
|
||||
exit check_alloc_ok;
|
||||
end if;
|
||||
end loop;
|
||||
CYC_I <= '0';
|
||||
|
||||
emac_action <= emac_idle;
|
||||
|
||||
end procedure emac_alloc;
|
||||
|
||||
procedure emac_commit is
|
||||
begin
|
||||
|
||||
-- RX- DEALLOCATION
|
||||
emac_action <= emac_commit;
|
||||
|
||||
-- set free request
|
||||
CYC_I <= '1';
|
||||
wait until rising_edge(CLK) and SRDY_O = '1';
|
||||
WE_I <= '0';
|
||||
STB_I <= '1';
|
||||
ADDR_I <= TX_STATUS_REG_ADDR;
|
||||
wait until rising_edge(CLK) and SRDY_O = '1';
|
||||
STB_I <= '0';
|
||||
wait until rising_edge(CLK) and ACK_O = '1';
|
||||
status_reg <= DAT_O;
|
||||
wait until rising_edge(CLK) and SRDY_O = '1';
|
||||
DAT_I <= X"0001_0000" or (not X"0002_0000" and status_reg);
|
||||
STB_I <= '1';
|
||||
WE_I <= '1';
|
||||
ADDR_I <= TX_STATUS_REG_ADDR;
|
||||
wait until rising_edge(CLK) and SRDY_O = '1';
|
||||
STB_I <= '0';
|
||||
WE_I <= '0';
|
||||
|
||||
emac_action <= emac_idle;
|
||||
|
||||
end procedure emac_commit;
|
||||
|
||||
procedure emac_write (size : natural) is
|
||||
variable data : unsigned (7 downto 0);
|
||||
variable num_words : natural;
|
||||
begin
|
||||
|
||||
-- FILL TX data
|
||||
emac_action <= emac_write;
|
||||
if (size mod 4) = 0 then
|
||||
num_words := size/4;
|
||||
else
|
||||
num_words := size/4 + 1;
|
||||
end if;
|
||||
|
||||
CYC_I <= '1';
|
||||
wait until rising_edge(CLK) and SRDY_O = '1';
|
||||
data := X"00";
|
||||
ADDR_I <= DATA_REG_ADDR;
|
||||
WE_I <= '1';
|
||||
for i in 1 to num_words loop
|
||||
STB_I <= '1';
|
||||
DAT_I(7 downto 0) <= data;
|
||||
data := data + 1;
|
||||
DAT_I(15 downto 8) <= data;
|
||||
data := data + 1;
|
||||
DAT_I(23 downto 16) <= data;
|
||||
data := data + 1;
|
||||
DAT_I(31 downto 24) <= data;
|
||||
data := data + 1;
|
||||
wait until rising_edge(CLK) and SRDY_O = '1';
|
||||
end loop;
|
||||
|
||||
STB_I <= '0';
|
||||
wait until rising_edge(CLK) and SRDY_O = '1';
|
||||
|
||||
emac_commit;
|
||||
|
||||
emac_action <= emac_idle;
|
||||
|
||||
end procedure emac_write;
|
||||
|
||||
procedure emac_read (size_in : natural) is
|
||||
variable data : unsigned (7 downto 0);
|
||||
variable size, num_words : natural;
|
||||
begin
|
||||
|
||||
return;
|
||||
emac_action <= emac_wait_data;
|
||||
|
||||
-- check if data available
|
||||
check_data_avail:
|
||||
while (true) loop
|
||||
CYC_I <= '1';
|
||||
wait until rising_edge(CLK) and SRDY_O = '1';
|
||||
WE_I <= '0';
|
||||
STB_I <= '1';
|
||||
ADDR_I <= RX_STATUS_REG_ADDR;
|
||||
wait until rising_edge(CLK) and SRDY_O = '1';
|
||||
STB_I <= '0';
|
||||
wait until rising_edge(CLK) and ACK_O = '1';
|
||||
status_reg <= DAT_O;
|
||||
wait until rising_edge(CLK);
|
||||
if status_reg(17) = '1' and status_reg(16) = '1' then
|
||||
exit check_data_avail;
|
||||
end if;
|
||||
end loop;
|
||||
|
||||
read_size:
|
||||
dat_o_cnt_rst <= '1';
|
||||
CYC_I <= '1';
|
||||
wait until rising_edge(CLK) and SRDY_O = '1';
|
||||
WE_I <= '0';
|
||||
STB_I <= '1';
|
||||
ADDR_I <= RX_SIZE_REG_ADDR;
|
||||
wait until rising_edge(CLK) and SRDY_O = '1';
|
||||
STB_I <= '0';
|
||||
wait until rising_edge(CLK) and ACK_O = '1';
|
||||
size_reg <= DAT_O;
|
||||
wait until rising_edge(CLK);
|
||||
|
||||
-- set packet request
|
||||
CYC_I <= '1';
|
||||
wait until rising_edge(CLK) and SRDY_O = '1';
|
||||
WE_I <= '0';
|
||||
STB_I <= '1';
|
||||
ADDR_I <= RX_STATUS_REG_ADDR;
|
||||
wait until rising_edge(CLK) and SRDY_O = '1';
|
||||
STB_I <= '0';
|
||||
wait until rising_edge(CLK) and ACK_O = '1';
|
||||
status_reg <= DAT_O;
|
||||
wait until rising_edge(CLK) and SRDY_O = '1';
|
||||
DAT_I <= X"0002_0000" or (not X"0001_0000" and status_reg);
|
||||
STB_I <= '1';
|
||||
WE_I <= '1';
|
||||
ADDR_I <= RX_STATUS_REG_ADDR;
|
||||
wait until rising_edge(CLK) and SRDY_O = '1';
|
||||
STB_I <= '0';
|
||||
WE_I <= '0';
|
||||
|
||||
emac_action <= emac_read;
|
||||
-- Read RX data
|
||||
size := size_in;
|
||||
if (size_in = 0) then
|
||||
size := to_integer(size_reg(15 downto 0));
|
||||
end if;
|
||||
|
||||
if (size mod 4) = 0 then
|
||||
num_words := size/4;
|
||||
else
|
||||
num_words := size/4 + 1;
|
||||
end if;
|
||||
|
||||
dat_o_cnt_rst <= '0';
|
||||
dat_o_cnt_en <= '1';
|
||||
CYC_I <= '1';
|
||||
wait until rising_edge(CLK) and SRDY_O = '1';
|
||||
ADDR_I <= DATA_REG_ADDR;
|
||||
WE_I <= '0';
|
||||
STB_I <= '1';
|
||||
for i in 1 to num_words loop
|
||||
wait until rising_edge(CLK) and SRDY_O = '1';
|
||||
end loop;
|
||||
STB_I <= '0';
|
||||
wait until rising_edge(CLK) and dat_o_cnt = num_words;
|
||||
dat_o_cnt_en <= '0';
|
||||
emac_action <= emac_idle;
|
||||
|
||||
end procedure emac_read;
|
||||
|
||||
procedure emac_free is
|
||||
begin
|
||||
|
||||
return;
|
||||
-- RX- DEALLOCATION
|
||||
emac_action <= emac_free;
|
||||
|
||||
-- set free request
|
||||
CYC_I <= '1';
|
||||
wait until rising_edge(CLK) and SRDY_O = '1';
|
||||
WE_I <= '0';
|
||||
STB_I <= '1';
|
||||
ADDR_I <= RX_STATUS_REG_ADDR;
|
||||
wait until rising_edge(CLK) and SRDY_O = '1';
|
||||
STB_I <= '0';
|
||||
wait until rising_edge(CLK) and ACK_O = '1';
|
||||
status_reg <= DAT_O;
|
||||
wait until rising_edge(CLK) and SRDY_O = '1';
|
||||
DAT_I <= X"0001_0000" or (not X"0002_0000" and status_reg);
|
||||
STB_I <= '1';
|
||||
WE_I <= '1';
|
||||
ADDR_I <= RX_STATUS_REG_ADDR;
|
||||
wait until rising_edge(CLK) and SRDY_O = '1';
|
||||
STB_I <= '0';
|
||||
WE_I <= '0';
|
||||
|
||||
emac_action <= emac_idle;
|
||||
|
||||
end procedure emac_free;
|
||||
|
||||
begin
|
||||
|
||||
wait for 6*MII_CLK_PERIOD;
|
||||
RST <= '0';
|
||||
wait for 60*CLK_PERIOD;
|
||||
emac_rx_reset_100mbps;
|
||||
emac_tx_reset_100mbps;
|
||||
pktgen_gigabit <= '0';
|
||||
pktgen_fcs_en <= '1';
|
||||
wait for 60*CLK_PERIOD;
|
||||
|
||||
emac_alloc (1004);
|
||||
emac_alloc (1004);
|
||||
emac_alloc (1004);
|
||||
emac_alloc (1004);
|
||||
emac_alloc (1004);
|
||||
emac_alloc (1004);
|
||||
emac_alloc (1004);
|
||||
emac_alloc (1004);
|
||||
emac_alloc (1004);
|
||||
emac_alloc (1004);
|
||||
emac_alloc (1004);
|
||||
emac_alloc (1004);
|
||||
|
||||
for i in 1 to 10 loop
|
||||
for j in 1 to 100 loop
|
||||
emac_alloc (72);
|
||||
emac_write (72);
|
||||
end loop;
|
||||
wait for 1 ms;
|
||||
end loop;
|
||||
|
||||
wait until rising_edge(mii_tx_clk) and mii_tx_en = '0';
|
||||
wait for 6000*CLK_PERIOD;
|
||||
|
||||
loop_back_en <= '1';
|
||||
|
||||
emac_alloc (74);
|
||||
emac_write (74);
|
||||
|
||||
emac_alloc (105);
|
||||
emac_write (105);
|
||||
|
||||
emac_read (0);
|
||||
emac_free;
|
||||
|
||||
emac_read (0);
|
||||
emac_free;
|
||||
|
||||
emac_alloc (103);
|
||||
emac_write (103);
|
||||
|
||||
emac_read (0);
|
||||
emac_free;
|
||||
|
||||
emac_alloc (71);
|
||||
emac_write (71);
|
||||
|
||||
emac_read (0);
|
||||
emac_free;
|
||||
|
||||
emac_alloc (82);
|
||||
emac_write (82);
|
||||
|
||||
emac_alloc (86);
|
||||
emac_write (86);
|
||||
|
||||
emac_read (0);
|
||||
emac_free;
|
||||
|
||||
emac_read (0);
|
||||
emac_free;
|
||||
|
||||
emac_alloc (77);
|
||||
emac_write (77);
|
||||
|
||||
emac_alloc (99);
|
||||
emac_write (99);
|
||||
|
||||
emac_alloc (65);
|
||||
emac_write (65);
|
||||
|
||||
emac_alloc (321);
|
||||
emac_write (321);
|
||||
|
||||
emac_read (0);
|
||||
emac_free;
|
||||
|
||||
emac_alloc (1111);
|
||||
emac_write (1111);
|
||||
|
||||
emac_read (0);
|
||||
emac_free;
|
||||
|
||||
emac_alloc (73);
|
||||
emac_write (73);
|
||||
|
||||
emac_alloc (107);
|
||||
emac_write (107);
|
||||
|
||||
emac_alloc (83);
|
||||
emac_write (83);
|
||||
|
||||
emac_read (0);
|
||||
emac_free;
|
||||
|
||||
emac_alloc (72);
|
||||
emac_write (72);
|
||||
|
||||
emac_alloc (1003);
|
||||
emac_write (1003);
|
||||
|
||||
emac_read (0);
|
||||
emac_free;
|
||||
|
||||
emac_read (0);
|
||||
emac_free;
|
||||
|
||||
emac_read (0);
|
||||
emac_free;
|
||||
|
||||
emac_read (0);
|
||||
emac_free;
|
||||
|
||||
emac_read (0);
|
||||
emac_free;
|
||||
|
||||
emac_read (0);
|
||||
emac_free;
|
||||
|
||||
emac_read (0);
|
||||
emac_free;
|
||||
|
||||
wait for 6000*CLK_PERIOD;
|
||||
|
||||
loop_back_en <= '0';
|
||||
pktgen_en <= '1';
|
||||
pkt_count <= 0;
|
||||
for i in 1 to 500 loop
|
||||
wait for 1 us;
|
||||
emac_read (0);
|
||||
emac_free;
|
||||
pkt_count <= pkt_count + 1;
|
||||
end loop;
|
||||
pktgen_en <= '0';
|
||||
emac_read (0);
|
||||
emac_free;
|
||||
|
||||
|
||||
wait;
|
||||
|
||||
end process;
|
||||
|
||||
END;
|
||||
@@ -0,0 +1,317 @@
|
||||
-----------------------------------------------------------------------
|
||||
-- $Header: /tmp/cvsroot/VHDL/lib/misc/async_port_wb.vhd,v 1.16 2010-02-09 09:56:37 Jens Exp $
|
||||
-----------------------------------------------------------------------
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.NUMERIC_STD.ALL;
|
||||
use work.async_types.all;
|
||||
|
||||
------------------------------------------------------------------
|
||||
entity async_port_wb is
|
||||
Generic
|
||||
(
|
||||
f_sysclk : real := 100.0;
|
||||
addr_width : natural := 32;
|
||||
data_width : natural := 32;
|
||||
byte_sel_width : natural := 4;
|
||||
async_timespec : async_timespec_t
|
||||
);
|
||||
Port
|
||||
(
|
||||
CLK_I : in STD_LOGIC;
|
||||
RST_I : in STD_LOGIC;
|
||||
CYC_I : in STD_LOGIC;
|
||||
STB_I : in STD_LOGIC;
|
||||
WE_I : in STD_LOGIC;
|
||||
ACK_O : out STD_LOGIC;
|
||||
SRDY_O : out STD_LOGIC;
|
||||
MRDY_I : in STD_LOGIC;
|
||||
SEL_I : in unsigned(3 downto 0);
|
||||
ADDR_I : in unsigned(31 downto 0);
|
||||
DAT_I : in unsigned(31 downto 0);
|
||||
DAT_O : out unsigned(31 downto 0);
|
||||
page_mode_en : in STD_LOGIC;
|
||||
async_a : out unsigned(addr_width-1 downto 0);
|
||||
async_d : inout unsigned(data_width-1 downto 0);
|
||||
async_cs : out std_logic;
|
||||
async_wr : out std_logic;
|
||||
async_rd : out std_logic;
|
||||
async_be : out unsigned(byte_sel_width-1 downto 0);
|
||||
async_rst : out std_logic
|
||||
);
|
||||
end async_port_wb;
|
||||
|
||||
architecture Behavioral of async_port_wb is
|
||||
|
||||
type async_t is record
|
||||
cs : std_logic;
|
||||
wr : std_logic;
|
||||
rd : std_logic;
|
||||
rst : std_logic;
|
||||
drive_d : std_logic;
|
||||
end record;
|
||||
|
||||
type async_state_t is (start, reset, idle, leadin, pulse, leadout, release);
|
||||
|
||||
signal s, sn : async_state_t;
|
||||
signal as : async_t;
|
||||
signal ack : std_logic;
|
||||
signal cc_rst : std_logic;
|
||||
signal cycle_cnt : natural range 0 to 31;
|
||||
signal cycle_reload : natural range 0 to 31;
|
||||
signal rdy : std_logic;
|
||||
signal rdyo : std_logic;
|
||||
signal en : std_logic;
|
||||
signal is_idle : std_logic;
|
||||
signal DAT_I_r : unsigned(data_width-1 downto 0);
|
||||
signal SEL_I_r : unsigned(byte_sel_width-1 downto 0);
|
||||
signal WE_I_r : std_logic;
|
||||
signal ADDR_I_r : unsigned(addr_width-1 downto 0);
|
||||
signal page_mode_en_r : std_logic;
|
||||
signal do_page_read : std_logic;
|
||||
|
||||
------------------------------------------------------------------
|
||||
begin
|
||||
|
||||
ASSERT to_cycles(async_timespec.T_pulse_rd, f_sysclk) > 0 report "Read pulse length must be greater than zero!" severity failure;
|
||||
ASSERT to_cycles(async_timespec.T_pulse_wr, f_sysclk) > 0 report "Write pulse length must be greater than zero!" severity failure;
|
||||
ASSERT (not async_timespec.can_page_rd OR (to_cycles(async_timespec.T_pulse_page_rd, f_sysclk) > 1)) report "Read page pulse length must be greater than one!" severity failure;
|
||||
|
||||
SRDY_O <= CYC_I and rdyo;
|
||||
en <= CYC_I and STB_I;
|
||||
|
||||
do_page_read <= '1' when (async_timespec.can_page_rd and (WE_I = '0') and (WE_I_r = '0') and (ADDR_I(addr_width-1 downto async_timespec.nbits_page_rd) = ADDR_I_r(addr_width-1 downto async_timespec.nbits_page_rd))) else '0';
|
||||
|
||||
proc_cycle_counter:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if cc_rst = '1' then
|
||||
cycle_cnt <= cycle_reload;
|
||||
elsif cycle_cnt /= 0 then
|
||||
cycle_cnt <= cycle_cnt - 1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
proc_state_next:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if RST_I = '1' then
|
||||
s <= start;
|
||||
else
|
||||
s <= sn;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
proc_state:
|
||||
process(s, cycle_cnt, en, WE_I, WE_I_r, do_page_read)
|
||||
begin
|
||||
|
||||
cycle_reload <= to_cycles(async_timespec.T_pulse_rst, f_sysclk);
|
||||
cc_rst <= '0';
|
||||
as.rst <= '0';
|
||||
as.cs <= '0';
|
||||
as.wr <= '0';
|
||||
as.rd <= '0';
|
||||
as.drive_d <= '0';
|
||||
ack <= '0';
|
||||
rdy <= '0';
|
||||
is_idle <= '0';
|
||||
|
||||
sn <= s;
|
||||
case s is
|
||||
|
||||
when start =>
|
||||
cc_rst <= '1';
|
||||
sn <= reset;
|
||||
when reset =>
|
||||
as.rst <= '1';
|
||||
if cycle_cnt = 0 then
|
||||
sn <= idle;
|
||||
end if;
|
||||
when idle =>
|
||||
rdy <= '1';
|
||||
is_idle <= '1';
|
||||
if en = '1' then
|
||||
as.cs <= '1';
|
||||
cc_rst <= '1';
|
||||
if to_cycles(async_timespec.T_leadin, f_sysclk) = 0 then
|
||||
sn <= pulse;
|
||||
if WE_I = '1' then
|
||||
cycle_reload <= 0;
|
||||
sn <= leadin; -- always lead-in for writes
|
||||
else
|
||||
cycle_reload <= to_cycles(async_timespec.T_pulse_rd, f_sysclk) - 1;
|
||||
as.rd <= '1';
|
||||
end if;
|
||||
else
|
||||
cycle_reload <= to_cycles(async_timespec.T_leadin, f_sysclk) - 1;
|
||||
sn <= leadin;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
when leadin =>
|
||||
as.cs <= '1';
|
||||
as.rd <= not WE_I_r;
|
||||
as.drive_d <= WE_I_r;
|
||||
as.wr <= WE_I_r;
|
||||
if cycle_cnt = 0 then
|
||||
cc_rst <= '1';
|
||||
sn <= pulse;
|
||||
if WE_I_r = '1' then
|
||||
cycle_reload <= to_cycles(async_timespec.T_pulse_wr, f_sysclk) - 1;
|
||||
else
|
||||
cycle_reload <= to_cycles(async_timespec.T_pulse_rd, f_sysclk) - 1;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
when pulse =>
|
||||
as.cs <= '1';
|
||||
as.rd <= not WE_I_r;
|
||||
as.drive_d <= WE_I_r;
|
||||
as.wr <= WE_I_r;
|
||||
if cycle_cnt = 0 then
|
||||
as.wr <= '0';
|
||||
cc_rst <= '1';
|
||||
ack <= not WE_I_r;
|
||||
rdy <= do_page_read;
|
||||
if en = '1' and do_page_read = '1' then
|
||||
cycle_reload <= to_cycles(async_timespec.T_pulse_page_rd, f_sysclk) - 1;
|
||||
sn <= pulse;
|
||||
elsif to_cycles(async_timespec.T_leadout, f_sysclk) = 0 then
|
||||
if to_cycles(async_timespec.T_release, f_sysclk) = 0 then
|
||||
sn <= idle;
|
||||
else
|
||||
cycle_reload <= to_cycles(async_timespec.T_release, f_sysclk) - 1;
|
||||
sn <= release;
|
||||
end if;
|
||||
else
|
||||
cycle_reload <= to_cycles(async_timespec.T_leadout, f_sysclk) - 1;
|
||||
sn <= leadout;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
when leadout =>
|
||||
as.cs <= '1';
|
||||
as.drive_d <= WE_I_r;
|
||||
if cycle_cnt = 0 then
|
||||
cc_rst <= '1';
|
||||
if to_cycles(async_timespec.T_release, f_sysclk) = 0 then
|
||||
sn <= idle;
|
||||
else
|
||||
cycle_reload <= to_cycles(async_timespec.T_release, f_sysclk) - 1;
|
||||
sn <= release;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
when release =>
|
||||
if cycle_cnt = 0 then
|
||||
sn <= idle;
|
||||
end if;
|
||||
|
||||
when others =>
|
||||
sn <= idle;
|
||||
|
||||
end case;
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
output_ctrl:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
async_cs <= (not async_timespec.pol_cs) xor as.cs;
|
||||
async_wr <= (not async_timespec.pol_we) xor as.wr;
|
||||
async_rd <= (not async_timespec.pol_oe) xor as.rd;
|
||||
async_rst <= (not async_timespec.pol_rst) xor as.rst;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
din_register:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if as.rd = '1' then
|
||||
DAT_O(data_width-1 downto 0) <= async_d;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
output_addr:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if RST_I = '1' then
|
||||
async_a <= (others => '0');
|
||||
SEL_I_r <= (others => '0');
|
||||
elsif en = '1' and rdy = '1' then
|
||||
async_a <= ADDR_I(addr_width-1 downto 0);
|
||||
async_be <= (byte_sel_width-1 downto 0 => not async_timespec.pol_be) xor ((byte_sel_width-1 downto 0 => as.cs) and SEL_I(byte_sel_width-1 downto 0));
|
||||
SEL_I_r <= SEL_I(byte_sel_width-1 downto 0);
|
||||
if is_idle = '1' then
|
||||
ADDR_I_r <= ADDR_I(addr_width-1 downto 0);
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
data_register:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
page_mode_en_r <= page_mode_en;
|
||||
if en = '1' and rdy = '1' then
|
||||
DAT_I_r <= DAT_I(data_width-1 downto 0);
|
||||
WE_I_r <= WE_I;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
output_SRDY:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if RST_I = '1' then
|
||||
rdyo <= '1';
|
||||
elsif en = '1' then
|
||||
rdyo <= rdy and not rdyo;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
output_ACK:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if RST_I = '1' then
|
||||
ACK_O <= '0';
|
||||
else
|
||||
ACK_O <= ack;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
output_data:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
async_d <= (others => 'Z');
|
||||
if as.drive_d = '1' then
|
||||
async_d <= DAT_I_r;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
|
||||
end Behavioral;
|
||||
@@ -0,0 +1,60 @@
|
||||
-------------------------------------------------------------------------
|
||||
-- Project: MIPS System controller
|
||||
-- This file:
|
||||
--
|
||||
-- Copyright (C) 2008 J. Ahrensfeld
|
||||
--
|
||||
-- This program is free software: you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation, either version 3 of the License, or
|
||||
-- (at your option) any later version.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
--
|
||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||
--
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
library IEEE;
|
||||
USE IEEE.STD_LOGIC_1164.ALL;
|
||||
USE IEEE.NUMERIC_STD.ALL;
|
||||
USE IEEE.MATH_REAL.ALL;
|
||||
|
||||
package async_types is
|
||||
|
||||
type async_timespec_t is record
|
||||
T_leadin : real;
|
||||
T_pulse_rd : real;
|
||||
T_pulse_wr : real;
|
||||
T_leadout : real;
|
||||
T_release : real;
|
||||
T_pulse_rst : real;
|
||||
T_pulse_page_rd : real;
|
||||
can_page_rd : boolean;
|
||||
nbits_page_rd : natural;
|
||||
pol_cs : std_logic;
|
||||
pol_oe : std_logic;
|
||||
pol_we : std_logic;
|
||||
pol_be : std_logic;
|
||||
pol_rst : std_logic;
|
||||
end record;
|
||||
|
||||
function to_cycles(T_ns : real; f_Mhz : real) return natural;
|
||||
|
||||
end async_types;
|
||||
|
||||
package body async_types is
|
||||
|
||||
function to_cycles(T_ns : real; f_Mhz : real) return natural is
|
||||
begin
|
||||
|
||||
return natural(ceil(1.0E-3*T_ns*f_Mhz));
|
||||
|
||||
end to_cycles;
|
||||
end async_types;
|
||||
@@ -0,0 +1,79 @@
|
||||
-------------------------------------------------------------------------
|
||||
-- Project: JCPU, a portable 8-bit RISC CPU written in VHDL
|
||||
-- This file: Dual-ported register file with asynchrous read
|
||||
|
||||
-- Copyright (C) 2007 J. Ahrensfeld
|
||||
|
||||
-- This library is free software; you can redistribute it and/or
|
||||
-- modify it under the terms of the GNU Lesser General Public
|
||||
-- License as published by the Free Software Foundation; either
|
||||
-- version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
-- This library is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
-- Lesser General Public License for more details.
|
||||
|
||||
-- You should have received a copy of the GNU Lesser General Public
|
||||
-- License along with this library; if not, write to the Free Software
|
||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
-- $Header: /tmp/cvsroot/VHDL/lib/misc/dpram_1w1r.vhd,v 1.1 2008-08-23 08:20:29 Jens Exp $
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
LIBRARY IEEE;
|
||||
USE IEEE.STD_LOGIC_1164.ALL;
|
||||
USE IEEE.NUMERIC_STD.ALL;
|
||||
|
||||
entity dpram_1w1r is
|
||||
Generic (
|
||||
addr_width : integer := 3;
|
||||
data_width : integer := 8
|
||||
);
|
||||
Port (
|
||||
clka : in STD_LOGIC;
|
||||
clkb : in STD_LOGIC;
|
||||
en_a : in STD_LOGIC;
|
||||
en_b : in STD_LOGIC;
|
||||
we_a : in STD_LOGIC;
|
||||
addr_a : in unsigned (addr_width-1 downto 0);
|
||||
addr_b : in unsigned (addr_width-1 downto 0);
|
||||
din_a : in unsigned (data_width-1 downto 0);
|
||||
dout_b : out unsigned (data_width-1 downto 0)
|
||||
);
|
||||
end dpram_1w1r;
|
||||
|
||||
architecture Behavioral of dpram_1w1r is
|
||||
|
||||
constant depth : integer := 2**addr_width;
|
||||
type RAMtype is array (0 to depth-1) of unsigned (data_width-1 downto 0);
|
||||
signal RAM : RAMtype;
|
||||
|
||||
begin
|
||||
|
||||
process (clka)
|
||||
begin
|
||||
if clka'event and clka = '1' then
|
||||
if en_a = '1' then
|
||||
if we_a = '1' then
|
||||
RAM(to_integer(addr_a)) <= din_a;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process (clkb)
|
||||
begin
|
||||
if clkb'event and clkb = '1' then
|
||||
if en_b = '1' then
|
||||
dout_b <= RAM(to_integer(addr_b));
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
|
||||
end Behavioral;
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
-------------------------------------------------------------------------
|
||||
-- Project: JCPU, a portable 8-bit RISC CPU written in VHDL
|
||||
-- This file: Dual-ported register file with asynchrous read
|
||||
|
||||
-- Copyright (C) 2007 J. Ahrensfeld
|
||||
|
||||
-- This library is free software; you can redistribute it and/or
|
||||
-- modify it under the terms of the GNU Lesser General Public
|
||||
-- License as published by the Free Software Foundation; either
|
||||
-- version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
-- This library is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
-- Lesser General Public License for more details.
|
||||
|
||||
-- You should have received a copy of the GNU Lesser General Public
|
||||
-- License along with this library; if not, write to the Free Software
|
||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
-- $Header: /tmp/cvsroot/VHDL/lib/misc/dpram_2w2r.vhd,v 1.2 2009-01-14 20:26:29 Jens Exp $
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.numeric_std.ALL;
|
||||
|
||||
entity dpram_2w2r is
|
||||
Generic
|
||||
(
|
||||
addr_width : integer := 3;
|
||||
data_width : integer := 8
|
||||
);
|
||||
Port
|
||||
(
|
||||
clk_a : in STD_LOGIC;
|
||||
clk_b : in STD_LOGIC;
|
||||
en_a : in STD_LOGIC;
|
||||
en_b : in STD_LOGIC;
|
||||
we_a : in STD_LOGIC;
|
||||
we_b : in STD_LOGIC;
|
||||
addr_a : in unsigned (addr_width-1 downto 0);
|
||||
addr_b : in unsigned (addr_width-1 downto 0);
|
||||
din_a : in unsigned (data_width-1 downto 0);
|
||||
din_b : in unsigned (data_width-1 downto 0);
|
||||
dout_a : out unsigned (data_width-1 downto 0);
|
||||
dout_b : out unsigned (data_width-1 downto 0)
|
||||
);
|
||||
end dpram_2w2r;
|
||||
|
||||
architecture Behavioral of dpram_2w2r is
|
||||
|
||||
constant depth : integer := 2**addr_width;
|
||||
type RAMtype is array (0 to depth-1) of unsigned (data_width-1 downto 0);
|
||||
shared variable RAM : RAMtype;
|
||||
|
||||
begin
|
||||
|
||||
process (clk_a)
|
||||
begin
|
||||
if clk_a'event and clk_a = '1' then
|
||||
if en_a = '1' then
|
||||
if we_a = '1' then
|
||||
RAM(to_integer(addr_a)) := din_a;
|
||||
end if;
|
||||
dout_a <= RAM(to_integer(addr_a));
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process (clk_b)
|
||||
begin
|
||||
if clk_b'event and clk_b = '1' then
|
||||
if en_b = '1' then
|
||||
if we_b = '1' then
|
||||
RAM(to_integer(addr_b)) := din_b;
|
||||
end if;
|
||||
dout_b <= RAM(to_integer(addr_b));
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
|
||||
end Behavioral;
|
||||
|
||||
@@ -0,0 +1,309 @@
|
||||
LIBRARY IEEE;
|
||||
USE IEEE.STD_LOGIC_1164.ALL;
|
||||
USE IEEE.NUMERIC_STD.ALL;
|
||||
|
||||
ENTITY gpio_wb IS
|
||||
Generic
|
||||
(
|
||||
f_sysclk : real := 100.0
|
||||
);
|
||||
Port
|
||||
(
|
||||
CLK_I : in STD_LOGIC;
|
||||
RST_I : in STD_LOGIC;
|
||||
CYC_I : in STD_LOGIC;
|
||||
STB_I : in STD_LOGIC;
|
||||
SEL_I : in unsigned(3 downto 0);
|
||||
WE_I : in STD_LOGIC;
|
||||
ACK_O : out STD_LOGIC;
|
||||
SRDY_O : out STD_LOGIC;
|
||||
MRDY_I : in STD_LOGIC;
|
||||
ADDR_I : in unsigned(31 downto 0);
|
||||
DAT_I : in unsigned(31 downto 0);
|
||||
DAT_O : out unsigned(31 downto 0);
|
||||
INT_TIM_O : out STD_LOGIC;
|
||||
|
||||
sys_gpi_0 : in unsigned(31 downto 0);
|
||||
sys_gpo_0 : out unsigned(31 downto 0)
|
||||
|
||||
);
|
||||
END gpio_wb;
|
||||
|
||||
ARCHITECTURE behavior OF gpio_wb IS
|
||||
|
||||
constant num_timers : natural := 2;
|
||||
constant ncycles_usec : natural := natural(f_sysclk);
|
||||
|
||||
signal gpio_0_dout_reg : unsigned(31 downto 0);
|
||||
signal gpio_0_dir_reg : unsigned(31 downto 0);
|
||||
signal gpio_0_din_reg : unsigned(31 downto 0);
|
||||
|
||||
-- Signals to form an timer generating an interrupt every microsecond
|
||||
subtype tick_usec_t is natural range 0 to ncycles_usec-1;
|
||||
signal tick_usec : tick_usec_t := 0;
|
||||
signal cnt_usec : unsigned(31 downto 0);
|
||||
signal cnt_sec : unsigned(31 downto 0);
|
||||
signal cnt_usec_preset : unsigned(31 downto 0);
|
||||
signal cnt_sec_preset : unsigned(31 downto 0);
|
||||
signal cnt_usec_en : std_logic;
|
||||
signal cnt_usec_we : std_logic;
|
||||
signal cnt_sec_en : std_logic;
|
||||
signal cnt_sec_we : std_logic;
|
||||
|
||||
type timer_array_t is array (0 to num_timers-1) of unsigned(31 downto 0);
|
||||
signal timer_cnt : timer_array_t;
|
||||
signal timer_cmp : timer_array_t;
|
||||
signal timer_en : unsigned(0 to num_timers-1);
|
||||
signal timer_inten : unsigned(0 to num_timers-1);
|
||||
signal timer_irq : unsigned(0 to num_timers-1);
|
||||
signal timer_ovl : unsigned(0 to num_timers-1);
|
||||
signal timer_irq_ack : unsigned(0 to num_timers-1);
|
||||
signal timer_cnt_we : unsigned(0 to num_timers-1);
|
||||
signal timer_cmp_we : unsigned(0 to num_timers-1);
|
||||
|
||||
signal reg_data_wr : unsigned(31 downto 0);
|
||||
|
||||
begin
|
||||
|
||||
SRDY_O <= CYC_I;
|
||||
|
||||
tim_irq:
|
||||
process(timer_irq)
|
||||
variable irq : std_logic;
|
||||
begin
|
||||
irq := '0';
|
||||
for i in 0 to num_timers-1 loop
|
||||
irq := irq or timer_irq(i);
|
||||
end loop;
|
||||
INT_TIM_O <= irq;
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
gpio_0_out:
|
||||
process(gpio_0_dir_reg, gpio_0_dout_reg)
|
||||
begin
|
||||
for i in 0 to 31 loop
|
||||
sys_gpo_0(i) <= 'Z';
|
||||
if gpio_0_dir_reg(i) = '1' then
|
||||
sys_gpo_0(i) <= gpio_0_dout_reg(i);
|
||||
end if;
|
||||
end loop;
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
gpio_0_in:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
for i in 0 to 31 loop
|
||||
if gpio_0_dir_reg(i) = '1' then
|
||||
gpio_0_din_reg(i) <= gpio_0_dout_reg(i);
|
||||
else
|
||||
gpio_0_din_reg(i) <= sys_gpi_0(i);
|
||||
end if;
|
||||
end loop;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
|
||||
------------------------------------------------------------------
|
||||
registers_write:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
cnt_usec_we <= '0';
|
||||
cnt_sec_we <= '0';
|
||||
timer_cnt_we <= (others => '0');
|
||||
timer_cmp_we <= (others => '0');
|
||||
timer_irq_ack <= (others => '0');
|
||||
if RST_I = '1' then
|
||||
gpio_0_dout_reg <= (others => '0');
|
||||
gpio_0_dir_reg <= (others => '0');
|
||||
timer_en <= (others => '0');
|
||||
timer_inten <= (others => '0');
|
||||
elsif (STB_I and CYC_I and WE_I) = '1' then
|
||||
reg_data_wr <= DAT_I;
|
||||
case ADDR_I(6 downto 2) is
|
||||
|
||||
when "00000" =>
|
||||
gpio_0_dout_reg <= DAT_I;
|
||||
|
||||
when "00001" =>
|
||||
gpio_0_dir_reg <= DAT_I;
|
||||
|
||||
when "00010" =>
|
||||
cnt_usec_we <= '1';
|
||||
|
||||
when "00011" =>
|
||||
cnt_sec_we <= '1';
|
||||
|
||||
when "00110" => -- timer control
|
||||
for i in 0 to num_timers-1 loop
|
||||
timer_en(i) <= DAT_I(2*i+0);
|
||||
timer_inten(i) <= DAT_I(2*i+1);
|
||||
end loop;
|
||||
when "00111" => -- timer status
|
||||
for i in 0 to num_timers-1 loop
|
||||
timer_irq_ack(i) <= DAT_I(2*i); -- IRQ acknowledge
|
||||
end loop;
|
||||
|
||||
when "01000" => -- timer count 0
|
||||
timer_cnt_we(0) <= '1';
|
||||
|
||||
when "01001" => -- timer count 1
|
||||
timer_cnt_we(1) <= '1';
|
||||
|
||||
when "01100" => -- timer compare 0
|
||||
timer_cmp_we(0) <= '1';
|
||||
|
||||
when "01101" => -- timer compare 1
|
||||
timer_cmp_we(1) <= '1';
|
||||
|
||||
when others => null;
|
||||
end case;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
registers_read:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
ACK_O <= '0';
|
||||
if (STB_I and CYC_I) = '1' then
|
||||
ACK_O <= not WE_I;
|
||||
DAT_O <= (others => '0');
|
||||
case ADDR_I(6 downto 2) is
|
||||
|
||||
when "00000" =>
|
||||
DAT_O <= gpio_0_din_reg;
|
||||
|
||||
when "00001" =>
|
||||
DAT_O <= gpio_0_dir_reg;
|
||||
|
||||
when "00010" =>
|
||||
DAT_O <= cnt_usec;
|
||||
|
||||
when "00011" =>
|
||||
DAT_O <= cnt_sec;
|
||||
|
||||
when "00110" => -- timer control
|
||||
for i in 0 to num_timers-1 loop
|
||||
DAT_O(2*i+0) <= timer_en(i);
|
||||
DAT_O(2*i+1) <= timer_inten(i);
|
||||
end loop;
|
||||
|
||||
when "00111" => -- timer status
|
||||
for i in 0 to num_timers-1 loop
|
||||
DAT_O(2*i+0) <= timer_irq(i);
|
||||
DAT_O(2*i+1) <= timer_ovl(i);
|
||||
end loop;
|
||||
|
||||
when "01000" => -- timer count 0
|
||||
DAT_O <= timer_cnt(0);
|
||||
|
||||
when "01001" => -- timer count 1
|
||||
DAT_O <= timer_cnt(1);
|
||||
|
||||
when "01100" => -- timer compare 0
|
||||
DAT_O <= timer_cmp(0);
|
||||
|
||||
when "01101" => -- timer compare 1
|
||||
DAT_O <= timer_cmp(1);
|
||||
|
||||
when others => null;
|
||||
end case;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
cnt_usec_tick:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
cnt_usec_en <= '0';
|
||||
if tick_usec >= tick_usec_t'high then
|
||||
tick_usec <= 0;
|
||||
cnt_usec_en <= '1';
|
||||
else
|
||||
tick_usec <= tick_usec + 1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- H/W Clock
|
||||
cnt_usec_clock:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
cnt_sec_en <= '0';
|
||||
if cnt_usec_we = '1' then
|
||||
cnt_usec <= reg_data_wr;
|
||||
elsif cnt_usec_en = '1' then
|
||||
if to_01(cnt_usec) >= to_unsigned(1E6 - 1, 32) then
|
||||
cnt_usec <= (others => '0');
|
||||
cnt_sec_en <= '1';
|
||||
else
|
||||
cnt_usec <= cnt_usec + 1;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
cnt_sec_clock:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if cnt_sec_we = '1' then
|
||||
cnt_sec <= reg_data_wr;
|
||||
elsif cnt_sec_en = '1' then
|
||||
cnt_sec <= cnt_sec + 1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- Interrupt timer
|
||||
proc_int_timer:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
for i in 0 to num_timers-1 loop
|
||||
if RST_I = '1' then
|
||||
timer_ovl(i) <= '0';
|
||||
timer_irq(i) <= '0';
|
||||
elsif timer_irq_ack(i) = '1' then
|
||||
timer_ovl(i) <= '0';
|
||||
timer_irq(i) <= '0';
|
||||
elsif timer_cnt_we(i) = '1' then
|
||||
timer_cnt(i) <= reg_data_wr;
|
||||
elsif timer_en(i) = '1' then
|
||||
if to_01(timer_cnt(i)) >= timer_cmp(i) then
|
||||
timer_cnt(i) <= (others => '0');
|
||||
if timer_inten(i) = '1' then
|
||||
if timer_irq(i) = '1' then
|
||||
timer_ovl(i) <= '1';
|
||||
end if;
|
||||
timer_irq(i) <= '1';
|
||||
end if;
|
||||
else
|
||||
timer_cnt(i) <= timer_cnt(i) + 1;
|
||||
end if;
|
||||
end if;
|
||||
end loop;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
proc_int_timer_reload:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
for i in 0 to num_timers-1 loop
|
||||
if timer_cmp_we(i) = '1' then
|
||||
timer_cmp(i) <= reg_data_wr;
|
||||
end if;
|
||||
end loop;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
end behavior;
|
||||
@@ -0,0 +1,61 @@
|
||||
LIBRARY IEEE;
|
||||
USE IEEE.STD_LOGIC_1164.ALL;
|
||||
USE IEEE.NUMERIC_STD.ALL;
|
||||
|
||||
ENTITY rom_wb IS
|
||||
Port
|
||||
(
|
||||
CLK_I : in STD_LOGIC;
|
||||
RST_I : in STD_LOGIC;
|
||||
CYC_I : in STD_LOGIC;
|
||||
STB_I : in STD_LOGIC;
|
||||
ACK_O : out STD_LOGIC;
|
||||
MRDY_I : in STD_LOGIC;
|
||||
SRDY_O : out STD_LOGIC;
|
||||
ADDR_I : in unsigned(31 downto 0);
|
||||
DAT_O : out unsigned(31 downto 0)
|
||||
);
|
||||
END rom_wb;
|
||||
|
||||
ARCHITECTURE behavior OF rom_wb IS
|
||||
|
||||
COMPONENT rom
|
||||
PORT
|
||||
(
|
||||
clk : in STD_LOGIC;
|
||||
ce : in STD_LOGIC;
|
||||
addr : in unsigned(31 downto 0);
|
||||
dout : out unsigned(31 downto 0)
|
||||
);
|
||||
END COMPONENT;
|
||||
|
||||
signal data_en : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
data_en <= CYC_I and STB_I and MRDY_I;
|
||||
SRDY_O <= CYC_I;
|
||||
|
||||
data_valid_register:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if RST_I = '1' then
|
||||
ACK_O <= '0';
|
||||
else
|
||||
ACK_O <= data_en; -- and not WE_I;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
inst_rom : rom
|
||||
PORT MAP
|
||||
(
|
||||
clk => CLK_I,
|
||||
ce => data_en,
|
||||
addr => ADDR_I,
|
||||
dout => DAT_O
|
||||
);
|
||||
|
||||
|
||||
end behavior;
|
||||
@@ -0,0 +1,281 @@
|
||||
-- 'Bucket Brigade' FIFO
|
||||
-- 16 deep
|
||||
-- 8-bit data
|
||||
--
|
||||
-- Version : 1.10
|
||||
-- Version Date : 3rd December 2003
|
||||
-- Reason : '--translate' directives changed to '--synthesis translate' directives
|
||||
--
|
||||
-- Version : 1.00
|
||||
-- Version Date : 14th October 2002
|
||||
--
|
||||
-- Start of design entry : 14th October 2002
|
||||
--
|
||||
-- Ken Chapman
|
||||
-- Xilinx Ltd
|
||||
-- Benchmark House
|
||||
-- 203 Brooklands Road
|
||||
-- Weybridge
|
||||
-- Surrey KT13 ORH
|
||||
-- United Kingdom
|
||||
--
|
||||
-- chapman@xilinx.com
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- NOTICE:
|
||||
--
|
||||
-- Copyright Xilinx, Inc. 2002. This code may be contain portions patented by other
|
||||
-- third parties. By providing this core as one possible implementation of a standard,
|
||||
-- Xilinx is making no representation that the provided implementation of this standard
|
||||
-- is free from any claims of infringement by any third party. Xilinx expressly
|
||||
-- disclaims any warranty with respect to the adequacy of the implementation, including
|
||||
-- but not limited to any warranty or representation that the implementation is free
|
||||
-- from claims of any third party. Futhermore, Xilinx is providing this core as a
|
||||
-- courtesy to you and suggests that you contact all third parties to obtain the
|
||||
-- necessary rights to use this implementation.
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- Library declarations
|
||||
--
|
||||
-- The Unisim Library is used to define Xilinx primitives. It is also used during
|
||||
-- simulation. The source can be viewed at %XILINX%\vhdl\src\unisims\unisim_VCOMP.vhd
|
||||
--
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.STD_LOGIC_ARITH.ALL;
|
||||
use IEEE.STD_LOGIC_UNSIGNED.ALL;
|
||||
library unisim;
|
||||
use unisim.vcomponents.all;
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- Main Entity for BBFIFO_16x8
|
||||
--
|
||||
entity bbfifo_16x8 is
|
||||
Port ( data_in : in std_logic_vector(7 downto 0);
|
||||
data_out : out std_logic_vector(7 downto 0);
|
||||
reset : in std_logic;
|
||||
write : in std_logic;
|
||||
read : in std_logic;
|
||||
full : out std_logic;
|
||||
half_full : out std_logic;
|
||||
data_present : out std_logic;
|
||||
clk : in std_logic);
|
||||
end bbfifo_16x8;
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- Start of Main Architecture for BBFIFO_16x8
|
||||
--
|
||||
architecture low_level_definition of bbfifo_16x8 is
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- Signals used in BBFIFO_16x8
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
signal pointer : std_logic_vector(3 downto 0);
|
||||
signal next_count : std_logic_vector(3 downto 0);
|
||||
signal half_count : std_logic_vector(3 downto 0);
|
||||
signal count_carry : std_logic_vector(2 downto 0);
|
||||
|
||||
signal pointer_zero : std_logic;
|
||||
signal pointer_full : std_logic;
|
||||
signal decode_data_present : std_logic;
|
||||
signal data_present_int : std_logic;
|
||||
signal valid_write : std_logic;
|
||||
--
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- Attributes to define LUT contents during implementation
|
||||
-- The information is repeated in the generic map for functional simulation--
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
attribute INIT : string;
|
||||
attribute INIT of zero_lut : label is "0001";
|
||||
attribute INIT of full_lut : label is "8000";
|
||||
attribute INIT of dp_lut : label is "BFA0";
|
||||
attribute INIT of valid_lut : label is "C4";
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- Start of BBFIFO_16x8 circuit description
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
begin
|
||||
|
||||
-- SRL16E data storage
|
||||
|
||||
data_width_loop: for i in 0 to 7 generate
|
||||
--
|
||||
attribute INIT : string;
|
||||
attribute INIT of data_srl : label is "0000";
|
||||
--
|
||||
begin
|
||||
|
||||
data_srl: SRL16E
|
||||
--synthesis translate_off
|
||||
generic map (INIT => X"0000")
|
||||
--synthesis translate_on
|
||||
port map( D => data_in(i),
|
||||
CE => valid_write,
|
||||
CLK => clk,
|
||||
A0 => pointer(0),
|
||||
A1 => pointer(1),
|
||||
A2 => pointer(2),
|
||||
A3 => pointer(3),
|
||||
Q => data_out(i) );
|
||||
|
||||
end generate data_width_loop;
|
||||
|
||||
-- 4-bit counter to act as data pointer
|
||||
-- Counter is clock enabled by 'data_present'
|
||||
-- Counter will be reset when 'reset' is active
|
||||
-- Counter will increment when 'valid_write' is active
|
||||
|
||||
count_width_loop: for i in 0 to 3 generate
|
||||
--
|
||||
attribute INIT : string;
|
||||
attribute INIT of count_lut : label is "6606";
|
||||
--
|
||||
begin
|
||||
|
||||
register_bit: FDRE
|
||||
port map ( D => next_count(i),
|
||||
Q => pointer(i),
|
||||
CE => data_present_int,
|
||||
R => reset,
|
||||
C => clk);
|
||||
|
||||
count_lut: LUT4
|
||||
--synthesis translate_off
|
||||
generic map (INIT => X"6606")
|
||||
--synthesis translate_on
|
||||
port map( I0 => pointer(i),
|
||||
I1 => read,
|
||||
I2 => pointer_zero,
|
||||
I3 => write,
|
||||
O => half_count(i));
|
||||
|
||||
lsb_count: if i=0 generate
|
||||
begin
|
||||
|
||||
count_muxcy: MUXCY
|
||||
port map( DI => pointer(i),
|
||||
CI => valid_write,
|
||||
S => half_count(i),
|
||||
O => count_carry(i));
|
||||
|
||||
count_xor: XORCY
|
||||
port map( LI => half_count(i),
|
||||
CI => valid_write,
|
||||
O => next_count(i));
|
||||
|
||||
end generate lsb_count;
|
||||
|
||||
mid_count: if i>0 and i<3 generate
|
||||
begin
|
||||
|
||||
count_muxcy: MUXCY
|
||||
port map( DI => pointer(i),
|
||||
CI => count_carry(i-1),
|
||||
S => half_count(i),
|
||||
O => count_carry(i));
|
||||
|
||||
count_xor: XORCY
|
||||
port map( LI => half_count(i),
|
||||
CI => count_carry(i-1),
|
||||
O => next_count(i));
|
||||
|
||||
end generate mid_count;
|
||||
|
||||
upper_count: if i=3 generate
|
||||
begin
|
||||
|
||||
count_xor: XORCY
|
||||
port map( LI => half_count(i),
|
||||
CI => count_carry(i-1),
|
||||
O => next_count(i));
|
||||
|
||||
end generate upper_count;
|
||||
|
||||
end generate count_width_loop;
|
||||
|
||||
|
||||
-- Detect when pointer is zero and maximum
|
||||
|
||||
zero_lut: LUT4
|
||||
--synthesis translate_off
|
||||
generic map (INIT => X"0001")
|
||||
--synthesis translate_on
|
||||
port map( I0 => pointer(0),
|
||||
I1 => pointer(1),
|
||||
I2 => pointer(2),
|
||||
I3 => pointer(3),
|
||||
O => pointer_zero );
|
||||
|
||||
|
||||
full_lut: LUT4
|
||||
--synthesis translate_off
|
||||
generic map (INIT => X"8000")
|
||||
--synthesis translate_on
|
||||
port map( I0 => pointer(0),
|
||||
I1 => pointer(1),
|
||||
I2 => pointer(2),
|
||||
I3 => pointer(3),
|
||||
O => pointer_full );
|
||||
|
||||
|
||||
-- Data Present status
|
||||
|
||||
dp_lut: LUT4
|
||||
--synthesis translate_off
|
||||
generic map (INIT => X"BFA0")
|
||||
--synthesis translate_on
|
||||
port map( I0 => write,
|
||||
I1 => read,
|
||||
I2 => pointer_zero,
|
||||
I3 => data_present_int,
|
||||
O => decode_data_present );
|
||||
|
||||
dp_flop: FDR
|
||||
port map ( D => decode_data_present,
|
||||
Q => data_present_int,
|
||||
R => reset,
|
||||
C => clk);
|
||||
|
||||
-- Valid write signal
|
||||
|
||||
valid_lut: LUT3
|
||||
--synthesis translate_off
|
||||
generic map (INIT => X"C4")
|
||||
--synthesis translate_on
|
||||
port map( I0 => pointer_full,
|
||||
I1 => write,
|
||||
I2 => read,
|
||||
O => valid_write );
|
||||
|
||||
|
||||
-- assign internal signals to outputs
|
||||
|
||||
full <= pointer_full;
|
||||
half_full <= pointer(3);
|
||||
data_present <= data_present_int;
|
||||
|
||||
end low_level_definition;
|
||||
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- END OF FILE BBFIFO_16x8.VHD
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -0,0 +1,352 @@
|
||||
-- Constant (K) Compact UART Receiver
|
||||
--
|
||||
-- Version : 1.10
|
||||
-- Version Date : 3rd December 2003
|
||||
-- Reason : '--translate' directives changed to '--synthesis translate' directives
|
||||
--
|
||||
-- Version : 1.00
|
||||
-- Version Date : 16th October 2002
|
||||
--
|
||||
-- Start of design entry : 16th October 2002
|
||||
--
|
||||
-- Ken Chapman
|
||||
-- Xilinx Ltd
|
||||
-- Benchmark House
|
||||
-- 203 Brooklands Road
|
||||
-- Weybridge
|
||||
-- Surrey KT13 ORH
|
||||
-- United Kingdom
|
||||
--
|
||||
-- chapman@xilinx.com
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- NOTICE:
|
||||
--
|
||||
-- Copyright Xilinx, Inc. 2002. This code may be contain portions patented by other
|
||||
-- third parties. By providing this core as one possible implementation of a standard,
|
||||
-- Xilinx is making no representation that the provided implementation of this standard
|
||||
-- is free from any claims of infringement by any third party. Xilinx expressly
|
||||
-- disclaims any warranty with respect to the adequacy of the implementation, including
|
||||
-- but not limited to any warranty or representation that the implementation is free
|
||||
-- from claims of any third party. Futhermore, Xilinx is providing this core as a
|
||||
-- courtesy to you and suggests that you contact all third parties to obtain the
|
||||
-- necessary rights to use this implementation.
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- Library declarations
|
||||
--
|
||||
-- The Unisim Library is used to define Xilinx primitives. It is also used during
|
||||
-- simulation. The source can be viewed at %XILINX%\vhdl\src\unisims\unisim_VCOMP.vhd
|
||||
--
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.STD_LOGIC_ARITH.ALL;
|
||||
use IEEE.STD_LOGIC_UNSIGNED.ALL;
|
||||
library unisim;
|
||||
use unisim.vcomponents.all;
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- Main Entity for KCUART_RX
|
||||
--
|
||||
entity kcuart_rx is
|
||||
Port ( serial_in : in std_logic;
|
||||
data_out : out std_logic_vector(7 downto 0);
|
||||
data_strobe : out std_logic;
|
||||
en_16_x_baud : in std_logic;
|
||||
clk : in std_logic);
|
||||
end kcuart_rx;
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- Start of Main Architecture for KCUART_RX
|
||||
--
|
||||
architecture low_level_definition of kcuart_rx is
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- Signals used in KCUART_RX
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
signal sync_serial : std_logic;
|
||||
signal stop_bit : std_logic;
|
||||
signal data_int : std_logic_vector(7 downto 0);
|
||||
signal data_delay : std_logic_vector(7 downto 0);
|
||||
signal start_delay : std_logic;
|
||||
signal start_bit : std_logic;
|
||||
signal edge_delay : std_logic;
|
||||
signal start_edge : std_logic;
|
||||
signal decode_valid_char : std_logic;
|
||||
signal valid_char : std_logic;
|
||||
signal decode_purge : std_logic;
|
||||
signal purge : std_logic;
|
||||
signal valid_srl_delay : std_logic_vector(8 downto 0);
|
||||
signal valid_reg_delay : std_logic_vector(8 downto 0);
|
||||
signal decode_data_strobe : std_logic;
|
||||
--
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- Attributes to define LUT contents during implementation
|
||||
-- The information is repeated in the generic map for functional simulation--
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
attribute INIT : string;
|
||||
attribute INIT of start_srl : label is "0000";
|
||||
attribute INIT of edge_srl : label is "0000";
|
||||
attribute INIT of valid_lut : label is "0040";
|
||||
attribute INIT of purge_lut : label is "54";
|
||||
attribute INIT of strobe_lut : label is "8";
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- Start of KCUART_RX circuit description
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
begin
|
||||
|
||||
-- Synchronise input serial data to system clock
|
||||
|
||||
sync_reg: FD
|
||||
port map ( D => serial_in,
|
||||
Q => sync_serial,
|
||||
C => clk);
|
||||
|
||||
stop_reg: FD
|
||||
port map ( D => sync_serial,
|
||||
Q => stop_bit,
|
||||
C => clk);
|
||||
|
||||
|
||||
-- Data delays to capture data at 16 time baud rate
|
||||
-- Each SRL16E is followed by a flip-flop for best timing
|
||||
|
||||
data_loop: for i in 0 to 7 generate
|
||||
begin
|
||||
|
||||
lsbs: if i<7 generate
|
||||
--
|
||||
attribute INIT : string;
|
||||
attribute INIT of delay15_srl : label is "0000";
|
||||
--
|
||||
begin
|
||||
|
||||
delay15_srl: SRL16E
|
||||
--synthesis translate_off
|
||||
generic map (INIT => X"0000")
|
||||
--synthesis translate_on
|
||||
port map( D => data_int(i+1),
|
||||
CE => en_16_x_baud,
|
||||
CLK => clk,
|
||||
A0 => '0',
|
||||
A1 => '1',
|
||||
A2 => '1',
|
||||
A3 => '1',
|
||||
Q => data_delay(i) );
|
||||
|
||||
end generate lsbs;
|
||||
|
||||
msb: if i=7 generate
|
||||
--
|
||||
attribute INIT : string;
|
||||
attribute INIT of delay15_srl : label is "0000";
|
||||
--
|
||||
begin
|
||||
|
||||
delay15_srl: SRL16E
|
||||
--synthesis translate_off
|
||||
generic map (INIT => X"0000")
|
||||
--synthesis translate_on
|
||||
port map( D => stop_bit,
|
||||
CE => en_16_x_baud,
|
||||
CLK => clk,
|
||||
A0 => '0',
|
||||
A1 => '1',
|
||||
A2 => '1',
|
||||
A3 => '1',
|
||||
Q => data_delay(i) );
|
||||
|
||||
end generate msb;
|
||||
|
||||
data_reg: FDE
|
||||
port map ( D => data_delay(i),
|
||||
Q => data_int(i),
|
||||
CE => en_16_x_baud,
|
||||
C => clk);
|
||||
|
||||
end generate data_loop;
|
||||
|
||||
-- Assign internal signals to outputs
|
||||
|
||||
data_out <= data_int;
|
||||
|
||||
-- Data delays to capture start bit at 16 time baud rate
|
||||
|
||||
start_srl: SRL16E
|
||||
--synthesis translate_off
|
||||
generic map (INIT => X"0000")
|
||||
--synthesis translate_on
|
||||
port map( D => data_int(0),
|
||||
CE => en_16_x_baud,
|
||||
CLK => clk,
|
||||
A0 => '0',
|
||||
A1 => '1',
|
||||
A2 => '1',
|
||||
A3 => '1',
|
||||
Q => start_delay );
|
||||
|
||||
start_reg: FDE
|
||||
port map ( D => start_delay,
|
||||
Q => start_bit,
|
||||
CE => en_16_x_baud,
|
||||
C => clk);
|
||||
|
||||
|
||||
-- Data delays to capture start bit leading edge at 16 time baud rate
|
||||
-- Delay ensures data is captured at mid-bit position
|
||||
|
||||
edge_srl: SRL16E
|
||||
--synthesis translate_off
|
||||
generic map (INIT => X"0000")
|
||||
--synthesis translate_on
|
||||
port map( D => start_bit,
|
||||
CE => en_16_x_baud,
|
||||
CLK => clk,
|
||||
A0 => '1',
|
||||
A1 => '0',
|
||||
A2 => '1',
|
||||
A3 => '0',
|
||||
Q => edge_delay );
|
||||
|
||||
edge_reg: FDE
|
||||
port map ( D => edge_delay,
|
||||
Q => start_edge,
|
||||
CE => en_16_x_baud,
|
||||
C => clk);
|
||||
|
||||
-- Detect a valid character
|
||||
|
||||
valid_lut: LUT4
|
||||
--synthesis translate_off
|
||||
generic map (INIT => X"0040")
|
||||
--synthesis translate_on
|
||||
port map( I0 => purge,
|
||||
I1 => stop_bit,
|
||||
I2 => start_edge,
|
||||
I3 => edge_delay,
|
||||
O => decode_valid_char );
|
||||
|
||||
valid_reg: FDE
|
||||
port map ( D => decode_valid_char,
|
||||
Q => valid_char,
|
||||
CE => en_16_x_baud,
|
||||
C => clk);
|
||||
|
||||
-- Purge of data status
|
||||
|
||||
purge_lut: LUT3
|
||||
--synthesis translate_off
|
||||
generic map (INIT => X"54")
|
||||
--synthesis translate_on
|
||||
port map( I0 => valid_reg_delay(8),
|
||||
I1 => valid_char,
|
||||
I2 => purge,
|
||||
O => decode_purge );
|
||||
|
||||
purge_reg: FDE
|
||||
port map ( D => decode_purge,
|
||||
Q => purge,
|
||||
CE => en_16_x_baud,
|
||||
C => clk);
|
||||
|
||||
-- Delay of valid_char pulse of length equivalent to the time taken
|
||||
-- to purge data shift register of all data which has been used.
|
||||
-- Requires 9x16 + 8 delays which is achieved by packing of SRL16E with
|
||||
-- up to 16 delays and utilising the dedicated flip flop in each stage.
|
||||
|
||||
valid_loop: for i in 0 to 8 generate
|
||||
begin
|
||||
|
||||
lsb: if i=0 generate
|
||||
--
|
||||
attribute INIT : string;
|
||||
attribute INIT of delay15_srl : label is "0000";
|
||||
--
|
||||
begin
|
||||
|
||||
delay15_srl: SRL16E
|
||||
--synthesis translate_off
|
||||
generic map (INIT => X"0000")
|
||||
--synthesis translate_on
|
||||
port map( D => valid_char,
|
||||
CE => en_16_x_baud,
|
||||
CLK => clk,
|
||||
A0 => '0',
|
||||
A1 => '1',
|
||||
A2 => '1',
|
||||
A3 => '1',
|
||||
Q => valid_srl_delay(i) );
|
||||
|
||||
end generate lsb;
|
||||
|
||||
msbs: if i>0 generate
|
||||
--
|
||||
attribute INIT : string;
|
||||
attribute INIT of delay16_srl : label is "0000";
|
||||
--
|
||||
begin
|
||||
|
||||
delay16_srl: SRL16E
|
||||
--synthesis translate_off
|
||||
generic map (INIT => X"0000")
|
||||
--synthesis translate_on
|
||||
port map( D => valid_reg_delay(i-1),
|
||||
CE => en_16_x_baud,
|
||||
CLK => clk,
|
||||
A0 => '1',
|
||||
A1 => '1',
|
||||
A2 => '1',
|
||||
A3 => '1',
|
||||
Q => valid_srl_delay(i) );
|
||||
|
||||
end generate msbs;
|
||||
|
||||
data_reg: FDE
|
||||
port map ( D => valid_srl_delay(i),
|
||||
Q => valid_reg_delay(i),
|
||||
CE => en_16_x_baud,
|
||||
C => clk);
|
||||
|
||||
end generate valid_loop;
|
||||
|
||||
-- Form data strobe
|
||||
|
||||
strobe_lut: LUT2
|
||||
--synthesis translate_off
|
||||
generic map (INIT => X"8")
|
||||
--synthesis translate_on
|
||||
port map( I0 => valid_char,
|
||||
I1 => en_16_x_baud,
|
||||
O => decode_data_strobe );
|
||||
|
||||
strobe_reg: FD
|
||||
port map ( D => decode_data_strobe,
|
||||
Q => data_strobe,
|
||||
C => clk);
|
||||
|
||||
end low_level_definition;
|
||||
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- END OF FILE KCUART_RX.VHD
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -0,0 +1,394 @@
|
||||
-- Constant (K) Compact UART Transmitter
|
||||
--
|
||||
-- Version : 1.10
|
||||
-- Version Date : 3rd December 2003
|
||||
-- Reason : '--translate' directives changed to '--synthesis translate' directives
|
||||
--
|
||||
-- Version : 1.00
|
||||
-- Version Date : 14th October 2002
|
||||
--
|
||||
-- Start of design entry : 2nd October 2002
|
||||
--
|
||||
-- Ken Chapman
|
||||
-- Xilinx Ltd
|
||||
-- Benchmark House
|
||||
-- 203 Brooklands Road
|
||||
-- Weybridge
|
||||
-- Surrey KT13 ORH
|
||||
-- United Kingdom
|
||||
--
|
||||
-- chapman@xilinx.com
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- NOTICE:
|
||||
--
|
||||
-- Copyright Xilinx, Inc. 2002. This code may be contain portions patented by other
|
||||
-- third parties. By providing this core as one possible implementation of a standard,
|
||||
-- Xilinx is making no representation that the provided implementation of this standard
|
||||
-- is free from any claims of infringement by any third party. Xilinx expressly
|
||||
-- disclaims any warranty with respect to the adequacy of the implementation, including
|
||||
-- but not limited to any warranty or representation that the implementation is free
|
||||
-- from claims of any third party. Futhermore, Xilinx is providing this core as a
|
||||
-- courtesy to you and suggests that you contact all third parties to obtain the
|
||||
-- necessary rights to use this implementation.
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- Library declarations
|
||||
--
|
||||
-- The Unisim Library is used to define Xilinx primitives. It is also used during
|
||||
-- simulation. The source can be viewed at %XILINX%\vhdl\src\unisims\unisim_VCOMP.vhd
|
||||
--
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.STD_LOGIC_ARITH.ALL;
|
||||
use IEEE.STD_LOGIC_UNSIGNED.ALL;
|
||||
library unisim;
|
||||
use unisim.vcomponents.all;
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- Main Entity for KCUART_TX
|
||||
--
|
||||
entity kcuart_tx is
|
||||
Port ( data_in : in std_logic_vector(7 downto 0);
|
||||
send_character : in std_logic;
|
||||
en_16_x_baud : in std_logic;
|
||||
serial_out : out std_logic;
|
||||
Tx_complete : out std_logic;
|
||||
clk : in std_logic);
|
||||
end kcuart_tx;
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- Start of Main Architecture for KCUART_TX
|
||||
--
|
||||
architecture low_level_definition of kcuart_tx is
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- Signals used in KCUART_TX
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
signal data_01 : std_logic;
|
||||
signal data_23 : std_logic;
|
||||
signal data_45 : std_logic;
|
||||
signal data_67 : std_logic;
|
||||
signal data_0123 : std_logic;
|
||||
signal data_4567 : std_logic;
|
||||
signal data_01234567 : std_logic;
|
||||
signal bit_select : std_logic_vector(2 downto 0);
|
||||
signal next_count : std_logic_vector(2 downto 0);
|
||||
signal mask_count : std_logic_vector(2 downto 0);
|
||||
signal mask_count_carry : std_logic_vector(2 downto 0);
|
||||
signal count_carry : std_logic_vector(2 downto 0);
|
||||
signal ready_to_start : std_logic;
|
||||
signal decode_Tx_start : std_logic;
|
||||
signal Tx_start : std_logic;
|
||||
signal decode_Tx_run : std_logic;
|
||||
signal Tx_run : std_logic;
|
||||
signal decode_hot_state : std_logic;
|
||||
signal hot_state : std_logic;
|
||||
signal hot_delay : std_logic;
|
||||
signal Tx_bit : std_logic;
|
||||
signal decode_Tx_stop : std_logic;
|
||||
signal Tx_stop : std_logic;
|
||||
signal decode_Tx_complete : std_logic;
|
||||
--
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- Attributes to define LUT contents during implementation
|
||||
-- The information is repeated in the generic map for functional simulation--
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
attribute INIT : string;
|
||||
attribute INIT of mux1_lut : label is "E4FF";
|
||||
attribute INIT of mux2_lut : label is "E4FF";
|
||||
attribute INIT of mux3_lut : label is "E4FF";
|
||||
attribute INIT of mux4_lut : label is "E4FF";
|
||||
attribute INIT of ready_lut : label is "10";
|
||||
attribute INIT of start_lut : label is "0190";
|
||||
attribute INIT of run_lut : label is "1540";
|
||||
attribute INIT of hot_state_lut : label is "94";
|
||||
attribute INIT of delay14_srl : label is "0000";
|
||||
attribute INIT of stop_lut : label is "0180";
|
||||
attribute INIT of complete_lut : label is "8";
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- Start of KCUART_TX circuit description
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
begin
|
||||
|
||||
-- 8 to 1 multiplexer to convert parallel data to serial
|
||||
|
||||
mux1_lut: LUT4
|
||||
--synthesis translate_off
|
||||
generic map (INIT => X"E4FF")
|
||||
--synthesis translate_on
|
||||
port map( I0 => bit_select(0),
|
||||
I1 => data_in(0),
|
||||
I2 => data_in(1),
|
||||
I3 => Tx_run,
|
||||
O => data_01 );
|
||||
|
||||
mux2_lut: LUT4
|
||||
--synthesis translate_off
|
||||
generic map (INIT => X"E4FF")
|
||||
--synthesis translate_on
|
||||
port map( I0 => bit_select(0),
|
||||
I1 => data_in(2),
|
||||
I2 => data_in(3),
|
||||
I3 => Tx_run,
|
||||
O => data_23 );
|
||||
|
||||
mux3_lut: LUT4
|
||||
--synthesis translate_off
|
||||
generic map (INIT => X"E4FF")
|
||||
--synthesis translate_on
|
||||
port map( I0 => bit_select(0),
|
||||
I1 => data_in(4),
|
||||
I2 => data_in(5),
|
||||
I3 => Tx_run,
|
||||
O => data_45 );
|
||||
|
||||
mux4_lut: LUT4
|
||||
--synthesis translate_off
|
||||
generic map (INIT => X"E4FF")
|
||||
--synthesis translate_on
|
||||
port map( I0 => bit_select(0),
|
||||
I1 => data_in(6),
|
||||
I2 => data_in(7),
|
||||
I3 => Tx_run,
|
||||
O => data_67 );
|
||||
|
||||
mux5_muxf5: MUXF5
|
||||
port map( I1 => data_23,
|
||||
I0 => data_01,
|
||||
S => bit_select(1),
|
||||
O => data_0123 );
|
||||
|
||||
mux6_muxf5: MUXF5
|
||||
port map( I1 => data_67,
|
||||
I0 => data_45,
|
||||
S => bit_select(1),
|
||||
O => data_4567 );
|
||||
|
||||
mux7_muxf6: MUXF6
|
||||
port map( I1 => data_4567,
|
||||
I0 => data_0123,
|
||||
S => bit_select(2),
|
||||
O => data_01234567 );
|
||||
|
||||
-- Register serial output and force start and stop bits
|
||||
|
||||
pipeline_serial: FDRS
|
||||
port map ( D => data_01234567,
|
||||
Q => serial_out,
|
||||
R => Tx_start,
|
||||
S => Tx_stop,
|
||||
C => clk);
|
||||
|
||||
-- 3-bit counter
|
||||
-- Counter is clock enabled by en_16_x_baud
|
||||
-- Counter will be reset when 'Tx_start' is active
|
||||
-- Counter will increment when Tx_bit is active
|
||||
-- Tx_run must be active to count
|
||||
-- count_carry(2) indicates when terminal count (7) is reached and Tx_bit=1 (ie overflow)
|
||||
|
||||
count_width_loop: for i in 0 to 2 generate
|
||||
--
|
||||
attribute INIT : string;
|
||||
attribute INIT of count_lut : label is "8";
|
||||
--
|
||||
begin
|
||||
|
||||
register_bit: FDRE
|
||||
port map ( D => next_count(i),
|
||||
Q => bit_select(i),
|
||||
CE => en_16_x_baud,
|
||||
R => Tx_start,
|
||||
C => clk);
|
||||
|
||||
count_lut: LUT2
|
||||
--synthesis translate_off
|
||||
generic map (INIT => X"8")
|
||||
--synthesis translate_on
|
||||
port map( I0 => bit_select(i),
|
||||
I1 => Tx_run,
|
||||
O => mask_count(i));
|
||||
|
||||
mask_and: MULT_AND
|
||||
port map( I0 => bit_select(i),
|
||||
I1 => Tx_run,
|
||||
LO => mask_count_carry(i));
|
||||
|
||||
lsb_count: if i=0 generate
|
||||
begin
|
||||
|
||||
count_muxcy: MUXCY
|
||||
port map( DI => mask_count_carry(i),
|
||||
CI => Tx_bit,
|
||||
S => mask_count(i),
|
||||
O => count_carry(i));
|
||||
|
||||
count_xor: XORCY
|
||||
port map( LI => mask_count(i),
|
||||
CI => Tx_bit,
|
||||
O => next_count(i));
|
||||
|
||||
end generate lsb_count;
|
||||
|
||||
upper_count: if i>0 generate
|
||||
begin
|
||||
|
||||
count_muxcy: MUXCY
|
||||
port map( DI => mask_count_carry(i),
|
||||
CI => count_carry(i-1),
|
||||
S => mask_count(i),
|
||||
O => count_carry(i));
|
||||
|
||||
count_xor: XORCY
|
||||
port map( LI => mask_count(i),
|
||||
CI => count_carry(i-1),
|
||||
O => next_count(i));
|
||||
|
||||
end generate upper_count;
|
||||
|
||||
end generate count_width_loop;
|
||||
|
||||
-- Ready to start decode
|
||||
|
||||
ready_lut: LUT3
|
||||
--synthesis translate_off
|
||||
generic map (INIT => X"10")
|
||||
--synthesis translate_on
|
||||
port map( I0 => Tx_run,
|
||||
I1 => Tx_start,
|
||||
I2 => send_character,
|
||||
O => ready_to_start );
|
||||
|
||||
-- Start bit enable
|
||||
|
||||
start_lut: LUT4
|
||||
--synthesis translate_off
|
||||
generic map (INIT => X"0190")
|
||||
--synthesis translate_on
|
||||
port map( I0 => Tx_bit,
|
||||
I1 => Tx_stop,
|
||||
I2 => ready_to_start,
|
||||
I3 => Tx_start,
|
||||
O => decode_Tx_start );
|
||||
|
||||
Tx_start_reg: FDE
|
||||
port map ( D => decode_Tx_start,
|
||||
Q => Tx_start,
|
||||
CE => en_16_x_baud,
|
||||
C => clk);
|
||||
|
||||
|
||||
-- Run bit enable
|
||||
|
||||
run_lut: LUT4
|
||||
--synthesis translate_off
|
||||
generic map (INIT => X"1540")
|
||||
--synthesis translate_on
|
||||
port map( I0 => count_carry(2),
|
||||
I1 => Tx_bit,
|
||||
I2 => Tx_start,
|
||||
I3 => Tx_run,
|
||||
O => decode_Tx_run );
|
||||
|
||||
Tx_run_reg: FDE
|
||||
port map ( D => decode_Tx_run,
|
||||
Q => Tx_run,
|
||||
CE => en_16_x_baud,
|
||||
C => clk);
|
||||
|
||||
-- Bit rate enable
|
||||
|
||||
hot_state_lut: LUT3
|
||||
--synthesis translate_off
|
||||
generic map (INIT => X"94")
|
||||
--synthesis translate_on
|
||||
port map( I0 => Tx_stop,
|
||||
I1 => ready_to_start,
|
||||
I2 => Tx_bit,
|
||||
O => decode_hot_state );
|
||||
|
||||
hot_state_reg: FDE
|
||||
port map ( D => decode_hot_state,
|
||||
Q => hot_state,
|
||||
CE => en_16_x_baud,
|
||||
C => clk);
|
||||
|
||||
delay14_srl: SRL16E
|
||||
--synthesis translate_off
|
||||
generic map (INIT => X"0000")
|
||||
--synthesis translate_on
|
||||
port map( D => hot_state,
|
||||
CE => en_16_x_baud,
|
||||
CLK => clk,
|
||||
A0 => '1',
|
||||
A1 => '0',
|
||||
A2 => '1',
|
||||
A3 => '1',
|
||||
Q => hot_delay );
|
||||
|
||||
Tx_bit_reg: FDE
|
||||
port map ( D => hot_delay,
|
||||
Q => Tx_bit,
|
||||
CE => en_16_x_baud,
|
||||
C => clk);
|
||||
|
||||
-- Stop bit enable
|
||||
|
||||
stop_lut: LUT4
|
||||
--synthesis translate_off
|
||||
generic map (INIT => X"0180")
|
||||
--synthesis translate_on
|
||||
port map( I0 => Tx_bit,
|
||||
I1 => Tx_run,
|
||||
I2 => count_carry(2),
|
||||
I3 => Tx_stop,
|
||||
O => decode_Tx_stop );
|
||||
|
||||
Tx_stop_reg: FDE
|
||||
port map ( D => decode_Tx_stop,
|
||||
Q => Tx_stop,
|
||||
CE => en_16_x_baud,
|
||||
C => clk);
|
||||
|
||||
-- Tx_complete strobe
|
||||
|
||||
complete_lut: LUT2
|
||||
--synthesis translate_off
|
||||
generic map (INIT => X"8")
|
||||
--synthesis translate_on
|
||||
port map( I0 => count_carry(2),
|
||||
I1 => en_16_x_baud,
|
||||
O => decode_Tx_complete );
|
||||
|
||||
Tx_complete_reg: FD
|
||||
port map ( D => decode_Tx_complete,
|
||||
Q => Tx_complete,
|
||||
C => clk);
|
||||
|
||||
|
||||
end low_level_definition;
|
||||
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- END OF FILE KCUART_TX.VHD
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
-- UART Receiver with integral 16 byte FIFO buffer
|
||||
--
|
||||
-- 8 bit, no parity, 1 stop bit
|
||||
--
|
||||
-- Version : 1.00
|
||||
-- Version Date : 16th October 2002
|
||||
--
|
||||
-- Start of design entry : 16th October 2002
|
||||
--
|
||||
-- Ken Chapman
|
||||
-- Xilinx Ltd
|
||||
-- Benchmark House
|
||||
-- 203 Brooklands Road
|
||||
-- Weybridge
|
||||
-- Surrey KT13 ORH
|
||||
-- United Kingdom
|
||||
--
|
||||
-- chapman@xilinx.com
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- NOTICE:
|
||||
--
|
||||
-- Copyright Xilinx, Inc. 2002. This code may be contain portions patented by other
|
||||
-- third parties. By providing this core as one possible implementation of a standard,
|
||||
-- Xilinx is making no representation that the provided implementation of this standard
|
||||
-- is free from any claims of infringement by any third party. Xilinx expressly
|
||||
-- disclaims any warranty with respect to the adequacy of the implementation, including
|
||||
-- but not limited to any warranty or representation that the implementation is free
|
||||
-- from claims of any third party. Futhermore, Xilinx is providing this core as a
|
||||
-- courtesy to you and suggests that you contact all third parties to obtain the
|
||||
-- necessary rights to use this implementation.
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- Library declarations
|
||||
--
|
||||
-- The Unisim Library is used to define Xilinx primitives. It is also used during
|
||||
-- simulation. The source can be viewed at %XILINX%\vhdl\src\unisims\unisim_VCOMP.vhd
|
||||
--
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.STD_LOGIC_ARITH.ALL;
|
||||
use IEEE.STD_LOGIC_UNSIGNED.ALL;
|
||||
library unisim;
|
||||
use unisim.vcomponents.all;
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- Main Entity for UART_RX
|
||||
--
|
||||
entity uart_rx is
|
||||
Port ( serial_in : in std_logic;
|
||||
data_out : out std_logic_vector(7 downto 0);
|
||||
read_buffer : in std_logic;
|
||||
reset_buffer : in std_logic;
|
||||
en_16_x_baud : in std_logic;
|
||||
buffer_data_present : out std_logic;
|
||||
buffer_full : out std_logic;
|
||||
buffer_half_full : out std_logic;
|
||||
clk : in std_logic);
|
||||
end uart_rx;
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- Start of Main Architecture for UART_RX
|
||||
--
|
||||
architecture macro_level_definition of uart_rx is
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- Components used in UART_RX and defined in subsequent entities.
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- Constant (K) Compact UART Receiver
|
||||
--
|
||||
component kcuart_rx
|
||||
Port ( serial_in : in std_logic;
|
||||
data_out : out std_logic_vector(7 downto 0);
|
||||
data_strobe : out std_logic;
|
||||
en_16_x_baud : in std_logic;
|
||||
clk : in std_logic);
|
||||
end component;
|
||||
--
|
||||
-- 'Bucket Brigade' FIFO
|
||||
--
|
||||
component bbfifo_16x8
|
||||
Port ( data_in : in std_logic_vector(7 downto 0);
|
||||
data_out : out std_logic_vector(7 downto 0);
|
||||
reset : in std_logic;
|
||||
write : in std_logic;
|
||||
read : in std_logic;
|
||||
full : out std_logic;
|
||||
half_full : out std_logic;
|
||||
data_present : out std_logic;
|
||||
clk : in std_logic);
|
||||
end component;
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- Signals used in UART_RX
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
signal uart_data_out : std_logic_vector(7 downto 0);
|
||||
signal fifo_write : std_logic;
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- Start of UART_RX circuit description
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
begin
|
||||
|
||||
-- 8 to 1 multiplexer to convert parallel data to serial
|
||||
|
||||
kcuart: kcuart_rx
|
||||
port map ( serial_in => serial_in,
|
||||
data_out => uart_data_out,
|
||||
data_strobe => fifo_write,
|
||||
en_16_x_baud => en_16_x_baud,
|
||||
clk => clk );
|
||||
|
||||
|
||||
buf: bbfifo_16x8
|
||||
port map ( data_in => uart_data_out,
|
||||
data_out => data_out,
|
||||
reset => reset_buffer,
|
||||
write => fifo_write,
|
||||
read => read_buffer,
|
||||
full => buffer_full,
|
||||
half_full => buffer_half_full,
|
||||
data_present => buffer_data_present,
|
||||
clk => clk);
|
||||
|
||||
end macro_level_definition;
|
||||
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- END OF FILE UART_RX.VHD
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
-- UART Transmitter with integral 16 byte FIFO buffer
|
||||
--
|
||||
-- 8 bit, no parity, 1 stop bit
|
||||
--
|
||||
-- Version : 1.00
|
||||
-- Version Date : 14th October 2002
|
||||
--
|
||||
-- Start of design entry : 14th October 2002
|
||||
--
|
||||
-- Ken Chapman
|
||||
-- Xilinx Ltd
|
||||
-- Benchmark House
|
||||
-- 203 Brooklands Road
|
||||
-- Weybridge
|
||||
-- Surrey KT13 ORH
|
||||
-- United Kingdom
|
||||
--
|
||||
-- chapman@xilinx.com
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- NOTICE:
|
||||
--
|
||||
-- Copyright Xilinx, Inc. 2002. This code may be contain portions patented by other
|
||||
-- third parties. By providing this core as one possible implementation of a standard,
|
||||
-- Xilinx is making no representation that the provided implementation of this standard
|
||||
-- is free from any claims of infringement by any third party. Xilinx expressly
|
||||
-- disclaims any warranty with respect to the adequacy of the implementation, including
|
||||
-- but not limited to any warranty or representation that the implementation is free
|
||||
-- from claims of any third party. Futhermore, Xilinx is providing this core as a
|
||||
-- courtesy to you and suggests that you contact all third parties to obtain the
|
||||
-- necessary rights to use this implementation.
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- Library declarations
|
||||
--
|
||||
-- The Unisim Library is used to define Xilinx primitives. It is also used during
|
||||
-- simulation. The source can be viewed at %XILINX%\vhdl\src\unisims\unisim_VCOMP.vhd
|
||||
--
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.STD_LOGIC_ARITH.ALL;
|
||||
use IEEE.STD_LOGIC_UNSIGNED.ALL;
|
||||
library unisim;
|
||||
use unisim.vcomponents.all;
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- Main Entity for UART_TX
|
||||
--
|
||||
entity uart_tx is
|
||||
Port ( data_in : in std_logic_vector(7 downto 0);
|
||||
write_buffer : in std_logic;
|
||||
reset_buffer : in std_logic;
|
||||
en_16_x_baud : in std_logic;
|
||||
serial_out : out std_logic;
|
||||
buffer_full : out std_logic;
|
||||
buffer_half_full : out std_logic;
|
||||
tx_complete : out std_logic;
|
||||
tx_empty : out std_logic;
|
||||
clk : in std_logic);
|
||||
end uart_tx;
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- Start of Main Architecture for UART_TX
|
||||
--
|
||||
architecture macro_level_definition of uart_tx is
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- Components used in UART_TX and defined in subsequent entities.
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- Constant (K) Compact UART Transmitter
|
||||
--
|
||||
component kcuart_tx
|
||||
Port ( data_in : in std_logic_vector(7 downto 0);
|
||||
send_character : in std_logic;
|
||||
en_16_x_baud : in std_logic;
|
||||
serial_out : out std_logic;
|
||||
Tx_complete : out std_logic;
|
||||
clk : in std_logic);
|
||||
end component;
|
||||
--
|
||||
-- 'Bucket Brigade' FIFO
|
||||
--
|
||||
component bbfifo_16x8
|
||||
Port ( data_in : in std_logic_vector(7 downto 0);
|
||||
data_out : out std_logic_vector(7 downto 0);
|
||||
reset : in std_logic;
|
||||
write : in std_logic;
|
||||
read : in std_logic;
|
||||
full : out std_logic;
|
||||
half_full : out std_logic;
|
||||
data_present : out std_logic;
|
||||
clk : in std_logic);
|
||||
end component;
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- Signals used in UART_TX
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
signal fifo_data_out : std_logic_vector(7 downto 0);
|
||||
signal fifo_data_present : std_logic;
|
||||
signal fifo_read : std_logic;
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- Start of UART_TX circuit description
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
begin
|
||||
|
||||
tx_complete <= fifo_read;
|
||||
tx_empty <= not fifo_data_present;
|
||||
|
||||
-- 8 to 1 multiplexer to convert parallel data to serial
|
||||
|
||||
kcuart: kcuart_tx
|
||||
port map ( data_in => fifo_data_out,
|
||||
send_character => fifo_data_present,
|
||||
en_16_x_baud => en_16_x_baud,
|
||||
serial_out => serial_out,
|
||||
Tx_complete => fifo_read,
|
||||
clk => clk);
|
||||
|
||||
|
||||
buf: bbfifo_16x8
|
||||
port map ( data_in => data_in,
|
||||
data_out => fifo_data_out,
|
||||
reset => reset_buffer,
|
||||
write => write_buffer,
|
||||
read => fifo_read,
|
||||
full => buffer_full,
|
||||
half_full => buffer_half_full,
|
||||
data_present => fifo_data_present,
|
||||
clk => clk);
|
||||
|
||||
end macro_level_definition;
|
||||
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- END OF FILE UART_TX.VHD
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -0,0 +1,214 @@
|
||||
LIBRARY IEEE;
|
||||
USE IEEE.STD_LOGIC_1164.ALL;
|
||||
USE IEEE.NUMERIC_STD.ALL;
|
||||
use std.textio.all; -- Imports the standard textio package.
|
||||
|
||||
ENTITY uart_wb IS
|
||||
Generic
|
||||
(
|
||||
simulate_tx : boolean := false
|
||||
);
|
||||
Port
|
||||
(
|
||||
CLK_I : in STD_LOGIC;
|
||||
RST_I : in STD_LOGIC;
|
||||
INT_O : out STD_LOGIC;
|
||||
CYC_I : in STD_LOGIC;
|
||||
STB_I : in STD_LOGIC;
|
||||
SEL_I : in unsigned(3 downto 0);
|
||||
WE_I : in STD_LOGIC;
|
||||
ACK_O : out STD_LOGIC;
|
||||
SRDY_O : out STD_LOGIC;
|
||||
MRDY_I : in STD_LOGIC;
|
||||
ADDR_I : in unsigned(31 downto 0);
|
||||
DAT_I : in unsigned(31 downto 0);
|
||||
DAT_O : out unsigned(31 downto 0);
|
||||
ser_rx : in std_logic;
|
||||
ser_tx : out std_logic
|
||||
);
|
||||
END uart_wb;
|
||||
|
||||
ARCHITECTURE behavior OF uart_wb IS
|
||||
|
||||
COMPONENT uart_tx
|
||||
Port
|
||||
(
|
||||
data_in : in std_logic_vector(7 downto 0);
|
||||
write_buffer : in std_logic;
|
||||
reset_buffer : in std_logic;
|
||||
en_16_x_baud : in std_logic;
|
||||
serial_out : out std_logic;
|
||||
buffer_full : out std_logic;
|
||||
buffer_half_full : out std_logic;
|
||||
tx_complete : out std_logic;
|
||||
tx_empty : out std_logic;
|
||||
clk : in std_logic
|
||||
);
|
||||
END COMPONENT;
|
||||
|
||||
COMPONENT uart_rx
|
||||
Port
|
||||
(
|
||||
serial_in : in std_logic;
|
||||
data_out : out std_logic_vector(7 downto 0);
|
||||
read_buffer : in std_logic;
|
||||
reset_buffer : in std_logic;
|
||||
en_16_x_baud : in std_logic;
|
||||
buffer_data_present : out std_logic;
|
||||
buffer_full : out std_logic;
|
||||
buffer_half_full : out std_logic;
|
||||
clk : in std_logic
|
||||
);
|
||||
END COMPONENT;
|
||||
|
||||
-- Signals for UART connections
|
||||
signal baud_count : unsigned(15 downto 0);
|
||||
signal en_16_x_baud : std_logic;
|
||||
signal reg_we_uart_tx : std_logic;
|
||||
signal tx_full : std_logic;
|
||||
signal tx_half_full : std_logic;
|
||||
signal reg_re_uart_rx : std_logic;
|
||||
signal reg_uart_tx : unsigned(7 downto 0);
|
||||
signal reg_uart_rx : std_logic_vector(7 downto 0);
|
||||
signal rx_data_present : std_logic;
|
||||
signal rx_full : std_logic;
|
||||
signal rx_half_full : std_logic;
|
||||
signal uart_status_port : unsigned(15 downto 0);
|
||||
signal reg_uart_baud : unsigned(15 downto 0);
|
||||
signal rx_int_en : std_logic;
|
||||
signal tx_int_en : std_logic;
|
||||
signal irq_rx : std_logic;
|
||||
signal irq_tx : std_logic;
|
||||
signal tx_complete : std_logic;
|
||||
signal tx_empty : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
SRDY_O <= CYC_I;
|
||||
|
||||
------------------------------------------------------------------
|
||||
registers_write:
|
||||
process(CLK_I)
|
||||
file output: text open write_mode is "STD_OUTPUT";
|
||||
variable L : line;
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
reg_we_uart_tx <= '0';
|
||||
if RST_I = '1' then
|
||||
reg_uart_baud <= to_unsigned(53, 16);
|
||||
rx_int_en <= '0';
|
||||
tx_int_en <= '0';
|
||||
elsif (STB_I and CYC_I and WE_I) = '1' then
|
||||
case ADDR_I(5 downto 2) is
|
||||
|
||||
when "0000" =>
|
||||
if simulate_tx then
|
||||
if DAT_I(7 downto 0) /= X"0D" then
|
||||
write(L, character'val(to_integer(DAT_I(7 downto 0))));
|
||||
end if;
|
||||
if DAT_I(7 downto 0) = X"0A" then
|
||||
writeline(output, L);
|
||||
end if;
|
||||
else
|
||||
reg_we_uart_tx <= '1';
|
||||
reg_uart_tx <= DAT_I(7 downto 0);
|
||||
end if;
|
||||
|
||||
when "0001" =>
|
||||
rx_int_en <= DAT_I(6);
|
||||
tx_int_en <= DAT_I(5);
|
||||
|
||||
when "0010" =>
|
||||
reg_uart_baud <= DAT_I(15 downto 0);
|
||||
|
||||
when others => null;
|
||||
end case;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
registers_read:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
reg_re_uart_rx <= '0';
|
||||
ACK_O <= '0';
|
||||
if (STB_I and CYC_I) = '1' then
|
||||
ACK_O <= not WE_I;
|
||||
DAT_O <= (others => '0');
|
||||
case ADDR_I(5 downto 2) is
|
||||
|
||||
when "0000" =>
|
||||
reg_re_uart_rx <= not WE_I;
|
||||
DAT_O(7 downto 0) <= unsigned(reg_uart_rx);
|
||||
|
||||
when "0001" =>
|
||||
DAT_O(15 downto 0) <= uart_status_port;
|
||||
|
||||
when "0010" =>
|
||||
DAT_O(15 downto 0) <= reg_uart_baud;
|
||||
|
||||
when others => null;
|
||||
end case;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
baud_timer:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
if RST_I = '1' then
|
||||
baud_count <= (others => '0');
|
||||
elsif baud_count = reg_uart_baud then
|
||||
baud_count <= (others => '0');
|
||||
en_16_x_baud <= '1';
|
||||
else
|
||||
baud_count <= baud_count + 1;
|
||||
en_16_x_baud <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
irq_register:
|
||||
process(CLK_I)
|
||||
begin
|
||||
if rising_edge(CLK_I) then
|
||||
irq_tx <= tx_empty and tx_int_en;
|
||||
irq_rx <= rx_data_present and rx_int_en;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
inst_uart_tx: uart_tx
|
||||
port map
|
||||
(
|
||||
data_in => std_logic_vector(reg_uart_tx),
|
||||
write_buffer => reg_we_uart_tx,
|
||||
reset_buffer => RST_I,
|
||||
en_16_x_baud => en_16_x_baud,
|
||||
serial_out => ser_tx,
|
||||
buffer_full => tx_full,
|
||||
buffer_half_full => tx_half_full,
|
||||
tx_complete => tx_complete,
|
||||
tx_empty => tx_empty,
|
||||
clk => CLK_I
|
||||
);
|
||||
|
||||
inst_uart_rx: uart_rx
|
||||
port map
|
||||
(
|
||||
serial_in => ser_rx,
|
||||
data_out => reg_uart_rx,
|
||||
read_buffer => reg_re_uart_rx,
|
||||
reset_buffer => RST_I,
|
||||
en_16_x_baud => en_16_x_baud,
|
||||
buffer_data_present => rx_data_present,
|
||||
buffer_full => rx_full,
|
||||
buffer_half_full => rx_half_full,
|
||||
clk => CLK_I
|
||||
);
|
||||
|
||||
uart_status_port <= "000000" & irq_rx & irq_tx & '0' & rx_int_en & tx_int_en & rx_data_present & rx_full & rx_half_full & tx_full & tx_half_full;
|
||||
INT_O <= irq_rx or irq_tx;
|
||||
|
||||
end behavior;
|
||||
Reference in New Issue
Block a user