mirror of
git://projects.qi-hardware.com/nn-usb-fpga.git
synced 2025-01-06 15:20:14 +02:00
Adding lm32 demo to SAKC project
This commit is contained in:
parent
26b0c73a84
commit
61d4408f2a
@ -1,6 +1,6 @@
|
||||
CC = mipsel-openwrt-linux-gcc
|
||||
|
||||
all: jz_init_sram jz_test_gpio
|
||||
all: jz_init_sram jz_test_gpio enable_rx
|
||||
|
||||
DEBUG = -O3 -g0
|
||||
|
||||
@ -26,6 +26,9 @@ jz_init_sram: $(COMMON_OBJECTS)
|
||||
jz_test_gpio: $(COMMON_OBJECTS)
|
||||
$(CC) $(LDFLAGS) $(COMMON_OBJECTS) jz_test_gpio.c -o jz_test_gpio
|
||||
|
||||
enable_rx: $(COMMON_OBJECTS)
|
||||
$(CC) $(LDFLAGS) $(COMMON_OBJECTS) enable_rx.c -o enable_rx
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CCFLAGS) $< -o $@
|
||||
|
||||
@ -33,7 +36,7 @@ upload: jz_init_sram jz_test_gpio
|
||||
scp jz_test_gpio jz_init_sram root@$(NANO_IP):
|
||||
|
||||
clean:
|
||||
rm -f *.o jz_init_sram jz_test_gpio ${EXEC} *~
|
||||
rm -f *.o jz_init_sram jz_test_gpio enable_rx ${EXEC} *~
|
||||
|
||||
indent:
|
||||
indent -bad -bap -nbc -bl -nce -i2 --no-tabs --line-length120 $(COMMON_SOURCES) $(H_SOURCES)
|
||||
|
40
Examples/sram/src/enable_rx.c
Normal file
40
Examples/sram/src/enable_rx.c
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
JZ47xx test gpio
|
||||
|
||||
Copyright (C) 2010 Andres Calderon andres.calderon@emqbit.com
|
||||
Carlos Camargo cicamargoba@unal.edu.co
|
||||
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "jz47xx_gpio.h"
|
||||
|
||||
#define RXD_PORT JZ_GPIO_PORT_D
|
||||
#define RXD_PIN 26
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
JZ_PIO *pio = jz_gpio_map (RXD_PORT);
|
||||
|
||||
if (!pio)
|
||||
return -1;
|
||||
|
||||
jz_gpio_as_func (pio, RXD_PIN, 1);
|
||||
|
||||
return 0;
|
||||
}
|
@ -79,18 +79,21 @@ jz_gpio_as_func (JZ_PIO * pio, unsigned int o, int func)
|
||||
pio->PXFUNS = (1 << o);
|
||||
pio->PXTRGC = (1 << o);
|
||||
pio->PXSELC = (1 << o);
|
||||
pio->PXPES = (1 << o);
|
||||
return 1;
|
||||
|
||||
case 1:
|
||||
pio->PXFUNS = (1 << o);
|
||||
pio->PXTRGC = (1 << o);
|
||||
pio->PXSELS = (1 << o);
|
||||
pio->PXPES = (1 << o);
|
||||
return 1;
|
||||
|
||||
case 2:
|
||||
pio->PXFUNS = (1 << o);
|
||||
pio->PXTRGS = (1 << o);
|
||||
pio->PXSELC = (1 << o);
|
||||
pio->PXPES = (1 << o);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
131
lm32/logic/sakc/Makefile
Normal file
131
lm32/logic/sakc/Makefile
Normal file
@ -0,0 +1,131 @@
|
||||
VINCDIR= \
|
||||
-I../rtl/wb_conbus \
|
||||
-I../rtl/lm32 \
|
||||
-I../rtl/wb_ddr
|
||||
|
||||
SYN_SRC=
|
||||
|
||||
SIM_SRC= \
|
||||
system_tb.v \
|
||||
../sim/sram/sram16.v \
|
||||
../sim/unisims/BUFG.v \
|
||||
../sim/unisims/DCM.v
|
||||
|
||||
SRC= \
|
||||
../system.v \
|
||||
../rtl/lac/lac.v \
|
||||
../rtl/lac/uart.v \
|
||||
../rtl/lac/dp_ram.v \
|
||||
../rtl/lm32/lm32_cpu.v \
|
||||
../rtl/lm32/lm32_instruction_unit.v \
|
||||
../rtl/lm32/lm32_decoder.v \
|
||||
../rtl/lm32/lm32_simtrace.v \
|
||||
../rtl/lm32/lm32_load_store_unit.v \
|
||||
../rtl/lm32/lm32_adder.v \
|
||||
../rtl/lm32/lm32_addsub.v \
|
||||
../rtl/lm32/lm32_logic_op.v \
|
||||
../rtl/lm32/lm32_shifter.v \
|
||||
../rtl/lm32/lm32_multiplier.v \
|
||||
../rtl/lm32/lm32_mc_arithmetic.v \
|
||||
../rtl/lm32/lm32_interrupt.v \
|
||||
../rtl/lm32/lm32_icache.v \
|
||||
../rtl/lm32/lm32_dcache.v \
|
||||
../rtl/lm32/lm32_ram.v \
|
||||
../rtl/wb_bram/wb_bram.v \
|
||||
../rtl/wb_uart/wb_uart.v \
|
||||
../rtl/wb_timer/wb_timer.v \
|
||||
../rtl/wb_gpio/wb_gpio.v \
|
||||
../rtl/wb_conbus/wb_conbus_top.v \
|
||||
../rtl/wb_conbus/wb_conbus_arb.v \
|
||||
../rtl/wb_sram/wb_sram32.v
|
||||
|
||||
#############################################################################
|
||||
# Synthesis constants
|
||||
SYNCLEAN=system.bgn system.drc system.mrp system.ngd system.pcf
|
||||
SYNCLEAN+=system.bld system.lso system.ncd system.ngm system.srp
|
||||
SYNCLEAN+=system.bit system_signalbrowser.* system-routed_pad.tx
|
||||
SYNCLEAN+=system.map system_summary.xml timing.twr
|
||||
SYNCLEAN+=system-routed* system_usage* system.ngc param.opt netlist.lst
|
||||
SYNCLEAN+=xst system.prj *ngr *xrpt _xmsgs xlnx_auto_0_xdb *html *log *xwbt
|
||||
|
||||
USAGE_DEPTH=0
|
||||
SMARTGUIDE=
|
||||
|
||||
#############################################################################
|
||||
# Simulation constants
|
||||
SIMCLEAN=system_tb.vvp system_tb.vcd verilog.log system_tb.vvp.list simulation
|
||||
|
||||
CVER=cver
|
||||
GTKWAVE=gtkwave
|
||||
IVERILOG=iverilog
|
||||
VVP=vvp
|
||||
|
||||
#############################################################################
|
||||
#
|
||||
sim: system_tb.vcd
|
||||
syn: system.bit
|
||||
view: system_tb.view
|
||||
|
||||
#############################################################################
|
||||
# Ikarus verilog simulation
|
||||
|
||||
system_tb.vvp:
|
||||
rm -rf simulation && mkdir simulation
|
||||
cp system_tb.v system_conf.v simulation && cd simulation && rm -f $@.list
|
||||
for i in $(SRC); do echo $$i >> simulation/$@.list; done
|
||||
for i in $(SIM_SRC); do echo $$i >> simulation/$@.list; done
|
||||
cd simulation && $(IVERILOG) -o $@ $(VINCDIR) -c $@.list -s $(@:.vvp=)
|
||||
|
||||
%.vcd: %.vvp
|
||||
cd simulation && $(VVP) $<
|
||||
|
||||
#############################################################################
|
||||
# ISE Synthesis
|
||||
|
||||
|
||||
system.prj:
|
||||
rm -rf build && mkdir build
|
||||
@rm -f $@
|
||||
for i in $(SRC); do echo verilog work $$i >> build/$@; done
|
||||
for i in $(SRC_HDL); do echo VHDL work $$i >> build/$@; done
|
||||
|
||||
system.ngc: system.prj
|
||||
cd build && xst -ifn ../system.xst
|
||||
|
||||
system.ngd: system.ngc system.ucf
|
||||
cd build && ngdbuild -uc ../system.ucf system.ngc
|
||||
|
||||
system.ncd: system.ngd
|
||||
cd build && map $(SMARTGUIDE) system.ngd
|
||||
|
||||
system-routed.ncd: system.ncd
|
||||
cd build && par $(SMARTGUIDE) -ol high -w system.ncd system-routed.ncd
|
||||
|
||||
system.bit: system-routed.ncd
|
||||
cd build && bitgen -w system-routed.ncd system.bit
|
||||
@mv -f build/system.bit $@
|
||||
|
||||
system.mcs: system.bit
|
||||
cd build && promgen -u 0 system
|
||||
|
||||
system-routed.xdl: system-routed.ncd
|
||||
cd build && xdl -ncd2xdl system-routed.ncd system-routed.xdl
|
||||
|
||||
system-routed.twr: system-routed.ncd
|
||||
cd build && trce -v 10 system-routed.ncd system.pcf
|
||||
|
||||
timing: system-routed.twr
|
||||
|
||||
usage: system-routed.xdl
|
||||
xdlanalyze.pl system-routed.xdl $(USAGE_DEPTH)
|
||||
|
||||
####################################################################
|
||||
# final targets
|
||||
|
||||
%.view: %.vcd
|
||||
cd simulation && $(GTKWAVE) $< $<.save
|
||||
|
||||
clean:
|
||||
rm -Rf build $(SYNCLEAN) $(SIMCLEAN)
|
||||
|
||||
.PHONY: clean view
|
50
lm32/logic/sakc/firmware/boot0-serial/Makefile
Normal file
50
lm32/logic/sakc/firmware/boot0-serial/Makefile
Normal file
@ -0,0 +1,50 @@
|
||||
LM32_CC=lm32-elf-gcc
|
||||
LM32_LD=lm32-elf-ld
|
||||
LM32_OBJCOPY=lm32-elf-objcopy
|
||||
LM32_OBJDUMP=lm32-elf-objdump
|
||||
|
||||
SREC2VRAM ?= ../../tools/srec2vram/srec2vram
|
||||
|
||||
VRAMFILE=image.ram
|
||||
|
||||
CFLAGS=-MMD -O2 -Wall -g -s -fomit-frame-pointer -mbarrel-shift-enabled -mmultiply-enabled -mdivide-enabled -msign-extend-enabled
|
||||
LDFLAGS=-nostdlib -nodefaultlibs -Tlinker.ld
|
||||
SEGMENTS = -j .text -j .rodata -j .data
|
||||
|
||||
all: $(VRAMFILE)
|
||||
|
||||
crt0ram.o: crt0ram.S
|
||||
$(LM32_CC) $(CFLAGS) -c crt0ram.S
|
||||
|
||||
main.o: main.c
|
||||
$(LM32_CC) $(CFLAGS) -c main.c
|
||||
|
||||
soc-hw.o: soc-hw.c
|
||||
$(LM32_CC) $(CFLAGS) -c soc-hw.c
|
||||
|
||||
image: crt0ram.o main.o soc-hw.o
|
||||
$(LM32_LD) $(LDFLAGS) -Map image.map -N -o image crt0ram.o main.o soc-hw.o
|
||||
|
||||
image.lst: image
|
||||
$(LM32_OBJDUMP) -h -S $< > $@
|
||||
|
||||
image.bin: image
|
||||
$(LM32_OBJCOPY) $(SEGMENTS) -O srec image image.bin
|
||||
|
||||
image.srec: image image.lst
|
||||
$(LM32_OBJCOPY) $(SEGMENTS) -O srec image image.srec
|
||||
|
||||
$(VHDLFILE): image.srec
|
||||
$(SREC2VHDL) image.srec > $(VHDLFILE)
|
||||
|
||||
$(VRAMFILE): image.srec
|
||||
$(SREC2VRAM) image.srec 0x00000000 0x1000 > $(VRAMFILE)
|
||||
|
||||
clean:
|
||||
rm -f image image.lst image.bin image.srec image.map *.o *.d
|
||||
|
||||
DEPS := $(wildcard *.d)
|
||||
ifneq ($(DEPS),)
|
||||
include $(DEPS)
|
||||
endif
|
||||
|
85
lm32/logic/sakc/firmware/boot0-serial/crt0ram.S
Normal file
85
lm32/logic/sakc/firmware/boot0-serial/crt0ram.S
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* LatticeMico32 C startup code.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* Exception handlers - Must be 32 bytes long. */
|
||||
.section .text, "ax", @progbits
|
||||
.global _start
|
||||
.global irq_enable, irq_disable, irq_mask, jump, halt
|
||||
_start:
|
||||
_reset_handler:
|
||||
xor r0, r0, r0
|
||||
wcsr IE, r0
|
||||
mvhi r1, hi(_reset_handler)
|
||||
ori r1, r1, lo(_reset_handler)
|
||||
wcsr EBA, r1
|
||||
calli _crt0
|
||||
nop
|
||||
nop
|
||||
|
||||
_crt0:
|
||||
/* Setup stack and global pointer */
|
||||
mvhi sp, hi(_fstack)
|
||||
ori sp, sp, lo(_fstack)
|
||||
mvhi gp, hi(_gp)
|
||||
ori gp, gp, lo(_gp)
|
||||
|
||||
/* Clear BSS */
|
||||
mvhi r1, hi(_fbss)
|
||||
ori r1, r1, lo(_fbss)
|
||||
mvhi r3, hi(_ebss)
|
||||
ori r3, r3, lo(_ebss)
|
||||
.clearBSS:
|
||||
be r1, r3, .callMain
|
||||
sw (r1+0), r0
|
||||
addi r1, r1, 4
|
||||
bi .clearBSS
|
||||
|
||||
.callMain:
|
||||
mvi r1, 0
|
||||
mvi r2, 0
|
||||
mvi r3, 0
|
||||
calli main
|
||||
|
||||
irq_enable:
|
||||
mvi r1, 1
|
||||
wcsr IE, r1
|
||||
ret
|
||||
|
||||
irq_mask:
|
||||
mvi r1, 0x0000000f
|
||||
wcsr IM, r1
|
||||
ret
|
||||
|
||||
irq_disable:
|
||||
mvi r1, 0
|
||||
wcsr IE, r1
|
||||
ret
|
||||
|
||||
jump:
|
||||
b r1
|
||||
|
||||
halt:
|
||||
bi halt
|
||||
|
1
lm32/logic/sakc/firmware/boot0-serial/crt0ram.d
Normal file
1
lm32/logic/sakc/firmware/boot0-serial/crt0ram.d
Normal file
@ -0,0 +1 @@
|
||||
crt0ram.o: crt0ram.S
|
BIN
lm32/logic/sakc/firmware/boot0-serial/crt0ram.o
Normal file
BIN
lm32/logic/sakc/firmware/boot0-serial/crt0ram.o
Normal file
Binary file not shown.
BIN
lm32/logic/sakc/firmware/boot0-serial/image
Executable file
BIN
lm32/logic/sakc/firmware/boot0-serial/image
Executable file
Binary file not shown.
44
lm32/logic/sakc/firmware/boot0-serial/image.bin
Executable file
44
lm32/logic/sakc/firmware/boot0-serial/image.bin
Executable file
@ -0,0 +1,44 @@
|
||||
S00C0000696D6167652E62696E89
|
||||
S113000098000000D00000007801000038210000B2
|
||||
S1130010D0E10000F80000033400000034000000C8
|
||||
S1130020781C00003B9C0FFC781A00003B5A02A08D
|
||||
S11300307801000038210298780300003863029C9C
|
||||
S1130040442300045820000034210004E3FFFFFD92
|
||||
S1130050340100003402000034030000F800001DE5
|
||||
S113006034010001D0010000C3A000003401000FDE
|
||||
S1130070D0210000C3A0000034010000D001000022
|
||||
S1130080C3A00000C0200000E0000000379CFFF87F
|
||||
S11300905B8B00085B9D0004F80000573C2B0008B4
|
||||
S11300A0F8000055B56108003C2B0008F800005228
|
||||
S11300B0B56108003C2B0008F800004FB56108004A
|
||||
S11300C02B9D00042B8B0008379C0008C3A0000064
|
||||
S11300D0379CFFE45B8B001C5B8C00185B8D001469
|
||||
S11300E05B8E00105B8F000C5B9000085B9D00042E
|
||||
S11300F0F8000040340D00673401002A340E007506
|
||||
S1130100340F006478100000442D0008442E0016BB
|
||||
S1130110442F000ABA00080038210270F800004891
|
||||
S1130120F80000355C2DFFFAFBFFFFD9FBFFFFD67B
|
||||
S1130130F8000031E3FFFFFCFBFFFFD5B8205800B7
|
||||
S1130140FBFFFFD3B5616000516CFFF64161000015
|
||||
S1130150356B0001F8000031558BFFFDF8000026D7
|
||||
S1130160E3FFFFF1FBFFFFCAB8205800FBFFFFC805
|
||||
S1130170B5616000516CFFEBF800001F31610000B5
|
||||
S1130180356B0001558BFFFDF800001BE3FFFFE614
|
||||
S113019078020000384202903803C350284200001D
|
||||
S11301A0882308005841001034010000584100140D
|
||||
S11301B03401000A5841000C2841000C20210001A0
|
||||
S11301C04420FFFEC3A00000780100003821029003
|
||||
S11301D0282100003802C3505822000434020000D1
|
||||
S11301E0582200083402000E58220000C3A0000068
|
||||
S11301F0C3A00000780100003821028C28220000EE
|
||||
S113020028410000202100014420FFFE2841000471
|
||||
S1130210202100FFC3A00000780200003842028CB5
|
||||
S113022028430000202100FF286200002042001023
|
||||
S11302305C40FFFE58610004C3A00000402400009D
|
||||
S11302404480000B780200003842028C28430000EE
|
||||
S113025028620000204200105C40FFFE5864000445
|
||||
S113026034210001402400005C82FFFAC3A0000096
|
||||
S11302702A2A53414B432F626F6F746C6F6164651C
|
||||
S10F0280722A2A203E200D0A0000000013
|
||||
S10F028CF0000000F0010000F00200008F
|
||||
S9030000FC
|
454
lm32/logic/sakc/firmware/boot0-serial/image.lst
Normal file
454
lm32/logic/sakc/firmware/boot0-serial/image.lst
Normal file
@ -0,0 +1,454 @@
|
||||
|
||||
image: file format elf32-lm32
|
||||
|
||||
Sections:
|
||||
Idx Name Size VMA LMA File off Algn
|
||||
0 .text 00000270 00000000 00000000 00000054 2**2
|
||||
CONTENTS, ALLOC, LOAD, CODE
|
||||
1 .rodata 0000001c 00000270 00000270 000002c4 2**2
|
||||
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
||||
2 .data 0000000c 0000028c 0000028c 000002e0 2**2
|
||||
CONTENTS, ALLOC, LOAD, DATA
|
||||
3 .bss 00000004 00000298 00000298 000002ec 2**2
|
||||
ALLOC
|
||||
4 .debug_abbrev 00000219 00000000 00000000 000002ec 2**0
|
||||
CONTENTS, READONLY, DEBUGGING
|
||||
5 .debug_info 000003d0 00000000 00000000 00000505 2**0
|
||||
CONTENTS, READONLY, DEBUGGING
|
||||
6 .debug_line 000002d8 00000000 00000000 000008d5 2**0
|
||||
CONTENTS, READONLY, DEBUGGING
|
||||
7 .debug_frame 000000a0 00000000 00000000 00000bb0 2**2
|
||||
CONTENTS, READONLY, DEBUGGING
|
||||
8 .debug_loc 000000fb 00000000 00000000 00000c50 2**0
|
||||
CONTENTS, READONLY, DEBUGGING
|
||||
9 .debug_pubnames 000000bc 00000000 00000000 00000d4b 2**0
|
||||
CONTENTS, READONLY, DEBUGGING
|
||||
10 .debug_aranges 00000040 00000000 00000000 00000e07 2**0
|
||||
CONTENTS, READONLY, DEBUGGING
|
||||
11 .debug_ranges 00000018 00000000 00000000 00000e47 2**0
|
||||
CONTENTS, READONLY, DEBUGGING
|
||||
12 .debug_str 0000017b 00000000 00000000 00000e5f 2**0
|
||||
CONTENTS, READONLY, DEBUGGING
|
||||
13 .comment 00000011 00000000 00000000 00000fda 2**0
|
||||
CONTENTS, READONLY
|
||||
|
||||
Disassembly of section .text:
|
||||
|
||||
00000000 <_ftext>:
|
||||
0: 98 00 00 00 xor r0,r0,r0
|
||||
4: d0 00 00 00 wcsr IE,r0
|
||||
8: 78 01 00 00 mvhi r1,0x0
|
||||
c: 38 21 00 00 ori r1,r1,0x0
|
||||
10: d0 e1 00 00 wcsr EBA,r1
|
||||
14: f8 00 00 03 calli 20 <_crt0>
|
||||
18: 34 00 00 00 nop
|
||||
1c: 34 00 00 00 nop
|
||||
|
||||
00000020 <_crt0>:
|
||||
20: 78 1c 00 00 mvhi sp,0x0
|
||||
24: 3b 9c 0f fc ori sp,sp,0xffc
|
||||
28: 78 1a 00 00 mvhi gp,0x0
|
||||
2c: 3b 5a 02 a0 ori gp,gp,0x2a0
|
||||
30: 78 01 00 00 mvhi r1,0x0
|
||||
34: 38 21 02 98 ori r1,r1,0x298
|
||||
38: 78 03 00 00 mvhi r3,0x0
|
||||
3c: 38 63 02 9c ori r3,r3,0x29c
|
||||
|
||||
00000040 <.clearBSS>:
|
||||
40: 44 23 00 04 be r1,r3,50 <.callMain>
|
||||
44: 58 20 00 00 sw (r1+0),r0
|
||||
48: 34 21 00 04 addi r1,r1,4
|
||||
4c: e3 ff ff fd bi 40 <.clearBSS>
|
||||
|
||||
00000050 <.callMain>:
|
||||
50: 34 01 00 00 mvi r1,0
|
||||
54: 34 02 00 00 mvi r2,0
|
||||
58: 34 03 00 00 mvi r3,0
|
||||
5c: f8 00 00 1d calli d0 <main>
|
||||
|
||||
00000060 <irq_enable>:
|
||||
60: 34 01 00 01 mvi r1,1
|
||||
64: d0 01 00 00 wcsr IE,r1
|
||||
68: c3 a0 00 00 ret
|
||||
|
||||
0000006c <irq_mask>:
|
||||
6c: 34 01 00 0f mvi r1,15
|
||||
70: d0 21 00 00 wcsr IM,r1
|
||||
74: c3 a0 00 00 ret
|
||||
|
||||
00000078 <irq_disable>:
|
||||
78: 34 01 00 00 mvi r1,0
|
||||
7c: d0 01 00 00 wcsr IE,r1
|
||||
80: c3 a0 00 00 ret
|
||||
|
||||
00000084 <jump>:
|
||||
84: c0 20 00 00 b r1
|
||||
|
||||
00000088 <halt>:
|
||||
88: e0 00 00 00 bi 88 <halt>
|
||||
|
||||
0000008c <read_uint32>:
|
||||
*/
|
||||
#include "soc-hw.h"
|
||||
|
||||
/* prototypes */
|
||||
uint32_t read_uint32()
|
||||
{
|
||||
8c: 37 9c ff f8 addi sp,sp,-8
|
||||
90: 5b 8b 00 08 sw (sp+8),r11
|
||||
94: 5b 9d 00 04 sw (sp+4),ra
|
||||
uint32_t val = 0, i;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
val <<= 8;
|
||||
val += (uint8_t)uart_getchar();
|
||||
98: f8 00 00 57 calli 1f4 <uart_getchar>
|
||||
uint32_t read_uint32()
|
||||
{
|
||||
uint32_t val = 0, i;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
val <<= 8;
|
||||
9c: 3c 2b 00 08 sli r11,r1,8
|
||||
val += (uint8_t)uart_getchar();
|
||||
a0: f8 00 00 55 calli 1f4 <uart_getchar>
|
||||
a4: b5 61 08 00 add r1,r11,r1
|
||||
uint32_t read_uint32()
|
||||
{
|
||||
uint32_t val = 0, i;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
val <<= 8;
|
||||
a8: 3c 2b 00 08 sli r11,r1,8
|
||||
val += (uint8_t)uart_getchar();
|
||||
ac: f8 00 00 52 calli 1f4 <uart_getchar>
|
||||
b0: b5 61 08 00 add r1,r11,r1
|
||||
uint32_t read_uint32()
|
||||
{
|
||||
uint32_t val = 0, i;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
val <<= 8;
|
||||
b4: 3c 2b 00 08 sli r11,r1,8
|
||||
val += (uint8_t)uart_getchar();
|
||||
b8: f8 00 00 4f calli 1f4 <uart_getchar>
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
bc: b5 61 08 00 add r1,r11,r1
|
||||
c0: 2b 9d 00 04 lw ra,(sp+4)
|
||||
c4: 2b 8b 00 08 lw r11,(sp+8)
|
||||
c8: 37 9c 00 08 addi sp,sp,8
|
||||
cc: c3 a0 00 00 ret
|
||||
|
||||
000000d0 <main>:
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
d0: 37 9c ff e4 addi sp,sp,-28
|
||||
d4: 5b 8b 00 1c sw (sp+28),r11
|
||||
d8: 5b 8c 00 18 sw (sp+24),r12
|
||||
dc: 5b 8d 00 14 sw (sp+20),r13
|
||||
e0: 5b 8e 00 10 sw (sp+16),r14
|
||||
e4: 5b 8f 00 0c sw (sp+12),r15
|
||||
e8: 5b 90 00 08 sw (sp+8),r16
|
||||
ec: 5b 9d 00 04 sw (sp+4),ra
|
||||
int8_t *p;
|
||||
uint8_t c;
|
||||
|
||||
// Initialize UART
|
||||
uart_init();
|
||||
f0: f8 00 00 40 calli 1f0 <uart_init>
|
||||
|
||||
c = '*'; // print msg on first iteration
|
||||
for(;;) {
|
||||
uint32_t start, size;
|
||||
|
||||
switch (c) {
|
||||
f4: 34 0d 00 67 mvi r13,103
|
||||
{
|
||||
int8_t *p;
|
||||
uint8_t c;
|
||||
|
||||
// Initialize UART
|
||||
uart_init();
|
||||
f8: 34 01 00 2a mvi r1,42
|
||||
|
||||
c = '*'; // print msg on first iteration
|
||||
for(;;) {
|
||||
uint32_t start, size;
|
||||
|
||||
switch (c) {
|
||||
fc: 34 0e 00 75 mvi r14,117
|
||||
100: 34 0f 00 64 mvi r15,100
|
||||
case 'g': // goto
|
||||
start = read_uint32();
|
||||
jump(start);
|
||||
break;
|
||||
default:
|
||||
uart_putstr("**SAKC/bootloader** > \r\n");
|
||||
104: 78 10 00 00 mvhi r16,0x0
|
||||
|
||||
c = '*'; // print msg on first iteration
|
||||
for(;;) {
|
||||
uint32_t start, size;
|
||||
|
||||
switch (c) {
|
||||
108: 44 2d 00 08 be r1,r13,128 <main+0x58>
|
||||
10c: 44 2e 00 16 be r1,r14,164 <main+0x94>
|
||||
110: 44 2f 00 0a be r1,r15,138 <main+0x68>
|
||||
case 'g': // goto
|
||||
start = read_uint32();
|
||||
jump(start);
|
||||
break;
|
||||
default:
|
||||
uart_putstr("**SAKC/bootloader** > \r\n");
|
||||
114: ba 00 08 00 mv r1,r16
|
||||
118: 38 21 02 70 ori r1,r1,0x270
|
||||
11c: f8 00 00 48 calli 23c <uart_putstr>
|
||||
break;
|
||||
};
|
||||
c = uart_getchar();
|
||||
120: f8 00 00 35 calli 1f4 <uart_getchar>
|
||||
|
||||
c = '*'; // print msg on first iteration
|
||||
for(;;) {
|
||||
uint32_t start, size;
|
||||
|
||||
switch (c) {
|
||||
124: 5c 2d ff fa bne r1,r13,10c <main+0x3c>
|
||||
size = read_uint32();
|
||||
for (p = (int8_t *) start; p < (int8_t *) (start+size); p++)
|
||||
uart_putchar( *p );
|
||||
break;
|
||||
case 'g': // goto
|
||||
start = read_uint32();
|
||||
128: fb ff ff d9 calli 8c <read_uint32>
|
||||
jump(start);
|
||||
12c: fb ff ff d6 calli 84 <jump>
|
||||
break;
|
||||
default:
|
||||
uart_putstr("**SAKC/bootloader** > \r\n");
|
||||
break;
|
||||
};
|
||||
c = uart_getchar();
|
||||
130: f8 00 00 31 calli 1f4 <uart_getchar>
|
||||
134: e3 ff ff fc bi 124 <main+0x54>
|
||||
size = read_uint32();
|
||||
for (p = (int8_t *) start; p < (int8_t *) (start+size); p++)
|
||||
*p = uart_getchar();
|
||||
break;
|
||||
case 'd': // download
|
||||
start = read_uint32();
|
||||
138: fb ff ff d5 calli 8c <read_uint32>
|
||||
size = read_uint32();
|
||||
for (p = (int8_t *) start; p < (int8_t *) (start+size); p++)
|
||||
13c: b8 20 58 00 mv r11,r1
|
||||
for (p = (int8_t *) start; p < (int8_t *) (start+size); p++)
|
||||
*p = uart_getchar();
|
||||
break;
|
||||
case 'd': // download
|
||||
start = read_uint32();
|
||||
size = read_uint32();
|
||||
140: fb ff ff d3 calli 8c <read_uint32>
|
||||
for (p = (int8_t *) start; p < (int8_t *) (start+size); p++)
|
||||
144: b5 61 60 00 add r12,r11,r1
|
||||
148: 51 6c ff f6 bgeu r11,r12,120 <main+0x50>
|
||||
uart_putchar( *p );
|
||||
14c: 41 61 00 00 lbu r1,(r11+0)
|
||||
*p = uart_getchar();
|
||||
break;
|
||||
case 'd': // download
|
||||
start = read_uint32();
|
||||
size = read_uint32();
|
||||
for (p = (int8_t *) start; p < (int8_t *) (start+size); p++)
|
||||
150: 35 6b 00 01 addi r11,r11,1
|
||||
uart_putchar( *p );
|
||||
154: f8 00 00 31 calli 218 <uart_putchar>
|
||||
*p = uart_getchar();
|
||||
break;
|
||||
case 'd': // download
|
||||
start = read_uint32();
|
||||
size = read_uint32();
|
||||
for (p = (int8_t *) start; p < (int8_t *) (start+size); p++)
|
||||
158: 55 8b ff fd bgu r12,r11,14c <main+0x7c>
|
||||
break;
|
||||
default:
|
||||
uart_putstr("**SAKC/bootloader** > \r\n");
|
||||
break;
|
||||
};
|
||||
c = uart_getchar();
|
||||
15c: f8 00 00 26 calli 1f4 <uart_getchar>
|
||||
160: e3 ff ff f1 bi 124 <main+0x54>
|
||||
for(;;) {
|
||||
uint32_t start, size;
|
||||
|
||||
switch (c) {
|
||||
case 'u': // upload
|
||||
start = read_uint32();
|
||||
164: fb ff ff ca calli 8c <read_uint32>
|
||||
size = read_uint32();
|
||||
for (p = (int8_t *) start; p < (int8_t *) (start+size); p++)
|
||||
168: b8 20 58 00 mv r11,r1
|
||||
uint32_t start, size;
|
||||
|
||||
switch (c) {
|
||||
case 'u': // upload
|
||||
start = read_uint32();
|
||||
size = read_uint32();
|
||||
16c: fb ff ff c8 calli 8c <read_uint32>
|
||||
for (p = (int8_t *) start; p < (int8_t *) (start+size); p++)
|
||||
170: b5 61 60 00 add r12,r11,r1
|
||||
174: 51 6c ff eb bgeu r11,r12,120 <main+0x50>
|
||||
*p = uart_getchar();
|
||||
178: f8 00 00 1f calli 1f4 <uart_getchar>
|
||||
17c: 31 61 00 00 sb (r11+0),r1
|
||||
|
||||
switch (c) {
|
||||
case 'u': // upload
|
||||
start = read_uint32();
|
||||
size = read_uint32();
|
||||
for (p = (int8_t *) start; p < (int8_t *) (start+size); p++)
|
||||
180: 35 6b 00 01 addi r11,r11,1
|
||||
184: 55 8b ff fd bgu r12,r11,178 <main+0xa8>
|
||||
break;
|
||||
default:
|
||||
uart_putstr("**SAKC/bootloader** > \r\n");
|
||||
break;
|
||||
};
|
||||
c = uart_getchar();
|
||||
188: f8 00 00 1b calli 1f4 <uart_getchar>
|
||||
18c: e3 ff ff e6 bi 124 <main+0x54>
|
||||
|
||||
00000190 <sleep>:
|
||||
void sleep(int msec)
|
||||
{
|
||||
uint32_t tcr;
|
||||
|
||||
// Use timer0.1
|
||||
timer0->compare1 = (FCPU/1000)*msec;
|
||||
190: 78 02 00 00 mvhi r2,0x0
|
||||
194: 38 42 02 90 ori r2,r2,0x290
|
||||
198: 38 03 c3 50 mvu r3,0xc350
|
||||
19c: 28 42 00 00 lw r2,(r2+0)
|
||||
1a0: 88 23 08 00 mul r1,r1,r3
|
||||
1a4: 58 41 00 10 sw (r2+16),r1
|
||||
timer0->counter1 = 0;
|
||||
1a8: 34 01 00 00 mvi r1,0
|
||||
1ac: 58 41 00 14 sw (r2+20),r1
|
||||
timer0->tcr1 = TIMER_EN | TIMER_IRQEN;
|
||||
1b0: 34 01 00 0a mvi r1,10
|
||||
1b4: 58 41 00 0c sw (r2+12),r1
|
||||
|
||||
do {
|
||||
//halt();
|
||||
tcr = timer0->tcr1;
|
||||
1b8: 28 41 00 0c lw r1,(r2+12)
|
||||
} while ( ! (tcr & TIMER_TRIG) );
|
||||
1bc: 20 21 00 01 andi r1,r1,0x1
|
||||
1c0: 44 20 ff fe be r1,r0,1b8 <sleep+0x28>
|
||||
}
|
||||
1c4: c3 a0 00 00 ret
|
||||
|
||||
000001c8 <tic_init>:
|
||||
|
||||
void tic_init()
|
||||
{
|
||||
// Setup timer0.0
|
||||
timer0->compare0 = (FCPU/1000);
|
||||
1c8: 78 01 00 00 mvhi r1,0x0
|
||||
1cc: 38 21 02 90 ori r1,r1,0x290
|
||||
1d0: 28 21 00 00 lw r1,(r1+0)
|
||||
1d4: 38 02 c3 50 mvu r2,0xc350
|
||||
1d8: 58 22 00 04 sw (r1+4),r2
|
||||
timer0->counter0 = 0;
|
||||
1dc: 34 02 00 00 mvi r2,0
|
||||
1e0: 58 22 00 08 sw (r1+8),r2
|
||||
timer0->tcr0 = TIMER_EN | TIMER_AR | TIMER_IRQEN;
|
||||
1e4: 34 02 00 0e mvi r2,14
|
||||
1e8: 58 22 00 00 sw (r1+0),r2
|
||||
}
|
||||
1ec: c3 a0 00 00 ret
|
||||
|
||||
000001f0 <uart_init>:
|
||||
//uart0->lcr = 0x03; // Line Control Register: 8N1
|
||||
//uart0->mcr = 0x00; // Modem Control Register
|
||||
|
||||
// Setup Divisor register (Fclk / Baud)
|
||||
//uart0->div = (FCPU/(57600*16));
|
||||
}
|
||||
1f0: c3 a0 00 00 ret
|
||||
|
||||
000001f4 <uart_getchar>:
|
||||
|
||||
char uart_getchar()
|
||||
{
|
||||
1f4: 78 01 00 00 mvhi r1,0x0
|
||||
1f8: 38 21 02 8c ori r1,r1,0x28c
|
||||
1fc: 28 22 00 00 lw r2,(r1+0)
|
||||
while (! (uart0->ucr & UART_DR)) ;
|
||||
200: 28 41 00 00 lw r1,(r2+0)
|
||||
204: 20 21 00 01 andi r1,r1,0x1
|
||||
208: 44 20 ff fe be r1,r0,200 <uart_getchar+0xc>
|
||||
return uart0->rxtx;
|
||||
20c: 28 41 00 04 lw r1,(r2+4)
|
||||
}
|
||||
210: 20 21 00 ff andi r1,r1,0xff
|
||||
214: c3 a0 00 00 ret
|
||||
|
||||
00000218 <uart_putchar>:
|
||||
|
||||
void uart_putchar(char c)
|
||||
{
|
||||
218: 78 02 00 00 mvhi r2,0x0
|
||||
21c: 38 42 02 8c ori r2,r2,0x28c
|
||||
220: 28 43 00 00 lw r3,(r2+0)
|
||||
224: 20 21 00 ff andi r1,r1,0xff
|
||||
while (uart0->ucr & UART_BUSY) ;
|
||||
228: 28 62 00 00 lw r2,(r3+0)
|
||||
22c: 20 42 00 10 andi r2,r2,0x10
|
||||
230: 5c 40 ff fe bne r2,r0,228 <uart_putchar+0x10>
|
||||
uart0->rxtx = c;
|
||||
234: 58 61 00 04 sw (r3+4),r1
|
||||
}
|
||||
238: c3 a0 00 00 ret
|
||||
|
||||
0000023c <uart_putstr>:
|
||||
|
||||
void uart_putstr(char *str)
|
||||
{
|
||||
char *c = str;
|
||||
while(*c) {
|
||||
23c: 40 24 00 00 lbu r4,(r1+0)
|
||||
240: 44 80 00 0b be r4,r0,26c <uart_putstr+0x30>
|
||||
244: 78 02 00 00 mvhi r2,0x0
|
||||
248: 38 42 02 8c ori r2,r2,0x28c
|
||||
24c: 28 43 00 00 lw r3,(r2+0)
|
||||
return uart0->rxtx;
|
||||
}
|
||||
|
||||
void uart_putchar(char c)
|
||||
{
|
||||
while (uart0->ucr & UART_BUSY) ;
|
||||
250: 28 62 00 00 lw r2,(r3+0)
|
||||
254: 20 42 00 10 andi r2,r2,0x10
|
||||
258: 5c 40 ff fe bne r2,r0,250 <uart_putstr+0x14>
|
||||
uart0->rxtx = c;
|
||||
25c: 58 64 00 04 sw (r3+4),r4
|
||||
void uart_putstr(char *str)
|
||||
{
|
||||
char *c = str;
|
||||
while(*c) {
|
||||
uart_putchar(*c);
|
||||
c++;
|
||||
260: 34 21 00 01 addi r1,r1,1
|
||||
}
|
||||
|
||||
void uart_putstr(char *str)
|
||||
{
|
||||
char *c = str;
|
||||
while(*c) {
|
||||
264: 40 24 00 00 lbu r4,(r1+0)
|
||||
268: 5c 82 ff fa bne r4,r2,250 <uart_putstr+0x14>
|
||||
26c: c3 a0 00 00 ret
|
127
lm32/logic/sakc/firmware/boot0-serial/image.map
Normal file
127
lm32/logic/sakc/firmware/boot0-serial/image.map
Normal file
@ -0,0 +1,127 @@
|
||||
|
||||
Memory Configuration
|
||||
|
||||
Name Origin Length Attributes
|
||||
bram 0x00000000 0x00001000
|
||||
*default* 0x00000000 0xffffffff
|
||||
|
||||
Linker script and memory map
|
||||
|
||||
0x00000000 __DYNAMIC = 0x0
|
||||
0x00000000 _BRAM_START = 0x0
|
||||
0x00001000 _BRAM_SIZE = 0x1000
|
||||
0x00001000 _BRAM_END = (_BRAM_START + _BRAM_SIZE)
|
||||
|
||||
.text 0x00000000 0x270
|
||||
0x00000000 _ftext = .
|
||||
*(.text .stub .text.* .gnu.linkonce.t.*)
|
||||
.text 0x00000000 0x8c crt0ram.o
|
||||
0x00000000 _start
|
||||
0x00000060 irq_enable
|
||||
0x0000006c irq_mask
|
||||
0x00000078 irq_disable
|
||||
0x00000084 jump
|
||||
0x00000088 halt
|
||||
.text 0x0000008c 0x104 main.o
|
||||
0x0000008c read_uint32
|
||||
0x000000d0 main
|
||||
.text 0x00000190 0xe0 soc-hw.o
|
||||
0x00000190 sleep
|
||||
0x000001c8 tic_init
|
||||
0x000001f0 uart_init
|
||||
0x000001f4 uart_getchar
|
||||
0x00000218 uart_putchar
|
||||
0x0000023c uart_putstr
|
||||
0x00000270 _etext = .
|
||||
|
||||
.rodata 0x00000270 0x1c
|
||||
0x00000270 . = ALIGN (0x4)
|
||||
0x00000270 _frodata = .
|
||||
*(.rodata .rodata.* .gnu.linkonce.r.*)
|
||||
.rodata.str1.4
|
||||
0x00000270 0x1c main.o
|
||||
*(.rodata1)
|
||||
0x0000028c _erodata = .
|
||||
|
||||
.data 0x0000028c 0xc
|
||||
0x0000028c . = ALIGN (0x4)
|
||||
0x0000028c _fdata = .
|
||||
*(.data .data.* .gnu.linkonce.d.*)
|
||||
.data 0x0000028c 0x0 crt0ram.o
|
||||
.data 0x0000028c 0x0 main.o
|
||||
.data 0x0000028c 0xc soc-hw.o
|
||||
0x0000028c uart0
|
||||
0x00000290 timer0
|
||||
0x00000294 gpio0
|
||||
*(.data1)
|
||||
0x000002a0 _gp = ALIGN (0x10)
|
||||
*(.sdata .sdata.* .gnu.linkonce.s.*)
|
||||
0x00000298 _edata = .
|
||||
|
||||
.bss 0x00000298 0x4
|
||||
0x00000298 . = ALIGN (0x4)
|
||||
0x00000298 _fbss = .
|
||||
*(.dynsbss)
|
||||
*(.sbss .sbss.* .gnu.linkonce.sb.*)
|
||||
*(.scommon)
|
||||
*(.dynbss)
|
||||
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||
.bss 0x00000298 0x0 crt0ram.o
|
||||
.bss 0x00000298 0x0 main.o
|
||||
.bss 0x00000298 0x4 soc-hw.o
|
||||
0x00000298 msec
|
||||
*(COMMON)
|
||||
0x0000029c _ebss = .
|
||||
0x0000029c _end = .
|
||||
0x00000ffc PROVIDE (_fstack, 0xffc)
|
||||
LOAD crt0ram.o
|
||||
LOAD main.o
|
||||
LOAD soc-hw.o
|
||||
OUTPUT(image elf32-lm32)
|
||||
|
||||
.debug_abbrev 0x00000000 0x219
|
||||
.debug_abbrev 0x00000000 0xcd main.o
|
||||
.debug_abbrev 0x000000cd 0x14c soc-hw.o
|
||||
|
||||
.debug_info 0x00000000 0x3d0
|
||||
.debug_info 0x00000000 0x121 main.o
|
||||
.debug_info 0x00000121 0x2af soc-hw.o
|
||||
|
||||
.debug_line 0x00000000 0x2d8
|
||||
.debug_line 0x00000000 0x18f main.o
|
||||
.debug_line 0x0000018f 0x149 soc-hw.o
|
||||
|
||||
.debug_frame 0x00000000 0xa0
|
||||
.debug_frame 0x00000000 0x30 main.o
|
||||
.debug_frame 0x00000030 0x70 soc-hw.o
|
||||
|
||||
.debug_loc 0x00000000 0xfb
|
||||
.debug_loc 0x00000000 0xb7 main.o
|
||||
.debug_loc 0x000000b7 0x44 soc-hw.o
|
||||
|
||||
.debug_pubnames
|
||||
0x00000000 0xbc
|
||||
.debug_pubnames
|
||||
0x00000000 0x2b main.o
|
||||
.debug_pubnames
|
||||
0x0000002b 0x91 soc-hw.o
|
||||
|
||||
.debug_aranges 0x00000000 0x40
|
||||
.debug_aranges
|
||||
0x00000000 0x20 main.o
|
||||
.debug_aranges
|
||||
0x00000020 0x20 soc-hw.o
|
||||
|
||||
.debug_ranges 0x00000000 0x18
|
||||
.debug_ranges 0x00000000 0x18 main.o
|
||||
|
||||
.debug_str 0x00000000 0x17b
|
||||
.debug_str 0x00000000 0xb8 main.o
|
||||
0xd0 (size before relaxing)
|
||||
.debug_str 0x000000b8 0xc3 soc-hw.o
|
||||
0x157 (size before relaxing)
|
||||
|
||||
.comment 0x00000000 0x11
|
||||
.comment 0x00000000 0x11 main.o
|
||||
0x12 (size before relaxing)
|
||||
.comment 0x00000000 0x12 soc-hw.o
|
1024
lm32/logic/sakc/firmware/boot0-serial/image.ram
Normal file
1024
lm32/logic/sakc/firmware/boot0-serial/image.ram
Normal file
File diff suppressed because it is too large
Load Diff
44
lm32/logic/sakc/firmware/boot0-serial/image.srec
Executable file
44
lm32/logic/sakc/firmware/boot0-serial/image.srec
Executable file
@ -0,0 +1,44 @@
|
||||
S00D0000696D6167652E7372656314
|
||||
S113000098000000D00000007801000038210000B2
|
||||
S1130010D0E10000F80000033400000034000000C8
|
||||
S1130020781C00003B9C0FFC781A00003B5A02A08D
|
||||
S11300307801000038210298780300003863029C9C
|
||||
S1130040442300045820000034210004E3FFFFFD92
|
||||
S1130050340100003402000034030000F800001DE5
|
||||
S113006034010001D0010000C3A000003401000FDE
|
||||
S1130070D0210000C3A0000034010000D001000022
|
||||
S1130080C3A00000C0200000E0000000379CFFF87F
|
||||
S11300905B8B00085B9D0004F80000573C2B0008B4
|
||||
S11300A0F8000055B56108003C2B0008F800005228
|
||||
S11300B0B56108003C2B0008F800004FB56108004A
|
||||
S11300C02B9D00042B8B0008379C0008C3A0000064
|
||||
S11300D0379CFFE45B8B001C5B8C00185B8D001469
|
||||
S11300E05B8E00105B8F000C5B9000085B9D00042E
|
||||
S11300F0F8000040340D00673401002A340E007506
|
||||
S1130100340F006478100000442D0008442E0016BB
|
||||
S1130110442F000ABA00080038210270F800004891
|
||||
S1130120F80000355C2DFFFAFBFFFFD9FBFFFFD67B
|
||||
S1130130F8000031E3FFFFFCFBFFFFD5B8205800B7
|
||||
S1130140FBFFFFD3B5616000516CFFF64161000015
|
||||
S1130150356B0001F8000031558BFFFDF8000026D7
|
||||
S1130160E3FFFFF1FBFFFFCAB8205800FBFFFFC805
|
||||
S1130170B5616000516CFFEBF800001F31610000B5
|
||||
S1130180356B0001558BFFFDF800001BE3FFFFE614
|
||||
S113019078020000384202903803C350284200001D
|
||||
S11301A0882308005841001034010000584100140D
|
||||
S11301B03401000A5841000C2841000C20210001A0
|
||||
S11301C04420FFFEC3A00000780100003821029003
|
||||
S11301D0282100003802C3505822000434020000D1
|
||||
S11301E0582200083402000E58220000C3A0000068
|
||||
S11301F0C3A00000780100003821028C28220000EE
|
||||
S113020028410000202100014420FFFE2841000471
|
||||
S1130210202100FFC3A00000780200003842028CB5
|
||||
S113022028430000202100FF286200002042001023
|
||||
S11302305C40FFFE58610004C3A00000402400009D
|
||||
S11302404480000B780200003842028C28430000EE
|
||||
S113025028620000204200105C40FFFE5864000445
|
||||
S113026034210001402400005C82FFFAC3A0000096
|
||||
S11302702A2A53414B432F626F6F746C6F6164651C
|
||||
S10F0280722A2A203E200D0A0000000013
|
||||
S10F028CF0000000F0010000F00200008F
|
||||
S9030000FC
|
59
lm32/logic/sakc/firmware/boot0-serial/linker.ld
Normal file
59
lm32/logic/sakc/firmware/boot0-serial/linker.ld
Normal file
@ -0,0 +1,59 @@
|
||||
OUTPUT_FORMAT("elf32-lm32")
|
||||
ENTRY(_start)
|
||||
|
||||
__DYNAMIC = 0;
|
||||
|
||||
|
||||
_BRAM_START = 0x00000000;
|
||||
_BRAM_SIZE = 0x1000;
|
||||
_BRAM_END = _BRAM_START + _BRAM_SIZE;
|
||||
|
||||
MEMORY {
|
||||
bram : ORIGIN = 0x00000000, LENGTH = 0x1000 /* 4k */
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text :
|
||||
{
|
||||
_ftext = .;
|
||||
*(.text .stub .text.* .gnu.linkonce.t.*)
|
||||
_etext = .;
|
||||
} > bram
|
||||
|
||||
.rodata :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_frodata = .;
|
||||
*(.rodata .rodata.* .gnu.linkonce.r.*)
|
||||
*(.rodata1)
|
||||
_erodata = .;
|
||||
} > bram
|
||||
|
||||
.data :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_fdata = .;
|
||||
*(.data .data.* .gnu.linkonce.d.*)
|
||||
*(.data1)
|
||||
_gp = ALIGN(16);
|
||||
*(.sdata .sdata.* .gnu.linkonce.s.*)
|
||||
_edata = .;
|
||||
} > bram
|
||||
|
||||
.bss :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_fbss = .;
|
||||
*(.dynsbss)
|
||||
*(.sbss .sbss.* .gnu.linkonce.sb.*)
|
||||
*(.scommon)
|
||||
*(.dynbss)
|
||||
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
_ebss = .;
|
||||
_end = .;
|
||||
} > bram
|
||||
}
|
||||
|
||||
PROVIDE(_fstack = ORIGIN(bram) + LENGTH(bram) - 4);
|
57
lm32/logic/sakc/firmware/boot0-serial/main.c
Normal file
57
lm32/logic/sakc/firmware/boot0-serial/main.c
Normal file
@ -0,0 +1,57 @@
|
||||
/**
|
||||
* Primitive first stage bootloader
|
||||
*
|
||||
*
|
||||
*/
|
||||
#include "soc-hw.h"
|
||||
|
||||
/* prototypes */
|
||||
uint32_t read_uint32()
|
||||
{
|
||||
uint32_t val = 0, i;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
val <<= 8;
|
||||
val += (uint8_t)uart_getchar();
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int8_t *p;
|
||||
uint8_t c;
|
||||
|
||||
// Initialize UART
|
||||
uart_init();
|
||||
|
||||
c = '*'; // print msg on first iteration
|
||||
for(;;) {
|
||||
uint32_t start, size;
|
||||
|
||||
switch (c) {
|
||||
case 'u': // upload
|
||||
start = read_uint32();
|
||||
size = read_uint32();
|
||||
for (p = (int8_t *) start; p < (int8_t *) (start+size); p++)
|
||||
*p = uart_getchar();
|
||||
break;
|
||||
case 'd': // download
|
||||
start = read_uint32();
|
||||
size = read_uint32();
|
||||
for (p = (int8_t *) start; p < (int8_t *) (start+size); p++)
|
||||
uart_putchar( *p );
|
||||
break;
|
||||
case 'g': // goto
|
||||
start = read_uint32();
|
||||
jump(start);
|
||||
break;
|
||||
default:
|
||||
uart_putstr("**SAKC/bootloader** > \r\n");
|
||||
break;
|
||||
};
|
||||
c = uart_getchar();
|
||||
}
|
||||
}
|
||||
|
1
lm32/logic/sakc/firmware/boot0-serial/main.d
Normal file
1
lm32/logic/sakc/firmware/boot0-serial/main.d
Normal file
@ -0,0 +1 @@
|
||||
main.o: main.c soc-hw.h
|
BIN
lm32/logic/sakc/firmware/boot0-serial/main.o
Normal file
BIN
lm32/logic/sakc/firmware/boot0-serial/main.o
Normal file
Binary file not shown.
69
lm32/logic/sakc/firmware/boot0-serial/soc-hw.c
Normal file
69
lm32/logic/sakc/firmware/boot0-serial/soc-hw.c
Normal file
@ -0,0 +1,69 @@
|
||||
#include "soc-hw.h"
|
||||
|
||||
uart_t *uart0 = (uart_t *) 0xF0000000;
|
||||
timer_t *timer0 = (timer_t *) 0xF0010000;
|
||||
gpio_t *gpio0 = (gpio_t *) 0xF0020000;
|
||||
// uint32_t *sram0 = (uint32_t *) 0x40000000;
|
||||
|
||||
uint32_t msec = 0;
|
||||
|
||||
/***************************************************************************
|
||||
* General utility functions
|
||||
*/
|
||||
void sleep(int msec)
|
||||
{
|
||||
uint32_t tcr;
|
||||
|
||||
// Use timer0.1
|
||||
timer0->compare1 = (FCPU/1000)*msec;
|
||||
timer0->counter1 = 0;
|
||||
timer0->tcr1 = TIMER_EN | TIMER_IRQEN;
|
||||
|
||||
do {
|
||||
//halt();
|
||||
tcr = timer0->tcr1;
|
||||
} while ( ! (tcr & TIMER_TRIG) );
|
||||
}
|
||||
|
||||
void tic_init()
|
||||
{
|
||||
// Setup timer0.0
|
||||
timer0->compare0 = (FCPU/1000);
|
||||
timer0->counter0 = 0;
|
||||
timer0->tcr0 = TIMER_EN | TIMER_AR | TIMER_IRQEN;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* UART Functions
|
||||
*/
|
||||
void uart_init()
|
||||
{
|
||||
//uart0->ier = 0x00; // Interrupt Enable Register
|
||||
//uart0->lcr = 0x03; // Line Control Register: 8N1
|
||||
//uart0->mcr = 0x00; // Modem Control Register
|
||||
|
||||
// Setup Divisor register (Fclk / Baud)
|
||||
//uart0->div = (FCPU/(57600*16));
|
||||
}
|
||||
|
||||
char uart_getchar()
|
||||
{
|
||||
while (! (uart0->ucr & UART_DR)) ;
|
||||
return uart0->rxtx;
|
||||
}
|
||||
|
||||
void uart_putchar(char c)
|
||||
{
|
||||
while (uart0->ucr & UART_BUSY) ;
|
||||
uart0->rxtx = c;
|
||||
}
|
||||
|
||||
void uart_putstr(char *str)
|
||||
{
|
||||
char *c = str;
|
||||
while(*c) {
|
||||
uart_putchar(*c);
|
||||
c++;
|
||||
}
|
||||
}
|
||||
|
1
lm32/logic/sakc/firmware/boot0-serial/soc-hw.d
Normal file
1
lm32/logic/sakc/firmware/boot0-serial/soc-hw.d
Normal file
@ -0,0 +1 @@
|
||||
soc-hw.o: soc-hw.c soc-hw.h
|
108
lm32/logic/sakc/firmware/boot0-serial/soc-hw.h
Normal file
108
lm32/logic/sakc/firmware/boot0-serial/soc-hw.h
Normal file
@ -0,0 +1,108 @@
|
||||
#ifndef SPIKEHW_H
|
||||
#define SPIKEHW_H
|
||||
|
||||
#define PROMSTART 0x00000000
|
||||
#define RAMSTART 0x00000800
|
||||
#define RAMSIZE 0x400
|
||||
#define RAMEND (RAMSTART + RAMSIZE)
|
||||
|
||||
#define RAM_START 0x40000000
|
||||
#define RAM_SIZE 0x04000000
|
||||
|
||||
#define FCPU 50000000
|
||||
|
||||
#define UART_RXBUFSIZE 32
|
||||
|
||||
/****************************************************************************
|
||||
* Types
|
||||
*/
|
||||
typedef unsigned int uint32_t; // 32 Bit
|
||||
typedef signed int int32_t; // 32 Bit
|
||||
|
||||
typedef unsigned char uint8_t; // 8 Bit
|
||||
typedef signed char int8_t; // 8 Bit
|
||||
|
||||
/****************************************************************************
|
||||
* Interrupt handling
|
||||
*/
|
||||
typedef void(*isr_ptr_t)(void);
|
||||
|
||||
void irq_enable();
|
||||
void irq_disable();
|
||||
void irq_set_mask(uint32_t mask);
|
||||
uint32_t irq_get_mak();
|
||||
|
||||
void isr_init();
|
||||
void isr_register(int irq, isr_ptr_t isr);
|
||||
void isr_unregister(int irq);
|
||||
|
||||
/****************************************************************************
|
||||
* General Stuff
|
||||
*/
|
||||
void halt();
|
||||
void jump(uint32_t addr);
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* Timer
|
||||
*/
|
||||
#define TIMER_EN 0x08 // Enable Timer
|
||||
#define TIMER_AR 0x04 // Auto-Reload
|
||||
#define TIMER_IRQEN 0x02 // IRQ Enable
|
||||
#define TIMER_TRIG 0x01 // Triggered (reset when writing to TCR)
|
||||
|
||||
typedef struct {
|
||||
volatile uint32_t tcr0;
|
||||
volatile uint32_t compare0;
|
||||
volatile uint32_t counter0;
|
||||
volatile uint32_t tcr1;
|
||||
volatile uint32_t compare1;
|
||||
volatile uint32_t counter1;
|
||||
} timer_t;
|
||||
|
||||
void msleep(uint32_t msec);
|
||||
void nsleep(uint32_t nsec);
|
||||
|
||||
void tic_init();
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* GPIO0
|
||||
*/
|
||||
typedef struct {
|
||||
volatile uint32_t ctrl;
|
||||
volatile uint32_t dummy1;
|
||||
volatile uint32_t dummy2;
|
||||
volatile uint32_t dummy3;
|
||||
volatile uint32_t in;
|
||||
volatile uint32_t out;
|
||||
volatile uint32_t oe;
|
||||
} gpio_t;
|
||||
|
||||
/***************************************************************************
|
||||
* UART0
|
||||
*/
|
||||
#define UART_DR 0x01 // RX Data Ready
|
||||
#define UART_ERR 0x02 // RX Error
|
||||
#define UART_BUSY 0x10 // TX Busy
|
||||
|
||||
typedef struct {
|
||||
volatile uint32_t ucr;
|
||||
volatile uint32_t rxtx;
|
||||
} uart_t;
|
||||
|
||||
void uart_init();
|
||||
void uart_putchar(char c);
|
||||
void uart_putstr(char *str);
|
||||
char uart_getchar();
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* Pointer to actual components
|
||||
*/
|
||||
extern timer_t *timer0;
|
||||
extern uart_t *uart0;
|
||||
extern gpio_t *gpio0;
|
||||
extern uint32_t *sram0;
|
||||
|
||||
#endif // SPIKEHW_H
|
BIN
lm32/logic/sakc/firmware/boot0-serial/soc-hw.o
Normal file
BIN
lm32/logic/sakc/firmware/boot0-serial/soc-hw.o
Normal file
Binary file not shown.
50
lm32/logic/sakc/firmware/ddr-phaser/Makefile
Normal file
50
lm32/logic/sakc/firmware/ddr-phaser/Makefile
Normal file
@ -0,0 +1,50 @@
|
||||
LM32_CC=lm32-elf-gcc
|
||||
LM32_LD=lm32-elf-ld
|
||||
LM32_OBJCOPY=lm32-elf-objcopy
|
||||
LM32_OBJDUMP=lm32-elf-objdump
|
||||
|
||||
SREC2VRAM ?= ../../tools/srec2vram/srec2vram
|
||||
|
||||
VRAMFILE=image.ram
|
||||
|
||||
CFLAGS=-MMD -O2 -Wall -g -s -fomit-frame-pointer -mbarrel-shift-enabled -mmultiply-enabled -mdivide-enabled -msign-extend-enabled
|
||||
LDFLAGS=-nostdlib -nodefaultlibs -Tlinker.ld
|
||||
SEGMENTS = -j .text -j .rodata -j .data
|
||||
|
||||
all: $(VRAMFILE)
|
||||
|
||||
crt0ram.o: crt0ram.S
|
||||
$(LM32_CC) $(CFLAGS) -c crt0ram.S
|
||||
|
||||
main.o: main.c
|
||||
$(LM32_CC) $(CFLAGS) -c main.c
|
||||
|
||||
spike_hw.o: spike_hw.c
|
||||
$(LM32_CC) $(CFLAGS) -c spike_hw.c
|
||||
|
||||
image: crt0ram.o main.o spike_hw.o
|
||||
$(LM32_LD) $(LDFLAGS) -Map image.map -N -o image crt0ram.o main.o spike_hw.o
|
||||
|
||||
image.lst: image
|
||||
$(LM32_OBJDUMP) -h -S $< > $@
|
||||
|
||||
image.bin: image
|
||||
$(LM32_OBJCOPY) $(SEGMENTS) -O srec image image.bin
|
||||
|
||||
image.srec: image image.lst
|
||||
$(LM32_OBJCOPY) $(SEGMENTS) -O srec image image.srec
|
||||
|
||||
$(VHDLFILE): image.srec
|
||||
$(SREC2VHDL) image.srec > $(VHDLFILE)
|
||||
|
||||
$(VRAMFILE): image.srec
|
||||
$(SREC2VRAM) image.srec 0x00000000 0x1000 > $(VRAMFILE)
|
||||
|
||||
clean:
|
||||
rm -f image image.lst image.bin image.srec image.map *.o *.d
|
||||
|
||||
DEPS := $(wildcard *.d)
|
||||
ifneq ($(DEPS),)
|
||||
include $(DEPS)
|
||||
endif
|
||||
|
166
lm32/logic/sakc/firmware/ddr-phaser/crt0ram.S
Normal file
166
lm32/logic/sakc/firmware/ddr-phaser/crt0ram.S
Normal file
@ -0,0 +1,166 @@
|
||||
/*
|
||||
* LatticeMico32 C startup code.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* Exception handlers - Must be 32 bytes long. */
|
||||
.section .text, "ax", @progbits
|
||||
.global _start
|
||||
.global irq_enable, irq_disable, irq_mask, jump, halt
|
||||
_start:
|
||||
_reset_handler:
|
||||
xor r0, r0, r0
|
||||
wcsr IE, r0
|
||||
mvhi r1, hi(_reset_handler)
|
||||
ori r1, r1, lo(_reset_handler)
|
||||
wcsr EBA, r1
|
||||
calli _crt0
|
||||
nop
|
||||
nop
|
||||
|
||||
_crt0:
|
||||
/* Setup stack and global pointer */
|
||||
mvhi sp, hi(_fstack)
|
||||
ori sp, sp, lo(_fstack)
|
||||
mvhi gp, hi(_gp)
|
||||
ori gp, gp, lo(_gp)
|
||||
|
||||
/* Clear BSS */
|
||||
mvhi r1, hi(_fbss)
|
||||
ori r1, r1, lo(_fbss)
|
||||
mvhi r3, hi(_ebss)
|
||||
ori r3, r3, lo(_ebss)
|
||||
.clearBSS:
|
||||
be r1, r3, .callMain
|
||||
sw (r1+0), r0
|
||||
addi r1, r1, 4
|
||||
bi .clearBSS
|
||||
|
||||
.callMain:
|
||||
mvi r1, 0
|
||||
mvi r2, 0
|
||||
mvi r3, 0
|
||||
calli main
|
||||
|
||||
irq_enable:
|
||||
mvi r1, 1
|
||||
wcsr IE, r1
|
||||
ret
|
||||
|
||||
irq_mask:
|
||||
mvi r1, 0x0000000f
|
||||
wcsr IM, r1
|
||||
ret
|
||||
|
||||
irq_disable:
|
||||
mvi r1, 0
|
||||
wcsr IE, r1
|
||||
ret
|
||||
|
||||
jump:
|
||||
b r1
|
||||
|
||||
halt:
|
||||
bi halt
|
||||
|
||||
/* Save all registers onto the stack */
|
||||
_save_all:
|
||||
addi sp, sp, -128
|
||||
sw (sp+4), r1
|
||||
sw (sp+8), r2
|
||||
sw (sp+12), r3
|
||||
sw (sp+16), r4
|
||||
sw (sp+20), r5
|
||||
sw (sp+24), r6
|
||||
sw (sp+28), r7
|
||||
sw (sp+32), r8
|
||||
sw (sp+36), r9
|
||||
sw (sp+40), r10
|
||||
#ifdef MICO32_FULL_CONTEXT_SAVE_RESTORE
|
||||
sw (sp+44), r11
|
||||
sw (sp+48), r12
|
||||
sw (sp+52), r13
|
||||
sw (sp+56), r14
|
||||
sw (sp+60), r15
|
||||
sw (sp+64), r16
|
||||
sw (sp+68), r17
|
||||
sw (sp+72), r18
|
||||
sw (sp+76), r19
|
||||
sw (sp+80), r20
|
||||
sw (sp+84), r21
|
||||
sw (sp+88), r22
|
||||
sw (sp+92), r23
|
||||
sw (sp+96), r24
|
||||
sw (sp+100), r25
|
||||
sw (sp+104), r26
|
||||
sw (sp+108), r27
|
||||
#endif
|
||||
sw (sp+120), ea
|
||||
sw (sp+124), ba
|
||||
/* ra and sp need special handling, as they have been modified */
|
||||
lw r1, (sp+128)
|
||||
sw (sp+116), r1
|
||||
mv r1, sp
|
||||
addi r1, r1, 128
|
||||
sw (sp+112), r1
|
||||
ret
|
||||
|
||||
/* Restore all registers and return from exception */
|
||||
_restore_all_and_return:
|
||||
lw r1, (sp+4)
|
||||
lw r2, (sp+8)
|
||||
lw r3, (sp+12)
|
||||
lw r4, (sp+16)
|
||||
lw r5, (sp+20)
|
||||
lw r6, (sp+24)
|
||||
lw r7, (sp+28)
|
||||
lw r8, (sp+32)
|
||||
lw r9, (sp+36)
|
||||
lw r10, (sp+40)
|
||||
#ifdef MICO32_FULL_CONTEXT_SAVE_RESTORE
|
||||
lw r11, (sp+44)
|
||||
lw r12, (sp+48)
|
||||
lw r13, (sp+52)
|
||||
lw r14, (sp+56)
|
||||
lw r15, (sp+60)
|
||||
lw r16, (sp+64)
|
||||
lw r17, (sp+68)
|
||||
lw r18, (sp+72)
|
||||
lw r19, (sp+76)
|
||||
lw r20, (sp+80)
|
||||
lw r21, (sp+84)
|
||||
lw r22, (sp+88)
|
||||
lw r23, (sp+92)
|
||||
lw r24, (sp+96)
|
||||
lw r25, (sp+100)
|
||||
lw r26, (sp+104)
|
||||
lw r27, (sp+108)
|
||||
#endif
|
||||
lw ra, (sp+116)
|
||||
lw ea, (sp+120)
|
||||
lw ba, (sp+124)
|
||||
/* Stack pointer must be restored last, in case it has been updated */
|
||||
lw sp, (sp+112)
|
||||
eret
|
||||
|
||||
|
1024
lm32/logic/sakc/firmware/ddr-phaser/image.ram
Normal file
1024
lm32/logic/sakc/firmware/ddr-phaser/image.ram
Normal file
File diff suppressed because it is too large
Load Diff
59
lm32/logic/sakc/firmware/ddr-phaser/linker.ld
Normal file
59
lm32/logic/sakc/firmware/ddr-phaser/linker.ld
Normal file
@ -0,0 +1,59 @@
|
||||
OUTPUT_FORMAT("elf32-lm32")
|
||||
ENTRY(_start)
|
||||
|
||||
__DYNAMIC = 0;
|
||||
|
||||
|
||||
_BRAM_START = 0x00000000;
|
||||
_BRAM_SIZE = 0x1000;
|
||||
_BRAM_END = _BRAM_START + _BRAM_SIZE;
|
||||
|
||||
MEMORY {
|
||||
bram : ORIGIN = 0x00000000, LENGTH = 0x1000 /* 4k */
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text :
|
||||
{
|
||||
_ftext = .;
|
||||
*(.text .stub .text.* .gnu.linkonce.t.*)
|
||||
_etext = .;
|
||||
} > bram
|
||||
|
||||
.rodata :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_frodata = .;
|
||||
*(.rodata .rodata.* .gnu.linkonce.r.*)
|
||||
*(.rodata1)
|
||||
_erodata = .;
|
||||
} > bram
|
||||
|
||||
.data :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_fdata = .;
|
||||
*(.data .data.* .gnu.linkonce.d.*)
|
||||
*(.data1)
|
||||
_gp = ALIGN(16);
|
||||
*(.sdata .sdata.* .gnu.linkonce.s.*)
|
||||
_edata = .;
|
||||
} > bram
|
||||
|
||||
.bss :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_fbss = .;
|
||||
*(.dynsbss)
|
||||
*(.sbss .sbss.* .gnu.linkonce.sb.*)
|
||||
*(.scommon)
|
||||
*(.dynbss)
|
||||
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
_ebss = .;
|
||||
_end = .;
|
||||
} > bram
|
||||
}
|
||||
|
||||
PROVIDE(_fstack = ORIGIN(bram) + LENGTH(bram) - 4);
|
105
lm32/logic/sakc/firmware/ddr-phaser/main.c
Normal file
105
lm32/logic/sakc/firmware/ddr-phaser/main.c
Normal file
@ -0,0 +1,105 @@
|
||||
/**
|
||||
* DDR Phase Shifter
|
||||
*/
|
||||
|
||||
#include "spike_hw.h"
|
||||
|
||||
/******************************************************************************
|
||||
* Control DDR phase shift
|
||||
*/
|
||||
inline int ps_ready()
|
||||
{
|
||||
return (gpio0->in & (1 << 16)); // return 1 when ready, 0 otherwise
|
||||
}
|
||||
|
||||
inline void ps_inc()
|
||||
{
|
||||
uint32_t tmp;
|
||||
|
||||
while ( ! ps_ready() );
|
||||
|
||||
tmp = gpio0->out;
|
||||
gpio0->out = tmp | (1 << 16);
|
||||
gpio0->out = tmp;
|
||||
|
||||
while ( ! ps_ready() );
|
||||
}
|
||||
|
||||
inline void ps_dec()
|
||||
{
|
||||
uint32_t tmp;
|
||||
|
||||
while ( ! ps_ready() );
|
||||
|
||||
tmp = gpio0->out;
|
||||
gpio0->out = tmp | (1 << 17);
|
||||
gpio0->out = tmp;
|
||||
|
||||
while ( ! ps_ready() );
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Simple memory tester
|
||||
*
|
||||
* Returns -1 on error, 0 when OK.
|
||||
*/
|
||||
inline int memtest(uint32_t size)
|
||||
{
|
||||
volatile uint32_t *p;
|
||||
int res = 0;
|
||||
|
||||
for (p=(uint32_t *)RAM_START; p<(uint32_t *)(RAM_START+size); p++) {
|
||||
*p = (uint32_t) p;
|
||||
}
|
||||
|
||||
for (p=(uint32_t *)RAM_START; p<(uint32_t *)(RAM_START+size); p++) {
|
||||
if (*p != (uint32_t)p) {
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
void scan_phase(int dir, uint32_t size)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<=255; i++) {
|
||||
if (memtest(size) == 0)
|
||||
uart_putchar('O');
|
||||
else
|
||||
uart_putchar('-');
|
||||
|
||||
if (dir == 1) ps_inc(); else ps_dec();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
uint32_t scan_size = 16*1024; // scan 16 kByte
|
||||
|
||||
// Initialize stuff
|
||||
uart_init();
|
||||
|
||||
uart_putstr("\r\n\r\n** SOC-LM32 DDR PAHSER **\n\n");
|
||||
uart_putstr("'O' => Memtest OK ; '-' => Memtest failed\n\n");
|
||||
uart_putstr("Press [u] for upward scan, [d] for downward\n");
|
||||
|
||||
for(;;) {
|
||||
uint8_t c = uart_getchar();
|
||||
|
||||
switch (c) {
|
||||
case 'u': // scan upward
|
||||
scan_phase(1, scan_size);
|
||||
break;
|
||||
case 'd': // scan downward
|
||||
scan_phase(-1, scan_size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
68
lm32/logic/sakc/firmware/ddr-phaser/spike_hw.c
Normal file
68
lm32/logic/sakc/firmware/ddr-phaser/spike_hw.c
Normal file
@ -0,0 +1,68 @@
|
||||
#include "spike_hw.h"
|
||||
|
||||
uart_t *uart0 = (uart_t *) 0xF0000000;
|
||||
timer_t *timer0 = (timer_t *) 0xF0010000;
|
||||
gpio_t *gpio0 = (gpio_t *) 0xF0020000;
|
||||
|
||||
uint32_t msec = 0;
|
||||
|
||||
/***************************************************************************
|
||||
* General utility functions
|
||||
*/
|
||||
void sleep(int msec)
|
||||
{
|
||||
uint32_t tcr;
|
||||
|
||||
// Use timer0.1
|
||||
timer0->compare1 = (FCPU/1000)*msec;
|
||||
timer0->counter1 = 0;
|
||||
timer0->tcr1 = TIMER_EN | TIMER_IRQEN;
|
||||
|
||||
do {
|
||||
//halt();
|
||||
tcr = timer0->tcr1;
|
||||
} while ( ! (tcr & TIMER_TRIG) );
|
||||
}
|
||||
|
||||
void tic_init()
|
||||
{
|
||||
// Setup timer0.0
|
||||
timer0->compare0 = (FCPU/1000);
|
||||
timer0->counter0 = 0;
|
||||
timer0->tcr0 = TIMER_EN | TIMER_AR | TIMER_IRQEN;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* UART Functions
|
||||
*/
|
||||
void uart_init()
|
||||
{
|
||||
//uart0->ier = 0x00; // Interrupt Enable Register
|
||||
//uart0->lcr = 0x03; // Line Control Register: 8N1
|
||||
//uart0->mcr = 0x00; // Modem Control Register
|
||||
|
||||
// Setup Divisor register (Fclk / Baud)
|
||||
//uart0->div = (FCPU/(57600*16));
|
||||
}
|
||||
|
||||
char uart_getchar()
|
||||
{
|
||||
while (! (uart0->ucr & UART_DR)) ;
|
||||
return uart0->rxtx;
|
||||
}
|
||||
|
||||
void uart_putchar(char c)
|
||||
{
|
||||
while (uart0->ucr & UART_BUSY) ;
|
||||
uart0->rxtx = c;
|
||||
}
|
||||
|
||||
void uart_putstr(char *str)
|
||||
{
|
||||
char *c = str;
|
||||
while(*c) {
|
||||
uart_putchar(*c);
|
||||
c++;
|
||||
}
|
||||
}
|
||||
|
108
lm32/logic/sakc/firmware/ddr-phaser/spike_hw.h
Normal file
108
lm32/logic/sakc/firmware/ddr-phaser/spike_hw.h
Normal file
@ -0,0 +1,108 @@
|
||||
#ifndef SPIKEHW_H
|
||||
#define SPIKEHW_H
|
||||
|
||||
#define PROMSTART 0x00000000
|
||||
#define RAMSTART 0x00000800
|
||||
#define RAMSIZE 0x400
|
||||
#define RAMEND (RAMSTART + RAMSIZE)
|
||||
|
||||
#define RAM_START 0x40000000
|
||||
#define RAM_SIZE 0x04000000
|
||||
|
||||
#define FCPU 50000000
|
||||
|
||||
#define UART_RXBUFSIZE 32
|
||||
|
||||
/****************************************************************************
|
||||
* Types
|
||||
*/
|
||||
typedef unsigned int uint32_t; // 32 Bit
|
||||
typedef signed int int32_t; // 32 Bit
|
||||
|
||||
typedef unsigned char uint8_t; // 8 Bit
|
||||
typedef signed char int8_t; // 8 Bit
|
||||
|
||||
/****************************************************************************
|
||||
* Interrupt handling
|
||||
*/
|
||||
typedef void(*isr_ptr_t)(void);
|
||||
|
||||
void irq_enable();
|
||||
void irq_disable();
|
||||
void irq_set_mask(uint32_t mask);
|
||||
uint32_t irq_get_mak();
|
||||
|
||||
void isr_init();
|
||||
void isr_register(int irq, isr_ptr_t isr);
|
||||
void isr_unregister(int irq);
|
||||
|
||||
/****************************************************************************
|
||||
* General Stuff
|
||||
*/
|
||||
void halt();
|
||||
void jump(uint32_t addr);
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* Timer
|
||||
*/
|
||||
#define TIMER_EN 0x08 // Enable Timer
|
||||
#define TIMER_AR 0x04 // Auto-Reload
|
||||
#define TIMER_IRQEN 0x02 // IRQ Enable
|
||||
#define TIMER_TRIG 0x01 // Triggered (reset when writing to TCR)
|
||||
|
||||
typedef struct {
|
||||
volatile uint32_t tcr0;
|
||||
volatile uint32_t compare0;
|
||||
volatile uint32_t counter0;
|
||||
volatile uint32_t tcr1;
|
||||
volatile uint32_t compare1;
|
||||
volatile uint32_t counter1;
|
||||
} timer_t;
|
||||
|
||||
void msleep(uint32_t msec);
|
||||
void nsleep(uint32_t nsec);
|
||||
|
||||
void tic_init();
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* GPIO0
|
||||
*/
|
||||
typedef struct {
|
||||
volatile uint32_t ctrl;
|
||||
volatile uint32_t dummy1;
|
||||
volatile uint32_t dummy2;
|
||||
volatile uint32_t dummy3;
|
||||
volatile uint32_t in;
|
||||
volatile uint32_t out;
|
||||
volatile uint32_t oe;
|
||||
} gpio_t;
|
||||
|
||||
/***************************************************************************
|
||||
* UART0
|
||||
*/
|
||||
#define UART_DR 0x01 // RX Data Ready
|
||||
#define UART_ERR 0x02 // RX Error
|
||||
#define UART_BUSY 0x10 // TX Busy
|
||||
|
||||
typedef struct {
|
||||
volatile uint32_t ucr;
|
||||
volatile uint32_t rxtx;
|
||||
} uart_t;
|
||||
|
||||
void uart_init();
|
||||
void uart_putchar(char c);
|
||||
void uart_putstr(char *str);
|
||||
char uart_getchar();
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* Pointer to actual components
|
||||
*/
|
||||
extern timer_t *timer0;
|
||||
extern uart_t *uart0;
|
||||
extern gpio_t *gpio0;
|
||||
extern uint32_t *sram0;
|
||||
|
||||
#endif // SPIKEHW_H
|
43
lm32/logic/sakc/firmware/gdb-test/Makefile
Normal file
43
lm32/logic/sakc/firmware/gdb-test/Makefile
Normal file
@ -0,0 +1,43 @@
|
||||
LM32_CC=lm32-elf-gcc
|
||||
LM32_LD=lm32-elf-ld
|
||||
LM32_OBJCOPY=lm32-elf-objcopy
|
||||
LM32_OBJDUMP=lm32-elf-objdump
|
||||
|
||||
SREC2VRAM ?= ../../tools/srec2vram/srec2vram
|
||||
VRAMFILE=image.ram
|
||||
|
||||
CFLAGS=-MMD -O2 -Wall -g -s -fomit-frame-pointer -mbarrel-shift-enabled -mmultiply-enabled -mdivide-enabled -msign-extend-enabled
|
||||
LDFLAGS=-nostdlib -nodefaultlibs -Tlinker.ld
|
||||
SEGMENTS = -j .boot -j .text -j .rodata -j .data
|
||||
|
||||
all: image.srec $(VRAMFILE)
|
||||
|
||||
%.o: %.S
|
||||
$(LM32_CC) $(CFLAGS) -c $<
|
||||
|
||||
%.o: %.c
|
||||
$(LM32_CC) $(CFLAGS) -c $<
|
||||
|
||||
image: crt0gdb.o main.o soc-hw.o gdb.o gdb_uart.o
|
||||
$(LM32_LD) $(LDFLAGS) -Map image.map -N -o image $^
|
||||
|
||||
image.lst: image
|
||||
$(LM32_OBJDUMP) -h -S $< > $@
|
||||
|
||||
image.bin: image
|
||||
$(LM32_OBJCOPY) $(SEGMENTS) -O binary image image.bin
|
||||
|
||||
image.srec: image image.lst
|
||||
$(LM32_OBJCOPY) $(SEGMENTS) -O srec image image.srec
|
||||
|
||||
$(VRAMFILE): image.srec
|
||||
$(SREC2VRAM) image.srec 0x40000000 0x100000 > $(VRAMFILE)
|
||||
|
||||
clean:
|
||||
rm -f image image.lst image.bin image.srec image.map *.o *.d
|
||||
|
||||
DEPS := $(wildcard *.d)
|
||||
ifneq ($(DEPS),)
|
||||
include $(DEPS)
|
||||
endif
|
||||
|
290
lm32/logic/sakc/firmware/gdb-test/crt0gdb.S
Normal file
290
lm32/logic/sakc/firmware/gdb-test/crt0gdb.S
Normal file
@ -0,0 +1,290 @@
|
||||
/*
|
||||
* LatticeMico32 GDB C startup code.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* Exception handlers - Must be 32 bytes long. */
|
||||
|
||||
.section .boot, "ax", @progbits
|
||||
|
||||
.global _start
|
||||
_start:
|
||||
_reset_handler:
|
||||
bi _crt0
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
_breakpoint_handler:
|
||||
sw (sp+0), ra
|
||||
calli _save_all
|
||||
sw (sp+128), ba
|
||||
mvi r1, 1
|
||||
sw (sp+132), r1
|
||||
mv r1, sp
|
||||
calli _handle_exception
|
||||
bi _b_restore_all_and_return
|
||||
|
||||
_instruction_bus_error_handler:
|
||||
sw (sp+0), ra
|
||||
calli _save_all
|
||||
sw (sp+128), ea
|
||||
mvi r1, 2
|
||||
sw (sp+132), r1
|
||||
mv r1, sp
|
||||
calli _handle_exception
|
||||
bi _e_restore_all_and_return
|
||||
|
||||
_watchpoint_handler:
|
||||
sw (sp+0), ra
|
||||
calli _save_all
|
||||
sw (sp+128), ba
|
||||
mvi r1, 3
|
||||
sw (sp+132), r1
|
||||
mv r1, sp
|
||||
calli _handle_exception
|
||||
bi _b_restore_all_and_return
|
||||
|
||||
_data_bus_error_handler:
|
||||
sw (sp+0), ra
|
||||
calli _save_all
|
||||
sw (sp+128), ea
|
||||
mvi r1, 4
|
||||
sw (sp+132), r1
|
||||
mv r1, sp
|
||||
calli _handle_exception
|
||||
bi _e_restore_all_and_return
|
||||
|
||||
_divide_by_zero_handler:
|
||||
sw (sp+0), ra
|
||||
calli _save_all
|
||||
sw (sp+128), ea
|
||||
mvi r1, 5
|
||||
sw (sp+132), r1
|
||||
mv r1, sp
|
||||
calli _handle_exception
|
||||
bi _e_restore_all_and_return
|
||||
|
||||
_interrupt_handler:
|
||||
sw (sp+0), ra
|
||||
calli _save_all
|
||||
sw (sp+128), ea
|
||||
mvi r1, 6
|
||||
sw (sp+132), r1
|
||||
mv r1, sp
|
||||
calli _handle_exception
|
||||
bi _e_restore_all_and_return
|
||||
|
||||
_system_call_handler:
|
||||
sw (sp+0), ra
|
||||
calli _save_all
|
||||
sw (sp+128), ea
|
||||
mvi r1, 7
|
||||
sw (sp+132), r1
|
||||
mv r1, sp
|
||||
calli _handle_exception
|
||||
bi _e_restore_all_and_return
|
||||
|
||||
/* Program starts here */
|
||||
|
||||
_crt0:
|
||||
/* Clear r0 */
|
||||
xor r0, r0, r0
|
||||
|
||||
/* Clear all other regs (needed so that simulations match) */
|
||||
mvi r1, 0
|
||||
mvi r2, 0
|
||||
mvi r3, 0
|
||||
mvi r4, 0
|
||||
mvi r5, 0
|
||||
mvi r6, 0
|
||||
mvi r7, 0
|
||||
mvi r8, 0
|
||||
mvi r9, 0
|
||||
mvi r10, 0
|
||||
mvi r11, 0
|
||||
mvi r12, 0
|
||||
mvi r13, 0
|
||||
mvi r14, 0
|
||||
mvi r15, 0
|
||||
mvi r16, 0
|
||||
mvi r17, 0
|
||||
mvi r18, 0
|
||||
mvi r19, 0
|
||||
mvi r20, 0
|
||||
mvi r21, 0
|
||||
mvi r22, 0
|
||||
mvi r23, 0
|
||||
mvi r24, 0
|
||||
mvi r25, 0
|
||||
mvi r26, 0
|
||||
mvi r27, 0
|
||||
mvi r28, 0
|
||||
mvi r29, 0
|
||||
mvi r30, 0
|
||||
mvi r31, 0
|
||||
|
||||
/* Setup stack and global pointer */
|
||||
mvhi sp, hi(_fstack)
|
||||
ori sp, sp, lo(_fstack)
|
||||
mvhi gp, hi(_gp)
|
||||
ori gp, gp, lo(_gp)
|
||||
|
||||
/* Clear BSS */
|
||||
mvhi r1, hi(_fbss)
|
||||
ori r1, r1, lo(_fbss)
|
||||
mvhi r3, hi(_ebss)
|
||||
ori r3, r3, lo(_ebss)
|
||||
.clearBSS:
|
||||
be r1, r3, .callMain
|
||||
sw (r1+0), r0
|
||||
addi r1, r1, 4
|
||||
bi .clearBSS
|
||||
|
||||
.callMain:
|
||||
mvi r1, 0
|
||||
mvi r2, 0
|
||||
mvi r3, 0
|
||||
/* Enter debug exception handler */
|
||||
mvhi ba, hi(main)
|
||||
ori ba, ba, lo(main)
|
||||
bi _breakpoint_handler
|
||||
|
||||
/* Save all registers onto the stack */
|
||||
_save_all:
|
||||
addi sp, sp, -136
|
||||
sw (sp+0), r0
|
||||
sw (sp+4), r1
|
||||
sw (sp+8), r2
|
||||
sw (sp+12), r3
|
||||
sw (sp+16), r4
|
||||
sw (sp+20), r5
|
||||
sw (sp+24), r6
|
||||
sw (sp+28), r7
|
||||
sw (sp+32), r8
|
||||
sw (sp+36), r9
|
||||
sw (sp+40), r10
|
||||
sw (sp+44), r11
|
||||
sw (sp+48), r12
|
||||
sw (sp+52), r13
|
||||
sw (sp+56), r14
|
||||
sw (sp+60), r15
|
||||
sw (sp+64), r16
|
||||
sw (sp+68), r17
|
||||
sw (sp+72), r18
|
||||
sw (sp+76), r19
|
||||
sw (sp+80), r20
|
||||
sw (sp+84), r21
|
||||
sw (sp+88), r22
|
||||
sw (sp+92), r23
|
||||
sw (sp+96), r24
|
||||
sw (sp+100), r25
|
||||
sw (sp+104), r26
|
||||
sw (sp+108), r27
|
||||
sw (sp+120), ea
|
||||
sw (sp+124), ba
|
||||
/* ra and sp need special handling, as they have been modified */
|
||||
lw r1, (sp+136)
|
||||
sw (sp+116), r1
|
||||
mv r1, sp
|
||||
addi r1, r1, 136
|
||||
sw (sp+112), r1
|
||||
ret
|
||||
|
||||
/* Restore all registers and return from exception */
|
||||
_e_restore_all_and_return:
|
||||
lw r1, (sp+4)
|
||||
lw r2, (sp+8)
|
||||
lw r3, (sp+12)
|
||||
lw r4, (sp+16)
|
||||
lw r5, (sp+20)
|
||||
lw r6, (sp+24)
|
||||
lw r7, (sp+28)
|
||||
lw r8, (sp+32)
|
||||
lw r9, (sp+36)
|
||||
lw r10, (sp+40)
|
||||
lw r11, (sp+44)
|
||||
lw r12, (sp+48)
|
||||
lw r13, (sp+52)
|
||||
lw r14, (sp+56)
|
||||
lw r15, (sp+60)
|
||||
lw r16, (sp+64)
|
||||
lw r17, (sp+68)
|
||||
lw r18, (sp+72)
|
||||
lw r19, (sp+76)
|
||||
lw r20, (sp+80)
|
||||
lw r21, (sp+84)
|
||||
lw r22, (sp+88)
|
||||
lw r23, (sp+92)
|
||||
lw r24, (sp+96)
|
||||
lw r25, (sp+100)
|
||||
lw r26, (sp+104)
|
||||
lw r27, (sp+108)
|
||||
lw ra, (sp+116)
|
||||
lw ba, (sp+124)
|
||||
/* Restore EA from PC */
|
||||
lw ea, (sp+128)
|
||||
/* Stack pointer must be restored last, in case it has been updated */
|
||||
lw sp, (sp+112)
|
||||
eret
|
||||
|
||||
/* Restore all registers and return from breakpoint */
|
||||
_b_restore_all_and_return:
|
||||
lw r1, (sp+4)
|
||||
lw r2, (sp+8)
|
||||
lw r3, (sp+12)
|
||||
lw r4, (sp+16)
|
||||
lw r5, (sp+20)
|
||||
lw r6, (sp+24)
|
||||
lw r7, (sp+28)
|
||||
lw r8, (sp+32)
|
||||
lw r9, (sp+36)
|
||||
lw r10, (sp+40)
|
||||
lw r11, (sp+44)
|
||||
lw r12, (sp+48)
|
||||
lw r13, (sp+52)
|
||||
lw r14, (sp+56)
|
||||
lw r15, (sp+60)
|
||||
lw r16, (sp+64)
|
||||
lw r17, (sp+68)
|
||||
lw r18, (sp+72)
|
||||
lw r19, (sp+76)
|
||||
lw r20, (sp+80)
|
||||
lw r21, (sp+84)
|
||||
lw r22, (sp+88)
|
||||
lw r23, (sp+92)
|
||||
lw r24, (sp+96)
|
||||
lw r25, (sp+100)
|
||||
lw r26, (sp+104)
|
||||
lw r27, (sp+108)
|
||||
lw ra, (sp+116)
|
||||
lw ea, (sp+120)
|
||||
/* Restore BA from PC */
|
||||
lw ba, (sp+128)
|
||||
/* Stack pointer must be restored last, in case it has been updated */
|
||||
lw sp, (sp+112)
|
||||
bret
|
1214
lm32/logic/sakc/firmware/gdb-test/gdb.c
Normal file
1214
lm32/logic/sakc/firmware/gdb-test/gdb.c
Normal file
File diff suppressed because it is too large
Load Diff
37
lm32/logic/sakc/firmware/gdb-test/gdb.h
Normal file
37
lm32/logic/sakc/firmware/gdb-test/gdb.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* LatticeMico32 GDB I/O.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _LM32_GDB_H
|
||||
#define _LM32_GDB_H
|
||||
|
||||
/* Write a single character to debug host */
|
||||
void _gdb_write_char (char);
|
||||
/* Read and return a single character from debug host */
|
||||
char _gdb_read_char (void);
|
||||
/* Acknowledge interrupt that caused CPU to enter debug mode */
|
||||
void _gdb_ack_interrupt (void);
|
||||
|
||||
#endif /* _LM32_GDB_H */
|
||||
|
23
lm32/logic/sakc/firmware/gdb-test/gdb_uart.c
Normal file
23
lm32/logic/sakc/firmware/gdb-test/gdb_uart.c
Normal file
@ -0,0 +1,23 @@
|
||||
#include "soc-hw.h"
|
||||
|
||||
/* Write a single character to debug host */
|
||||
void
|
||||
_gdb_write_char (char c)
|
||||
{
|
||||
uart_putchar(c);
|
||||
}
|
||||
|
||||
/* Read and return a single character from debug host */
|
||||
char
|
||||
_gdb_read_char (void)
|
||||
{
|
||||
return uart_getchar();
|
||||
}
|
||||
|
||||
/* Acknowledge specified interrupt that caused CPU to enter debug mode */
|
||||
void
|
||||
_gdb_ack_interrupt (void)
|
||||
{
|
||||
/* ACK interrupt */
|
||||
/*__asm__ ("wcsr\tIA, %0" : : "d" (1 << interrupt));*/
|
||||
}
|
5
lm32/logic/sakc/firmware/gdb-test/gdb_uart.h
Normal file
5
lm32/logic/sakc/firmware/gdb-test/gdb_uart.h
Normal file
@ -0,0 +1,5 @@
|
||||
|
||||
void _gdb_write_char (char c);
|
||||
char _gdb_read_char (void);
|
||||
void _gdb_ack_interrupt (void) ;
|
||||
|
67
lm32/logic/sakc/firmware/gdb-test/linker.ld
Normal file
67
lm32/logic/sakc/firmware/gdb-test/linker.ld
Normal file
@ -0,0 +1,67 @@
|
||||
OUTPUT_FORMAT("elf32-lm32")
|
||||
ENTRY(_start)
|
||||
|
||||
__DYNAMIC = 0;
|
||||
|
||||
|
||||
_RAM_START = 0x40000000;
|
||||
_RAM_SIZE = 0x100000;
|
||||
_RAM_END = _RAM_START + _RAM_SIZE;
|
||||
|
||||
MEMORY {
|
||||
ram : ORIGIN = 0x40000000, LENGTH = 0x100000 /* 1M */
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.boot :
|
||||
{
|
||||
_fboot = .;
|
||||
*(.boot)
|
||||
_eboot = .;
|
||||
} > ram
|
||||
|
||||
.text :
|
||||
{
|
||||
_ftext = .;
|
||||
*(.text .stub .text.* .gnu.linkonce.t.*)
|
||||
_etext = .;
|
||||
} > ram
|
||||
|
||||
.rodata :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_frodata = .;
|
||||
*(.rodata .rodata.* .gnu.linkonce.r.*)
|
||||
*(.rodata1)
|
||||
_erodata = .;
|
||||
} > ram
|
||||
|
||||
.data :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_fdata = .;
|
||||
*(.data .data.* .gnu.linkonce.d.*)
|
||||
*(.data1)
|
||||
_gp = ALIGN(16);
|
||||
*(.sdata .sdata.* .gnu.linkonce.s.*)
|
||||
_edata = .;
|
||||
} > ram
|
||||
|
||||
.bss :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_fbss = .;
|
||||
*(.dynsbss)
|
||||
*(.sbss .sbss.* .gnu.linkonce.sb.*)
|
||||
*(.scommon)
|
||||
*(.dynbss)
|
||||
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
_ebss = .;
|
||||
_end = .;
|
||||
} > ram
|
||||
}
|
||||
|
||||
PROVIDE(_fstack = ORIGIN(ram) + LENGTH(ram) - 4);
|
||||
|
20
lm32/logic/sakc/firmware/gdb-test/main.c
Normal file
20
lm32/logic/sakc/firmware/gdb-test/main.c
Normal file
@ -0,0 +1,20 @@
|
||||
#include "soc-hw.h"
|
||||
|
||||
void main()
|
||||
{
|
||||
gpio0->oe = 0x000000ff;
|
||||
for(;;) {
|
||||
int i;
|
||||
|
||||
for(i=0; i<8; i++) {
|
||||
uint32_t out1, out2;
|
||||
|
||||
out1 = 0x01 << i;
|
||||
out2 = 0x80 >> i;
|
||||
gpio0->out = out1 | out2;
|
||||
|
||||
msleep(100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
133
lm32/logic/sakc/firmware/gdb-test/soc-hw.c
Normal file
133
lm32/logic/sakc/firmware/gdb-test/soc-hw.c
Normal file
@ -0,0 +1,133 @@
|
||||
#include "soc-hw.h"
|
||||
|
||||
uart_t *uart0 = (uart_t *) 0xf0000000;
|
||||
timer_t *timer0 = (timer_t *) 0xf0010000;
|
||||
gpio_t *gpio0 = (gpio_t *) 0xF0020000;
|
||||
|
||||
isr_ptr_t isr_table[32];
|
||||
|
||||
|
||||
void tic_isr();
|
||||
/***************************************************************************
|
||||
* IRQ handling
|
||||
*/
|
||||
void isr_null()
|
||||
{
|
||||
}
|
||||
|
||||
void irq_handler(uint32_t pending)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<32; i++) {
|
||||
if (pending & 0x01) (*isr_table[i])();
|
||||
pending >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
void isr_init()
|
||||
{
|
||||
int i;
|
||||
for(i=0; i<32; i++)
|
||||
isr_table[i] = &isr_null;
|
||||
}
|
||||
|
||||
void isr_register(int irq, isr_ptr_t isr)
|
||||
{
|
||||
isr_table[irq] = isr;
|
||||
}
|
||||
|
||||
void isr_unregister(int irq)
|
||||
{
|
||||
isr_table[irq] = &isr_null;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* TIMER Functions
|
||||
*/
|
||||
void msleep(uint32_t msec)
|
||||
{
|
||||
uint32_t tcr;
|
||||
|
||||
// Use timer0.1
|
||||
timer0->compare1 = (FCPU/1000)*msec;
|
||||
timer0->counter1 = 0;
|
||||
timer0->tcr1 = TIMER_EN;
|
||||
|
||||
do {
|
||||
//halt();
|
||||
tcr = timer0->tcr1;
|
||||
} while ( ! (tcr & TIMER_TRIG) );
|
||||
}
|
||||
|
||||
void nsleep(uint32_t nsec)
|
||||
{
|
||||
uint32_t tcr;
|
||||
|
||||
// Use timer0.1
|
||||
timer0->compare1 = (FCPU/1000000)*nsec;
|
||||
timer0->counter1 = 0;
|
||||
timer0->tcr1 = TIMER_EN;
|
||||
|
||||
do {
|
||||
//halt();
|
||||
tcr = timer0->tcr1;
|
||||
} while ( ! (tcr & TIMER_TRIG) );
|
||||
}
|
||||
|
||||
|
||||
uint32_t tic_msec;
|
||||
|
||||
void tic_isr()
|
||||
{
|
||||
tic_msec++;
|
||||
timer0->tcr0 = TIMER_EN | TIMER_AR | TIMER_IRQEN;
|
||||
}
|
||||
|
||||
void tic_init()
|
||||
{
|
||||
tic_msec = 0;
|
||||
|
||||
// Setup timer0.0
|
||||
timer0->compare0 = (FCPU/10000);
|
||||
timer0->counter0 = 0;
|
||||
timer0->tcr0 = TIMER_EN | TIMER_AR | TIMER_IRQEN;
|
||||
|
||||
isr_register(1, &tic_isr);
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* UART Functions
|
||||
*/
|
||||
void uart_init()
|
||||
{
|
||||
//uart0->ier = 0x00; // Interrupt Enable Register
|
||||
//uart0->lcr = 0x03; // Line Control Register: 8N1
|
||||
//uart0->mcr = 0x00; // Modem Control Register
|
||||
|
||||
// Setup Divisor register (Fclk / Baud)
|
||||
//uart0->div = (FCPU/(57600*16));
|
||||
}
|
||||
|
||||
char uart_getchar()
|
||||
{
|
||||
while (! (uart0->ucr & UART_DR)) ;
|
||||
return uart0->rxtx;
|
||||
}
|
||||
|
||||
void uart_putchar(char c)
|
||||
{
|
||||
while (uart0->ucr & UART_BUSY) ;
|
||||
uart0->rxtx = c;
|
||||
}
|
||||
|
||||
void uart_putstr(char *str)
|
||||
{
|
||||
char *c = str;
|
||||
while(*c) {
|
||||
uart_putchar(*c);
|
||||
c++;
|
||||
}
|
||||
}
|
||||
|
108
lm32/logic/sakc/firmware/gdb-test/soc-hw.h
Normal file
108
lm32/logic/sakc/firmware/gdb-test/soc-hw.h
Normal file
@ -0,0 +1,108 @@
|
||||
#ifndef SPIKEHW_H
|
||||
#define SPIKEHW_H
|
||||
|
||||
#define PROMSTART 0x00000000
|
||||
#define RAMSTART 0x00000800
|
||||
#define RAMSIZE 0x400
|
||||
#define RAMEND (RAMSTART + RAMSIZE)
|
||||
|
||||
#define RAM_START 0x40000000
|
||||
#define RAM_SIZE 0x04000000
|
||||
|
||||
#define FCPU 50000000
|
||||
|
||||
#define UART_RXBUFSIZE 32
|
||||
|
||||
/****************************************************************************
|
||||
* Types
|
||||
*/
|
||||
typedef unsigned int uint32_t; // 32 Bit
|
||||
typedef signed int int32_t; // 32 Bit
|
||||
|
||||
typedef unsigned char uint8_t; // 8 Bit
|
||||
typedef signed char int8_t; // 8 Bit
|
||||
|
||||
/****************************************************************************
|
||||
* Interrupt handling
|
||||
*/
|
||||
typedef void(*isr_ptr_t)(void);
|
||||
|
||||
void irq_enable();
|
||||
void irq_disable();
|
||||
void irq_set_mask(uint32_t mask);
|
||||
uint32_t irq_get_mak();
|
||||
|
||||
void isr_init();
|
||||
void isr_register(int irq, isr_ptr_t isr);
|
||||
void isr_unregister(int irq);
|
||||
|
||||
/****************************************************************************
|
||||
* General Stuff
|
||||
*/
|
||||
void halt();
|
||||
void jump(uint32_t addr);
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* Timer
|
||||
*/
|
||||
#define TIMER_EN 0x08 // Enable Timer
|
||||
#define TIMER_AR 0x04 // Auto-Reload
|
||||
#define TIMER_IRQEN 0x02 // IRQ Enable
|
||||
#define TIMER_TRIG 0x01 // Triggered (reset when writing to TCR)
|
||||
|
||||
typedef struct {
|
||||
volatile uint32_t tcr0;
|
||||
volatile uint32_t compare0;
|
||||
volatile uint32_t counter0;
|
||||
volatile uint32_t tcr1;
|
||||
volatile uint32_t compare1;
|
||||
volatile uint32_t counter1;
|
||||
} timer_t;
|
||||
|
||||
void msleep(uint32_t msec);
|
||||
void nsleep(uint32_t nsec);
|
||||
|
||||
void tic_init();
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* GPIO0
|
||||
*/
|
||||
typedef struct {
|
||||
volatile uint32_t ctrl;
|
||||
volatile uint32_t dummy1;
|
||||
volatile uint32_t dummy2;
|
||||
volatile uint32_t dummy3;
|
||||
volatile uint32_t in;
|
||||
volatile uint32_t out;
|
||||
volatile uint32_t oe;
|
||||
} gpio_t;
|
||||
|
||||
/***************************************************************************
|
||||
* UART0
|
||||
*/
|
||||
#define UART_DR 0x01 // RX Data Ready
|
||||
#define UART_ERR 0x02 // RX Error
|
||||
#define UART_BUSY 0x10 // TX Busy
|
||||
|
||||
typedef struct {
|
||||
volatile uint32_t ucr;
|
||||
volatile uint32_t rxtx;
|
||||
} uart_t;
|
||||
|
||||
void uart_init();
|
||||
void uart_putchar(char c);
|
||||
void uart_putstr(char *str);
|
||||
char uart_getchar();
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* Pointer to actual components
|
||||
*/
|
||||
extern timer_t *timer0;
|
||||
extern uart_t *uart0;
|
||||
extern gpio_t *gpio0;
|
||||
extern uint32_t *sram0;
|
||||
|
||||
#endif // SPIKEHW_H
|
6
lm32/logic/sakc/firmware/gdb-test/start-gdb
Normal file
6
lm32/logic/sakc/firmware/gdb-test/start-gdb
Normal file
@ -0,0 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
lm32-elf-gdb image << ENDL
|
||||
target remote /dev/ttyUSB0
|
||||
ENDL
|
||||
|
46
lm32/logic/sakc/firmware/hw-test/Makefile
Normal file
46
lm32/logic/sakc/firmware/hw-test/Makefile
Normal file
@ -0,0 +1,46 @@
|
||||
LM32_CC=lm32-elf-gcc
|
||||
LM32_LD=lm32-elf-ld
|
||||
LM32_OBJCOPY=lm32-elf-objcopy
|
||||
LM32_OBJDUMP=lm32-elf-objdump
|
||||
|
||||
SREC2VRAM ?= ../../tools/srec2vram/srec2vram
|
||||
VRAMFILE=image.ram
|
||||
|
||||
CFLAGS=-MMD -O2 -Wall -g -s -fomit-frame-pointer -mbarrel-shift-enabled -mmultiply-enabled -mdivide-enabled -msign-extend-enabled
|
||||
LDFLAGS=-nostdlib -nodefaultlibs -Tlinker.ld
|
||||
SEGMENTS = -j .text -j .rodata -j .data
|
||||
|
||||
all: image.srec $(VRAMFILE)
|
||||
|
||||
crt0ram.o: crt0ram.S
|
||||
$(LM32_CC) $(CFLAGS) -c crt0ram.S
|
||||
|
||||
main.o: main.c
|
||||
$(LM32_CC) $(CFLAGS) -c main.c
|
||||
|
||||
soc-hw.o: soc-hw.c
|
||||
$(LM32_CC) $(CFLAGS) -c soc-hw.c
|
||||
|
||||
image: crt0ram.o main.o soc-hw.o linker.ld Makefile
|
||||
$(LM32_LD) $(LDFLAGS) -Map image.map -N -o image crt0ram.o main.o soc-hw.o
|
||||
|
||||
image.lst: image
|
||||
$(LM32_OBJDUMP) -h -S $< > $@
|
||||
|
||||
image.bin: image
|
||||
$(LM32_OBJCOPY) $(SEGMENTS) -O binary image image.bin
|
||||
|
||||
image.srec: image image.lst
|
||||
$(LM32_OBJCOPY) $(SEGMENTS) -O srec image image.srec
|
||||
|
||||
$(VRAMFILE): image.srec
|
||||
$(SREC2VRAM) image.srec 0x40000000 0x1000 > $(VRAMFILE)
|
||||
|
||||
clean:
|
||||
rm -f image image.lst image.bin image.srec image.map *.o *.d
|
||||
|
||||
DEPS := $(wildcard *.d)
|
||||
ifneq ($(DEPS),)
|
||||
include $(DEPS)
|
||||
endif
|
||||
|
249
lm32/logic/sakc/firmware/hw-test/crt0ram.S
Normal file
249
lm32/logic/sakc/firmware/hw-test/crt0ram.S
Normal file
@ -0,0 +1,249 @@
|
||||
/*
|
||||
* LatticeMico32 C startup code.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* Exception handlers - Must be 32 bytes long. */
|
||||
.section .text, "ax", @progbits
|
||||
.global _start
|
||||
.global irq_enable, irq_disable, irq_set_mask, irq_get_mask
|
||||
.global jump, halt
|
||||
.global get_sp, get_gp
|
||||
|
||||
_start:
|
||||
_reset_handler:
|
||||
xor r0, r0, r0
|
||||
wcsr IE, r0
|
||||
mvhi r1, hi(_reset_handler)
|
||||
ori r1, r1, lo(_reset_handler)
|
||||
wcsr EBA, r1
|
||||
calli _crt0
|
||||
nop
|
||||
nop
|
||||
|
||||
_breakpoint_handler:
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
_ibuserror_handler:
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
_watchpoint_handler:
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
_dbuserror_handler:
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
_divzero_handler:
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
_interrupt_handler:
|
||||
sw (sp+0), ra
|
||||
calli _save_all
|
||||
rcsr r1, IP
|
||||
calli irq_handler
|
||||
mvhi r1, 0xffff
|
||||
ori r1, r1, 0xffff
|
||||
wcsr IP, r1
|
||||
bi _restore_all_and_eret
|
||||
|
||||
_scall_handler:
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
_crt0:
|
||||
/* Setup stack and global pointer */
|
||||
mvhi sp, hi(_fstack)
|
||||
ori sp, sp, lo(_fstack)
|
||||
mvhi gp, hi(_gp)
|
||||
ori gp, gp, lo(_gp)
|
||||
|
||||
/* Clear BSS */
|
||||
mvhi r1, hi(_fbss)
|
||||
ori r1, r1, lo(_fbss)
|
||||
mvhi r3, hi(_ebss)
|
||||
ori r3, r3, lo(_ebss)
|
||||
.clearBSS:
|
||||
be r1, r3, .callMain
|
||||
sw (r1+0), r0
|
||||
addi r1, r1, 4
|
||||
bi .clearBSS
|
||||
|
||||
.callMain:
|
||||
mvi r1, 0
|
||||
mvi r2, 0
|
||||
mvi r3, 0
|
||||
calli main
|
||||
|
||||
irq_enable:
|
||||
mvi r1, 1
|
||||
wcsr IE, r1
|
||||
ret
|
||||
|
||||
irq_disable:
|
||||
mvi r1, 0
|
||||
wcsr IE, r1
|
||||
ret
|
||||
|
||||
irq_set_mask:
|
||||
wcsr IM, r1
|
||||
ret
|
||||
|
||||
irq_get_mask:
|
||||
rcsr r1, IM
|
||||
ret
|
||||
|
||||
jump:
|
||||
b r1
|
||||
|
||||
halt:
|
||||
bi halt
|
||||
|
||||
/* Save all registers onto the stack */
|
||||
_save_all:
|
||||
addi sp, sp, -128
|
||||
sw (sp+4), r1
|
||||
sw (sp+8), r2
|
||||
sw (sp+12), r3
|
||||
sw (sp+16), r4
|
||||
sw (sp+20), r5
|
||||
sw (sp+24), r6
|
||||
sw (sp+28), r7
|
||||
sw (sp+32), r8
|
||||
sw (sp+36), r9
|
||||
sw (sp+40), r10
|
||||
#ifdef MICO32_FULL_CONTEXT_SAVE_RESTORE
|
||||
sw (sp+44), r11
|
||||
sw (sp+48), r12
|
||||
sw (sp+52), r13
|
||||
sw (sp+56), r14
|
||||
sw (sp+60), r15
|
||||
sw (sp+64), r16
|
||||
sw (sp+68), r17
|
||||
sw (sp+72), r18
|
||||
sw (sp+76), r19
|
||||
sw (sp+80), r20
|
||||
sw (sp+84), r21
|
||||
sw (sp+88), r22
|
||||
sw (sp+92), r23
|
||||
sw (sp+96), r24
|
||||
sw (sp+100), r25
|
||||
sw (sp+104), r26
|
||||
sw (sp+108), r27
|
||||
#endif
|
||||
sw (sp+120), ea
|
||||
sw (sp+124), ba
|
||||
/* ra and sp need special handling, as they have been modified */
|
||||
lw r1, (sp+128)
|
||||
sw (sp+116), r1
|
||||
mv r1, sp
|
||||
addi r1, r1, 128
|
||||
sw (sp+112), r1
|
||||
ret
|
||||
|
||||
/* Restore all registers and return from exception */
|
||||
_restore_all_and_eret:
|
||||
lw r1, (sp+4)
|
||||
lw r2, (sp+8)
|
||||
lw r3, (sp+12)
|
||||
lw r4, (sp+16)
|
||||
lw r5, (sp+20)
|
||||
lw r6, (sp+24)
|
||||
lw r7, (sp+28)
|
||||
lw r8, (sp+32)
|
||||
lw r9, (sp+36)
|
||||
lw r10, (sp+40)
|
||||
#ifdef MICO32_FULL_CONTEXT_SAVE_RESTORE
|
||||
lw r11, (sp+44)
|
||||
lw r12, (sp+48)
|
||||
lw r13, (sp+52)
|
||||
lw r14, (sp+56)
|
||||
lw r15, (sp+60)
|
||||
lw r16, (sp+64)
|
||||
lw r17, (sp+68)
|
||||
lw r18, (sp+72)
|
||||
lw r19, (sp+76)
|
||||
lw r20, (sp+80)
|
||||
lw r21, (sp+84)
|
||||
lw r22, (sp+88)
|
||||
lw r23, (sp+92)
|
||||
lw r24, (sp+96)
|
||||
lw r25, (sp+100)
|
||||
lw r26, (sp+104)
|
||||
lw r27, (sp+108)
|
||||
#endif
|
||||
lw ra, (sp+116)
|
||||
lw ea, (sp+120)
|
||||
lw ba, (sp+124)
|
||||
/* Stack pointer must be restored last, in case it has been updated */
|
||||
lw sp, (sp+112)
|
||||
eret
|
||||
|
||||
get_sp:
|
||||
mv r1, sp
|
||||
ret
|
||||
|
||||
get_gp:
|
||||
mv r1, gp
|
||||
ret
|
||||
|
59
lm32/logic/sakc/firmware/hw-test/linker.ld
Normal file
59
lm32/logic/sakc/firmware/hw-test/linker.ld
Normal file
@ -0,0 +1,59 @@
|
||||
OUTPUT_FORMAT("elf32-lm32")
|
||||
ENTRY(_start)
|
||||
|
||||
__DYNAMIC = 0;
|
||||
|
||||
|
||||
_RAM_START = 0x40000000;
|
||||
_RAM_SIZE = 0x1000;
|
||||
_RAM_END = _RAM_START + _RAM_SIZE;
|
||||
|
||||
MEMORY {
|
||||
ram : ORIGIN = 0x40000000, LENGTH = 0x1000 /* 4k */
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text :
|
||||
{
|
||||
_ftext = .;
|
||||
*(.text .stub .text.* .gnu.linkonce.t.*)
|
||||
_etext = .;
|
||||
} > ram
|
||||
|
||||
.rodata :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_frodata = .;
|
||||
*(.rodata .rodata.* .gnu.linkonce.r.*)
|
||||
*(.rodata1)
|
||||
_erodata = .;
|
||||
} > ram
|
||||
|
||||
.data :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_fdata = .;
|
||||
*(.data .data.* .gnu.linkonce.d.*)
|
||||
*(.data1)
|
||||
_gp = ALIGN(16);
|
||||
*(.sdata .sdata.* .gnu.linkonce.s.*)
|
||||
_edata = .;
|
||||
} > ram
|
||||
|
||||
.bss :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_fbss = .;
|
||||
*(.dynsbss)
|
||||
*(.sbss .sbss.* .gnu.linkonce.sb.*)
|
||||
*(.scommon)
|
||||
*(.dynbss)
|
||||
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
_ebss = .;
|
||||
_end = .;
|
||||
} > ram
|
||||
}
|
||||
|
||||
PROVIDE(_fstack = ORIGIN(ram) + LENGTH(ram) - 4);
|
151
lm32/logic/sakc/firmware/hw-test/main.c
Normal file
151
lm32/logic/sakc/firmware/hw-test/main.c
Normal file
@ -0,0 +1,151 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
#include "soc-hw.h"
|
||||
|
||||
inline void writeint(uint32_t val)
|
||||
{
|
||||
uint32_t i, digit;
|
||||
|
||||
for (i=0; i<8; i++) {
|
||||
digit = (val & 0xf0000000) >> 28;
|
||||
if (digit >= 0xA)
|
||||
uart_putchar('A'+digit-10);
|
||||
else
|
||||
uart_putchar('0'+digit);
|
||||
val <<= 4;
|
||||
}
|
||||
}
|
||||
|
||||
void test2() {
|
||||
uart_putchar('b');
|
||||
}
|
||||
|
||||
void test() {
|
||||
uart_putchar('a');
|
||||
test2();
|
||||
uart_putchar('c');
|
||||
}
|
||||
|
||||
char glob[] = "Global";
|
||||
|
||||
volatile uint32_t *p;
|
||||
volatile uint8_t *p2;
|
||||
|
||||
extern uint32_t tic_msec;
|
||||
|
||||
int main()
|
||||
{
|
||||
char test2[] = "Lokalerstr";
|
||||
char *str = test2;
|
||||
uint32_t i;
|
||||
|
||||
// for (i = 0; i < 4; i++)
|
||||
// test2[i] = 'l';
|
||||
// glob[0] = 'g';
|
||||
|
||||
// Initialize stuff
|
||||
uart_init();
|
||||
|
||||
// Say Hello!
|
||||
uart_putstr( "** Spike Test Firmware **\n" );
|
||||
|
||||
// Initialize TIC
|
||||
isr_init();
|
||||
tic_init();
|
||||
irq_set_mask( 0x00000002 );
|
||||
irq_enable();
|
||||
|
||||
// Say Hello!
|
||||
uart_putstr( "Timer Interrupt instelled.\n" );
|
||||
|
||||
// Do some trivial tests
|
||||
uart_putstr( "Subroutine-Return Test: " );
|
||||
test();
|
||||
uart_putchar('\n');
|
||||
|
||||
uart_putstr( "Local-Pointer Test:" );
|
||||
for (;*str; str++) {
|
||||
uart_putchar(*str);
|
||||
}
|
||||
uart_putchar('\n');
|
||||
|
||||
uart_putstr( "Global-Pointer Test:" );
|
||||
str = glob;
|
||||
for (;*str; str++) {
|
||||
uart_putchar(*str);
|
||||
}
|
||||
uart_putchar('\n');
|
||||
|
||||
uart_putstr( "Stack Pointer : " );
|
||||
writeint(get_sp());
|
||||
uart_putchar('\n');
|
||||
|
||||
uart_putstr( "Global Pointer: " );
|
||||
writeint(get_gp());
|
||||
uart_putchar('\n');
|
||||
|
||||
uart_putstr( "Timer Test (1s): " );
|
||||
for(i=0; i<4; i++) {
|
||||
uart_putstr("tic...");
|
||||
msleep(1000);
|
||||
}
|
||||
uart_putchar('\n');
|
||||
|
||||
uart_putstr( "Timer Interrupt counter: " );
|
||||
writeint( tic_msec );
|
||||
uart_putchar('\n');
|
||||
|
||||
int val = tic_msec;
|
||||
uart_putstr( "Shift: " );
|
||||
writeint( val );
|
||||
uart_putstr(" <-> ");
|
||||
for(i=0; i<32; i++) {
|
||||
if (val & 0x80000000)
|
||||
uart_putchar( '1' );
|
||||
else
|
||||
uart_putchar( '0' );
|
||||
|
||||
val <<= 1;
|
||||
}
|
||||
uart_putstr("\r\n");
|
||||
|
||||
uart_putstr( "GPIO Test..." );
|
||||
gpio0->oe = 0x000000ff;
|
||||
for(;;) {
|
||||
for(i=0; i<8; i++) {
|
||||
uint32_t out1, out2;
|
||||
|
||||
out1 = 0x01 << i;
|
||||
out2 = 0x80 >> i;
|
||||
gpio0->out = out1 | out2;
|
||||
|
||||
msleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
uart_putstr( "Memory Dump: " );
|
||||
uint32_t *start = (uint32_t *)0x40000000;
|
||||
uint32_t *end = (uint32_t *)0x40000100;
|
||||
uint32_t *p;
|
||||
for (p=start; p<end; p++) {
|
||||
if (((uint32_t)p & 12) == 0) {
|
||||
uart_putstr("\r\n[");
|
||||
writeint((uint32_t) p);
|
||||
uart_putchar(']');
|
||||
}
|
||||
|
||||
uart_putchar(' ');
|
||||
writeint(*p);
|
||||
}
|
||||
*/
|
||||
|
||||
uart_putstr("Entering Echo Test...\n");
|
||||
while (1) {
|
||||
uart_putchar(uart_getchar());
|
||||
}
|
||||
}
|
||||
|
133
lm32/logic/sakc/firmware/hw-test/soc-hw.c
Normal file
133
lm32/logic/sakc/firmware/hw-test/soc-hw.c
Normal file
@ -0,0 +1,133 @@
|
||||
#include "soc-hw.h"
|
||||
|
||||
uart_t *uart0 = (uart_t *) 0xf0000000;
|
||||
timer_t *timer0 = (timer_t *) 0xf0010000;
|
||||
gpio_t *gpio0 = (gpio_t *) 0xF0020000;
|
||||
|
||||
isr_ptr_t isr_table[32];
|
||||
|
||||
|
||||
void tic_isr();
|
||||
/***************************************************************************
|
||||
* IRQ handling
|
||||
*/
|
||||
void isr_null()
|
||||
{
|
||||
}
|
||||
|
||||
void irq_handler(uint32_t pending)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<32; i++) {
|
||||
if (pending & 0x01) (*isr_table[i])();
|
||||
pending >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
void isr_init()
|
||||
{
|
||||
int i;
|
||||
for(i=0; i<32; i++)
|
||||
isr_table[i] = &isr_null;
|
||||
}
|
||||
|
||||
void isr_register(int irq, isr_ptr_t isr)
|
||||
{
|
||||
isr_table[irq] = isr;
|
||||
}
|
||||
|
||||
void isr_unregister(int irq)
|
||||
{
|
||||
isr_table[irq] = &isr_null;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* TIMER Functions
|
||||
*/
|
||||
void msleep(uint32_t msec)
|
||||
{
|
||||
uint32_t tcr;
|
||||
|
||||
// Use timer0.1
|
||||
timer0->compare1 = (FCPU/1000)*msec;
|
||||
timer0->counter1 = 0;
|
||||
timer0->tcr1 = TIMER_EN;
|
||||
|
||||
do {
|
||||
//halt();
|
||||
tcr = timer0->tcr1;
|
||||
} while ( ! (tcr & TIMER_TRIG) );
|
||||
}
|
||||
|
||||
void nsleep(uint32_t nsec)
|
||||
{
|
||||
uint32_t tcr;
|
||||
|
||||
// Use timer0.1
|
||||
timer0->compare1 = (FCPU/1000000)*nsec;
|
||||
timer0->counter1 = 0;
|
||||
timer0->tcr1 = TIMER_EN;
|
||||
|
||||
do {
|
||||
//halt();
|
||||
tcr = timer0->tcr1;
|
||||
} while ( ! (tcr & TIMER_TRIG) );
|
||||
}
|
||||
|
||||
|
||||
uint32_t tic_msec;
|
||||
|
||||
void tic_isr()
|
||||
{
|
||||
tic_msec++;
|
||||
timer0->tcr0 = TIMER_EN | TIMER_AR | TIMER_IRQEN;
|
||||
}
|
||||
|
||||
void tic_init()
|
||||
{
|
||||
tic_msec = 0;
|
||||
|
||||
// Setup timer0.0
|
||||
timer0->compare0 = (FCPU/10000);
|
||||
timer0->counter0 = 0;
|
||||
timer0->tcr0 = TIMER_EN | TIMER_AR | TIMER_IRQEN;
|
||||
|
||||
isr_register(1, &tic_isr);
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* UART Functions
|
||||
*/
|
||||
void uart_init()
|
||||
{
|
||||
//uart0->ier = 0x00; // Interrupt Enable Register
|
||||
//uart0->lcr = 0x03; // Line Control Register: 8N1
|
||||
//uart0->mcr = 0x00; // Modem Control Register
|
||||
|
||||
// Setup Divisor register (Fclk / Baud)
|
||||
//uart0->div = (FCPU/(57600*16));
|
||||
}
|
||||
|
||||
char uart_getchar()
|
||||
{
|
||||
while (! (uart0->ucr & UART_DR)) ;
|
||||
return uart0->rxtx;
|
||||
}
|
||||
|
||||
void uart_putchar(char c)
|
||||
{
|
||||
while (uart0->ucr & UART_BUSY) ;
|
||||
uart0->rxtx = c;
|
||||
}
|
||||
|
||||
void uart_putstr(char *str)
|
||||
{
|
||||
char *c = str;
|
||||
while(*c) {
|
||||
uart_putchar(*c);
|
||||
c++;
|
||||
}
|
||||
}
|
||||
|
108
lm32/logic/sakc/firmware/hw-test/soc-hw.h
Normal file
108
lm32/logic/sakc/firmware/hw-test/soc-hw.h
Normal file
@ -0,0 +1,108 @@
|
||||
#ifndef SPIKEHW_H
|
||||
#define SPIKEHW_H
|
||||
|
||||
#define PROMSTART 0x00000000
|
||||
#define RAMSTART 0x00000800
|
||||
#define RAMSIZE 0x400
|
||||
#define RAMEND (RAMSTART + RAMSIZE)
|
||||
|
||||
#define RAM_START 0x40000000
|
||||
#define RAM_SIZE 0x04000000
|
||||
|
||||
#define FCPU 50000000
|
||||
|
||||
#define UART_RXBUFSIZE 32
|
||||
|
||||
/****************************************************************************
|
||||
* Types
|
||||
*/
|
||||
typedef unsigned int uint32_t; // 32 Bit
|
||||
typedef signed int int32_t; // 32 Bit
|
||||
|
||||
typedef unsigned char uint8_t; // 8 Bit
|
||||
typedef signed char int8_t; // 8 Bit
|
||||
|
||||
/****************************************************************************
|
||||
* Interrupt handling
|
||||
*/
|
||||
typedef void(*isr_ptr_t)(void);
|
||||
|
||||
void irq_enable();
|
||||
void irq_disable();
|
||||
void irq_set_mask(uint32_t mask);
|
||||
uint32_t irq_get_mak();
|
||||
|
||||
void isr_init();
|
||||
void isr_register(int irq, isr_ptr_t isr);
|
||||
void isr_unregister(int irq);
|
||||
|
||||
/****************************************************************************
|
||||
* General Stuff
|
||||
*/
|
||||
void halt();
|
||||
void jump(uint32_t addr);
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* Timer
|
||||
*/
|
||||
#define TIMER_EN 0x08 // Enable Timer
|
||||
#define TIMER_AR 0x04 // Auto-Reload
|
||||
#define TIMER_IRQEN 0x02 // IRQ Enable
|
||||
#define TIMER_TRIG 0x01 // Triggered (reset when writing to TCR)
|
||||
|
||||
typedef struct {
|
||||
volatile uint32_t tcr0;
|
||||
volatile uint32_t compare0;
|
||||
volatile uint32_t counter0;
|
||||
volatile uint32_t tcr1;
|
||||
volatile uint32_t compare1;
|
||||
volatile uint32_t counter1;
|
||||
} timer_t;
|
||||
|
||||
void msleep(uint32_t msec);
|
||||
void nsleep(uint32_t nsec);
|
||||
|
||||
void tic_init();
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* GPIO0
|
||||
*/
|
||||
typedef struct {
|
||||
volatile uint32_t ctrl;
|
||||
volatile uint32_t dummy1;
|
||||
volatile uint32_t dummy2;
|
||||
volatile uint32_t dummy3;
|
||||
volatile uint32_t in;
|
||||
volatile uint32_t out;
|
||||
volatile uint32_t oe;
|
||||
} gpio_t;
|
||||
|
||||
/***************************************************************************
|
||||
* UART0
|
||||
*/
|
||||
#define UART_DR 0x01 // RX Data Ready
|
||||
#define UART_ERR 0x02 // RX Error
|
||||
#define UART_BUSY 0x10 // TX Busy
|
||||
|
||||
typedef struct {
|
||||
volatile uint32_t ucr;
|
||||
volatile uint32_t rxtx;
|
||||
} uart_t;
|
||||
|
||||
void uart_init();
|
||||
void uart_putchar(char c);
|
||||
void uart_putstr(char *str);
|
||||
char uart_getchar();
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* Pointer to actual components
|
||||
*/
|
||||
extern timer_t *timer0;
|
||||
extern uart_t *uart0;
|
||||
extern gpio_t *gpio0;
|
||||
extern uint32_t *sram0;
|
||||
|
||||
#endif // SPIKEHW_H
|
43
lm32/logic/sakc/rtl/lac/dp_ram.v
Normal file
43
lm32/logic/sakc/rtl/lac/dp_ram.v
Normal file
@ -0,0 +1,43 @@
|
||||
//------------------------------------------------------------------
|
||||
// Dual port memory (one read and one write port, same width)
|
||||
//------------------------------------------------------------------
|
||||
|
||||
module dp_ram #(
|
||||
parameter adr_width = 11,
|
||||
parameter dat_width = 8
|
||||
) (
|
||||
// read port a
|
||||
input clk_a,
|
||||
input [adr_width-1:0] adr_a,
|
||||
output reg [dat_width-1:0] dat_a,
|
||||
// write port b
|
||||
input clk_b,
|
||||
input [adr_width-1:0] adr_b,
|
||||
input [dat_width-1:0] dat_b,
|
||||
input we_b
|
||||
);
|
||||
|
||||
parameter depth = (1 << adr_width);
|
||||
|
||||
// actual ram cells
|
||||
reg [dat_width-1:0] ram [0:depth-1];
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// read port
|
||||
//------------------------------------------------------------------
|
||||
always @(posedge clk_a)
|
||||
begin
|
||||
dat_a <= ram[adr_a];
|
||||
end
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// write port
|
||||
//------------------------------------------------------------------
|
||||
always @(posedge clk_b)
|
||||
begin
|
||||
if (we_b) begin
|
||||
ram[adr_b] <= dat_b;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
262
lm32/logic/sakc/rtl/lac/lac.v
Normal file
262
lm32/logic/sakc/rtl/lac/lac.v
Normal file
@ -0,0 +1,262 @@
|
||||
//------------------------------------------------------------------
|
||||
// Logic Analyzer Component
|
||||
//------------------------------------------------------------------
|
||||
|
||||
module lac #(
|
||||
parameter uart_freq_hz = 100000000,
|
||||
parameter uart_baud = 115200,
|
||||
parameter adr_width = 11,
|
||||
parameter width = 8
|
||||
) (
|
||||
input reset,
|
||||
input uart_clk,
|
||||
input uart_rxd,
|
||||
output uart_cts,
|
||||
output uart_txd,
|
||||
input uart_rts,
|
||||
// actual probe input
|
||||
input probe_clk,
|
||||
input [width-1:0] probe,
|
||||
output reg [7:0] select
|
||||
);
|
||||
|
||||
parameter cmd_nop = 8'h20;
|
||||
parameter cmd_arm = 8'h01;
|
||||
parameter cmd_disarm = 8'h02;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// uart instantiation
|
||||
//------------------------------------------------------------------
|
||||
assign uart_cts = 1;
|
||||
|
||||
reg tx_wr;
|
||||
wire tx_busy;
|
||||
reg [7:0] tx_data;
|
||||
|
||||
wire [7:0] rx_data;
|
||||
wire rx_avail;
|
||||
reg rx_ack;
|
||||
|
||||
uart #(
|
||||
.freq_hz( uart_freq_hz ),
|
||||
.baud( uart_baud )
|
||||
) uart0 (
|
||||
.reset( reset ),
|
||||
.clk( uart_clk ),
|
||||
// UART
|
||||
.uart_txd( uart_txd ),
|
||||
.uart_rxd( uart_rxd ),
|
||||
//
|
||||
.rx_data( rx_data ),
|
||||
.rx_avail( rx_avail ),
|
||||
.rx_error( rx_error ),
|
||||
.rx_ack( rx_ack ),
|
||||
.tx_data( tx_data ),
|
||||
.tx_wr( tx_wr ),
|
||||
.tx_busy( tx_busy )
|
||||
);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// handshake signal between clock domains
|
||||
//------------------------------------------------------------------
|
||||
reg [7:0] trig_mask;
|
||||
reg [7:0] trig_cond;
|
||||
reg [7:0] trig_pre;
|
||||
|
||||
reg [adr_width-1:0] start_adr; // set in probe_clk domain
|
||||
|
||||
reg armed; // set in uart_clk domain
|
||||
reg triggered; // set in probe_clk domain
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// uart state machine
|
||||
//------------------------------------------------------------------
|
||||
wire rx_req;
|
||||
assign rx_req = rx_avail & ~rx_ack;
|
||||
|
||||
reg triggered_synced;
|
||||
wire [width-1:0] read_dat;
|
||||
reg [adr_width-1:0] read_adr;
|
||||
wire [adr_width-1:0] read_adr_next;
|
||||
|
||||
assign read_adr_next = read_adr + 1;
|
||||
|
||||
reg [2:0] state;
|
||||
|
||||
parameter s_idle = 0;
|
||||
parameter s_read_select= 1;
|
||||
parameter s_read_mask = 2;
|
||||
parameter s_read_comp = 3;
|
||||
parameter s_read_pre = 4;
|
||||
parameter s_triggered = 5;
|
||||
parameter s_send_byte = 6;
|
||||
|
||||
always @(posedge uart_clk)
|
||||
begin
|
||||
if (reset) begin
|
||||
state <= s_idle;
|
||||
select <= 0;
|
||||
armed <= 0;
|
||||
tx_wr <= 0;
|
||||
end else begin
|
||||
triggered_synced <= triggered;
|
||||
|
||||
rx_ack <= 0; // default until set otherwise
|
||||
tx_wr <= 0;
|
||||
|
||||
case (state)
|
||||
s_idle: begin
|
||||
|
||||
if (rx_req) begin
|
||||
case (rx_data)
|
||||
cmd_arm: begin
|
||||
rx_ack <= 1;
|
||||
state <= s_read_select;
|
||||
end
|
||||
cmd_disarm: begin
|
||||
rx_ack <= 1;
|
||||
armed <= 0;
|
||||
end
|
||||
default: begin
|
||||
rx_ack <= 1;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
if (~rx_req && triggered_synced) begin
|
||||
state <= s_triggered;
|
||||
end
|
||||
end
|
||||
s_read_select: begin
|
||||
if (rx_req) begin
|
||||
rx_ack <= 1;
|
||||
select <= rx_data;
|
||||
state <= s_read_mask;
|
||||
end
|
||||
end
|
||||
s_read_mask: begin
|
||||
if (rx_req) begin
|
||||
rx_ack <= 1;
|
||||
trig_mask <= rx_data;
|
||||
state <= s_read_comp;
|
||||
end
|
||||
end
|
||||
s_read_comp: begin
|
||||
if (rx_req) begin
|
||||
rx_ack <= 1;
|
||||
trig_cond <= rx_data;
|
||||
armed <= 1;
|
||||
state <= s_read_pre;
|
||||
end
|
||||
end
|
||||
s_read_pre: begin
|
||||
if (rx_req) begin
|
||||
rx_ack <= 1;
|
||||
trig_pre <= rx_data;
|
||||
armed <= 1;
|
||||
state <= s_idle;
|
||||
end
|
||||
end
|
||||
s_triggered: begin
|
||||
armed <= 0;
|
||||
read_adr <= start_adr;
|
||||
tx_data <= adr_width;
|
||||
tx_wr <= 1;
|
||||
state <= s_send_byte;
|
||||
end
|
||||
s_send_byte: begin
|
||||
tx_wr <= 0;
|
||||
|
||||
if (~tx_busy & ~tx_wr) begin
|
||||
if (read_adr_next == start_adr)
|
||||
state <= s_idle;
|
||||
|
||||
read_adr <= read_adr_next;
|
||||
tx_data <= read_dat;
|
||||
tx_wr <= 1;
|
||||
end
|
||||
end
|
||||
default:
|
||||
state <= s_idle;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Sampling clock domain
|
||||
//------------------------------------------------------------------
|
||||
|
||||
// register probe input for better F_max
|
||||
reg [width-1:0] probe_r;
|
||||
|
||||
always @(posedge probe_clk)
|
||||
probe_r <= probe;
|
||||
|
||||
// Sampling machinery
|
||||
reg armed_synced;
|
||||
reg armed_synced2;
|
||||
reg sampling;
|
||||
|
||||
reg [adr_width-1:0] write_adr;
|
||||
wire [adr_width-1:0] next_adr;
|
||||
assign next_adr = write_adr + 1;
|
||||
|
||||
wire cond_match;
|
||||
assign cond_match = (probe_r & trig_mask) == (trig_cond & trig_mask) && armed_synced2;
|
||||
|
||||
always @(posedge probe_clk)
|
||||
begin
|
||||
if (reset) begin
|
||||
armed_synced <= 0;
|
||||
armed_synced2 <= 0;
|
||||
sampling <= 0;
|
||||
triggered <= 0;
|
||||
write_adr <= 0;
|
||||
end else begin
|
||||
armed_synced <= armed;
|
||||
armed_synced2 <= armed_synced;
|
||||
|
||||
if (armed_synced2 || sampling) begin
|
||||
write_adr <= next_adr;
|
||||
end
|
||||
|
||||
if (~triggered && armed_synced2) begin
|
||||
if (cond_match) begin
|
||||
sampling <= 1;
|
||||
triggered <= 1;
|
||||
start_adr <= write_adr;
|
||||
end
|
||||
end
|
||||
|
||||
if (sampling && next_adr == start_adr) begin
|
||||
sampling <= 0;
|
||||
end
|
||||
|
||||
if (~sampling && ~armed_synced2 && triggered)
|
||||
triggered <= 0;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// dual port memory
|
||||
//------------------------------------------------------------------
|
||||
wire write_en;
|
||||
assign write_en = sampling || cond_match;
|
||||
|
||||
dp_ram #(
|
||||
.adr_width( adr_width ),
|
||||
.dat_width( width )
|
||||
) ram0 (
|
||||
// read port a
|
||||
.clk_a( uart_clk ),
|
||||
.adr_a( read_adr ),
|
||||
.dat_a( read_dat ),
|
||||
// write port b
|
||||
.clk_b( probe_clk ),
|
||||
.adr_b( write_adr ),
|
||||
.dat_b( probe_r ),
|
||||
.we_b( write_en )
|
||||
);
|
||||
|
||||
endmodule
|
155
lm32/logic/sakc/rtl/lac/uart.v
Normal file
155
lm32/logic/sakc/rtl/lac/uart.v
Normal file
@ -0,0 +1,155 @@
|
||||
//-----------------------------------------------------
|
||||
// Design Name : uart
|
||||
// File Name : uart.v
|
||||
//-----------------------------------------------------
|
||||
module uart #(
|
||||
parameter freq_hz = 100000000,
|
||||
parameter baud = 115200
|
||||
) (
|
||||
input reset,
|
||||
input clk,
|
||||
// UART lines
|
||||
input uart_rxd,
|
||||
output reg uart_txd,
|
||||
//
|
||||
output reg [7:0] rx_data,
|
||||
output reg rx_avail,
|
||||
output reg rx_error,
|
||||
input rx_ack,
|
||||
input [7:0] tx_data,
|
||||
input tx_wr,
|
||||
output reg tx_busy
|
||||
);
|
||||
|
||||
parameter divisor = freq_hz/baud/16;
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// enable16 generator
|
||||
//-----------------------------------------------------------------
|
||||
reg [15:0] enable16_counter;
|
||||
|
||||
wire enable16;
|
||||
assign enable16 = (enable16_counter == 0);
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
if (reset) begin
|
||||
enable16_counter <= divisor-1;
|
||||
end else begin
|
||||
enable16_counter <= enable16_counter - 1;
|
||||
if (enable16_counter == 0) begin
|
||||
enable16_counter <= divisor-1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// syncronize uart_rxd
|
||||
//-----------------------------------------------------------------
|
||||
reg uart_rxd1;
|
||||
reg uart_rxd2;
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
uart_rxd1 <= uart_rxd;
|
||||
uart_rxd2 <= uart_rxd1;
|
||||
end
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// UART RX Logic
|
||||
//-----------------------------------------------------------------
|
||||
reg rx_busy;
|
||||
reg [3:0] rx_count16;
|
||||
reg [3:0] rx_bitcount;
|
||||
reg [7:0] rxd_reg;
|
||||
|
||||
always @ (posedge clk)
|
||||
begin
|
||||
if (reset) begin
|
||||
rx_busy <= 0;
|
||||
rx_count16 <= 0;
|
||||
rx_bitcount <= 0;
|
||||
rx_avail <= 0;
|
||||
rx_error <= 0;
|
||||
end else begin
|
||||
if (rx_ack) begin
|
||||
rx_avail <= 0;
|
||||
rx_error <= 0;
|
||||
end
|
||||
|
||||
if (enable16) begin
|
||||
if (!rx_busy) begin // look for start bit
|
||||
if (!uart_rxd2) begin // start bit found
|
||||
rx_busy <= 1;
|
||||
rx_count16 <= 7;
|
||||
rx_bitcount <= 0;
|
||||
end
|
||||
end else begin
|
||||
rx_count16 <= rx_count16 + 1;
|
||||
|
||||
if (rx_count16 == 0) begin // sample
|
||||
rx_bitcount <= rx_bitcount + 1;
|
||||
|
||||
if (rx_bitcount == 0) begin // verify startbit
|
||||
if (uart_rxd2) begin
|
||||
rx_busy <= 0;
|
||||
end
|
||||
end else if (rx_bitcount == 9) begin // look for stop bit
|
||||
rx_busy <= 0;
|
||||
if (uart_rxd2) begin // stop bit ok
|
||||
rx_data <= rxd_reg;
|
||||
rx_avail <= 1;
|
||||
rx_error <= 0;
|
||||
end else begin // bas stop bit
|
||||
rx_error <= 1;
|
||||
end
|
||||
end else begin
|
||||
rxd_reg <= { uart_rxd2, rxd_reg[7:1] };
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// UART TX Logic
|
||||
//-----------------------------------------------------------------
|
||||
reg [3:0] tx_bitcount;
|
||||
reg [3:0] tx_count16;
|
||||
reg [7:0] txd_reg;
|
||||
|
||||
always @ (posedge clk)
|
||||
begin
|
||||
if (reset) begin
|
||||
tx_busy <= 0;
|
||||
uart_txd <= 1;
|
||||
end else begin
|
||||
if (tx_wr && !tx_busy) begin
|
||||
txd_reg <= tx_data;
|
||||
tx_bitcount <= 0;
|
||||
tx_count16 <= 1;
|
||||
tx_busy <= 1;
|
||||
uart_txd <= 0;
|
||||
end else if (enable16 && tx_busy) begin
|
||||
tx_count16 <= tx_count16 + 1;
|
||||
|
||||
if (tx_count16 == 0) begin
|
||||
tx_bitcount <= tx_bitcount + 1;
|
||||
|
||||
if (tx_bitcount == 8) begin
|
||||
uart_txd <= 'b1;
|
||||
end else if (tx_bitcount == 9) begin
|
||||
uart_txd <= 'b1;
|
||||
tx_busy <= 0;
|
||||
end else begin
|
||||
uart_txd <= txd_reg[0];
|
||||
txd_reg <= { 1'b0, txd_reg[7:1] };
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
endmodule
|
15
lm32/logic/sakc/rtl/lm32/JTAGB.v
Normal file
15
lm32/logic/sakc/rtl/lm32/JTAGB.v
Normal file
@ -0,0 +1,15 @@
|
||||
module JTAGB (
|
||||
output JTCK,
|
||||
output JRTI1,
|
||||
output JRTI2,
|
||||
output JTDI,
|
||||
output JSHIFT,
|
||||
output JUPDATE,
|
||||
output JRSTN,
|
||||
output JCE1,
|
||||
output JCE2,
|
||||
input JTDO1,
|
||||
input JTDO2
|
||||
) /*synthesis syn_black_box */;
|
||||
|
||||
endmodule
|
218
lm32/logic/sakc/rtl/lm32/er1.v
Normal file
218
lm32/logic/sakc/rtl/lm32/er1.v
Normal file
@ -0,0 +1,218 @@
|
||||
/*-- ---------------------------------------------------------------------------
|
||||
--
|
||||
-- Name : ER1.v
|
||||
--
|
||||
-- Description:
|
||||
--
|
||||
-- This module is where the ER1 register implemented. ER1 and ER2 registers
|
||||
-- can be registers implemented in Lattice FPGAs using normal FPGA's
|
||||
-- programmable logic resources. Once they are implemented, they can be
|
||||
-- accessed as if they are JTAG data registers through the FPGA JTAG port.
|
||||
-- In order to accessing these registers, JTAG instructions ER1(0x32) or
|
||||
-- ER2(0x38) needs to be written to the JTAG IR register for enabling the
|
||||
-- ER1/ER2 accessing logic. The ER1 or ER2 accessing logic can only be
|
||||
-- enabled one at a time. Once they are enabled, they will be disabled if
|
||||
-- another JTAG instruction is written into the JTAG instruction register.
|
||||
-- The registers allow dynamically accessing the FPGA internal information
|
||||
-- even when the device is running. Therefore, they are very useful for some
|
||||
-- of the IP cores. In order to let ER1/ER2 registers shared by multiple IP
|
||||
-- cores or other designs, there is a ER1/ER2 structure patterned by Lattice.
|
||||
-- The ER1/ER2 structure allows only one ER1 register but more than one ER2
|
||||
-- registers in an FPGA device. Please refer to the related document for
|
||||
-- this patterned ER1/ER2 structure.
|
||||
--
|
||||
-- $Log: $
|
||||
--
|
||||
-- $Header: $
|
||||
--
|
||||
-- Copyright (C) 2004 Lattice Semiconductor Corp. All rights reserved.
|
||||
--
|
||||
-- ---------------------------------------------------------------------------*/
|
||||
|
||||
module ER1 (input JTCK,
|
||||
input JTDI,
|
||||
output JTDO1,
|
||||
output reg JTDO2,
|
||||
input JSHIFT,
|
||||
input JUPDATE,
|
||||
input JRSTN,
|
||||
input JCE1,
|
||||
input [14:0] ER2_TDO,
|
||||
output reg [14:0] IP_ENABLE,
|
||||
input ISPTRACY_ER2_TDO,
|
||||
output ISPTRACY_ENABLE,
|
||||
output CONTROL_DATAN)/* synthesis syn_hier = hard */;
|
||||
|
||||
|
||||
wire controlDataNBit;
|
||||
wire ispTracyEnableBit;
|
||||
wire [3:0] encodedIpEnableBits;
|
||||
wire [9:0] er1TdiBit;
|
||||
wire captureDrER1;
|
||||
|
||||
|
||||
assign JTDO1 = er1TdiBit[0];
|
||||
|
||||
TYPEB BIT0 (.CLK(JTCK),
|
||||
.RESET_N(JRSTN),
|
||||
.CLKEN(JCE1),
|
||||
.TDI(er1TdiBit[1]),
|
||||
.TDO(er1TdiBit[0]),
|
||||
.DATA_IN(1'b0),
|
||||
.CAPTURE_DR(captureDrER1));
|
||||
|
||||
TYPEB BIT1 (.CLK(JTCK),
|
||||
.RESET_N(JRSTN),
|
||||
.CLKEN(JCE1),
|
||||
.TDI(er1TdiBit[2]),
|
||||
.TDO(er1TdiBit[1]),
|
||||
.DATA_IN(1'b0),
|
||||
.CAPTURE_DR(captureDrER1));
|
||||
|
||||
TYPEB BIT2 (.CLK(JTCK),
|
||||
.RESET_N(JRSTN),
|
||||
.CLKEN(JCE1),
|
||||
.TDI(er1TdiBit[3]),
|
||||
.TDO(er1TdiBit[2]),
|
||||
.DATA_IN(1'b1),
|
||||
.CAPTURE_DR(captureDrER1));
|
||||
|
||||
TYPEA BIT3 (.CLK(JTCK),
|
||||
.RESET_N(JRSTN),
|
||||
.CLKEN(JCE1),
|
||||
.TDI(er1TdiBit[4]),
|
||||
.TDO(er1TdiBit[3]),
|
||||
.DATA_OUT(controlDataNBit),
|
||||
.DATA_IN(controlDataNBit),
|
||||
.CAPTURE_DR(captureDrER1),
|
||||
.UPDATE_DR(JUPDATE));
|
||||
|
||||
assign CONTROL_DATAN = controlDataNBit;
|
||||
|
||||
TYPEA BIT4 (.CLK(JTCK),
|
||||
.RESET_N(JRSTN),
|
||||
.CLKEN(JCE1),
|
||||
.TDI(er1TdiBit[5]),
|
||||
.TDO(er1TdiBit[4]),
|
||||
.DATA_OUT(ispTracyEnableBit),
|
||||
.DATA_IN(ispTracyEnableBit),
|
||||
.CAPTURE_DR(captureDrER1),
|
||||
.UPDATE_DR(JUPDATE)
|
||||
);
|
||||
|
||||
assign ISPTRACY_ENABLE = ispTracyEnableBit;
|
||||
|
||||
TYPEA BIT5 (.CLK(JTCK),
|
||||
.RESET_N(JRSTN),
|
||||
.CLKEN(JCE1),
|
||||
.TDI(er1TdiBit[6]),
|
||||
.TDO(er1TdiBit[5]),
|
||||
.DATA_OUT(encodedIpEnableBits[0]),
|
||||
.DATA_IN(encodedIpEnableBits[0]),
|
||||
.CAPTURE_DR(captureDrER1),
|
||||
.UPDATE_DR(JUPDATE));
|
||||
|
||||
TYPEA BIT6 (.CLK(JTCK),
|
||||
.RESET_N(JRSTN),
|
||||
.CLKEN(JCE1),
|
||||
.TDI(er1TdiBit[7]),
|
||||
.TDO(er1TdiBit[6]),
|
||||
.DATA_OUT(encodedIpEnableBits[1]),
|
||||
.DATA_IN(encodedIpEnableBits[1]),
|
||||
.CAPTURE_DR(captureDrER1),
|
||||
.UPDATE_DR(JUPDATE));
|
||||
|
||||
TYPEA BIT7 (.CLK(JTCK),
|
||||
.RESET_N(JRSTN),
|
||||
.CLKEN(JCE1),
|
||||
.TDI(er1TdiBit[8]),
|
||||
.TDO(er1TdiBit[7]),
|
||||
.DATA_OUT(encodedIpEnableBits[2]),
|
||||
.DATA_IN(encodedIpEnableBits[2]),
|
||||
.CAPTURE_DR(captureDrER1),
|
||||
.UPDATE_DR(JUPDATE));
|
||||
|
||||
TYPEA BIT8 (.CLK(JTCK),
|
||||
.RESET_N(JRSTN),
|
||||
.CLKEN(JCE1),
|
||||
.TDI(er1TdiBit[9]),
|
||||
.TDO(er1TdiBit[8]),
|
||||
.DATA_OUT(encodedIpEnableBits[3]),
|
||||
.DATA_IN(encodedIpEnableBits[3]),
|
||||
.CAPTURE_DR(captureDrER1),
|
||||
.UPDATE_DR(JUPDATE)
|
||||
);
|
||||
|
||||
assign er1TdiBit[9] = JTDI;
|
||||
assign captureDrER1 = !JSHIFT & JCE1;
|
||||
|
||||
always @ (encodedIpEnableBits,ISPTRACY_ER2_TDO, ER2_TDO)
|
||||
begin
|
||||
case (encodedIpEnableBits)
|
||||
4'h0: begin
|
||||
IP_ENABLE <= 15'b000000000000000;
|
||||
JTDO2 <= ISPTRACY_ER2_TDO;
|
||||
end
|
||||
4'h1: begin
|
||||
IP_ENABLE <= 15'b000000000000001;
|
||||
JTDO2 <= ER2_TDO[0];
|
||||
end
|
||||
4'h2: begin
|
||||
IP_ENABLE <= 15'b000000000000010;
|
||||
JTDO2 <= ER2_TDO[1];
|
||||
end
|
||||
4'h3: begin
|
||||
IP_ENABLE <= 15'b000000000000100;
|
||||
JTDO2 <= ER2_TDO[2];
|
||||
end
|
||||
4'h4: begin
|
||||
IP_ENABLE <= 15'b000000000001000;
|
||||
JTDO2 <= ER2_TDO[3];
|
||||
end
|
||||
4'h5: begin
|
||||
IP_ENABLE <= 15'b000000000010000;
|
||||
JTDO2 <= ER2_TDO[4];
|
||||
end
|
||||
4'h6: begin
|
||||
IP_ENABLE <= 15'b000000000100000;
|
||||
JTDO2 <= ER2_TDO[5];
|
||||
end
|
||||
4'h7: begin
|
||||
IP_ENABLE <= 15'b000000001000000;
|
||||
JTDO2 <= ER2_TDO[6];
|
||||
end
|
||||
4'h8: begin
|
||||
IP_ENABLE <= 15'b000000010000000;
|
||||
JTDO2 <= ER2_TDO[7];
|
||||
end
|
||||
4'h9: begin
|
||||
IP_ENABLE <= 15'b000000100000000;
|
||||
JTDO2 <= ER2_TDO[8];
|
||||
end
|
||||
4'hA: begin
|
||||
IP_ENABLE <= 15'b000001000000000;
|
||||
JTDO2 <= ER2_TDO[9];
|
||||
end
|
||||
4'hB: begin
|
||||
IP_ENABLE <= 15'b000010000000000;
|
||||
JTDO2 <= ER2_TDO[10];
|
||||
end
|
||||
4'hC: begin
|
||||
IP_ENABLE <= 15'b000100000000000;
|
||||
JTDO2 <= ER2_TDO[11];
|
||||
end
|
||||
4'hD: begin
|
||||
IP_ENABLE <= 15'b001000000000000;
|
||||
JTDO2 <= ER2_TDO[12];
|
||||
end
|
||||
4'hE: begin
|
||||
IP_ENABLE <= 15'b010000000000000;
|
||||
JTDO2 <= ER2_TDO[13];
|
||||
end
|
||||
4'hF: begin
|
||||
IP_ENABLE <= 15'b100000000000000;
|
||||
JTDO2 <= ER2_TDO[14];
|
||||
end
|
||||
endcase
|
||||
end
|
||||
endmodule
|
213
lm32/logic/sakc/rtl/lm32/jtag_cores.v
Normal file
213
lm32/logic/sakc/rtl/lm32/jtag_cores.v
Normal file
@ -0,0 +1,213 @@
|
||||
// =============================================================================
|
||||
// COPYRIGHT NOTICE
|
||||
// Copyright 2006 (c) Lattice Semiconductor Corporation
|
||||
// ALL RIGHTS RESERVED
|
||||
// This confidential and proprietary software may be used only as authorised by
|
||||
// a licensing agreement from Lattice Semiconductor Corporation.
|
||||
// The entire notice above must be reproduced on all authorized copies and
|
||||
// copies may only be made to the extent permitted by a licensing agreement from
|
||||
// Lattice Semiconductor Corporation.
|
||||
//
|
||||
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
|
||||
// 5555 NE Moore Court 408-826-6000 (other locations)
|
||||
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
|
||||
// U.S.A email: techsupport@latticesemi.com
|
||||
// =============================================================================/
|
||||
// FILE DETAILS
|
||||
// Project : LatticeMico32
|
||||
// File : jtag_cores.v
|
||||
// Title : Instantiates all IP cores on JTAG chain.
|
||||
// Dependencies : system_conf.v
|
||||
// Version : 6.0.13
|
||||
// =============================================================================
|
||||
|
||||
`include "system_conf.v"
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Module interface
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
module jtag_cores (
|
||||
// ----- Inputs -------
|
||||
`ifdef INCLUDE_LM32
|
||||
reg_d,
|
||||
reg_addr_d,
|
||||
`endif
|
||||
`ifdef INCLUDE_SPI
|
||||
spi_q,
|
||||
`endif
|
||||
// ----- Outputs -------
|
||||
`ifdef INCLUDE_LM32
|
||||
reg_update,
|
||||
reg_q,
|
||||
reg_addr_q,
|
||||
`endif
|
||||
`ifdef INCLUDE_SPI
|
||||
spi_c,
|
||||
spi_d,
|
||||
spi_sn,
|
||||
`endif
|
||||
jtck,
|
||||
jrstn
|
||||
);
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Inputs
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
`ifdef INCLUDE_LM32
|
||||
input [7:0] reg_d;
|
||||
input [2:0] reg_addr_d;
|
||||
`endif
|
||||
|
||||
`ifdef INCLUDE_SPI
|
||||
input spi_q;
|
||||
`endif
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Outputs
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
`ifdef INCLUDE_LM32
|
||||
output reg_update;
|
||||
wire reg_update;
|
||||
output [7:0] reg_q;
|
||||
wire [7:0] reg_q;
|
||||
output [2:0] reg_addr_q;
|
||||
wire [2:0] reg_addr_q;
|
||||
`endif
|
||||
|
||||
`ifdef INCLUDE_SPI
|
||||
output spi_c;
|
||||
wire spi_c;
|
||||
output spi_d;
|
||||
wire spi_d;
|
||||
output spi_sn;
|
||||
wire spi_sn;
|
||||
`endif
|
||||
|
||||
output jtck;
|
||||
wire jtck; /* synthesis ER1_MARK="jtck" */ /* synthesis syn_keep=1 */
|
||||
output jrstn;
|
||||
wire jrstn; /* synthesis ER1_MARK="jrstn" */ /* synthesis syn_keep=1 */
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Internal nets and registers
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
wire rtiER1;
|
||||
wire rtiER2;
|
||||
wire tdi;/* synthesis ER1_MARK="jtdi" */ /* synthesis syn_keep=1 */
|
||||
wire tdoEr1;/* synthesis ER1_MARK="jtdo1" */ /* synthesis syn_keep=1 */
|
||||
wire tdoEr2;
|
||||
wire jtdo2_mux;/* synthesis ER1_MARK="jtdo2" */ /* synthesis syn_keep=1 */
|
||||
wire spi_tdo2;
|
||||
wire shiftDr;/* synthesis ER1_MARK="jshift" */ /* synthesis syn_keep=1 */
|
||||
wire updateDr;/* synthesis ER1_MARK="jupdate" */ /* synthesis syn_keep=1 */
|
||||
wire enableEr1;/* synthesis ER1_MARK="jce1" */ /* synthesis syn_keep=1 */
|
||||
wire enableEr2;/* synthesis ER1_MARK="jce2" */ /* synthesis syn_keep=1 */
|
||||
wire [14:0] ipEnable;/* synthesis ER1_MARK="ip_enable" */ /* synthesis syn_keep=1 */
|
||||
wire controlDataN;/* synthesis ER1_MARK="control_datan" */ /* synthesis syn_keep=1 */
|
||||
wire lm32_isptracy_enable;/* synthesis ER1_MARK="isptracy_enable" */ /* synthesis syn_keep=1 */
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Instantiations
|
||||
/////////////////////////////////////////////////////
|
||||
parameter lat_family = `LATTICE_FAMILY;
|
||||
|
||||
generate
|
||||
if (lat_family == "EC" || lat_family == "ECP" || lat_family == "XP") begin
|
||||
JTAGB jtagb (.JTCK (jtck),
|
||||
.JRTI1 (rtiER1),
|
||||
.JRTI2 (rtiER2),
|
||||
.JTDI (tdi),
|
||||
.JSHIFT (shiftDr),
|
||||
.JUPDATE (updateDr),
|
||||
.JRSTN (jrstn),
|
||||
.JCE1 (enableEr1),
|
||||
.JCE2 (enableEr2),
|
||||
.JTDO1 (tdoEr1),
|
||||
.JTDO2 (jtdo2_mux)) /* synthesis ER1="ENABLED" */ /* synthesis ER2="ENABLED" */ /* synthesis JTAG_FLASH_PRGRM="DISABLED" */;
|
||||
end else if (lat_family == "ECP2" || lat_family == "ECP2M") begin
|
||||
JTAGC jtagc (.JTCK (jtck),
|
||||
.JRTI1 (rtiER1),
|
||||
.JRTI2 (rtiER2),
|
||||
.JTDI (tdi),
|
||||
.JSHIFT (shiftDr),
|
||||
.JUPDATE (updateDr),
|
||||
.JRSTN (jrstn),
|
||||
.IJTAGEN (1'b1),
|
||||
.JCE1 (enableEr1),
|
||||
.JCE2 (enableEr2),
|
||||
.JTDO1 (tdoEr1),
|
||||
.JTDO2 (jtdo2_mux)) /* synthesis ER1="ENABLED" */ /* synthesis ER2="ENABLED" */ /* synthesis JTAG_FLASH_PRGRM="DISABLED" */;
|
||||
end else if (lat_family == "SC" || lat_family == "SCM") begin // if (lat_family == "ECP2" || lat_family == "ECP2M")
|
||||
JTAGA jtaga(.JTCK (jtck),
|
||||
.JRTI1 (rtiER1),
|
||||
.JRTI2 (rtiER2),
|
||||
.JTDI (tdi),
|
||||
.JSHIFT (shiftDr),
|
||||
.JUPDATE (updateDr),
|
||||
.JRSTN (jrstn),
|
||||
.JCE1 (enableEr1),
|
||||
.JCE2 (enableEr2),
|
||||
.JTDO1 (tdoEr1),
|
||||
.JTDO2 (jtdo2_mux)) /* synthesis ER1="ENABLED" */ /* synthesis ER2="ENABLED" */ /* synthesis JTAG_FLASH_PRGRM="DISABLED" */;
|
||||
end
|
||||
endgenerate
|
||||
|
||||
ER1 er1 (
|
||||
.JTCK (jtck),
|
||||
.JTDI (tdi),
|
||||
.JTDO1 (tdoEr1),
|
||||
.JTDO2 (jtdo2_mux),
|
||||
.JSHIFT (shiftDr),
|
||||
.JUPDATE (updateDr),
|
||||
.JRSTN (jrstn),
|
||||
.JCE1 (enableEr1),
|
||||
.ER2_TDO ({13'b0,tdoEr2,spi_tdo2}),
|
||||
.IP_ENABLE (ipEnable),
|
||||
.ISPTRACY_ENABLE(lm32_isptracy_enable),
|
||||
.ISPTRACY_ER2_TDO(lm32_isptracy_enable),
|
||||
.CONTROL_DATAN (controlDataN));
|
||||
|
||||
`ifdef INCLUDE_LM32
|
||||
jtag_lm32 jtag_lm32 (
|
||||
.JTCK (jtck),
|
||||
.JTDI (tdi),
|
||||
.JTDO2 (tdoEr2),
|
||||
.JSHIFT (shiftDr),
|
||||
.JUPDATE (updateDr),
|
||||
.JRSTN (jrstn),
|
||||
.JCE2 (enableEr2),
|
||||
.JTAGREG_ENABLE (ipEnable[1]),
|
||||
.CONTROL_DATAN (controlDataN),
|
||||
.REG_UPDATE (reg_update),
|
||||
.REG_D (reg_d),
|
||||
.REG_ADDR_D (reg_addr_d),
|
||||
.REG_Q (reg_q),
|
||||
.REG_ADDR_Q (reg_addr_q)
|
||||
);
|
||||
`endif
|
||||
|
||||
`ifdef INCLUDE_SPI
|
||||
SPIPROG spiprog_inst (
|
||||
.JTCK (tck),
|
||||
.JTDI (tdi),
|
||||
.JTDO2 (spi_tdo2),
|
||||
.JSHIFT (shiftDr),
|
||||
.JUPDATE (updateDr),
|
||||
.JRSTN (resetN),
|
||||
.JCE2 (enableEr2),
|
||||
.SPIPROG_ENABLE (ipEnable[0]),
|
||||
.CONTROL_DATAN (controlDataN),
|
||||
.SPI_C (spi_c),
|
||||
.SPI_D (spi_d),
|
||||
.SPI_SN (spi_sn),
|
||||
.SPI_Q (spi_q)
|
||||
);
|
||||
`endif
|
||||
|
||||
endmodule
|
195
lm32/logic/sakc/rtl/lm32/jtag_lm32.v
Normal file
195
lm32/logic/sakc/rtl/lm32/jtag_lm32.v
Normal file
@ -0,0 +1,195 @@
|
||||
// =============================================================================
|
||||
// COPYRIGHT NOTICE
|
||||
// Copyright 2006 (c) Lattice Semiconductor Corporation
|
||||
// ALL RIGHTS RESERVED
|
||||
// This confidential and proprietary software may be used only as authorised by
|
||||
// a licensing agreement from Lattice Semiconductor Corporation.
|
||||
// The entire notice above must be reproduced on all authorized copies and
|
||||
// copies may only be made to the extent permitted by a licensing agreement from
|
||||
// Lattice Semiconductor Corporation.
|
||||
//
|
||||
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
|
||||
// 5555 NE Moore Court 408-826-6000 (other locations)
|
||||
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
|
||||
// U.S.A email: techsupport@latticesemi.com
|
||||
// =============================================================================/
|
||||
// FILE DETAILS
|
||||
// Project : LatticeMico32
|
||||
// File : jtag_lm32.v
|
||||
// Title : JTAG data register for LM32 CPU debug interface
|
||||
// Version : 6.0.13
|
||||
// =============================================================================
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Module interface
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
module jtag_lm32 (
|
||||
input JTCK,
|
||||
input JTDI,
|
||||
output JTDO2,
|
||||
input JSHIFT,
|
||||
input JUPDATE,
|
||||
input JRSTN,
|
||||
input JCE2,
|
||||
input JTAGREG_ENABLE,
|
||||
input CONTROL_DATAN,
|
||||
output REG_UPDATE,
|
||||
input [7:0] REG_D,
|
||||
input [2:0] REG_ADDR_D,
|
||||
output [7:0] REG_Q,
|
||||
output [2:0] REG_ADDR_Q
|
||||
);
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Internal nets and registers
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
wire [9:0] tdibus;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Instantiations
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
TYPEA DATA_BIT0 (
|
||||
.CLK(JTCK),
|
||||
.RESET_N(JRSTN),
|
||||
.CLKEN(clk_enable),
|
||||
.TDI(JTDI),
|
||||
.TDO(tdibus[0]),
|
||||
.DATA_OUT(REG_Q[0]),
|
||||
.DATA_IN(REG_D[0]),
|
||||
.CAPTURE_DR(captureDr),
|
||||
.UPDATE_DR(JUPDATE)
|
||||
);
|
||||
|
||||
TYPEA DATA_BIT1 (
|
||||
.CLK(JTCK),
|
||||
.RESET_N(JRSTN),
|
||||
.CLKEN(clk_enable),
|
||||
.TDI(tdibus[0]),
|
||||
.TDO(tdibus[1]),
|
||||
.DATA_OUT(REG_Q[1]),
|
||||
.DATA_IN(REG_D[1]),
|
||||
.CAPTURE_DR(captureDr),
|
||||
.UPDATE_DR(JUPDATE)
|
||||
);
|
||||
|
||||
TYPEA DATA_BIT2 (
|
||||
.CLK(JTCK),
|
||||
.RESET_N(JRSTN),
|
||||
.CLKEN(clk_enable),
|
||||
.TDI(tdibus[1]),
|
||||
.TDO(tdibus[2]),
|
||||
.DATA_OUT(REG_Q[2]),
|
||||
.DATA_IN(REG_D[2]),
|
||||
.CAPTURE_DR(captureDr),
|
||||
.UPDATE_DR(JUPDATE)
|
||||
);
|
||||
|
||||
TYPEA DATA_BIT3 (
|
||||
.CLK(JTCK),
|
||||
.RESET_N(JRSTN),
|
||||
.CLKEN(clk_enable),
|
||||
.TDI(tdibus[2]),
|
||||
.TDO(tdibus[3]),
|
||||
.DATA_OUT(REG_Q[3]),
|
||||
.DATA_IN(REG_D[3]),
|
||||
.CAPTURE_DR(captureDr),
|
||||
.UPDATE_DR(JUPDATE)
|
||||
);
|
||||
|
||||
TYPEA DATA_BIT4 (
|
||||
.CLK(JTCK),
|
||||
.RESET_N(JRSTN),
|
||||
.CLKEN(clk_enable),
|
||||
.TDI(tdibus[3]),
|
||||
.TDO(tdibus[4]),
|
||||
.DATA_OUT(REG_Q[4]),
|
||||
.DATA_IN(REG_D[4]),
|
||||
.CAPTURE_DR(captureDr),
|
||||
.UPDATE_DR(JUPDATE)
|
||||
);
|
||||
|
||||
TYPEA DATA_BIT5 (
|
||||
.CLK(JTCK),
|
||||
.RESET_N(JRSTN),
|
||||
.CLKEN(clk_enable),
|
||||
.TDI(tdibus[4]),
|
||||
.TDO(tdibus[5]),
|
||||
.DATA_OUT(REG_Q[5]),
|
||||
.DATA_IN(REG_D[5]),
|
||||
.CAPTURE_DR(captureDr),
|
||||
.UPDATE_DR(JUPDATE)
|
||||
);
|
||||
|
||||
TYPEA DATA_BIT6 (
|
||||
.CLK(JTCK),
|
||||
.RESET_N(JRSTN),
|
||||
.CLKEN(clk_enable),
|
||||
.TDI(tdibus[5]),
|
||||
.TDO(tdibus[6]),
|
||||
.DATA_OUT(REG_Q[6]),
|
||||
.DATA_IN(REG_D[6]),
|
||||
.CAPTURE_DR(captureDr),
|
||||
.UPDATE_DR(JUPDATE)
|
||||
);
|
||||
|
||||
TYPEA DATA_BIT7 (
|
||||
.CLK(JTCK),
|
||||
.RESET_N(JRSTN),
|
||||
.CLKEN(clk_enable),
|
||||
.TDI(tdibus[6]),
|
||||
.TDO(tdibus[7]),
|
||||
.DATA_OUT(REG_Q[7]),
|
||||
.DATA_IN(REG_D[7]),
|
||||
.CAPTURE_DR(captureDr),
|
||||
.UPDATE_DR(JUPDATE)
|
||||
);
|
||||
|
||||
TYPEA ADDR_BIT0 (
|
||||
.CLK(JTCK),
|
||||
.RESET_N(JRSTN),
|
||||
.CLKEN(clk_enable),
|
||||
.TDI(tdibus[7]),
|
||||
.TDO(tdibus[8]),
|
||||
.DATA_OUT(REG_ADDR_Q[0]),
|
||||
.DATA_IN(REG_ADDR_D[0]),
|
||||
.CAPTURE_DR(captureDr),
|
||||
.UPDATE_DR(JUPDATE)
|
||||
);
|
||||
|
||||
TYPEA ADDR_BIT1 (
|
||||
.CLK(JTCK),
|
||||
.RESET_N(JRSTN),
|
||||
.CLKEN(clk_enable),
|
||||
.TDI(tdibus[8]),
|
||||
.TDO(tdibus[9]),
|
||||
.DATA_OUT(REG_ADDR_Q[1]),
|
||||
.DATA_IN(REG_ADDR_D[1]),
|
||||
.CAPTURE_DR(captureDr),
|
||||
.UPDATE_DR(JUPDATE)
|
||||
);
|
||||
|
||||
TYPEA ADDR_BIT2 (
|
||||
.CLK(JTCK),
|
||||
.RESET_N(JRSTN),
|
||||
.CLKEN(clk_enable),
|
||||
.TDI(tdibus[9]),
|
||||
.TDO(JTDO2),
|
||||
.DATA_OUT(REG_ADDR_Q[2]),
|
||||
.DATA_IN(REG_ADDR_D[2]),
|
||||
.CAPTURE_DR(captureDr),
|
||||
.UPDATE_DR(JUPDATE)
|
||||
);
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Combinational logic
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
assign clk_enable = JTAGREG_ENABLE & JCE2;
|
||||
assign captureDr = !JSHIFT & JCE2;
|
||||
// JCE2 is only active during shift
|
||||
assign REG_UPDATE = JTAGREG_ENABLE & JUPDATE;
|
||||
|
||||
endmodule
|
110
lm32/logic/sakc/rtl/lm32/lm32_adder.v
Normal file
110
lm32/logic/sakc/rtl/lm32/lm32_adder.v
Normal file
@ -0,0 +1,110 @@
|
||||
// =============================================================================
|
||||
// COPYRIGHT NOTICE
|
||||
// Copyright 2006 (c) Lattice Semiconductor Corporation
|
||||
// ALL RIGHTS RESERVED
|
||||
// This confidential and proprietary software may be used only as authorised by
|
||||
// a licensing agreement from Lattice Semiconductor Corporation.
|
||||
// The entire notice above must be reproduced on all authorized copies and
|
||||
// copies may only be made to the extent permitted by a licensing agreement from
|
||||
// Lattice Semiconductor Corporation.
|
||||
//
|
||||
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
|
||||
// 5555 NE Moore Court 408-826-6000 (other locations)
|
||||
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
|
||||
// U.S.A email: techsupport@latticesemi.com
|
||||
// ============================================================================/
|
||||
// FILE DETAILS
|
||||
// Project : LatticeMico32
|
||||
// File : lm32_adder.v
|
||||
// Title : Integer adder / subtractor with comparison flag generation
|
||||
// Dependencies : lm32_include.v
|
||||
// Version : 6.1.17
|
||||
// =============================================================================
|
||||
|
||||
`include "lm32_include.v"
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Module interface
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
module lm32_adder (
|
||||
// ----- Inputs -------
|
||||
adder_op_x,
|
||||
adder_op_x_n,
|
||||
operand_0_x,
|
||||
operand_1_x,
|
||||
// ----- Outputs -------
|
||||
adder_result_x,
|
||||
adder_carry_n_x,
|
||||
adder_overflow_x
|
||||
);
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Inputs
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
input adder_op_x; // Operating to perform, 0 for addition, 1 for subtraction
|
||||
input adder_op_x_n; // Inverted version of adder_op_x
|
||||
input [`LM32_WORD_RNG] operand_0_x; // Operand to add, or subtract from
|
||||
input [`LM32_WORD_RNG] operand_1_x; // Opearnd to add, or subtract by
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Outputs
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
output [`LM32_WORD_RNG] adder_result_x; // Result of addition or subtraction
|
||||
wire [`LM32_WORD_RNG] adder_result_x;
|
||||
output adder_carry_n_x; // Inverted carry
|
||||
wire adder_carry_n_x;
|
||||
output adder_overflow_x; // Indicates if overflow occured, only valid for subtractions
|
||||
reg adder_overflow_x;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Internal nets and registers
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
wire a_sign; // Sign (i.e. positive or negative) of operand 0
|
||||
wire b_sign; // Sign of operand 1
|
||||
wire result_sign; // Sign of result
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Instantiations
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
lm32_addsub addsub (
|
||||
// ----- Inputs -----
|
||||
.DataA (operand_0_x),
|
||||
.DataB (operand_1_x),
|
||||
.Cin (adder_op_x),
|
||||
.Add_Sub (adder_op_x_n),
|
||||
// ----- Ouputs -----
|
||||
.Result (adder_result_x),
|
||||
.Cout (adder_carry_n_x)
|
||||
);
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Combinational Logic
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
// Extract signs of operands and result
|
||||
|
||||
assign a_sign = operand_0_x[`LM32_WORD_WIDTH-1];
|
||||
assign b_sign = operand_1_x[`LM32_WORD_WIDTH-1];
|
||||
assign result_sign = adder_result_x[`LM32_WORD_WIDTH-1];
|
||||
|
||||
// Determine whether an overflow occured when performing a subtraction
|
||||
|
||||
always @*
|
||||
begin
|
||||
// +ve - -ve = -ve -> overflow
|
||||
// -ve - +ve = +ve -> overflow
|
||||
if ( (!a_sign & b_sign & result_sign)
|
||||
|| (a_sign & !b_sign & !result_sign)
|
||||
)
|
||||
adder_overflow_x = `TRUE;
|
||||
else
|
||||
adder_overflow_x = `FALSE;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
69
lm32/logic/sakc/rtl/lm32/lm32_addsub.v
Normal file
69
lm32/logic/sakc/rtl/lm32/lm32_addsub.v
Normal file
@ -0,0 +1,69 @@
|
||||
// =============================================================================
|
||||
// COPYRIGHT NOTICE
|
||||
// Copyright 2006 (c) Lattice Semiconductor Corporation
|
||||
// ALL RIGHTS RESERVED
|
||||
// This confidential and proprietary software may be used only as authorised by
|
||||
// a licensing agreement from Lattice Semiconductor Corporation.
|
||||
// The entire notice above must be reproduced on all authorized copies and
|
||||
// copies may only be made to the extent permitted by a licensing agreement from
|
||||
// Lattice Semiconductor Corporation.
|
||||
//
|
||||
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
|
||||
// 5555 NE Moore Court 408-826-6000 (other locations)
|
||||
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
|
||||
// U.S.A email: techsupport@latticesemi.com
|
||||
// =============================================================================/
|
||||
// FILE DETAILS
|
||||
// Project : LatticeMico32
|
||||
// File : lm32_addsub.v
|
||||
// Title : PMI adder/subtractor.
|
||||
// Version : 6.1.17
|
||||
// =============================================================================
|
||||
|
||||
`include "lm32_include.v"
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Module interface
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
module lm32_addsub (
|
||||
// ----- Inputs -------
|
||||
DataA,
|
||||
DataB,
|
||||
Cin,
|
||||
Add_Sub,
|
||||
// ----- Outputs -------
|
||||
Result,
|
||||
Cout
|
||||
);
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Inputs
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
input [31:0] DataA;
|
||||
input [31:0] DataB;
|
||||
input Cin;
|
||||
input Add_Sub;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Outputs
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
output [31:0] Result;
|
||||
wire [31:0] Result;
|
||||
output Cout;
|
||||
wire Cout;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Instantiations
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
wire [32:0] tmp_addResult = DataA + DataB + Cin;
|
||||
wire [32:0] tmp_subResult = DataA - DataB - !Cin;
|
||||
|
||||
assign Result = (Add_Sub == 1) ? tmp_addResult[31:0] : tmp_subResult[31:0];
|
||||
assign Cout = (Add_Sub == 1) ? tmp_addResult[32] : !tmp_subResult[32];
|
||||
|
||||
|
||||
endmodule
|
2304
lm32/logic/sakc/rtl/lm32/lm32_cpu.v
Normal file
2304
lm32/logic/sakc/rtl/lm32/lm32_cpu.v
Normal file
File diff suppressed because it is too large
Load Diff
494
lm32/logic/sakc/rtl/lm32/lm32_dcache.v
Normal file
494
lm32/logic/sakc/rtl/lm32/lm32_dcache.v
Normal file
@ -0,0 +1,494 @@
|
||||
// =============================================================================
|
||||
// COPYRIGHT NOTICE
|
||||
// Copyright 2006 (c) Lattice Semiconductor Corporation
|
||||
// ALL RIGHTS RESERVED
|
||||
// This confidential and proprietary software may be used only as authorised by
|
||||
// a licensing agreement from Lattice Semiconductor Corporation.
|
||||
// The entire notice above must be reproduced on all authorized copies and
|
||||
// copies may only be made to the extent permitted by a licensing agreement from
|
||||
// Lattice Semiconductor Corporation.
|
||||
//
|
||||
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
|
||||
// 5555 NE Moore Court 408-826-6000 (other locations)
|
||||
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
|
||||
// U.S.A email: techsupport@latticesemi.com
|
||||
// =============================================================================/
|
||||
// FILE DETAILS
|
||||
// Project : LatticeMico32
|
||||
// File : lm32_dcache.v
|
||||
// Title : Data cache
|
||||
// Dependencies : lm32_include.v
|
||||
// Version : 6.1.17
|
||||
// =============================================================================
|
||||
|
||||
`include "lm32_include.v"
|
||||
|
||||
`ifdef CFG_DCACHE_ENABLED
|
||||
|
||||
`define LM32_DC_ADDR_OFFSET_RNG addr_offset_msb:addr_offset_lsb
|
||||
`define LM32_DC_ADDR_SET_RNG addr_set_msb:addr_set_lsb
|
||||
`define LM32_DC_ADDR_TAG_RNG addr_tag_msb:addr_tag_lsb
|
||||
`define LM32_DC_ADDR_IDX_RNG addr_set_msb:addr_offset_lsb
|
||||
|
||||
`define LM32_DC_TMEM_ADDR_WIDTH addr_set_width
|
||||
`define LM32_DC_TMEM_ADDR_RNG (`LM32_DC_TMEM_ADDR_WIDTH-1):0
|
||||
`define LM32_DC_DMEM_ADDR_WIDTH (addr_offset_width+addr_set_width)
|
||||
`define LM32_DC_DMEM_ADDR_RNG (`LM32_DC_DMEM_ADDR_WIDTH-1):0
|
||||
|
||||
`define LM32_DC_TAGS_WIDTH (addr_tag_width+1)
|
||||
`define LM32_DC_TAGS_RNG (`LM32_DC_TAGS_WIDTH-1):0
|
||||
`define LM32_DC_TAGS_TAG_RNG (`LM32_DC_TAGS_WIDTH-1):1
|
||||
`define LM32_DC_TAGS_VALID_RNG 0
|
||||
|
||||
`define LM32_DC_STATE_RNG 2:0
|
||||
`define LM32_DC_STATE_FLUSH 3'b001
|
||||
`define LM32_DC_STATE_CHECK 3'b010
|
||||
`define LM32_DC_STATE_REFILL 3'b100
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Module interface
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
module lm32_dcache (
|
||||
// ----- Inputs -----
|
||||
clk_i,
|
||||
rst_i,
|
||||
stall_a,
|
||||
stall_x,
|
||||
stall_m,
|
||||
address_x,
|
||||
address_m,
|
||||
load_q_m,
|
||||
store_q_m,
|
||||
store_data,
|
||||
store_byte_select,
|
||||
refill_ready,
|
||||
refill_data,
|
||||
dflush,
|
||||
// ----- Outputs -----
|
||||
stall_request,
|
||||
restart_request,
|
||||
refill_request,
|
||||
refill_address,
|
||||
refilling,
|
||||
load_data
|
||||
);
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Parameters
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
parameter associativity = 1; // Associativity of the cache (Number of ways)
|
||||
parameter sets = 512; // Number of sets
|
||||
parameter bytes_per_line = 16; // Number of bytes per cache line
|
||||
parameter base_address = 0; // Base address of cachable memory
|
||||
parameter limit = 0; // Limit (highest address) of cachable memory
|
||||
|
||||
//localparam addr_offset_width = clogb2(bytes_per_line)-1-2;
|
||||
localparam addr_offset_width = 2;
|
||||
//localparam addr_set_width = clogb2(sets)-1;
|
||||
localparam addr_set_width = 9;
|
||||
localparam addr_offset_lsb = 2;
|
||||
localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1);
|
||||
localparam addr_set_lsb = (addr_offset_msb+1);
|
||||
localparam addr_set_msb = (addr_set_lsb+addr_set_width-1);
|
||||
localparam addr_tag_lsb = (addr_set_msb+1);
|
||||
localparam addr_tag_msb = 31;
|
||||
localparam addr_tag_width = (addr_tag_msb-addr_tag_lsb+1);
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Inputs
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
input clk_i; // Clock
|
||||
input rst_i; // Reset
|
||||
|
||||
input stall_a; // Stall A stage
|
||||
input stall_x; // Stall X stage
|
||||
input stall_m; // Stall M stage
|
||||
|
||||
input [`LM32_WORD_RNG] address_x; // X stage load/store address
|
||||
input [`LM32_WORD_RNG] address_m; // M stage load/store address
|
||||
input load_q_m; // Load instruction in M stage
|
||||
input store_q_m; // Store instruction in M stage
|
||||
input [`LM32_WORD_RNG] store_data; // Data to store
|
||||
input [`LM32_BYTE_SELECT_RNG] store_byte_select; // Which bytes in store data should be modified
|
||||
|
||||
input refill_ready; // Indicates next word of refill data is ready
|
||||
input [`LM32_WORD_RNG] refill_data; // Refill data
|
||||
|
||||
input dflush; // Indicates cache should be flushed
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Outputs
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
output stall_request; // Request pipeline be stalled because cache is busy
|
||||
wire stall_request;
|
||||
output restart_request; // Request to restart instruction that caused the cache miss
|
||||
reg restart_request;
|
||||
output refill_request; // Request a refill
|
||||
reg refill_request;
|
||||
output [`LM32_WORD_RNG] refill_address; // Address to refill from
|
||||
reg [`LM32_WORD_RNG] refill_address;
|
||||
output refilling; // Indicates if the cache is currently refilling
|
||||
reg refilling;
|
||||
output [`LM32_WORD_RNG] load_data; // Data read from cache
|
||||
wire [`LM32_WORD_RNG] load_data;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Internal nets and registers
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
wire read_port_enable; // Cache memory read port clock enable
|
||||
wire write_port_enable; // Cache memory write port clock enable
|
||||
wire [0:associativity-1] way_tmem_we; // Tag memory write enable
|
||||
wire [0:associativity-1] way_dmem_we; // Data memory write enable
|
||||
wire [`LM32_WORD_RNG] way_data[0:associativity-1]; // Data read from data memory
|
||||
wire [`LM32_DC_TAGS_TAG_RNG] way_tag[0:associativity-1];// Tag read from tag memory
|
||||
wire [0:associativity-1] way_valid; // Indicates which ways are valid
|
||||
wire [0:associativity-1] way_match; // Indicates which ways matched
|
||||
wire miss; // Indicates no ways matched
|
||||
|
||||
wire [`LM32_DC_TMEM_ADDR_RNG] tmem_read_address; // Tag memory read address
|
||||
wire [`LM32_DC_TMEM_ADDR_RNG] tmem_write_address; // Tag memory write address
|
||||
wire [`LM32_DC_DMEM_ADDR_RNG] dmem_read_address; // Data memory read address
|
||||
wire [`LM32_DC_DMEM_ADDR_RNG] dmem_write_address; // Data memory write address
|
||||
wire [`LM32_DC_TAGS_RNG] tmem_write_data; // Tag memory write data
|
||||
reg [`LM32_WORD_RNG] dmem_write_data; // Data memory write data
|
||||
|
||||
reg [`LM32_DC_STATE_RNG] state; // Current state of FSM
|
||||
wire flushing; // Indicates if cache is currently flushing
|
||||
wire check; // Indicates if cache is currently checking for hits/misses
|
||||
wire refill; // Indicates if cache is currently refilling
|
||||
|
||||
wire valid_store; // Indicates if there is a valid store instruction
|
||||
reg [associativity-1:0] refill_way_select; // Which way should be refilled
|
||||
reg [`LM32_DC_ADDR_OFFSET_RNG] refill_offset; // Which word in cache line should be refilled
|
||||
wire last_refill; // Indicates when on last cycle of cache refill
|
||||
reg [`LM32_DC_TMEM_ADDR_RNG] flush_set; // Which set is currently being flushed
|
||||
|
||||
genvar i, j;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Functions
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
`include "lm32_functions.v"
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Instantiations
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
generate
|
||||
for (i = 0; i < associativity; i = i + 1)
|
||||
begin : memories
|
||||
// Way data
|
||||
|
||||
if (`LM32_DC_DMEM_ADDR_WIDTH < 7)
|
||||
begin : data_memories
|
||||
lm32_ram #(
|
||||
// ----- Parameters -------
|
||||
.data_width (32),
|
||||
.address_width (`LM32_DC_DMEM_ADDR_WIDTH)
|
||||
) way_0_data_ram (
|
||||
// ----- Inputs -------
|
||||
.read_clk (clk_i),
|
||||
.write_clk (clk_i),
|
||||
.reset (rst_i),
|
||||
.read_address (dmem_read_address),
|
||||
.enable_read (read_port_enable),
|
||||
.write_address (dmem_write_address),
|
||||
.enable_write (write_port_enable),
|
||||
.write_enable (way_dmem_we[i]),
|
||||
.write_data (dmem_write_data),
|
||||
// ----- Outputs -------
|
||||
.read_data (way_data[i])
|
||||
);
|
||||
end
|
||||
else
|
||||
begin
|
||||
for (j = 0; j < 4; j = j + 1)
|
||||
begin : byte_memories
|
||||
lm32_ram #(
|
||||
// ----- Parameters -------
|
||||
.data_width (8),
|
||||
.address_width (`LM32_DC_DMEM_ADDR_WIDTH)
|
||||
) way_0_data_ram (
|
||||
// ----- Inputs -------
|
||||
.read_clk (clk_i),
|
||||
.write_clk (clk_i),
|
||||
.reset (rst_i),
|
||||
.read_address (dmem_read_address),
|
||||
.enable_read (read_port_enable),
|
||||
.write_address (dmem_write_address),
|
||||
.enable_write (write_port_enable),
|
||||
.write_enable (way_dmem_we[i] & (store_byte_select[j] | refill)),
|
||||
.write_data (dmem_write_data[(j+1)*8-1:j*8]),
|
||||
// ----- Outputs -------
|
||||
.read_data (way_data[i][(j+1)*8-1:j*8])
|
||||
);
|
||||
end
|
||||
end
|
||||
|
||||
// Way tags
|
||||
lm32_ram #(
|
||||
// ----- Parameters -------
|
||||
.data_width (`LM32_DC_TAGS_WIDTH),
|
||||
.address_width (`LM32_DC_TMEM_ADDR_WIDTH)
|
||||
) way_0_tag_ram (
|
||||
// ----- Inputs -------
|
||||
.read_clk (clk_i),
|
||||
.write_clk (clk_i),
|
||||
.reset (rst_i),
|
||||
.read_address (tmem_read_address),
|
||||
.enable_read (read_port_enable),
|
||||
.write_address (tmem_write_address),
|
||||
.enable_write (`TRUE),
|
||||
.write_enable (way_tmem_we[i]),
|
||||
.write_data (tmem_write_data),
|
||||
// ----- Outputs -------
|
||||
.read_data ({way_tag[i], way_valid[i]})
|
||||
);
|
||||
|
||||
end
|
||||
|
||||
endgenerate
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Combinational logic
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
// Compute which ways in the cache match the address being read
|
||||
generate
|
||||
for (i = 0; i < associativity; i = i + 1)
|
||||
begin : match
|
||||
assign way_match[i] = ({way_tag[i], way_valid[i]} == {address_m[`LM32_DC_ADDR_TAG_RNG], `TRUE});
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// Select data from way that matched the address being read
|
||||
generate
|
||||
if (associativity == 1)
|
||||
begin : data_1
|
||||
assign load_data = way_data[0];
|
||||
end
|
||||
else if (associativity == 2)
|
||||
begin : data_2
|
||||
assign load_data = way_match[0] ? way_data[0] : way_data[1];
|
||||
end
|
||||
endgenerate
|
||||
|
||||
generate
|
||||
if (`LM32_DC_DMEM_ADDR_WIDTH < 7)
|
||||
begin
|
||||
// Select data to write to data memories
|
||||
always @(*)
|
||||
begin
|
||||
if (refill == `TRUE)
|
||||
dmem_write_data = refill_data;
|
||||
else
|
||||
begin
|
||||
dmem_write_data[`LM32_BYTE_0_RNG] = store_byte_select[0] ? store_data[`LM32_BYTE_0_RNG] : load_data[`LM32_BYTE_0_RNG];
|
||||
dmem_write_data[`LM32_BYTE_1_RNG] = store_byte_select[1] ? store_data[`LM32_BYTE_1_RNG] : load_data[`LM32_BYTE_1_RNG];
|
||||
dmem_write_data[`LM32_BYTE_2_RNG] = store_byte_select[2] ? store_data[`LM32_BYTE_2_RNG] : load_data[`LM32_BYTE_2_RNG];
|
||||
dmem_write_data[`LM32_BYTE_3_RNG] = store_byte_select[3] ? store_data[`LM32_BYTE_3_RNG] : load_data[`LM32_BYTE_3_RNG];
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
begin
|
||||
// Select data to write to data memories - FIXME: Should use different write ports on dual port RAMs, but they don't work
|
||||
always @(*)
|
||||
begin
|
||||
if (refill == `TRUE)
|
||||
dmem_write_data = refill_data;
|
||||
else
|
||||
dmem_write_data = store_data;
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// Compute address to use to index into the data memories
|
||||
generate
|
||||
if (bytes_per_line > 4)
|
||||
assign dmem_write_address = (refill == `TRUE)
|
||||
? {refill_address[`LM32_DC_ADDR_SET_RNG], refill_offset}
|
||||
: address_m[`LM32_DC_ADDR_IDX_RNG];
|
||||
else
|
||||
assign dmem_write_address = (refill == `TRUE)
|
||||
? refill_address[`LM32_DC_ADDR_SET_RNG]
|
||||
: address_m[`LM32_DC_ADDR_IDX_RNG];
|
||||
endgenerate
|
||||
assign dmem_read_address = address_x[`LM32_DC_ADDR_IDX_RNG];
|
||||
// Compute address to use to index into the tag memories
|
||||
assign tmem_write_address = (flushing == `TRUE)
|
||||
? flush_set
|
||||
: refill_address[`LM32_DC_ADDR_SET_RNG];
|
||||
assign tmem_read_address = address_x[`LM32_DC_ADDR_SET_RNG];
|
||||
|
||||
// Compute signal to indicate when we are on the last refill accesses
|
||||
generate
|
||||
if (bytes_per_line > 4)
|
||||
assign last_refill = refill_offset == {addr_offset_width{1'b1}};
|
||||
else
|
||||
assign last_refill = `TRUE;
|
||||
endgenerate
|
||||
|
||||
// Compute data and tag memory access enable
|
||||
assign read_port_enable = (stall_x == `FALSE);
|
||||
assign write_port_enable = (refill_ready == `TRUE) || !stall_m;
|
||||
|
||||
// Determine when we have a valid store
|
||||
assign valid_store = (store_q_m == `TRUE) && (check == `TRUE);
|
||||
|
||||
// Compute data and tag memory write enables
|
||||
generate
|
||||
if (associativity == 1)
|
||||
begin : we_1
|
||||
assign way_dmem_we[0] = (refill_ready == `TRUE) || ((valid_store == `TRUE) && (way_match[0] == `TRUE));
|
||||
assign way_tmem_we[0] = (refill_ready == `TRUE) || (flushing == `TRUE);
|
||||
end
|
||||
else
|
||||
begin : we_2
|
||||
assign way_dmem_we[0] = ((refill_ready == `TRUE) && (refill_way_select[0] == `TRUE)) || ((valid_store == `TRUE) && (way_match[0] == `TRUE));
|
||||
assign way_dmem_we[1] = ((refill_ready == `TRUE) && (refill_way_select[1] == `TRUE)) || ((valid_store == `TRUE) && (way_match[1] == `TRUE));
|
||||
assign way_tmem_we[0] = ((refill_ready == `TRUE) && (refill_way_select[0] == `TRUE)) || (flushing == `TRUE);
|
||||
assign way_tmem_we[1] = ((refill_ready == `TRUE) && (refill_way_select[1] == `TRUE)) || (flushing == `TRUE);
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// On the last refill cycle set the valid bit, for all other writes it should be cleared
|
||||
assign tmem_write_data[`LM32_DC_TAGS_VALID_RNG] = ((last_refill == `TRUE) || (valid_store == `TRUE)) && (flushing == `FALSE);
|
||||
assign tmem_write_data[`LM32_DC_TAGS_TAG_RNG] = refill_address[`LM32_DC_ADDR_TAG_RNG];
|
||||
|
||||
// Signals that indicate which state we are in
|
||||
assign flushing = state[0];
|
||||
assign check = state[1];
|
||||
assign refill = state[2];
|
||||
|
||||
assign miss = (~(|way_match)) && (load_q_m == `TRUE) && (stall_m == `FALSE);
|
||||
assign stall_request = (check == `FALSE);
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Sequential logic
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
// Record way selected for replacement on a cache miss
|
||||
generate
|
||||
if (associativity >= 2)
|
||||
begin : way_select
|
||||
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
|
||||
begin
|
||||
if (rst_i == `TRUE)
|
||||
refill_way_select <= {{associativity-1{1'b0}}, 1'b1};
|
||||
else
|
||||
begin
|
||||
if (refill_request == `TRUE)
|
||||
refill_way_select <= {refill_way_select[0], refill_way_select[1]};
|
||||
end
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// Record whether we are currently refilling
|
||||
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
|
||||
begin
|
||||
if (rst_i == `TRUE)
|
||||
refilling <= `FALSE;
|
||||
else
|
||||
refilling <= refill;
|
||||
end
|
||||
|
||||
// Instruction cache control FSM
|
||||
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
|
||||
begin
|
||||
if (rst_i == `TRUE)
|
||||
begin
|
||||
state <= `LM32_DC_STATE_FLUSH;
|
||||
flush_set <= {`LM32_DC_TMEM_ADDR_WIDTH{1'b1}};
|
||||
refill_request <= `FALSE;
|
||||
refill_address <= {`LM32_WORD_WIDTH{1'bx}};
|
||||
restart_request <= `FALSE;
|
||||
end
|
||||
else
|
||||
begin
|
||||
case (state)
|
||||
|
||||
// Flush the cache
|
||||
`LM32_DC_STATE_FLUSH:
|
||||
begin
|
||||
if (flush_set == {`LM32_DC_TMEM_ADDR_WIDTH{1'b0}})
|
||||
state <= `LM32_DC_STATE_CHECK;
|
||||
flush_set <= flush_set - 1'b1;
|
||||
end
|
||||
|
||||
// Check for cache misses
|
||||
`LM32_DC_STATE_CHECK:
|
||||
begin
|
||||
if (stall_a == `FALSE)
|
||||
restart_request <= `FALSE;
|
||||
if (miss == `TRUE)
|
||||
begin
|
||||
refill_request <= `TRUE;
|
||||
refill_address <= address_m;
|
||||
state <= `LM32_DC_STATE_REFILL;
|
||||
end
|
||||
else if (dflush == `TRUE)
|
||||
state <= `LM32_DC_STATE_FLUSH;
|
||||
end
|
||||
|
||||
// Refill a cache line
|
||||
`LM32_DC_STATE_REFILL:
|
||||
begin
|
||||
refill_request <= `FALSE;
|
||||
if (refill_ready == `TRUE)
|
||||
begin
|
||||
if (last_refill == `TRUE)
|
||||
begin
|
||||
restart_request <= `TRUE;
|
||||
state <= `LM32_DC_STATE_CHECK;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
generate
|
||||
if (bytes_per_line > 4)
|
||||
begin
|
||||
// Refill offset
|
||||
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
|
||||
begin
|
||||
if (rst_i == `TRUE)
|
||||
refill_offset <= {addr_offset_width{1'b0}};
|
||||
else
|
||||
begin
|
||||
case (state)
|
||||
|
||||
// Check for cache misses
|
||||
`LM32_DC_STATE_CHECK:
|
||||
begin
|
||||
if (miss == `TRUE)
|
||||
refill_offset <= {addr_offset_width{1'b0}};
|
||||
end
|
||||
|
||||
// Refill a cache line
|
||||
`LM32_DC_STATE_REFILL:
|
||||
begin
|
||||
if (refill_ready == `TRUE)
|
||||
refill_offset <= refill_offset + 1'b1;
|
||||
end
|
||||
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
endmodule
|
||||
|
||||
`endif
|
||||
|
340
lm32/logic/sakc/rtl/lm32/lm32_debug.v
Normal file
340
lm32/logic/sakc/rtl/lm32/lm32_debug.v
Normal file
@ -0,0 +1,340 @@
|
||||
// =============================================================================
|
||||
// COPYRIGHT NOTICE
|
||||
// Copyright 2006 (c) Lattice Semiconductor Corporation
|
||||
// ALL RIGHTS RESERVED
|
||||
// This confidential and proprietary software may be used only as authorised by
|
||||
// a licensing agreement from Lattice Semiconductor Corporation.
|
||||
// The entire notice above must be reproduced on all authorized copies and
|
||||
// copies may only be made to the extent permitted by a licensing agreement from
|
||||
// Lattice Semiconductor Corporation.
|
||||
//
|
||||
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
|
||||
// 5555 NE Moore Court 408-826-6000 (other locations)
|
||||
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
|
||||
// U.S.A email: techsupport@latticesemi.com
|
||||
// =============================================================================/
|
||||
// FILE DETAILS
|
||||
// Project : LatticeMico32
|
||||
// File : lm32_debug.v
|
||||
// Title : Hardware debug registers and associated logic.
|
||||
// Dependencies : lm32_include.v
|
||||
// Version : 6.1.17
|
||||
// =============================================================================
|
||||
|
||||
`include "lm32_include.v"
|
||||
|
||||
`ifdef CFG_DEBUG_ENABLED
|
||||
|
||||
// States for single-step FSM
|
||||
`define LM32_DEBUG_SS_STATE_RNG 2:0
|
||||
`define LM32_DEBUG_SS_STATE_IDLE 3'b000
|
||||
`define LM32_DEBUG_SS_STATE_WAIT_FOR_RET 3'b001
|
||||
`define LM32_DEBUG_SS_STATE_EXECUTE_ONE_INSN 3'b010
|
||||
`define LM32_DEBUG_SS_STATE_RAISE_BREAKPOINT 3'b011
|
||||
`define LM32_DEBUG_SS_STATE_RESTART 3'b100
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Module interface
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
module lm32_debug (
|
||||
// ----- Inputs -------
|
||||
clk_i,
|
||||
rst_i,
|
||||
pc_x,
|
||||
load_x,
|
||||
store_x,
|
||||
load_store_address_x,
|
||||
csr_write_enable_x,
|
||||
csr_write_data,
|
||||
csr_x,
|
||||
`ifdef CFG_HW_DEBUG_ENABLED
|
||||
jtag_csr_write_enable,
|
||||
jtag_csr_write_data,
|
||||
jtag_csr,
|
||||
`endif
|
||||
`ifdef LM32_SINGLE_STEP_ENABLED
|
||||
eret_q_x,
|
||||
bret_q_x,
|
||||
stall_x,
|
||||
exception_x,
|
||||
q_x,
|
||||
`ifdef CFG_DCACHE_ENABLED
|
||||
dcache_refill_request,
|
||||
`endif
|
||||
`endif
|
||||
// ----- Outputs -------
|
||||
`ifdef LM32_SINGLE_STEP_ENABLED
|
||||
dc_ss,
|
||||
`endif
|
||||
dc_re,
|
||||
bp_match,
|
||||
wp_match
|
||||
);
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Parameters
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
parameter breakpoints = 0; // Number of breakpoint CSRs
|
||||
parameter watchpoints = 0; // Number of watchpoint CSRs
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Inputs
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
input clk_i; // Clock
|
||||
input rst_i; // Reset
|
||||
|
||||
input [`LM32_PC_RNG] pc_x; // X stage PC
|
||||
input load_x; // Load instruction in X stage
|
||||
input store_x; // Store instruction in X stage
|
||||
input [`LM32_WORD_RNG] load_store_address_x; // Load or store effective address
|
||||
input csr_write_enable_x; // wcsr instruction in X stage
|
||||
input [`LM32_WORD_RNG] csr_write_data; // Data to write to CSR
|
||||
input [`LM32_CSR_RNG] csr_x; // Which CSR to write
|
||||
`ifdef CFG_HW_DEBUG_ENABLED
|
||||
input jtag_csr_write_enable; // JTAG interface CSR write enable
|
||||
input [`LM32_WORD_RNG] jtag_csr_write_data; // Data to write to CSR
|
||||
input [`LM32_CSR_RNG] jtag_csr; // Which CSR to write
|
||||
`endif
|
||||
`ifdef LM32_SINGLE_STEP_ENABLED
|
||||
input eret_q_x; // eret instruction in X stage
|
||||
input bret_q_x; // bret instruction in X stage
|
||||
input stall_x; // Instruction in X stage is stalled
|
||||
input exception_x; // An exception has occured in X stage
|
||||
input q_x; // Indicates the instruction in the X stage is qualified
|
||||
`ifdef CFG_DCACHE_ENABLED
|
||||
input dcache_refill_request; // Indicates data cache wants to be refilled
|
||||
`endif
|
||||
`endif
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Outputs
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
`ifdef LM32_SINGLE_STEP_ENABLED
|
||||
output dc_ss; // Single-step enable
|
||||
reg dc_ss;
|
||||
`endif
|
||||
output dc_re; // Remap exceptions
|
||||
reg dc_re;
|
||||
output bp_match; // Indicates a breakpoint has matched
|
||||
wire bp_match;
|
||||
output wp_match; // Indicates a watchpoint has matched
|
||||
wire wp_match;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Internal nets and registers
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
genvar i; // Loop index for generate statements
|
||||
|
||||
// Debug CSRs
|
||||
|
||||
reg [`LM32_PC_RNG] bp_a[0:breakpoints-1]; // Instruction breakpoint address
|
||||
reg bp_e[0:breakpoints-1]; // Instruction breakpoint enable
|
||||
wire [0:breakpoints-1]bp_match_n; // Indicates if a h/w instruction breakpoint matched
|
||||
|
||||
reg [`LM32_WPC_C_RNG] wpc_c[0:watchpoints-1]; // Watchpoint enable
|
||||
reg [`LM32_WORD_RNG] wp[0:watchpoints-1]; // Watchpoint address
|
||||
wire [0:watchpoints-1]wp_match_n; // Indicates if a h/w data watchpoint matched
|
||||
|
||||
wire debug_csr_write_enable; // Debug CSR write enable (from either a wcsr instruction of external debugger)
|
||||
wire [`LM32_WORD_RNG] debug_csr_write_data; // Data to write to debug CSR
|
||||
wire [`LM32_CSR_RNG] debug_csr; // Debug CSR to write to
|
||||
|
||||
`ifdef LM32_SINGLE_STEP_ENABLED
|
||||
// FIXME: Declaring this as a reg causes ModelSim 6.1.15b to crash, so use integer for now
|
||||
//reg [`LM32_DEBUG_SS_STATE_RNG] state; // State of single-step FSM
|
||||
integer state; // State of single-step FSM
|
||||
`endif
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Functions
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
`include "lm32_functions.v"
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Combinational Logic
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
// Check for breakpoints
|
||||
generate
|
||||
for (i = 0; i < breakpoints; i = i + 1)
|
||||
begin : bp_comb
|
||||
assign bp_match_n[i] = ((bp_a[i] == pc_x) && (bp_e[i] == `TRUE));
|
||||
end
|
||||
endgenerate
|
||||
generate
|
||||
`ifdef LM32_SINGLE_STEP_ENABLED
|
||||
if (breakpoints > 0)
|
||||
assign bp_match = (|bp_match_n) || (state == `LM32_DEBUG_SS_STATE_RAISE_BREAKPOINT);
|
||||
else
|
||||
assign bp_match = state == `LM32_DEBUG_SS_STATE_RAISE_BREAKPOINT;
|
||||
`else
|
||||
if (breakpoints > 0)
|
||||
assign bp_match = |bp_match_n;
|
||||
else
|
||||
assign bp_match = `FALSE;
|
||||
`endif
|
||||
endgenerate
|
||||
|
||||
// Check for watchpoints
|
||||
generate
|
||||
for (i = 0; i < watchpoints; i = i + 1)
|
||||
begin : wp_comb
|
||||
assign wp_match_n[i] = (wp[i] == load_store_address_x) && ((load_x & wpc_c[i][0]) | (store_x & wpc_c[i][1]));
|
||||
end
|
||||
endgenerate
|
||||
generate
|
||||
if (watchpoints > 0)
|
||||
assign wp_match = |wp_match_n;
|
||||
else
|
||||
assign wp_match = `FALSE;
|
||||
endgenerate
|
||||
|
||||
`ifdef CFG_HW_DEBUG_ENABLED
|
||||
// Multiplex between wcsr instruction writes and debugger writes to the debug CSRs
|
||||
assign debug_csr_write_enable = (csr_write_enable_x == `TRUE) || (jtag_csr_write_enable == `TRUE);
|
||||
assign debug_csr_write_data = jtag_csr_write_enable == `TRUE ? jtag_csr_write_data : csr_write_data;
|
||||
assign debug_csr = jtag_csr_write_enable == `TRUE ? jtag_csr : csr_x;
|
||||
`else
|
||||
assign debug_csr_write_enable = csr_write_enable_x;
|
||||
assign debug_csr_write_data = csr_write_data;
|
||||
assign debug_csr = csr_x;
|
||||
`endif
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Sequential Logic
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
// Breakpoint address and enable CSRs
|
||||
generate
|
||||
for (i = 0; i < breakpoints; i = i + 1)
|
||||
begin : bp_seq
|
||||
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
|
||||
begin
|
||||
if (rst_i == `TRUE)
|
||||
begin
|
||||
bp_a[i] <= {`LM32_PC_WIDTH{1'bx}};
|
||||
bp_e[i] <= `FALSE;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if ((debug_csr_write_enable == `TRUE) && (debug_csr == `LM32_CSR_BP0 + i))
|
||||
begin
|
||||
bp_a[i] <= debug_csr_write_data[`LM32_PC_RNG];
|
||||
bp_e[i] <= debug_csr_write_data[0];
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// Watchpoint address and control flags CSRs
|
||||
generate
|
||||
for (i = 0; i < watchpoints; i = i + 1)
|
||||
begin : wp_seq
|
||||
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
|
||||
begin
|
||||
if (rst_i == `TRUE)
|
||||
begin
|
||||
wp[i] <= {`LM32_WORD_WIDTH{1'bx}};
|
||||
wpc_c[i] <= `LM32_WPC_C_DISABLED;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if (debug_csr_write_enable == `TRUE)
|
||||
begin
|
||||
if (debug_csr == `LM32_CSR_DC)
|
||||
wpc_c[i] <= debug_csr_write_data[3+i*2:2+i*2];
|
||||
if (debug_csr == `LM32_CSR_WP0 + i)
|
||||
wp[i] <= debug_csr_write_data;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// Remap exceptions control bit
|
||||
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
|
||||
begin
|
||||
if (rst_i == `TRUE)
|
||||
dc_re <= `FALSE;
|
||||
else
|
||||
begin
|
||||
if ((debug_csr_write_enable == `TRUE) && (debug_csr == `LM32_CSR_DC))
|
||||
dc_re <= debug_csr_write_data[1];
|
||||
end
|
||||
end
|
||||
|
||||
`ifdef LM32_SINGLE_STEP_ENABLED
|
||||
// Single-step control flag
|
||||
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
|
||||
begin
|
||||
if (rst_i == `TRUE)
|
||||
begin
|
||||
state <= `LM32_DEBUG_SS_STATE_IDLE;
|
||||
dc_ss <= `FALSE;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if ((debug_csr_write_enable == `TRUE) && (debug_csr == `LM32_CSR_DC))
|
||||
begin
|
||||
dc_ss <= debug_csr_write_data[0];
|
||||
if (debug_csr_write_data[0] == `FALSE)
|
||||
state <= `LM32_DEBUG_SS_STATE_IDLE;
|
||||
else
|
||||
state <= `LM32_DEBUG_SS_STATE_WAIT_FOR_RET;
|
||||
end
|
||||
case (state)
|
||||
`LM32_DEBUG_SS_STATE_WAIT_FOR_RET:
|
||||
begin
|
||||
// Wait for eret or bret instruction to be executed
|
||||
if ( ( (eret_q_x == `TRUE)
|
||||
|| (bret_q_x == `TRUE)
|
||||
)
|
||||
&& (stall_x == `FALSE)
|
||||
)
|
||||
state <= `LM32_DEBUG_SS_STATE_EXECUTE_ONE_INSN;
|
||||
end
|
||||
`LM32_DEBUG_SS_STATE_EXECUTE_ONE_INSN:
|
||||
begin
|
||||
// Wait for an instruction to be executed
|
||||
if ((q_x == `TRUE) && (stall_x == `FALSE))
|
||||
state <= `LM32_DEBUG_SS_STATE_RAISE_BREAKPOINT;
|
||||
end
|
||||
`LM32_DEBUG_SS_STATE_RAISE_BREAKPOINT:
|
||||
begin
|
||||
// Wait for exception to be raised
|
||||
`ifdef CFG_DCACHE_ENABLED
|
||||
if (dcache_refill_request == `TRUE)
|
||||
state <= `LM32_DEBUG_SS_STATE_EXECUTE_ONE_INSN;
|
||||
else
|
||||
`endif
|
||||
if ((exception_x == `TRUE) && (q_x == `TRUE) && (stall_x == `FALSE))
|
||||
begin
|
||||
dc_ss <= `FALSE;
|
||||
state <= `LM32_DEBUG_SS_STATE_RESTART;
|
||||
end
|
||||
end
|
||||
`LM32_DEBUG_SS_STATE_RESTART:
|
||||
begin
|
||||
// Watch to see if stepped instruction is restarted due to a cache miss
|
||||
`ifdef CFG_DCACHE_ENABLED
|
||||
if (dcache_refill_request == `TRUE)
|
||||
state <= `LM32_DEBUG_SS_STATE_EXECUTE_ONE_INSN;
|
||||
else
|
||||
`endif
|
||||
state <= `LM32_DEBUG_SS_STATE_IDLE;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
`endif
|
||||
|
||||
endmodule
|
||||
|
||||
`endif
|
564
lm32/logic/sakc/rtl/lm32/lm32_decoder.v
Normal file
564
lm32/logic/sakc/rtl/lm32/lm32_decoder.v
Normal file
@ -0,0 +1,564 @@
|
||||
// =============================================================================
|
||||
// COPYRIGHT NOTICE
|
||||
// Copyright 2006 (c) Lattice Semiconductor Corporation
|
||||
// ALL RIGHTS RESERVED
|
||||
// This confidential and proprietary software may be used only as authorised by
|
||||
// a licensing agreement from Lattice Semiconductor Corporation.
|
||||
// The entire notice above must be reproduced on all authorized copies and
|
||||
// copies may only be made to the extent permitted by a licensing agreement from
|
||||
// Lattice Semiconductor Corporation.
|
||||
//
|
||||
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
|
||||
// 5555 NE Moore Court 408-826-6000 (other locations)
|
||||
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
|
||||
// U.S.A email: techsupport@latticesemi.com
|
||||
// =============================================================================/
|
||||
// FILE DETAILS
|
||||
// Project : LatticeMico32
|
||||
// File : lm32_decoder.v
|
||||
// Title : Instruction decoder
|
||||
// Dependencies : lm32_include.v
|
||||
// Version : 6.1.17
|
||||
// =============================================================================
|
||||
|
||||
`include "lm32_include.v"
|
||||
|
||||
// Index of opcode field in an instruction
|
||||
`define LM32_OPCODE_RNG 31:26
|
||||
`define LM32_OP_RNG 30:26
|
||||
|
||||
// Opcodes - Some are only listed as 5 bits as their MSB is a don't care
|
||||
`define LM32_OPCODE_ADD 5'b01101
|
||||
`define LM32_OPCODE_AND 5'b01000
|
||||
`define LM32_OPCODE_ANDHI 6'b011000
|
||||
`define LM32_OPCODE_B 6'b110000
|
||||
`define LM32_OPCODE_BI 6'b111000
|
||||
`define LM32_OPCODE_BE 6'b010001
|
||||
`define LM32_OPCODE_BG 6'b010010
|
||||
`define LM32_OPCODE_BGE 6'b010011
|
||||
`define LM32_OPCODE_BGEU 6'b010100
|
||||
`define LM32_OPCODE_BGU 6'b010101
|
||||
`define LM32_OPCODE_BNE 6'b010111
|
||||
`define LM32_OPCODE_CALL 6'b110110
|
||||
`define LM32_OPCODE_CALLI 6'b111110
|
||||
`define LM32_OPCODE_CMPE 5'b11001
|
||||
`define LM32_OPCODE_CMPG 5'b11010
|
||||
`define LM32_OPCODE_CMPGE 5'b11011
|
||||
`define LM32_OPCODE_CMPGEU 5'b11100
|
||||
`define LM32_OPCODE_CMPGU 5'b11101
|
||||
`define LM32_OPCODE_CMPNE 5'b11111
|
||||
`define LM32_OPCODE_DIVU 6'b100011
|
||||
`define LM32_OPCODE_LB 6'b000100
|
||||
`define LM32_OPCODE_LBU 6'b010000
|
||||
`define LM32_OPCODE_LH 6'b000111
|
||||
`define LM32_OPCODE_LHU 6'b001011
|
||||
`define LM32_OPCODE_LW 6'b001010
|
||||
`define LM32_OPCODE_MODU 6'b110001
|
||||
`define LM32_OPCODE_MUL 5'b00010
|
||||
`define LM32_OPCODE_NOR 5'b00001
|
||||
`define LM32_OPCODE_OR 5'b01110
|
||||
`define LM32_OPCODE_ORHI 6'b011110
|
||||
`define LM32_OPCODE_RAISE 6'b101011
|
||||
`define LM32_OPCODE_RCSR 6'b100100
|
||||
`define LM32_OPCODE_SB 6'b001100
|
||||
`define LM32_OPCODE_SEXTB 6'b101100
|
||||
`define LM32_OPCODE_SEXTH 6'b110111
|
||||
`define LM32_OPCODE_SH 6'b000011
|
||||
`define LM32_OPCODE_SL 5'b01111
|
||||
`define LM32_OPCODE_SR 5'b00101
|
||||
`define LM32_OPCODE_SRU 5'b00000
|
||||
`define LM32_OPCODE_SUB 6'b110010
|
||||
`define LM32_OPCODE_SW 6'b010110
|
||||
`define LM32_OPCODE_USER 6'b110011
|
||||
`define LM32_OPCODE_WCSR 6'b110100
|
||||
`define LM32_OPCODE_XNOR 5'b01001
|
||||
`define LM32_OPCODE_XOR 5'b00110
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Module interface
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
module lm32_decoder (
|
||||
// ----- Inputs -------
|
||||
instruction,
|
||||
// ----- Outputs -------
|
||||
d_result_sel_0,
|
||||
d_result_sel_1,
|
||||
x_result_sel_csr,
|
||||
`ifdef LM32_MC_ARITHMETIC_ENABLED
|
||||
x_result_sel_mc_arith,
|
||||
`endif
|
||||
`ifdef LM32_NO_BARREL_SHIFT
|
||||
x_result_sel_shift,
|
||||
`endif
|
||||
`ifdef CFG_SIGN_EXTEND_ENABLED
|
||||
x_result_sel_sext,
|
||||
`endif
|
||||
x_result_sel_logic,
|
||||
`ifdef CFG_USER_ENABLED
|
||||
x_result_sel_user,
|
||||
`endif
|
||||
x_result_sel_add,
|
||||
m_result_sel_compare,
|
||||
`ifdef CFG_PL_BARREL_SHIFT_ENABLED
|
||||
m_result_sel_shift,
|
||||
`endif
|
||||
w_result_sel_load,
|
||||
`ifdef CFG_PL_MULTIPLY_ENABLED
|
||||
w_result_sel_mul,
|
||||
`endif
|
||||
x_bypass_enable,
|
||||
m_bypass_enable,
|
||||
read_enable_0,
|
||||
read_idx_0,
|
||||
read_enable_1,
|
||||
read_idx_1,
|
||||
write_enable,
|
||||
write_idx,
|
||||
immediate,
|
||||
branch_offset,
|
||||
load,
|
||||
store,
|
||||
size,
|
||||
sign_extend,
|
||||
adder_op,
|
||||
logic_op,
|
||||
`ifdef CFG_PL_BARREL_SHIFT_ENABLED
|
||||
direction,
|
||||
`endif
|
||||
`ifdef CFG_MC_BARREL_SHIFT_ENABLED
|
||||
shift_left,
|
||||
shift_right,
|
||||
`endif
|
||||
`ifdef CFG_MC_MULTIPLY_ENABLED
|
||||
multiply,
|
||||
`endif
|
||||
`ifdef CFG_MC_DIVIDE_ENABLED
|
||||
divide,
|
||||
modulus,
|
||||
`endif
|
||||
branch,
|
||||
branch_reg,
|
||||
condition,
|
||||
`ifdef CFG_DEBUG_ENABLED
|
||||
break,
|
||||
`endif
|
||||
scall,
|
||||
eret,
|
||||
`ifdef CFG_DEBUG_ENABLED
|
||||
bret,
|
||||
`endif
|
||||
`ifdef CFG_USER_ENABLED
|
||||
user_opcode,
|
||||
`endif
|
||||
csr_write_enable
|
||||
);
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Inputs
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
input [`LM32_INSTRUCTION_RNG] instruction; // Instruction to decode
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Outputs
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
output [`LM32_D_RESULT_SEL_0_RNG] d_result_sel_0;
|
||||
reg [`LM32_D_RESULT_SEL_0_RNG] d_result_sel_0;
|
||||
output [`LM32_D_RESULT_SEL_1_RNG] d_result_sel_1;
|
||||
reg [`LM32_D_RESULT_SEL_1_RNG] d_result_sel_1;
|
||||
output x_result_sel_csr;
|
||||
reg x_result_sel_csr;
|
||||
`ifdef LM32_MC_ARITHMETIC_ENABLED
|
||||
output x_result_sel_mc_arith;
|
||||
reg x_result_sel_mc_arith;
|
||||
`endif
|
||||
`ifdef LM32_NO_BARREL_SHIFT
|
||||
output x_result_sel_shift;
|
||||
reg x_result_sel_shift;
|
||||
`endif
|
||||
`ifdef CFG_SIGN_EXTEND_ENABLED
|
||||
output x_result_sel_sext;
|
||||
reg x_result_sel_sext;
|
||||
`endif
|
||||
output x_result_sel_logic;
|
||||
reg x_result_sel_logic;
|
||||
`ifdef CFG_USER_ENABLED
|
||||
output x_result_sel_user;
|
||||
reg x_result_sel_user;
|
||||
`endif
|
||||
output x_result_sel_add;
|
||||
reg x_result_sel_add;
|
||||
output m_result_sel_compare;
|
||||
reg m_result_sel_compare;
|
||||
`ifdef CFG_PL_BARREL_SHIFT_ENABLED
|
||||
output m_result_sel_shift;
|
||||
reg m_result_sel_shift;
|
||||
`endif
|
||||
output w_result_sel_load;
|
||||
reg w_result_sel_load;
|
||||
`ifdef CFG_PL_MULTIPLY_ENABLED
|
||||
output w_result_sel_mul;
|
||||
reg w_result_sel_mul;
|
||||
`endif
|
||||
output x_bypass_enable;
|
||||
wire x_bypass_enable;
|
||||
output m_bypass_enable;
|
||||
wire m_bypass_enable;
|
||||
output read_enable_0;
|
||||
wire read_enable_0;
|
||||
output [`LM32_REG_IDX_RNG] read_idx_0;
|
||||
wire [`LM32_REG_IDX_RNG] read_idx_0;
|
||||
output read_enable_1;
|
||||
wire read_enable_1;
|
||||
output [`LM32_REG_IDX_RNG] read_idx_1;
|
||||
wire [`LM32_REG_IDX_RNG] read_idx_1;
|
||||
output write_enable;
|
||||
wire write_enable;
|
||||
output [`LM32_REG_IDX_RNG] write_idx;
|
||||
wire [`LM32_REG_IDX_RNG] write_idx;
|
||||
output [`LM32_WORD_RNG] immediate;
|
||||
wire [`LM32_WORD_RNG] immediate;
|
||||
output [`LM32_PC_RNG] branch_offset;
|
||||
wire [`LM32_PC_RNG] branch_offset;
|
||||
output load;
|
||||
wire load;
|
||||
output store;
|
||||
wire store;
|
||||
output [`LM32_SIZE_RNG] size;
|
||||
wire [`LM32_SIZE_RNG] size;
|
||||
output sign_extend;
|
||||
wire sign_extend;
|
||||
output adder_op;
|
||||
wire adder_op;
|
||||
output [`LM32_LOGIC_OP_RNG] logic_op;
|
||||
wire [`LM32_LOGIC_OP_RNG] logic_op;
|
||||
`ifdef CFG_PL_BARREL_SHIFT_ENABLED
|
||||
output direction;
|
||||
wire direction;
|
||||
`endif
|
||||
`ifdef CFG_MC_BARREL_SHIFT_ENABLED
|
||||
output shift_left;
|
||||
wire shift_left;
|
||||
output shift_right;
|
||||
wire shift_right;
|
||||
`endif
|
||||
`ifdef CFG_MC_MULTIPLY_ENABLED
|
||||
output multiply;
|
||||
wire multiply;
|
||||
`endif
|
||||
`ifdef CFG_MC_DIVIDE_ENABLED
|
||||
output divide;
|
||||
wire divide;
|
||||
output modulus;
|
||||
wire modulus;
|
||||
`endif
|
||||
output branch;
|
||||
wire branch;
|
||||
output branch_reg;
|
||||
wire branch_reg;
|
||||
output [`LM32_CONDITION_RNG] condition;
|
||||
wire [`LM32_CONDITION_RNG] condition;
|
||||
`ifdef CFG_DEBUG_ENABLED
|
||||
output break;
|
||||
wire break;
|
||||
`endif
|
||||
output scall;
|
||||
wire scall;
|
||||
output eret;
|
||||
wire eret;
|
||||
`ifdef CFG_DEBUG_ENABLED
|
||||
output bret;
|
||||
wire bret;
|
||||
`endif
|
||||
`ifdef CFG_USER_ENABLED
|
||||
output [`LM32_USER_OPCODE_RNG] user_opcode;
|
||||
wire [`LM32_USER_OPCODE_RNG] user_opcode;
|
||||
`endif
|
||||
output csr_write_enable;
|
||||
wire csr_write_enable;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Internal nets and registers
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
wire [`LM32_WORD_RNG] extended_immediate; // Zero or sign extended immediate
|
||||
wire [`LM32_WORD_RNG] high_immediate; // Immediate as high 16 bits
|
||||
wire [`LM32_WORD_RNG] call_immediate; // Call immediate
|
||||
wire [`LM32_WORD_RNG] branch_immediate; // Conditional branch immediate
|
||||
wire sign_extend_immediate; // Whether the immediate should be sign extended (`TRUE) or zero extended (`FALSE)
|
||||
wire select_high_immediate; // Whether to select the high immediate
|
||||
wire select_call_immediate; // Whether to select the call immediate
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Functions
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
`include "lm32_functions.v"
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Combinational logic
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
// Determine opcode
|
||||
wire op_add = instruction[`LM32_OP_RNG] == `LM32_OPCODE_ADD;
|
||||
wire op_and = instruction[`LM32_OP_RNG] == `LM32_OPCODE_AND;
|
||||
wire op_andhi = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_ANDHI;
|
||||
wire op_b = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_B;
|
||||
wire op_bi = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_BI;
|
||||
wire op_be = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_BE;
|
||||
wire op_bg = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_BG;
|
||||
wire op_bge = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_BGE;
|
||||
wire op_bgeu = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_BGEU;
|
||||
wire op_bgu = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_BGU;
|
||||
wire op_bne = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_BNE;
|
||||
wire op_call = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_CALL;
|
||||
wire op_calli = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_CALLI;
|
||||
wire op_cmpe = instruction[`LM32_OP_RNG] == `LM32_OPCODE_CMPE;
|
||||
wire op_cmpg = instruction[`LM32_OP_RNG] == `LM32_OPCODE_CMPG;
|
||||
wire op_cmpge = instruction[`LM32_OP_RNG] == `LM32_OPCODE_CMPGE;
|
||||
wire op_cmpgeu = instruction[`LM32_OP_RNG] == `LM32_OPCODE_CMPGEU;
|
||||
wire op_cmpgu = instruction[`LM32_OP_RNG] == `LM32_OPCODE_CMPGU;
|
||||
wire op_cmpne = instruction[`LM32_OP_RNG] == `LM32_OPCODE_CMPNE;
|
||||
`ifdef CFG_MC_DIVIDE_ENABLED
|
||||
wire op_divu = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_DIVU;
|
||||
`endif
|
||||
wire op_lb = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_LB;
|
||||
wire op_lbu = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_LBU;
|
||||
wire op_lh = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_LH;
|
||||
wire op_lhu = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_LHU;
|
||||
wire op_lw = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_LW;
|
||||
`ifdef CFG_MC_DIVIDE_ENABLED
|
||||
wire op_modu = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_MODU;
|
||||
`endif
|
||||
`ifdef LM32_MULTIPLY_ENABLED
|
||||
wire op_mul = instruction[`LM32_OP_RNG] == `LM32_OPCODE_MUL;
|
||||
`endif
|
||||
wire op_nor = instruction[`LM32_OP_RNG] == `LM32_OPCODE_NOR;
|
||||
wire op_or = instruction[`LM32_OP_RNG] == `LM32_OPCODE_OR;
|
||||
wire op_orhi = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_ORHI;
|
||||
wire op_raise = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_RAISE;
|
||||
wire op_rcsr = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_RCSR;
|
||||
wire op_sb = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_SB;
|
||||
`ifdef CFG_SIGN_EXTEND_ENABLED
|
||||
wire op_sextb = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_SEXTB;
|
||||
wire op_sexth = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_SEXTH;
|
||||
`endif
|
||||
wire op_sh = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_SH;
|
||||
`ifdef LM32_BARREL_SHIFT_ENABLED
|
||||
wire op_sl = instruction[`LM32_OP_RNG] == `LM32_OPCODE_SL;
|
||||
`endif
|
||||
wire op_sr = instruction[`LM32_OP_RNG] == `LM32_OPCODE_SR;
|
||||
wire op_sru = instruction[`LM32_OP_RNG] == `LM32_OPCODE_SRU;
|
||||
wire op_sub = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_SUB;
|
||||
wire op_sw = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_SW;
|
||||
wire op_user = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_USER;
|
||||
wire op_wcsr = instruction[`LM32_OPCODE_RNG] == `LM32_OPCODE_WCSR;
|
||||
wire op_xnor = instruction[`LM32_OP_RNG] == `LM32_OPCODE_XNOR;
|
||||
wire op_xor = instruction[`LM32_OP_RNG] == `LM32_OPCODE_XOR;
|
||||
|
||||
// Group opcodes by function
|
||||
wire arith = op_add | op_sub;
|
||||
wire logicc = op_and | op_andhi | op_nor | op_or | op_orhi | op_xor | op_xnor;
|
||||
wire cmp = op_cmpe | op_cmpg | op_cmpge | op_cmpgeu | op_cmpgu | op_cmpne;
|
||||
wire bra = op_b | op_bi | op_be | op_bg | op_bge | op_bgeu | op_bgu | op_bne;
|
||||
wire call = op_call | op_calli;
|
||||
`ifdef LM32_BARREL_SHIFT_ENABLED
|
||||
wire shift = op_sl | op_sr | op_sru;
|
||||
`endif
|
||||
`ifdef LM32_NO_BARREL_SHIFT
|
||||
wire shift = op_sr | op_sru;
|
||||
`endif
|
||||
`ifdef CFG_MC_BARREL_SHIFT_ENABLED
|
||||
assign shift_left = op_sl;
|
||||
assign shift_right = op_sr | op_sru;
|
||||
`endif
|
||||
`ifdef CFG_SIGN_EXTEND_ENABLED
|
||||
wire sext = op_sextb | op_sexth;
|
||||
`endif
|
||||
`ifdef LM32_MULTIPLY_ENABLED
|
||||
wire multiply = op_mul;
|
||||
`endif
|
||||
`ifdef CFG_MC_DIVIDE_ENABLED
|
||||
assign divide = op_divu;
|
||||
assign modulus = op_modu;
|
||||
`endif
|
||||
assign load = op_lb | op_lbu | op_lh | op_lhu | op_lw;
|
||||
assign store = op_sb | op_sh | op_sw;
|
||||
|
||||
// Select pipeline multiplexor controls
|
||||
always @*
|
||||
begin
|
||||
// D stage
|
||||
if (call)
|
||||
d_result_sel_0 = `LM32_D_RESULT_SEL_0_NEXT_PC;
|
||||
else
|
||||
d_result_sel_0 = `LM32_D_RESULT_SEL_0_REG_0;
|
||||
if (call)
|
||||
d_result_sel_1 = `LM32_D_RESULT_SEL_1_ZERO;
|
||||
else if ((instruction[31] == 1'b0) && !bra)
|
||||
d_result_sel_1 = `LM32_D_RESULT_SEL_1_IMMEDIATE;
|
||||
else
|
||||
d_result_sel_1 = `LM32_D_RESULT_SEL_1_REG_1;
|
||||
// X stage
|
||||
x_result_sel_csr = `FALSE;
|
||||
`ifdef LM32_MC_ARITHMETIC_ENABLED
|
||||
x_result_sel_mc_arith = `FALSE;
|
||||
`endif
|
||||
`ifdef LM32_NO_BARREL_SHIFT
|
||||
x_result_sel_shift = `FALSE;
|
||||
`endif
|
||||
`ifdef CFG_SIGN_EXTEND_ENABLED
|
||||
x_result_sel_sext = `FALSE;
|
||||
`endif
|
||||
x_result_sel_logic = `FALSE;
|
||||
`ifdef CFG_USER_ENABLED
|
||||
x_result_sel_user = `FALSE;
|
||||
`endif
|
||||
x_result_sel_add = `FALSE;
|
||||
if (op_rcsr)
|
||||
x_result_sel_csr = `TRUE;
|
||||
`ifdef LM32_MC_ARITHMETIC_ENABLED
|
||||
`ifdef CFG_MC_BARREL_SHIFT_ENABLED
|
||||
else if (shift_left | shift_right)
|
||||
x_result_sel_mc_arith = `TRUE;
|
||||
`endif
|
||||
`ifdef CFG_MC_DIVIDE_ENABLED
|
||||
else if (divide | modulus)
|
||||
x_result_sel_mc_arith = `TRUE;
|
||||
`endif
|
||||
`ifdef CFG_MC_MULTIPLY_ENABLED
|
||||
else if (multiply)
|
||||
x_result_sel_mc_arith = `TRUE;
|
||||
`endif
|
||||
`endif
|
||||
`ifdef LM32_NO_BARREL_SHIFT
|
||||
else if (shift)
|
||||
x_result_sel_shift = `TRUE;
|
||||
`endif
|
||||
`ifdef CFG_SIGN_EXTEND_ENABLED
|
||||
else if (sext)
|
||||
x_result_sel_sext = `TRUE;
|
||||
`endif
|
||||
else if (logicc)
|
||||
x_result_sel_logic = `TRUE;
|
||||
`ifdef CFG_USER_ENABLED
|
||||
else if (op_user)
|
||||
x_result_sel_user = `TRUE;
|
||||
`endif
|
||||
else
|
||||
x_result_sel_add = `TRUE;
|
||||
|
||||
// M stage
|
||||
|
||||
m_result_sel_compare = cmp;
|
||||
`ifdef CFG_PL_BARREL_SHIFT_ENABLED
|
||||
m_result_sel_shift = shift;
|
||||
`endif
|
||||
|
||||
// W stage
|
||||
w_result_sel_load = load;
|
||||
`ifdef CFG_PL_MULTIPLY_ENABLED
|
||||
w_result_sel_mul = op_mul;
|
||||
`endif
|
||||
end
|
||||
|
||||
// Set if result is valid at end of X stage
|
||||
assign x_bypass_enable = arith
|
||||
| logicc
|
||||
`ifdef CFG_MC_BARREL_SHIFT_ENABLED
|
||||
| shift_left
|
||||
| shift_right
|
||||
`endif
|
||||
`ifdef CFG_MC_MULTIPLY_ENABLED
|
||||
| multiply
|
||||
`endif
|
||||
`ifdef CFG_MC_DIVIDE_ENABLED
|
||||
| divide
|
||||
| modulus
|
||||
`endif
|
||||
`ifdef LM32_NO_BARREL_SHIFT
|
||||
| shift
|
||||
`endif
|
||||
`ifdef CFG_SIGN_EXTEND_ENABLED
|
||||
| sext
|
||||
`endif
|
||||
`ifdef CFG_USER_ENABLED
|
||||
| op_user
|
||||
`endif
|
||||
| op_rcsr
|
||||
;
|
||||
// Set if result is valid at end of M stage
|
||||
assign m_bypass_enable = x_bypass_enable
|
||||
`ifdef CFG_PL_BARREL_SHIFT_ENABLED
|
||||
| shift
|
||||
`endif
|
||||
| cmp
|
||||
;
|
||||
// Register file read port 0
|
||||
assign read_enable_0 = ~(op_bi | op_calli);
|
||||
assign read_idx_0 = instruction[25:21];
|
||||
// Register file read port 1
|
||||
assign read_enable_1 = ~(op_bi | op_calli | load);
|
||||
assign read_idx_1 = instruction[20:16];
|
||||
// Register file write port
|
||||
assign write_enable = ~(bra | op_raise | store | op_wcsr);
|
||||
assign write_idx = call
|
||||
? 5'd29
|
||||
: instruction[31] == 1'b0
|
||||
? instruction[20:16]
|
||||
: instruction[15:11];
|
||||
|
||||
// Size of load/stores
|
||||
assign size = instruction[27:26];
|
||||
// Whether to sign or zero extend
|
||||
assign sign_extend = instruction[28];
|
||||
// Set adder_op to 1 to perform a subtraction
|
||||
assign adder_op = op_sub | op_cmpe | op_cmpg | op_cmpge | op_cmpgeu | op_cmpgu | op_cmpne | bra;
|
||||
// Logic operation (and, or, etc)
|
||||
assign logic_op = instruction[29:26];
|
||||
`ifdef CFG_PL_BARREL_SHIFT_ENABLED
|
||||
// Shift direction
|
||||
assign direction = instruction[29];
|
||||
`endif
|
||||
// Control flow microcodes
|
||||
assign branch = bra | call;
|
||||
assign branch_reg = op_call | op_b;
|
||||
assign condition = instruction[28:26];
|
||||
`ifdef CFG_DEBUG_ENABLED
|
||||
assign break = op_raise & ~instruction[2];
|
||||
`endif
|
||||
assign scall = op_raise & instruction[2];
|
||||
assign eret = op_b & (instruction[25:21] == 5'd30);
|
||||
`ifdef CFG_DEBUG_ENABLED
|
||||
assign bret = op_b & (instruction[25:21] == 5'd31);
|
||||
`endif
|
||||
`ifdef CFG_USER_ENABLED
|
||||
// Extract user opcode
|
||||
assign user_opcode = instruction[10:0];
|
||||
`endif
|
||||
// CSR read/write
|
||||
assign csr_write_enable = op_wcsr;
|
||||
|
||||
// Extract immediate from instruction
|
||||
|
||||
assign sign_extend_immediate = ~(op_and | op_cmpgeu | op_cmpgu | op_nor | op_or | op_xnor | op_xor);
|
||||
assign select_high_immediate = op_andhi | op_orhi;
|
||||
assign select_call_immediate = instruction[31];
|
||||
|
||||
assign high_immediate = {instruction[15:0], 16'h0000};
|
||||
assign extended_immediate = {{16{sign_extend_immediate & instruction[15]}}, instruction[15:0]};
|
||||
assign call_immediate = {{6{instruction[25]}}, instruction[25:0]};
|
||||
assign branch_immediate = {{16{instruction[15]}}, instruction[15:0]};
|
||||
|
||||
assign immediate = select_high_immediate == `TRUE
|
||||
? high_immediate
|
||||
: extended_immediate;
|
||||
|
||||
assign branch_offset = select_call_immediate == `TRUE
|
||||
? call_immediate
|
||||
: branch_immediate;
|
||||
|
||||
endmodule
|
||||
|
29
lm32/logic/sakc/rtl/lm32/lm32_functions.v
Normal file
29
lm32/logic/sakc/rtl/lm32/lm32_functions.v
Normal file
@ -0,0 +1,29 @@
|
||||
// =============================================================================
|
||||
// COPYRIGHT NOTICE
|
||||
// Copyright 2006 (c) Lattice Semiconductor Corporation
|
||||
// ALL RIGHTS RESERVED
|
||||
// This confidential and proprietary software may be used only as authorised by
|
||||
// a licensing agreement from Lattice Semiconductor Corporation.
|
||||
// The entire notice above must be reproduced on all authorized copies and
|
||||
// copies may only be made to the extent permitted by a licensing agreement from
|
||||
// Lattice Semiconductor Corporation.
|
||||
//
|
||||
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
|
||||
// 5555 NE Moore Court 408-826-6000 (other locations)
|
||||
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
|
||||
// U.S.A email: techsupport@latticesemi.com
|
||||
// =============================================================================/
|
||||
// FILE DETAILS
|
||||
// Project : LatticeMico32
|
||||
// File : lm32_functions.v
|
||||
// Title : Common functions
|
||||
// Version : 6.1.17
|
||||
// =============================================================================
|
||||
|
||||
function integer clogb2;
|
||||
input [31:0] value;
|
||||
begin
|
||||
for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1)
|
||||
value = value >> 1;
|
||||
end
|
||||
endfunction
|
428
lm32/logic/sakc/rtl/lm32/lm32_icache.v
Normal file
428
lm32/logic/sakc/rtl/lm32/lm32_icache.v
Normal file
@ -0,0 +1,428 @@
|
||||
// =============================================================================
|
||||
// COPYRIGHT NOTICE
|
||||
// Copyright 2006 (c) Lattice Semiconductor Corporation
|
||||
// ALL RIGHTS RESERVED
|
||||
// This confidential and proprietary software may be used only as authorised by
|
||||
// a licensing agreement from Lattice Semiconductor Corporation.
|
||||
// The entire notice above must be reproduced on all authorized copies and
|
||||
// copies may only be made to the extent permitted by a licensing agreement from
|
||||
// Lattice Semiconductor Corporation.
|
||||
//
|
||||
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
|
||||
// 5555 NE Moore Court 408-826-6000 (other locations)
|
||||
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
|
||||
// U.S.A email: techsupport@latticesemi.com
|
||||
// =============================================================================/
|
||||
// FILE DETAILS
|
||||
// Project : LatticeMico32
|
||||
// File : lm32_icache.v
|
||||
// Title : Instruction cache
|
||||
// Dependencies : lm32_include.v
|
||||
// Version : 6.1.17
|
||||
// =============================================================================
|
||||
|
||||
`include "lm32_include.v"
|
||||
|
||||
`define LM32_IC_ADDR_OFFSET_RNG addr_offset_msb:addr_offset_lsb
|
||||
`define LM32_IC_ADDR_SET_RNG addr_set_msb:addr_set_lsb
|
||||
`define LM32_IC_ADDR_TAG_RNG addr_tag_msb:addr_tag_lsb
|
||||
`define LM32_IC_ADDR_IDX_RNG addr_set_msb:addr_offset_lsb
|
||||
|
||||
`define LM32_IC_TMEM_ADDR_WIDTH addr_set_width
|
||||
`define LM32_IC_TMEM_ADDR_RNG (`LM32_IC_TMEM_ADDR_WIDTH-1):0
|
||||
`define LM32_IC_DMEM_ADDR_WIDTH (addr_offset_width+addr_set_width)
|
||||
`define LM32_IC_DMEM_ADDR_RNG (`LM32_IC_DMEM_ADDR_WIDTH-1):0
|
||||
|
||||
`define LM32_IC_TAGS_WIDTH (addr_tag_width+1)
|
||||
`define LM32_IC_TAGS_RNG (`LM32_IC_TAGS_WIDTH-1):0
|
||||
`define LM32_IC_TAGS_TAG_RNG (`LM32_IC_TAGS_WIDTH-1):1
|
||||
`define LM32_IC_TAGS_VALID_RNG 0
|
||||
|
||||
`define LM32_IC_STATE_RNG 3:0
|
||||
`define LM32_IC_STATE_FLUSH_INIT 4'b0001
|
||||
`define LM32_IC_STATE_FLUSH 4'b0010
|
||||
`define LM32_IC_STATE_CHECK 4'b0100
|
||||
`define LM32_IC_STATE_REFILL 4'b1000
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Module interface
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
module lm32_icache (
|
||||
// ----- Inputs -----
|
||||
clk_i,
|
||||
rst_i,
|
||||
stall_a,
|
||||
stall_f,
|
||||
address_a,
|
||||
address_f,
|
||||
read_enable_f,
|
||||
refill_ready,
|
||||
refill_data,
|
||||
iflush,
|
||||
// ----- Outputs -----
|
||||
stall_request,
|
||||
restart_request,
|
||||
refill_request,
|
||||
refill_address,
|
||||
refilling,
|
||||
inst
|
||||
);
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Parameters
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
parameter associativity = 1; // Associativity of the cache (Number of ways)
|
||||
parameter sets = 512; // Number of sets
|
||||
parameter bytes_per_line = 16; // Number of bytes per cache line
|
||||
parameter base_address = 0; // Base address of cachable memory
|
||||
parameter limit = 0; // Limit (highest address) of cachable memory
|
||||
|
||||
localparam addr_offset_width = 2;
|
||||
localparam addr_set_width = 9;
|
||||
localparam addr_offset_lsb = 2;
|
||||
localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1);
|
||||
localparam addr_set_lsb = (addr_offset_msb+1);
|
||||
localparam addr_set_msb = (addr_set_lsb+addr_set_width-1);
|
||||
localparam addr_tag_lsb = (addr_set_msb+1);
|
||||
localparam addr_tag_msb = 31;
|
||||
localparam addr_tag_width = (addr_tag_msb-addr_tag_lsb+1);
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Inputs
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
input clk_i; // Clock
|
||||
input rst_i; // Reset
|
||||
|
||||
input stall_a; // Stall instruction in A stage
|
||||
input stall_f; // Stall instruction in F stage
|
||||
|
||||
input [`LM32_PC_RNG] address_a; // Address of instruction in A stage
|
||||
input [`LM32_PC_RNG] address_f; // Address of instruction in F stage
|
||||
input read_enable_f; // Indicates if cache access is valid
|
||||
|
||||
input refill_ready; // Next word of refill data is ready
|
||||
input [`LM32_INSTRUCTION_RNG] refill_data; // Data to refill the cache with
|
||||
|
||||
input iflush; // Flush the cache
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Outputs
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
output stall_request; // Request to stall the pipeline
|
||||
wire stall_request;
|
||||
output restart_request; // Request to restart instruction that caused the cache miss
|
||||
reg restart_request;
|
||||
output refill_request; // Request to refill a cache line
|
||||
wire refill_request;
|
||||
output [`LM32_PC_RNG] refill_address; // Base address of cache refill
|
||||
reg [`LM32_PC_RNG] refill_address;
|
||||
output refilling; // Indicates the instruction cache is currently refilling
|
||||
reg refilling;
|
||||
output [`LM32_INSTRUCTION_RNG] inst; // Instruction read from cache
|
||||
wire [`LM32_INSTRUCTION_RNG] inst;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Internal nets and registers
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
wire enable;
|
||||
wire [0:associativity-1] way_mem_we;
|
||||
wire [`LM32_INSTRUCTION_RNG] way_data[0:associativity-1];
|
||||
wire [`LM32_IC_TAGS_TAG_RNG] way_tag[0:associativity-1];
|
||||
wire [0:associativity-1] way_valid;
|
||||
wire [0:associativity-1] way_match;
|
||||
wire miss;
|
||||
|
||||
wire [`LM32_IC_TMEM_ADDR_RNG] tmem_read_address;
|
||||
wire [`LM32_IC_TMEM_ADDR_RNG] tmem_write_address;
|
||||
wire [`LM32_IC_DMEM_ADDR_RNG] dmem_read_address;
|
||||
wire [`LM32_IC_DMEM_ADDR_RNG] dmem_write_address;
|
||||
wire [`LM32_IC_TAGS_RNG] tmem_write_data;
|
||||
|
||||
reg [`LM32_IC_STATE_RNG] state;
|
||||
wire flushing;
|
||||
wire check;
|
||||
wire refill;
|
||||
|
||||
reg [associativity-1:0] refill_way_select;
|
||||
reg [`LM32_IC_ADDR_OFFSET_RNG] refill_offset;
|
||||
wire last_refill;
|
||||
reg [`LM32_IC_TMEM_ADDR_RNG] flush_set;
|
||||
|
||||
genvar i;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Functions
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
`include "lm32_functions.v"
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Instantiations
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
generate
|
||||
for (i = 0; i < associativity; i = i + 1)
|
||||
begin : memories
|
||||
|
||||
// Way 0 data
|
||||
lm32_ram #(
|
||||
// ----- Parameters -------
|
||||
.data_width (32),
|
||||
.address_width (`LM32_IC_DMEM_ADDR_WIDTH)
|
||||
) way_0_data_ram (
|
||||
// ----- Inputs -------
|
||||
.read_clk (clk_i),
|
||||
.write_clk (clk_i),
|
||||
.reset (rst_i),
|
||||
.read_address (dmem_read_address),
|
||||
.enable_read (enable),
|
||||
.write_address (dmem_write_address),
|
||||
.enable_write (`TRUE),
|
||||
.write_enable (way_mem_we[i]),
|
||||
.write_data (refill_data),
|
||||
// ----- Outputs -------
|
||||
.read_data (way_data[i])
|
||||
);
|
||||
|
||||
// Way 0 tags
|
||||
lm32_ram #(
|
||||
// ----- Parameters -------
|
||||
.data_width (`LM32_IC_TAGS_WIDTH),
|
||||
.address_width (`LM32_IC_TMEM_ADDR_WIDTH)
|
||||
) way_0_tag_ram (
|
||||
// ----- Inputs -------
|
||||
.read_clk (clk_i),
|
||||
.write_clk (clk_i),
|
||||
.reset (rst_i),
|
||||
.read_address (tmem_read_address),
|
||||
.enable_read (enable),
|
||||
.write_address (tmem_write_address),
|
||||
.enable_write (`TRUE),
|
||||
.write_enable (way_mem_we[i] | flushing),
|
||||
.write_data (tmem_write_data),
|
||||
// ----- Outputs -------
|
||||
.read_data ({way_tag[i], way_valid[i]})
|
||||
);
|
||||
|
||||
end
|
||||
endgenerate
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Combinational logic
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
// Compute which ways in the cache match the address address being read
|
||||
generate
|
||||
for (i = 0; i < associativity; i = i + 1)
|
||||
begin : match
|
||||
assign way_match[i] = ({way_tag[i], way_valid[i]} == {address_f[`LM32_IC_ADDR_TAG_RNG], `TRUE});
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// Select data from way that matched the address being read
|
||||
generate
|
||||
if (associativity == 1)
|
||||
begin : inst_1
|
||||
assign inst = way_data[0];
|
||||
end
|
||||
else if (associativity == 2)
|
||||
begin : inst_2
|
||||
assign inst = way_match[0] ? way_data[0] : way_data[1];
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// Compute address to use to index into the data memories
|
||||
generate
|
||||
if (bytes_per_line > 4)
|
||||
begin : wadr1
|
||||
assign dmem_write_address = {refill_address[`LM32_IC_ADDR_SET_RNG], refill_offset};
|
||||
end
|
||||
else
|
||||
begin : wadr2
|
||||
assign dmem_write_address = refill_address[`LM32_IC_ADDR_SET_RNG];
|
||||
end
|
||||
endgenerate
|
||||
|
||||
assign dmem_read_address = address_a[`LM32_IC_ADDR_IDX_RNG];
|
||||
|
||||
// Compute address to use to index into the tag memories
|
||||
assign tmem_read_address = address_a[`LM32_IC_ADDR_SET_RNG];
|
||||
assign tmem_write_address = flushing
|
||||
? flush_set
|
||||
: refill_address[`LM32_IC_ADDR_SET_RNG];
|
||||
|
||||
// Compute signal to indicate when we are on the last refill accesses
|
||||
generate
|
||||
if (bytes_per_line > 4)
|
||||
begin : lrefil1
|
||||
assign last_refill = refill_offset == {addr_offset_width{1'b1}};
|
||||
end
|
||||
else
|
||||
begin : lrefil2
|
||||
assign last_refill = `TRUE;
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// Compute data and tag memory access enable
|
||||
assign enable = (stall_a == `FALSE);
|
||||
|
||||
// Compute data and tag memory write enables
|
||||
generate
|
||||
if (associativity == 1)
|
||||
begin : we_1
|
||||
assign way_mem_we[0] = (refill_ready == `TRUE);
|
||||
end
|
||||
else
|
||||
begin : we_2
|
||||
assign way_mem_we[0] = (refill_ready == `TRUE) && (refill_way_select[0] == `TRUE);
|
||||
assign way_mem_we[1] = (refill_ready == `TRUE) && (refill_way_select[1] == `TRUE);
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// On the last refill cycle set the valid bit, for all other writes it should be cleared
|
||||
assign tmem_write_data[`LM32_IC_TAGS_VALID_RNG] = last_refill & !flushing;
|
||||
assign tmem_write_data[`LM32_IC_TAGS_TAG_RNG] = refill_address[`LM32_IC_ADDR_TAG_RNG];
|
||||
|
||||
// Signals that indicate which state we are in
|
||||
assign flushing = |state[1:0];
|
||||
assign check = state[2];
|
||||
assign refill = state[3];
|
||||
|
||||
assign miss = (~(|way_match)) && (read_enable_f == `TRUE) && (stall_f == `FALSE);
|
||||
assign stall_request = (check == `FALSE);
|
||||
assign refill_request = (refill == `TRUE);
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Sequential logic
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
// Record way selected for replacement on a cache miss
|
||||
generate
|
||||
if (associativity >= 2)
|
||||
begin : way_select
|
||||
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
|
||||
begin
|
||||
if (rst_i == `TRUE)
|
||||
refill_way_select <= {{associativity-1{1'b0}}, 1'b1};
|
||||
else
|
||||
begin
|
||||
if (miss == `TRUE)
|
||||
refill_way_select <= {refill_way_select[0], refill_way_select[1]};
|
||||
end
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// Record whether we are refilling
|
||||
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
|
||||
begin
|
||||
if (rst_i == `TRUE)
|
||||
refilling <= `FALSE;
|
||||
else
|
||||
refilling <= refill;
|
||||
end
|
||||
|
||||
// Instruction cache control FSM
|
||||
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
|
||||
begin
|
||||
if (rst_i == `TRUE)
|
||||
begin
|
||||
state <= `LM32_IC_STATE_FLUSH_INIT;
|
||||
flush_set <= {`LM32_IC_TMEM_ADDR_WIDTH{1'b1}};
|
||||
refill_address <= {`LM32_PC_WIDTH{1'bx}};
|
||||
restart_request <= `FALSE;
|
||||
end
|
||||
else
|
||||
begin
|
||||
case (state)
|
||||
|
||||
// Flush the cache for the first time after reset
|
||||
`LM32_IC_STATE_FLUSH_INIT:
|
||||
begin
|
||||
if (flush_set == {`LM32_IC_TMEM_ADDR_WIDTH{1'b0}})
|
||||
state <= `LM32_IC_STATE_CHECK;
|
||||
flush_set <= flush_set - 1'b1;
|
||||
end
|
||||
|
||||
// Flush the cache in response to an write to the ICC CSR
|
||||
`LM32_IC_STATE_FLUSH:
|
||||
begin
|
||||
if (flush_set == {`LM32_IC_TMEM_ADDR_WIDTH{1'b0}})
|
||||
state <= `LM32_IC_STATE_REFILL;
|
||||
flush_set <= flush_set - 1'b1;
|
||||
end
|
||||
|
||||
// Check for cache misses
|
||||
`LM32_IC_STATE_CHECK:
|
||||
begin
|
||||
if (stall_a == `FALSE)
|
||||
restart_request <= `FALSE;
|
||||
if (iflush == `TRUE)
|
||||
begin
|
||||
refill_address <= address_f;
|
||||
state <= `LM32_IC_STATE_FLUSH;
|
||||
end
|
||||
else if (miss == `TRUE)
|
||||
begin
|
||||
refill_address <= address_f;
|
||||
state <= `LM32_IC_STATE_REFILL;
|
||||
end
|
||||
end
|
||||
|
||||
// Refill a cache line
|
||||
`LM32_IC_STATE_REFILL:
|
||||
begin
|
||||
if (refill_ready == `TRUE)
|
||||
begin
|
||||
if (last_refill == `TRUE)
|
||||
begin
|
||||
restart_request <= `TRUE;
|
||||
state <= `LM32_IC_STATE_CHECK;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
generate
|
||||
if (bytes_per_line > 4)
|
||||
begin : refilof1
|
||||
// Refill offset
|
||||
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
|
||||
begin
|
||||
if (rst_i == `TRUE)
|
||||
refill_offset <= {addr_offset_width{1'b0}};
|
||||
else
|
||||
begin
|
||||
case (state)
|
||||
|
||||
// Check for cache misses
|
||||
`LM32_IC_STATE_CHECK:
|
||||
begin
|
||||
if (iflush == `TRUE)
|
||||
refill_offset <= {addr_offset_width{1'b0}};
|
||||
else if (miss == `TRUE)
|
||||
refill_offset <= {addr_offset_width{1'b0}};
|
||||
end
|
||||
|
||||
// Refill a cache line
|
||||
`LM32_IC_STATE_REFILL:
|
||||
begin
|
||||
if (refill_ready == `TRUE)
|
||||
refill_offset <= refill_offset + 1'b1;
|
||||
end
|
||||
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
endmodule
|
320
lm32/logic/sakc/rtl/lm32/lm32_include.v
Normal file
320
lm32/logic/sakc/rtl/lm32/lm32_include.v
Normal file
@ -0,0 +1,320 @@
|
||||
// =============================================================================
|
||||
// COPYRIGHT NOTICE
|
||||
// Copyright 2006 (c) Lattice Semiconductor Corporation
|
||||
// ALL RIGHTS RESERVED
|
||||
// This confidential and proprietary software may be used only as authorised by
|
||||
// a licensing agreement from Lattice Semiconductor Corporation.
|
||||
// The entire notice above must be reproduced on all authorized copies and
|
||||
// copies may only be made to the extent permitted by a licensing agreement from
|
||||
// Lattice Semiconductor Corporation.
|
||||
//
|
||||
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
|
||||
// 5555 NE Moore Court 408-826-6000 (other locations)
|
||||
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
|
||||
// U.S.A email: techsupport@latticesemi.com
|
||||
// =============================================================================/
|
||||
// FILE DETAILS
|
||||
// Project : LatticeMico32
|
||||
// File : lm32_include.v
|
||||
// Title : CPU global macros
|
||||
// Version : 6.1.17
|
||||
// =============================================================================
|
||||
|
||||
`ifdef LM32_INCLUDE_V
|
||||
`else
|
||||
`define LM32_INCLUDE_V
|
||||
|
||||
// Configuration options
|
||||
`include "system_conf.v"
|
||||
|
||||
`ifdef TRUE
|
||||
`else
|
||||
`define TRUE 1'b1
|
||||
`define FALSE 1'b0
|
||||
`define TRUE_N 1'b0
|
||||
`define FALSE_N 1'b1
|
||||
`endif
|
||||
|
||||
// Wishbone configuration
|
||||
`define CFG_IWB_ENABLED
|
||||
`define CFG_DWB_ENABLED
|
||||
|
||||
// Data-path width
|
||||
`define LM32_WORD_WIDTH 32
|
||||
`define LM32_WORD_RNG (`LM32_WORD_WIDTH-1):0
|
||||
`define LM32_SHIFT_WIDTH 5
|
||||
`define LM32_SHIFT_RNG (`LM32_SHIFT_WIDTH-1):0
|
||||
`define LM32_BYTE_SELECT_WIDTH 4
|
||||
`define LM32_BYTE_SELECT_RNG (`LM32_BYTE_SELECT_WIDTH-1):0
|
||||
|
||||
// Register file size
|
||||
`define LM32_REGISTERS 32
|
||||
`define LM32_REG_IDX_WIDTH 5
|
||||
`define LM32_REG_IDX_RNG (`LM32_REG_IDX_WIDTH-1):0
|
||||
|
||||
// Standard register numbers
|
||||
`define LM32_RA_REG `LM32_REG_IDX_WIDTH'd29
|
||||
`define LM32_EA_REG `LM32_REG_IDX_WIDTH'd30
|
||||
`define LM32_BA_REG `LM32_REG_IDX_WIDTH'd31
|
||||
|
||||
// Range of Program Counter. Two LSBs are always 0.
|
||||
`ifdef CFG_ICACHE_ENABLED
|
||||
// XXX `define LM32_PC_WIDTH (clogb2(`CFG_ICACHE_LIMIT-`CFG_ICACHE_BASE_ADDRESS)-2) XXX
|
||||
`define LM32_PC_WIDTH 30
|
||||
`else
|
||||
`ifdef CFG_IWB_ENABLED
|
||||
`define LM32_PC_WIDTH (`LM32_WORD_WIDTH-2)
|
||||
`else
|
||||
`define LM32_PC_WIDTH `LM32_IROM_ADDRESS_WIDTH
|
||||
`endif
|
||||
`endif
|
||||
`define LM32_PC_RNG (`LM32_PC_WIDTH+2-1):2
|
||||
|
||||
// Range of an instruction
|
||||
`define LM32_INSTRUCTION_WIDTH 32
|
||||
`define LM32_INSTRUCTION_RNG (`LM32_INSTRUCTION_WIDTH-1):0
|
||||
|
||||
// Adder operation
|
||||
`define LM32_ADDER_OP_ADD 1'b0
|
||||
`define LM32_ADDER_OP_SUBTRACT 1'b1
|
||||
|
||||
// Shift direction
|
||||
`define LM32_SHIFT_OP_RIGHT 1'b0
|
||||
`define LM32_SHIFT_OP_LEFT 1'b1
|
||||
|
||||
// Currently always enabled
|
||||
`define CFG_BUS_ERRORS_ENABLED
|
||||
|
||||
// Derive macro that indicates whether we have single-stepping or not
|
||||
`ifdef CFG_ROM_DEBUG_ENABLED
|
||||
`define LM32_SINGLE_STEP_ENABLED
|
||||
`else
|
||||
`ifdef CFG_HW_DEBUG_ENABLED
|
||||
`define LM32_SINGLE_STEP_ENABLED
|
||||
`endif
|
||||
`endif
|
||||
|
||||
// Derive macro that indicates whether JTAG interface is required
|
||||
`ifdef CFG_JTAG_UART_ENABLED
|
||||
`define LM32_JTAG_ENABLED
|
||||
`else
|
||||
`ifdef CFG_DEBUG_ENABLED
|
||||
`define LM32_JTAG_ENABLED
|
||||
`else
|
||||
`endif
|
||||
`endif
|
||||
|
||||
// Derive macro that indicates whether we have a barrel-shifter or not
|
||||
`ifdef CFG_PL_BARREL_SHIFT_ENABLED
|
||||
`define LM32_BARREL_SHIFT_ENABLED
|
||||
`else // CFG_PL_BARREL_SHIFT_ENABLED
|
||||
`ifdef CFG_MC_BARREL_SHIFT_ENABLED
|
||||
`define LM32_BARREL_SHIFT_ENABLED
|
||||
`else
|
||||
`define LM32_NO_BARREL_SHIFT
|
||||
`endif
|
||||
`endif // CFG_PL_BARREL_SHIFT_ENABLED
|
||||
|
||||
// Derive macro that indicates whether we have a multiplier or not
|
||||
`ifdef CFG_PL_MULTIPLY_ENABLED
|
||||
`define LM32_MULTIPLY_ENABLED
|
||||
`else
|
||||
`ifdef CFG_MC_MULTIPLY_ENABLED
|
||||
`define LM32_MULTIPLY_ENABLED
|
||||
`endif
|
||||
`endif
|
||||
|
||||
// Derive a macro that indicates whether or not the multi-cycle arithmetic unit is required
|
||||
`ifdef CFG_MC_DIVIDE_ENABLED
|
||||
`define LM32_MC_ARITHMETIC_ENABLED
|
||||
`endif
|
||||
`ifdef CFG_MC_MULTIPLY_ENABLED
|
||||
`define LM32_MC_ARITHMETIC_ENABLED
|
||||
`endif
|
||||
`ifdef CFG_MC_BARREL_SHIFT_ENABLED
|
||||
`define LM32_MC_ARITHMETIC_ENABLED
|
||||
`endif
|
||||
|
||||
// Derive macro that indicates if we are using an EBR register file
|
||||
`ifdef CFG_EBR_POSEDGE_REGISTER_FILE
|
||||
`define LM32_EBR_REGISTER_FILE
|
||||
`endif
|
||||
`ifdef CFG_EBR_NEGEDGE_REGISTER_FILE
|
||||
`define LM32_EBR_REGISTER_FILE
|
||||
`endif
|
||||
|
||||
// Revision number
|
||||
`define LM32_REVISION 6'h11
|
||||
|
||||
// Logical operations - Function encoded directly in instruction
|
||||
`define LM32_LOGIC_OP_RNG 3:0
|
||||
|
||||
// Conditions for conditional branches
|
||||
`define LM32_CONDITION_WIDTH 3
|
||||
`define LM32_CONDITION_RNG (`LM32_CONDITION_WIDTH-1):0
|
||||
`define LM32_CONDITION_E 3'b001
|
||||
`define LM32_CONDITION_G 3'b010
|
||||
`define LM32_CONDITION_GE 3'b011
|
||||
`define LM32_CONDITION_GEU 3'b100
|
||||
`define LM32_CONDITION_GU 3'b101
|
||||
`define LM32_CONDITION_NE 3'b111
|
||||
`define LM32_CONDITION_U1 3'b000
|
||||
`define LM32_CONDITION_U2 3'b110
|
||||
|
||||
// Size of load or store instruction - Encoding corresponds to opcode
|
||||
`define LM32_SIZE_WIDTH 2
|
||||
`define LM32_SIZE_RNG 1:0
|
||||
`define LM32_SIZE_BYTE 2'b00
|
||||
`define LM32_SIZE_HWORD 2'b11
|
||||
`define LM32_SIZE_WORD 2'b10
|
||||
`define LM32_ADDRESS_LSBS_WIDTH 2
|
||||
|
||||
// Width and range of a CSR index
|
||||
`ifdef CFG_DEBUG_ENABLED
|
||||
`define LM32_CSR_WIDTH 5
|
||||
`define LM32_CSR_RNG (`LM32_CSR_WIDTH-1):0
|
||||
`else
|
||||
`ifdef CFG_JTAG_ENABLED
|
||||
`define LM32_CSR_WIDTH 4
|
||||
`define LM32_CSR_RNG (`LM32_CSR_WIDTH-1):0
|
||||
`else
|
||||
`define LM32_CSR_WIDTH 3
|
||||
`define LM32_CSR_RNG (`LM32_CSR_WIDTH-1):0
|
||||
`endif
|
||||
`endif
|
||||
|
||||
// CSR indices
|
||||
`define LM32_CSR_IE `LM32_CSR_WIDTH'h0
|
||||
`define LM32_CSR_IM `LM32_CSR_WIDTH'h1
|
||||
`define LM32_CSR_IP `LM32_CSR_WIDTH'h2
|
||||
`define LM32_CSR_ICC `LM32_CSR_WIDTH'h3
|
||||
`define LM32_CSR_DCC `LM32_CSR_WIDTH'h4
|
||||
`define LM32_CSR_CC `LM32_CSR_WIDTH'h5
|
||||
`define LM32_CSR_CFG `LM32_CSR_WIDTH'h6
|
||||
`define LM32_CSR_EBA `LM32_CSR_WIDTH'h7
|
||||
`ifdef CFG_DEBUG_ENABLED
|
||||
`define LM32_CSR_DC `LM32_CSR_WIDTH'h8
|
||||
`define LM32_CSR_DEBA `LM32_CSR_WIDTH'h9
|
||||
`endif
|
||||
`ifdef CFG_JTAG_ENABLED
|
||||
`define LM32_CSR_JTX `LM32_CSR_WIDTH'he
|
||||
`define LM32_CSR_JRX `LM32_CSR_WIDTH'hf
|
||||
`endif
|
||||
`ifdef CFG_DEBUG_ENABLED
|
||||
`define LM32_CSR_BP0 `LM32_CSR_WIDTH'h10
|
||||
`define LM32_CSR_BP1 `LM32_CSR_WIDTH'h11
|
||||
`define LM32_CSR_BP2 `LM32_CSR_WIDTH'h12
|
||||
`define LM32_CSR_BP3 `LM32_CSR_WIDTH'h13
|
||||
`define LM32_CSR_WP0 `LM32_CSR_WIDTH'h18
|
||||
`define LM32_CSR_WP1 `LM32_CSR_WIDTH'h19
|
||||
`define LM32_CSR_WP2 `LM32_CSR_WIDTH'h1a
|
||||
`define LM32_CSR_WP3 `LM32_CSR_WIDTH'h1b
|
||||
`endif
|
||||
|
||||
// Values for WPC CSR
|
||||
`define LM32_WPC_C_RNG 1:0
|
||||
`define LM32_WPC_C_DISABLED 2'b00
|
||||
`define LM32_WPC_C_READ 2'b01
|
||||
`define LM32_WPC_C_WRITE 2'b10
|
||||
`define LM32_WPC_C_READ_WRITE 2'b11
|
||||
|
||||
// Exception IDs
|
||||
`define LM32_EID_WIDTH 3
|
||||
`define LM32_EID_RNG (`LM32_EID_WIDTH-1):0
|
||||
`define LM32_EID_RESET 3'h0
|
||||
`define LM32_EID_BREAKPOINT 3'd1
|
||||
`define LM32_EID_INST_BUS_ERROR 3'h2
|
||||
`define LM32_EID_WATCHPOINT 3'd3
|
||||
`define LM32_EID_DATA_BUS_ERROR 3'h4
|
||||
`define LM32_EID_DIVIDE_BY_ZERO 3'h5
|
||||
`define LM32_EID_INTERRUPT 3'h6
|
||||
`define LM32_EID_SCALL 3'h7
|
||||
|
||||
// Pipeline result selection mux controls
|
||||
|
||||
`define LM32_D_RESULT_SEL_0_RNG 0:0
|
||||
`define LM32_D_RESULT_SEL_0_REG_0 1'b0
|
||||
`define LM32_D_RESULT_SEL_0_NEXT_PC 1'b1
|
||||
|
||||
`define LM32_D_RESULT_SEL_1_RNG 1:0
|
||||
`define LM32_D_RESULT_SEL_1_ZERO 2'b00
|
||||
`define LM32_D_RESULT_SEL_1_REG_1 2'b01
|
||||
`define LM32_D_RESULT_SEL_1_IMMEDIATE 2'b10
|
||||
|
||||
`define LM32_USER_OPCODE_WIDTH 11
|
||||
`define LM32_USER_OPCODE_RNG (`LM32_USER_OPCODE_WIDTH-1):0
|
||||
|
||||
// Derive a macro to indicate if either of the caches are implemented
|
||||
`ifdef CFG_ICACHE_ENABLED
|
||||
`define LM32_CACHE_ENABLED
|
||||
`else
|
||||
`ifdef CFG_DCACHE_ENABLED
|
||||
`define LM32_CACHE_ENABLED
|
||||
`endif
|
||||
`endif
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Interrupts
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
// Always enable interrupts
|
||||
`define CFG_INTERRUPTS_ENABLED
|
||||
|
||||
// Currently this is fixed to 32 and should not be changed
|
||||
`define CFG_INTERRUPTS 32
|
||||
`define LM32_INTERRUPT_WIDTH `CFG_INTERRUPTS
|
||||
`define LM32_INTERRUPT_RNG (`LM32_INTERRUPT_WIDTH-1):0
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// General
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
// Sub-word range types
|
||||
`define LM32_BYTE_WIDTH 8
|
||||
`define LM32_BYTE_RNG 7:0
|
||||
`define LM32_HWORD_WIDTH 16
|
||||
`define LM32_HWORD_RNG 15:0
|
||||
|
||||
// Word sub-byte indicies
|
||||
`define LM32_BYTE_0_RNG 7:0
|
||||
`define LM32_BYTE_1_RNG 15:8
|
||||
`define LM32_BYTE_2_RNG 23:16
|
||||
`define LM32_BYTE_3_RNG 31:24
|
||||
|
||||
// Word sub-halfword indices
|
||||
`define LM32_HWORD_0_RNG 15:0
|
||||
`define LM32_HWORD_1_RNG 31:16
|
||||
|
||||
// Use an asynchronous reset
|
||||
// To use a synchronous reset, define this macro as nothing
|
||||
`define CFG_RESET_SENSITIVITY or posedge rst_i
|
||||
|
||||
// V.T. Srce
|
||||
`define SRCE
|
||||
|
||||
// Whether to include context registers for debug exceptions
|
||||
// in addition to standard exception handling registers
|
||||
// Bizarre - Removing this increases LUT count!
|
||||
`define CFG_DEBUG_EXCEPTIONS_ENABLED
|
||||
|
||||
// Wishbone defines
|
||||
// Refer to Wishbone System-on-Chip Interconnection Architecture
|
||||
// These should probably be moved to a Wishbone common file
|
||||
|
||||
// Wishbone cycle types
|
||||
`define LM32_CTYPE_WIDTH 3
|
||||
`define LM32_CTYPE_RNG (`LM32_CTYPE_WIDTH-1):0
|
||||
`define LM32_CTYPE_CLASSIC 3'b000
|
||||
`define LM32_CTYPE_CONSTANT 3'b001
|
||||
`define LM32_CTYPE_INCREMENTING 3'b010
|
||||
`define LM32_CTYPE_END 3'b111
|
||||
|
||||
// Wishbone burst types
|
||||
`define LM32_BTYPE_WIDTH 2
|
||||
`define LM32_BTYPE_RNG (`LM32_BTYPE_WIDTH-1):0
|
||||
`define LM32_BTYPE_LINEAR 2'b00
|
||||
`define LM32_BTYPE_4_BEAT 2'b01
|
||||
`define LM32_BTYPE_8_BEAT 2'b10
|
||||
`define LM32_BTYPE_16_BEAT 2'b11
|
||||
|
||||
`endif
|
32
lm32/logic/sakc/rtl/lm32/lm32_include_all.v
Normal file
32
lm32/logic/sakc/rtl/lm32/lm32_include_all.v
Normal file
@ -0,0 +1,32 @@
|
||||
`ifndef LM32_ALL_FILES
|
||||
`define LM32_ALL_FILES
|
||||
//`ifndef SIMULATION
|
||||
//`include "pmi_def.v"
|
||||
//`endif
|
||||
// JTAG Debug related files
|
||||
`include "../components/lm32_top/rtl/verilog/er1.v"
|
||||
`include "../components/lm32_top/rtl/verilog/typeb.v"
|
||||
`include "../components/lm32_top/rtl/verilog/typea.v"
|
||||
`include "../components/lm32_top/rtl/verilog/jtag_cores.v"
|
||||
`include "../components/lm32_top/rtl/verilog/jtag_lm32.v"
|
||||
// CPU Core related files
|
||||
`include "../components/lm32_top/rtl/verilog/lm32_addsub.v"
|
||||
`include "../components/lm32_top/rtl/verilog/lm32_adder.v"
|
||||
`include "../components/lm32_top/rtl/verilog/lm32_cpu.v"
|
||||
`include "../components/lm32_top/rtl/verilog/lm32_dcache.v"
|
||||
`include "../components/lm32_top/rtl/verilog/lm32_debug.v"
|
||||
`include "../components/lm32_top/rtl/verilog/lm32_decoder.v"
|
||||
`include "../components/lm32_top/rtl/verilog/lm32_icache.v"
|
||||
`include "../components/lm32_top/rtl/verilog/lm32_instruction_unit.v"
|
||||
`include "../components/lm32_top/rtl/verilog/lm32_interrupt.v"
|
||||
`include "../components/lm32_top/rtl/verilog/lm32_load_store_unit.v"
|
||||
`include "../components/lm32_top/rtl/verilog/lm32_logic_op.v"
|
||||
`include "../components/lm32_top/rtl/verilog/lm32_mc_arithmetic.v"
|
||||
`include "../components/lm32_top/rtl/verilog/lm32_multiplier.v"
|
||||
`include "../components/lm32_top/rtl/verilog/lm32_shifter.v"
|
||||
`include "../components/lm32_top/rtl/verilog/lm32_top.v"
|
||||
`include "../components/lm32_top/rtl/verilog/lm32_monitor.v"
|
||||
`include "../components/lm32_top/rtl/verilog/lm32_monitor_ram.v"
|
||||
`include "../components/lm32_top/rtl/verilog/lm32_ram.v"
|
||||
`include "../components/lm32_top/rtl/verilog/lm32_jtag.v"
|
||||
`endif // LM32_ALL_FILES
|
751
lm32/logic/sakc/rtl/lm32/lm32_instruction_unit.v
Normal file
751
lm32/logic/sakc/rtl/lm32/lm32_instruction_unit.v
Normal file
@ -0,0 +1,751 @@
|
||||
// =============================================================================
|
||||
// COPYRIGHT NOTICE
|
||||
// Copyright 2006 (c) Lattice Semiconductor Corporation
|
||||
// ALL RIGHTS RESERVED
|
||||
// This confidential and proprietary software may be used only as authorised by
|
||||
// a licensing agreement from Lattice Semiconductor Corporation.
|
||||
// The entire notice above must be reproduced on all authorized copies and
|
||||
// copies may only be made to the extent permitted by a licensing agreement from
|
||||
// Lattice Semiconductor Corporation.
|
||||
//
|
||||
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
|
||||
// 5555 NE Moore Court 408-826-6000 (other locations)
|
||||
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
|
||||
// U.S.A email: techsupport@latticesemi.com
|
||||
// =============================================================================/
|
||||
// FILE DETAILS
|
||||
// Project : LatticeMico32
|
||||
// File : lm32_instruction_unit.v
|
||||
// Title : Instruction unit
|
||||
// Dependencies : lm32_include.v
|
||||
// Version : 6.1.17
|
||||
// =============================================================================
|
||||
|
||||
`include "lm32_include.v"
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Module interface
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
module lm32_instruction_unit (
|
||||
// ----- Inputs -------
|
||||
clk_i,
|
||||
rst_i,
|
||||
// From pipeline
|
||||
stall_a,
|
||||
stall_f,
|
||||
stall_d,
|
||||
stall_x,
|
||||
stall_m,
|
||||
valid_f,
|
||||
kill_f,
|
||||
`ifdef CFG_FAST_UNCONDITIONAL_BRANCH
|
||||
branch_taken_x,
|
||||
branch_target_x,
|
||||
`endif
|
||||
branch_taken_m,
|
||||
branch_target_m,
|
||||
`ifdef CFG_ICACHE_ENABLED
|
||||
iflush,
|
||||
`endif
|
||||
`ifdef CFG_DCACHE_ENABLED
|
||||
dcache_restart_request,
|
||||
dcache_refill_request,
|
||||
dcache_refilling,
|
||||
`endif
|
||||
`ifdef CFG_IWB_ENABLED
|
||||
// From Wishbone
|
||||
i_dat_i,
|
||||
i_ack_i,
|
||||
i_err_i,
|
||||
i_rty_i,
|
||||
`endif
|
||||
`ifdef CFG_HW_DEBUG_ENABLED
|
||||
jtag_read_enable,
|
||||
jtag_write_enable,
|
||||
jtag_write_data,
|
||||
jtag_address,
|
||||
`endif
|
||||
// ----- Outputs -------
|
||||
// To pipeline
|
||||
pc_f,
|
||||
pc_d,
|
||||
pc_x,
|
||||
pc_m,
|
||||
pc_w,
|
||||
`ifdef CFG_ICACHE_ENABLED
|
||||
icache_stall_request,
|
||||
icache_restart_request,
|
||||
icache_refill_request,
|
||||
icache_refilling,
|
||||
`endif
|
||||
`ifdef CFG_IWB_ENABLED
|
||||
// To Wishbone
|
||||
i_dat_o,
|
||||
i_adr_o,
|
||||
i_cyc_o,
|
||||
i_sel_o,
|
||||
i_stb_o,
|
||||
i_we_o,
|
||||
i_cti_o,
|
||||
i_lock_o,
|
||||
i_bte_o,
|
||||
`endif
|
||||
`ifdef CFG_HW_DEBUG_ENABLED
|
||||
jtag_read_data,
|
||||
jtag_access_complete,
|
||||
`endif
|
||||
`ifdef CFG_BUS_ERRORS_ENABLED
|
||||
bus_error_d,
|
||||
`endif
|
||||
`ifdef CFG_EBR_POSEDGE_REGISTER_FILE
|
||||
instruction_f,
|
||||
`endif
|
||||
instruction_d
|
||||
);
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Parameters
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
parameter associativity = 1; // Associativity of the cache (Number of ways)
|
||||
parameter sets = 512; // Number of sets
|
||||
parameter bytes_per_line = 16; // Number of bytes per cache line
|
||||
parameter base_address = 0; // Base address of cachable memory
|
||||
parameter limit = 0; // Limit (highest address) of cachable memory
|
||||
|
||||
// For bytes_per_line == 4, we set 1 so part-select range isn't reversed, even though not really used
|
||||
//localparam addr_offset_width = (bytes_per_line == 4 ? 1 : clogb2(bytes_per_line)-1-2);
|
||||
localparam addr_offset_width = 2;
|
||||
localparam addr_offset_lsb = 2;
|
||||
localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1);
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Inputs
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
input clk_i; // Clock
|
||||
input rst_i; // Reset
|
||||
|
||||
input stall_a; // Stall A stage instruction
|
||||
input stall_f; // Stall F stage instruction
|
||||
input stall_d; // Stall D stage instruction
|
||||
input stall_x; // Stall X stage instruction
|
||||
input stall_m; // Stall M stage instruction
|
||||
input valid_f; // Instruction in F stage is valid
|
||||
input kill_f; // Kill instruction in F stage
|
||||
|
||||
`ifdef CFG_FAST_UNCONDITIONAL_BRANCH
|
||||
input branch_taken_x; // Branch instruction in X stage is taken
|
||||
input [`LM32_PC_RNG] branch_target_x; // Target PC of X stage branch instruction
|
||||
`endif
|
||||
input branch_taken_m; // Branch instruction in M stage is taken
|
||||
input [`LM32_PC_RNG] branch_target_m; // Target PC of M stage branch instruction
|
||||
|
||||
`ifdef CFG_ICACHE_ENABLED
|
||||
input iflush; // Flush instruction cache
|
||||
`endif
|
||||
`ifdef CFG_DCACHE_ENABLED
|
||||
input dcache_restart_request; // Restart instruction that caused a data cache miss
|
||||
input dcache_refill_request; // Request to refill data cache
|
||||
input dcache_refilling;
|
||||
`endif
|
||||
|
||||
`ifdef CFG_IWB_ENABLED
|
||||
input [`LM32_WORD_RNG] i_dat_i; // Instruction Wishbone interface read data
|
||||
input i_ack_i; // Instruction Wishbone interface acknowledgement
|
||||
input i_err_i; // Instruction Wishbone interface error
|
||||
input i_rty_i; // Instruction Wishbone interface retry
|
||||
`endif
|
||||
|
||||
`ifdef CFG_HW_DEBUG_ENABLED
|
||||
input jtag_read_enable; // JTAG read memory request
|
||||
input jtag_write_enable; // JTAG write memory request
|
||||
input [`LM32_BYTE_RNG] jtag_write_data; // JTAG wrirte data
|
||||
input [`LM32_WORD_RNG] jtag_address; // JTAG read/write address
|
||||
`endif
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Outputs
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
output [`LM32_PC_RNG] pc_f; // F stage PC
|
||||
reg [`LM32_PC_RNG] pc_f;
|
||||
output [`LM32_PC_RNG] pc_d; // D stage PC
|
||||
reg [`LM32_PC_RNG] pc_d;
|
||||
output [`LM32_PC_RNG] pc_x; // X stage PC
|
||||
reg [`LM32_PC_RNG] pc_x;
|
||||
output [`LM32_PC_RNG] pc_m; // M stage PC
|
||||
reg [`LM32_PC_RNG] pc_m;
|
||||
output [`LM32_PC_RNG] pc_w; // W stage PC
|
||||
reg [`LM32_PC_RNG] pc_w;
|
||||
|
||||
`ifdef CFG_ICACHE_ENABLED
|
||||
output icache_stall_request; // Instruction cache stall request
|
||||
wire icache_stall_request;
|
||||
output icache_restart_request; // Request to restart instruction that cached instruction cache miss
|
||||
wire icache_restart_request;
|
||||
output icache_refill_request; // Instruction cache refill request
|
||||
wire icache_refill_request;
|
||||
output icache_refilling; // Indicates the icache is refilling
|
||||
wire icache_refilling;
|
||||
`endif
|
||||
|
||||
`ifdef CFG_IWB_ENABLED
|
||||
output [`LM32_WORD_RNG] i_dat_o; // Instruction Wishbone interface write data
|
||||
`ifdef CFG_HW_DEBUG_ENABLED
|
||||
reg [`LM32_WORD_RNG] i_dat_o;
|
||||
`else
|
||||
wire [`LM32_WORD_RNG] i_dat_o;
|
||||
`endif
|
||||
output [`LM32_WORD_RNG] i_adr_o; // Instruction Wishbone interface address
|
||||
reg [`LM32_WORD_RNG] i_adr_o;
|
||||
output i_cyc_o; // Instruction Wishbone interface cycle
|
||||
reg i_cyc_o;
|
||||
output [`LM32_BYTE_SELECT_RNG] i_sel_o; // Instruction Wishbone interface byte select
|
||||
`ifdef CFG_HW_DEBUG_ENABLED
|
||||
reg [`LM32_BYTE_SELECT_RNG] i_sel_o;
|
||||
`else
|
||||
wire [`LM32_BYTE_SELECT_RNG] i_sel_o;
|
||||
`endif
|
||||
output i_stb_o; // Instruction Wishbone interface strobe
|
||||
reg i_stb_o;
|
||||
output i_we_o; // Instruction Wishbone interface write enable
|
||||
`ifdef CFG_HW_DEBUG_ENABLED
|
||||
reg i_we_o;
|
||||
`else
|
||||
wire i_we_o;
|
||||
`endif
|
||||
output [`LM32_CTYPE_RNG] i_cti_o; // Instruction Wishbone interface cycle type
|
||||
reg [`LM32_CTYPE_RNG] i_cti_o;
|
||||
output i_lock_o; // Instruction Wishbone interface lock bus
|
||||
reg i_lock_o;
|
||||
output [`LM32_BTYPE_RNG] i_bte_o; // Instruction Wishbone interface burst type
|
||||
wire [`LM32_BTYPE_RNG] i_bte_o;
|
||||
`endif
|
||||
|
||||
`ifdef CFG_HW_DEBUG_ENABLED
|
||||
output [`LM32_BYTE_RNG] jtag_read_data; // Data read for JTAG interface
|
||||
reg [`LM32_BYTE_RNG] jtag_read_data;
|
||||
output jtag_access_complete; // Requested memory access by JTAG interface is complete
|
||||
wire jtag_access_complete;
|
||||
`endif
|
||||
|
||||
`ifdef CFG_BUS_ERRORS_ENABLED
|
||||
output bus_error_d; // Indicates a bus error occured while fetching the instruction
|
||||
reg bus_error_d;
|
||||
`endif
|
||||
`ifdef CFG_EBR_POSEDGE_REGISTER_FILE
|
||||
output [`LM32_INSTRUCTION_RNG] instruction_f; // F stage instruction (only to have register indices extracted from)
|
||||
wire [`LM32_INSTRUCTION_RNG] instruction_f;
|
||||
`endif
|
||||
output [`LM32_INSTRUCTION_RNG] instruction_d; // D stage instruction to be decoded
|
||||
reg [`LM32_INSTRUCTION_RNG] instruction_d;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Internal nets and registers
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
reg [`LM32_PC_RNG] pc_a; // A stage PC
|
||||
|
||||
`ifdef LM32_CACHE_ENABLED
|
||||
reg [`LM32_PC_RNG] restart_address; // Address to restart from after a cache miss
|
||||
`endif
|
||||
|
||||
`ifdef CFG_ICACHE_ENABLED
|
||||
wire icache_read_enable_f; // Indicates if instruction cache miss is valid
|
||||
wire [`LM32_PC_RNG] icache_refill_address; // Address that caused cache miss
|
||||
reg icache_refill_ready; // Indicates when next word of refill data is ready to be written to cache
|
||||
reg [`LM32_INSTRUCTION_RNG] icache_refill_data; // Next word of refill data, fetched from Wishbone
|
||||
wire [`LM32_INSTRUCTION_RNG] icache_data_f; // Instruction fetched from instruction cache
|
||||
wire [`LM32_CTYPE_RNG] first_cycle_type; // First Wishbone cycle type
|
||||
wire [`LM32_CTYPE_RNG] next_cycle_type; // Next Wishbone cycle type
|
||||
wire last_word; // Indicates if this is the last word in the cache line
|
||||
wire [`LM32_PC_RNG] first_address; // First cache refill address
|
||||
`else
|
||||
`ifdef CFG_IWB_ENABLED
|
||||
reg [`LM32_INSTRUCTION_RNG] wb_data_f; // Instruction fetched from Wishbone
|
||||
`endif
|
||||
`endif
|
||||
`ifdef CFG_IROM_ENABLED
|
||||
wire irom_select_a; // Indicates if A stage PC maps to a ROM address
|
||||
reg irom_select_f; // Indicates if F stage PC maps to a ROM address
|
||||
wire [`LM32_INSTRUCTION_RNG] irom_data_f; // Instruction fetched from ROM
|
||||
`endif
|
||||
`ifdef CFG_EBR_POSEDGE_REGISTER_FILE
|
||||
`else
|
||||
wire [`LM32_INSTRUCTION_RNG] instruction_f; // F stage instruction
|
||||
`endif
|
||||
`ifdef CFG_BUS_ERRORS_ENABLED
|
||||
reg bus_error_f; // Indicates if a bus error occured while fetching the instruction in the F stage
|
||||
`endif
|
||||
|
||||
`ifdef CFG_HW_DEBUG_ENABLED
|
||||
reg jtag_access; // Indicates if a JTAG WB access is in progress
|
||||
`endif
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Functions
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
`include "lm32_functions.v"
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Instantiations
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
// Instruction ROM
|
||||
`ifdef CFG_IROM_ENABLED
|
||||
pmi_ram_dp #(
|
||||
// ----- Parameters -------
|
||||
.pmi_wr_addr_depth (1 << (clogb2(`CFG_IROM_LIMIT/4-`CFG_IROM_BASE_ADDRESS/4+1)-1)),
|
||||
.pmi_wr_addr_width ((clogb2(`CFG_IROM_LIMIT/4-`CFG_IROM_BASE_ADDRESS/4+1)-1)),
|
||||
.pmi_wr_data_width (`LM32_INSTRUCTION_WIDTH),
|
||||
.pmi_rd_addr_depth (1 << (clogb2(`CFG_IROM_LIMIT/4-`CFG_IROM_BASE_ADDRESS/4+1)-1)),
|
||||
.pmi_rd_addr_width ((clogb2(`CFG_IROM_LIMIT/4-`CFG_IROM_BASE_ADDRESS/4+1)-1)),
|
||||
.pmi_rd_data_width (`LM32_INSTRUCTION_WIDTH),
|
||||
.pmi_regmode ("noreg"),
|
||||
.pmi_gsr ("enable"),
|
||||
.pmi_resetmode ("async"),
|
||||
.pmi_init_file (`CFG_IROM_INIT_FILE),
|
||||
.pmi_init_file_format ("hex"),
|
||||
.module_type ("pmi_ram_dp")
|
||||
) ram (
|
||||
// ----- Inputs -------
|
||||
.RdClock (clk_i),
|
||||
.WrClock (`FALSE),
|
||||
.Reset (rst_i),
|
||||
.Data ({32{1'b0}}),
|
||||
.RdAddress (pc_a[(clogb2(`CFG_IROM_LIMIT/4-`CFG_IROM_BASE_ADDRESS/4+1)-1)+2-1:2]),
|
||||
.WrAddress ({(clogb2(`CFG_IROM_LIMIT/4-`CFG_IROM_BASE_ADDRESS/4+1)-1){1'b0}}),
|
||||
.RdClockEn (~stall_a),
|
||||
.WrClockEn (`FALSE),
|
||||
.WE (`FALSE),
|
||||
// ----- Outputs -------
|
||||
.Q (irom_data_f)
|
||||
);
|
||||
`endif
|
||||
|
||||
`ifdef CFG_ICACHE_ENABLED
|
||||
// Instruction cache
|
||||
lm32_icache #(
|
||||
.associativity (associativity),
|
||||
.sets (sets),
|
||||
.bytes_per_line (bytes_per_line),
|
||||
.base_address (base_address),
|
||||
.limit (limit)
|
||||
) icache (
|
||||
// ----- Inputs -----
|
||||
.clk_i (clk_i),
|
||||
.rst_i (rst_i),
|
||||
.stall_a (stall_a),
|
||||
.stall_f (stall_f),
|
||||
.address_a (pc_a),
|
||||
.address_f (pc_f),
|
||||
.read_enable_f (icache_read_enable_f),
|
||||
.refill_ready (icache_refill_ready),
|
||||
.refill_data (icache_refill_data),
|
||||
.iflush (iflush),
|
||||
// ----- Outputs -----
|
||||
.stall_request (icache_stall_request),
|
||||
.restart_request (icache_restart_request),
|
||||
.refill_request (icache_refill_request),
|
||||
.refill_address (icache_refill_address),
|
||||
.refilling (icache_refilling),
|
||||
.inst (icache_data_f)
|
||||
);
|
||||
`endif
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Combinational Logic
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
`ifdef CFG_ICACHE_ENABLED
|
||||
// Generate signal that indicates when instruction cache misses are valid
|
||||
assign icache_read_enable_f = (valid_f == `TRUE)
|
||||
&& (kill_f == `FALSE)
|
||||
`ifdef CFG_DCACHE_ENABLED
|
||||
&& (dcache_restart_request == `FALSE)
|
||||
`endif
|
||||
`ifdef CFG_IROM_ENABLED
|
||||
&& (irom_select_f == `FALSE)
|
||||
`endif
|
||||
;
|
||||
`endif
|
||||
|
||||
// Compute address of next instruction to fetch
|
||||
always @(*)
|
||||
begin
|
||||
// The request from the latest pipeline stage must take priority
|
||||
`ifdef CFG_DCACHE_ENABLED
|
||||
if (dcache_restart_request == `TRUE)
|
||||
pc_a = restart_address;
|
||||
else
|
||||
`endif
|
||||
if (branch_taken_m == `TRUE)
|
||||
pc_a = branch_target_m;
|
||||
`ifdef CFG_FAST_UNCONDITIONAL_BRANCH
|
||||
else if (branch_taken_x == `TRUE)
|
||||
pc_a = branch_target_x;
|
||||
`endif
|
||||
else
|
||||
`ifdef CFG_ICACHE_ENABLED
|
||||
if (icache_restart_request == `TRUE)
|
||||
pc_a = restart_address;
|
||||
else
|
||||
`endif
|
||||
pc_a = pc_f + 1'b1;
|
||||
end
|
||||
|
||||
// Select where instruction should be fetched from
|
||||
`ifdef CFG_IROM_ENABLED
|
||||
assign irom_select_a = ({pc_a, 2'b00} >= `CFG_IROM_BASE_ADDRESS) && ({pc_a, 2'b00} <= `CFG_IROM_LIMIT);
|
||||
`endif
|
||||
|
||||
// Select instruction from selected source
|
||||
`ifdef CFG_ICACHE_ENABLED
|
||||
`ifdef CFG_IROM_ENABLED
|
||||
assign instruction_f = irom_select_f == `TRUE ? irom_data_f : icache_data_f;
|
||||
`else
|
||||
assign instruction_f = icache_data_f;
|
||||
`endif
|
||||
`else
|
||||
`ifdef CFG_IROM_ENABLED
|
||||
`ifdef CFG_IWB_ENABLED
|
||||
assign instruction_f = irom_select_f == `TRUE ? irom_data_f : wb_data_f;
|
||||
`else
|
||||
assign instruction_f = irom_data_f;
|
||||
`endif
|
||||
`else
|
||||
assign instruction_f = wb_data_f;
|
||||
`endif
|
||||
`endif
|
||||
|
||||
// Unused/constant Wishbone signals
|
||||
`ifdef CFG_IWB_ENABLED
|
||||
`ifdef CFG_HW_DEBUG_ENABLED
|
||||
`else
|
||||
assign i_dat_o = 32'd0;
|
||||
assign i_we_o = `FALSE;
|
||||
assign i_sel_o = 4'b1111;
|
||||
`endif
|
||||
assign i_bte_o = `LM32_BTYPE_LINEAR;
|
||||
`endif
|
||||
|
||||
`ifdef CFG_ICACHE_ENABLED
|
||||
// Determine parameters for next cache refill Wishbone access
|
||||
// generate
|
||||
// case (bytes_per_line)
|
||||
// 4:
|
||||
// begin
|
||||
// assign first_cycle_type = `LM32_CTYPE_END;
|
||||
// assign next_cycle_type = `LM32_CTYPE_END;
|
||||
// assign last_word = `TRUE;
|
||||
// assign first_address = icache_refill_address;
|
||||
// end
|
||||
// 8:
|
||||
// begin
|
||||
// assign first_cycle_type = `LM32_CTYPE_INCREMENTING;
|
||||
// assign next_cycle_type = `LM32_CTYPE_END;
|
||||
// assign last_word = i_adr_o[addr_offset_msb:addr_offset_lsb] == 1'b1;
|
||||
// assign first_address = {icache_refill_address[`LM32_PC_WIDTH+2-1:addr_offset_msb+1], {addr_offset_width{1'b0}}};
|
||||
// end
|
||||
// 16:
|
||||
// begin
|
||||
assign first_cycle_type = `LM32_CTYPE_INCREMENTING;
|
||||
assign next_cycle_type = i_adr_o[addr_offset_msb] == 1'b1 ? `LM32_CTYPE_END : `LM32_CTYPE_INCREMENTING;
|
||||
assign last_word = i_adr_o[addr_offset_msb:addr_offset_lsb] == 2'b11;
|
||||
assign first_address = {icache_refill_address[`LM32_PC_WIDTH+2-1:addr_offset_msb+1], {addr_offset_width{1'b0}}};
|
||||
// end
|
||||
// endcase
|
||||
// endgenerate
|
||||
`endif
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Sequential Logic
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
// PC
|
||||
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
|
||||
begin
|
||||
if (rst_i == `TRUE)
|
||||
begin
|
||||
pc_f <= (`CFG_EBA_RESET-4)/4;
|
||||
pc_d <= {`LM32_PC_WIDTH{1'b0}};
|
||||
pc_x <= {`LM32_PC_WIDTH{1'b0}};
|
||||
pc_m <= {`LM32_PC_WIDTH{1'b0}};
|
||||
pc_w <= {`LM32_PC_WIDTH{1'b0}};
|
||||
end
|
||||
else
|
||||
begin
|
||||
if (stall_f == `FALSE)
|
||||
pc_f <= pc_a;
|
||||
if (stall_d == `FALSE)
|
||||
pc_d <= pc_f;
|
||||
if (stall_x == `FALSE)
|
||||
pc_x <= pc_d;
|
||||
if (stall_m == `FALSE)
|
||||
pc_m <= pc_x;
|
||||
pc_w <= pc_m;
|
||||
end
|
||||
end
|
||||
|
||||
`ifdef LM32_CACHE_ENABLED
|
||||
// Address to restart from after a cache miss has been handled
|
||||
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
|
||||
begin
|
||||
if (rst_i == `TRUE)
|
||||
restart_address <= {`LM32_PC_WIDTH{1'b0}};
|
||||
else
|
||||
begin
|
||||
`ifdef CFG_DCACHE_ENABLED
|
||||
`ifdef CFG_ICACHE_ENABLED
|
||||
// D-cache restart address must take priority, otherwise instructions will be lost
|
||||
if (dcache_refill_request == `TRUE)
|
||||
restart_address <= pc_w;
|
||||
else if ((icache_refill_request == `TRUE) && (!dcache_refilling))
|
||||
restart_address <= icache_refill_address;
|
||||
`else
|
||||
if (dcache_refill_request == `TRUE)
|
||||
restart_address <= pc_w;
|
||||
`endif
|
||||
`else
|
||||
`ifdef CFG_ICACHE_ENABLED
|
||||
if (icache_refill_request == `TRUE)
|
||||
restart_address <= icache_refill_address;
|
||||
`endif
|
||||
`endif
|
||||
end
|
||||
end
|
||||
`endif
|
||||
|
||||
// Record where instruction was fetched from
|
||||
`ifdef CFG_IROM_ENABLED
|
||||
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
|
||||
begin
|
||||
if (rst_i == `TRUE)
|
||||
irom_select_f <= `FALSE;
|
||||
else
|
||||
begin
|
||||
if (stall_f == `FALSE)
|
||||
irom_select_f <= irom_select_a;
|
||||
end
|
||||
end
|
||||
`endif
|
||||
|
||||
`ifdef CFG_HW_DEBUG_ENABLED
|
||||
assign jtag_access_complete = (i_cyc_o == `TRUE) && ((i_ack_i == `TRUE) || (i_err_i == `TRUE)) && (jtag_access == `TRUE);
|
||||
always @*
|
||||
begin
|
||||
case (jtag_address[1:0])
|
||||
2'b00: jtag_read_data = i_dat_i[`LM32_BYTE_3_RNG];
|
||||
2'b01: jtag_read_data = i_dat_i[`LM32_BYTE_2_RNG];
|
||||
2'b10: jtag_read_data = i_dat_i[`LM32_BYTE_1_RNG];
|
||||
2'b11: jtag_read_data = i_dat_i[`LM32_BYTE_0_RNG];
|
||||
endcase
|
||||
end
|
||||
`endif
|
||||
|
||||
`ifdef CFG_IWB_ENABLED
|
||||
// Instruction Wishbone interface
|
||||
`ifdef CFG_ICACHE_ENABLED
|
||||
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
|
||||
begin
|
||||
if (rst_i == `TRUE)
|
||||
begin
|
||||
i_cyc_o <= `FALSE;
|
||||
i_stb_o <= `FALSE;
|
||||
i_adr_o <= {`LM32_WORD_WIDTH{1'b0}};
|
||||
i_cti_o <= `LM32_CTYPE_END;
|
||||
i_lock_o <= `FALSE;
|
||||
icache_refill_data <= {`LM32_INSTRUCTION_WIDTH{1'b0}};
|
||||
icache_refill_ready <= `FALSE;
|
||||
`ifdef CFG_BUS_ERRORS_ENABLED
|
||||
bus_error_f <= `FALSE;
|
||||
`endif
|
||||
`ifdef CFG_HW_DEBUG_ENABLED
|
||||
i_we_o <= `FALSE;
|
||||
i_sel_o <= 4'b1111;
|
||||
jtag_access <= `FALSE;
|
||||
`endif
|
||||
end
|
||||
else
|
||||
begin
|
||||
icache_refill_ready <= `FALSE;
|
||||
// Is a cycle in progress?
|
||||
if (i_cyc_o == `TRUE)
|
||||
begin
|
||||
// Has cycle completed?
|
||||
if ((i_ack_i == `TRUE) || (i_err_i == `TRUE))
|
||||
begin
|
||||
`ifdef CFG_HW_DEBUG_ENABLED
|
||||
if (jtag_access == `TRUE)
|
||||
begin
|
||||
i_cyc_o <= `FALSE;
|
||||
i_stb_o <= `FALSE;
|
||||
i_we_o <= `FALSE;
|
||||
jtag_access <= `FALSE;
|
||||
end
|
||||
else
|
||||
`endif
|
||||
begin
|
||||
if (last_word == `TRUE)
|
||||
begin
|
||||
// Cache line fill complete
|
||||
i_cyc_o <= `FALSE;
|
||||
i_stb_o <= `FALSE;
|
||||
i_lock_o <= `FALSE;
|
||||
end
|
||||
// Fetch next word in cache line
|
||||
i_adr_o[addr_offset_msb:addr_offset_lsb] <= i_adr_o[addr_offset_msb:addr_offset_lsb] + 1'b1;
|
||||
i_cti_o <= next_cycle_type;
|
||||
// Write fetched data into instruction cache
|
||||
icache_refill_ready <= `TRUE;
|
||||
icache_refill_data <= i_dat_i;
|
||||
end
|
||||
end
|
||||
`ifdef CFG_BUS_ERRORS_ENABLED
|
||||
if (i_err_i == `TRUE)
|
||||
begin
|
||||
bus_error_f <= `TRUE;
|
||||
$display ("Instruction bus error. Address: %x", i_adr_o);
|
||||
end
|
||||
`endif
|
||||
end
|
||||
else
|
||||
begin
|
||||
if ((icache_refill_request == `TRUE) && (icache_refill_ready == `FALSE))
|
||||
begin
|
||||
// Read first word of cache line
|
||||
`ifdef CFG_HW_DEBUG_ENABLED
|
||||
i_sel_o <= 4'b1111;
|
||||
`endif
|
||||
i_adr_o <= {first_address, 2'b00};
|
||||
i_cyc_o <= `TRUE;
|
||||
i_stb_o <= `TRUE;
|
||||
i_cti_o <= first_cycle_type;
|
||||
//i_lock_o <= `TRUE;
|
||||
`ifdef CFG_BUS_ERRORS_ENABLED
|
||||
bus_error_f <= `FALSE;
|
||||
`endif
|
||||
end
|
||||
`ifdef CFG_HW_DEBUG_ENABLED
|
||||
else
|
||||
begin
|
||||
if ((jtag_read_enable == `TRUE) || (jtag_write_enable == `TRUE))
|
||||
begin
|
||||
case (jtag_address[1:0])
|
||||
2'b00: i_sel_o <= 4'b1000;
|
||||
2'b01: i_sel_o <= 4'b0100;
|
||||
2'b10: i_sel_o <= 4'b0010;
|
||||
2'b11: i_sel_o <= 4'b0001;
|
||||
endcase
|
||||
i_adr_o <= jtag_address;
|
||||
i_dat_o <= {4{jtag_write_data}};
|
||||
i_cyc_o <= `TRUE;
|
||||
i_stb_o <= `TRUE;
|
||||
i_we_o <= jtag_write_enable;
|
||||
i_cti_o <= `LM32_CTYPE_END;
|
||||
jtag_access <= `TRUE;
|
||||
end
|
||||
end
|
||||
`endif
|
||||
`ifdef CFG_BUS_ERRORS_ENABLED
|
||||
// Clear bus error when exception taken, otherwise they would be
|
||||
// continually generated if exception handler is cached
|
||||
`ifdef CFG_FAST_UNCONDITIONAL_BRANCH
|
||||
if (branch_taken_x == `TRUE)
|
||||
bus_error_f <= `FALSE;
|
||||
`endif
|
||||
if (branch_taken_m == `TRUE)
|
||||
bus_error_f <= `FALSE;
|
||||
`endif
|
||||
end
|
||||
end
|
||||
end
|
||||
`else
|
||||
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
|
||||
begin
|
||||
if (rst_i == `TRUE)
|
||||
begin
|
||||
i_cyc_o <= `FALSE;
|
||||
i_stb_o <= `FALSE;
|
||||
i_adr_o <= {`LM32_WORD_WIDTH{1'b0}};
|
||||
i_cti_o <= `LM32_CTYPE_CLASSIC;
|
||||
i_lock_o <= `FALSE;
|
||||
wb_data_f <= {`LM32_INSTRUCTION_WIDTH{1'b0}};
|
||||
`ifdef CFG_BUS_ERRORS_ENABLED
|
||||
bus_error_f <= `FALSE;
|
||||
`endif
|
||||
end
|
||||
else
|
||||
begin
|
||||
// Is a cycle in progress?
|
||||
if (i_cyc_o == `TRUE)
|
||||
begin
|
||||
// Has cycle completed?
|
||||
if((i_ack_i == `TRUE) || (i_err_i == `TRUE))
|
||||
begin
|
||||
// Cycle complete
|
||||
i_cyc_o <= `FALSE;
|
||||
i_stb_o <= `FALSE;
|
||||
// Register fetched instruction
|
||||
wb_data_f <= i_dat_i;
|
||||
end
|
||||
`ifdef CFG_BUS_ERRORS_ENABLED
|
||||
if (i_err_i == `TRUE)
|
||||
begin
|
||||
bus_error_f <= `TRUE;
|
||||
$display ("Instruction bus error. Address: %x", i_adr_o);
|
||||
end
|
||||
`endif
|
||||
end
|
||||
else
|
||||
begin
|
||||
// Wait for an instruction fetch from an external address
|
||||
if ( (stall_a == `FALSE)
|
||||
`ifdef CFG_IROM_ENABLED
|
||||
&& (irom_select_a == `FALSE)
|
||||
`endif
|
||||
)
|
||||
begin
|
||||
// Fetch instruction
|
||||
`ifdef CFG_HW_DEBUG_ENABLED
|
||||
i_sel_o <= 4'b1111;
|
||||
`endif
|
||||
i_adr_o <= {pc_a, 2'b00};
|
||||
i_cyc_o <= `TRUE;
|
||||
i_stb_o <= `TRUE;
|
||||
`ifdef CFG_BUS_ERRORS_ENABLED
|
||||
bus_error_f <= `FALSE;
|
||||
`endif
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
`endif
|
||||
`endif
|
||||
|
||||
// Instruction register
|
||||
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
|
||||
begin
|
||||
if (rst_i == `TRUE)
|
||||
begin
|
||||
instruction_d <= {`LM32_INSTRUCTION_WIDTH{1'b0}};
|
||||
`ifdef CFG_BUS_ERRORS_ENABLED
|
||||
bus_error_d <= `FALSE;
|
||||
`endif
|
||||
end
|
||||
else
|
||||
begin
|
||||
if (stall_d == `FALSE)
|
||||
begin
|
||||
instruction_d <= instruction_f;
|
||||
`ifdef CFG_BUS_ERRORS_ENABLED
|
||||
bus_error_d <= bus_error_f;
|
||||
`endif
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
333
lm32/logic/sakc/rtl/lm32/lm32_interrupt.v
Normal file
333
lm32/logic/sakc/rtl/lm32/lm32_interrupt.v
Normal file
@ -0,0 +1,333 @@
|
||||
// =============================================================================
|
||||
// COPYRIGHT NOTICE
|
||||
// Copyright 2006 (c) Lattice Semiconductor Corporation
|
||||
// ALL RIGHTS RESERVED
|
||||
// This confidential and proprietary software may be used only as authorised by
|
||||
// a licensing agreement from Lattice Semiconductor Corporation.
|
||||
// The entire notice above must be reproduced on all authorized copies and
|
||||
// copies may only be made to the extent permitted by a licensing agreement from
|
||||
// Lattice Semiconductor Corporation.
|
||||
//
|
||||
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
|
||||
// 5555 NE Moore Court 408-826-6000 (other locations)
|
||||
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
|
||||
// U.S.A email: techsupport@latticesemi.com
|
||||
// =============================================================================/
|
||||
// FILE DETAILS
|
||||
// Project : LatticeMico32
|
||||
// File : lm32_interrupt.v
|
||||
// Title : Interrupt logic
|
||||
// Dependencies : lm32_include.v
|
||||
// Version : 6.1.17
|
||||
// =============================================================================
|
||||
|
||||
`include "system_conf.v"
|
||||
`include "lm32_include.v"
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Module interface
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
module lm32_interrupt (
|
||||
// ----- Inputs -------
|
||||
clk_i,
|
||||
rst_i,
|
||||
// From external devices
|
||||
interrupt_n,
|
||||
// From pipeline
|
||||
stall_x,
|
||||
`ifdef CFG_DEBUG_ENABLED
|
||||
non_debug_exception,
|
||||
debug_exception,
|
||||
`else
|
||||
exception,
|
||||
`endif
|
||||
eret_q_x,
|
||||
`ifdef CFG_DEBUG_ENABLED
|
||||
bret_q_x,
|
||||
`endif
|
||||
csr,
|
||||
csr_write_data,
|
||||
csr_write_enable,
|
||||
// ----- Outputs -------
|
||||
interrupt_exception,
|
||||
// To pipeline
|
||||
csr_read_data
|
||||
);
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Parameters
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
parameter interrupts = `CFG_INTERRUPTS; // Number of interrupts
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Inputs
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
input clk_i; // Clock
|
||||
input rst_i; // Reset
|
||||
|
||||
input [interrupts-1:0] interrupt_n; // Interrupt pins, active-low
|
||||
|
||||
input stall_x; // Stall X pipeline stage
|
||||
|
||||
`ifdef CFG_DEBUG_ENABLED
|
||||
input non_debug_exception; // Non-debug related exception has been raised
|
||||
input debug_exception; // Debug-related exception has been raised
|
||||
`else
|
||||
input exception; // Exception has been raised
|
||||
`endif
|
||||
input eret_q_x; // Return from exception
|
||||
`ifdef CFG_DEBUG_ENABLED
|
||||
input bret_q_x; // Return from breakpoint
|
||||
`endif
|
||||
|
||||
input [`LM32_CSR_RNG] csr; // CSR read/write index
|
||||
input [`LM32_WORD_RNG] csr_write_data; // Data to write to specified CSR
|
||||
input csr_write_enable; // CSR write enable
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Outputs
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
output interrupt_exception; // Request to raide an interrupt exception
|
||||
wire interrupt_exception;
|
||||
|
||||
output [`LM32_WORD_RNG] csr_read_data; // Data read from CSR
|
||||
reg [`LM32_WORD_RNG] csr_read_data;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Internal nets and registers
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
wire [interrupts-1:0] asserted; // Which interrupts are currently being asserted
|
||||
wire [interrupts-1:0] interrupt_n_exception;
|
||||
|
||||
// Interrupt CSRs
|
||||
|
||||
reg ie; // Interrupt enable
|
||||
reg eie; // Exception interrupt enable
|
||||
`ifdef CFG_DEBUG_ENABLED
|
||||
reg bie; // Breakpoint interrupt enable
|
||||
`endif
|
||||
reg [interrupts-1:0] ip; // Interrupt pending
|
||||
reg [interrupts-1:0] im; // Interrupt mask
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Combinational Logic
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
// Determine which interrupts have occured and are unmasked
|
||||
assign interrupt_n_exception = ip & im;
|
||||
|
||||
// Determine if any unmasked interrupts have occured
|
||||
assign interrupt_exception = (|interrupt_n_exception) & ie;
|
||||
|
||||
// Determine which interrupts are currently being asserted (active-low) or are already pending
|
||||
assign asserted = ip | ~interrupt_n;
|
||||
|
||||
//assign ie_csr_read_data = {{`LM32_WORD_WIDTH-3{1'b0}},
|
||||
//`ifdef CFG_DEBUG_ENABLED
|
||||
// bie,
|
||||
//`else
|
||||
// 1'b0,
|
||||
//`endif
|
||||
// eie,
|
||||
// ie
|
||||
// };
|
||||
wire ip_csr_read_data = ip;
|
||||
wire im_csr_read_data = im;
|
||||
// XXX JB XXX
|
||||
// generate
|
||||
// if (interrupts > 1)
|
||||
// begin
|
||||
// CSR read
|
||||
always @*
|
||||
begin
|
||||
case (csr)
|
||||
`LM32_CSR_IE: csr_read_data = {{`LM32_WORD_WIDTH-3{1'b0}},
|
||||
`ifdef CFG_DEBUG_ENABLED
|
||||
bie,
|
||||
`else
|
||||
1'b0,
|
||||
`endif
|
||||
eie,
|
||||
ie
|
||||
};
|
||||
`LM32_CSR_IP: csr_read_data = ip;
|
||||
`LM32_CSR_IM: csr_read_data = im;
|
||||
default: csr_read_data = {`LM32_WORD_WIDTH{1'bx}};
|
||||
endcase
|
||||
end
|
||||
// XXX JB XXX
|
||||
// end
|
||||
// else
|
||||
// begin
|
||||
//// CSR read
|
||||
//always @*
|
||||
//begin
|
||||
// case (csr)
|
||||
// `LM32_CSR_IE: csr_read_data = {{`LM32_WORD_WIDTH-3{1'b0}},
|
||||
//`ifdef CFG_DEBUG_ENABLED
|
||||
// bie,
|
||||
//`else
|
||||
// 1'b0,
|
||||
//`endif
|
||||
// eie,
|
||||
// ie
|
||||
// };
|
||||
// `LM32_CSR_IP: csr_read_data = ip;
|
||||
// default: csr_read_data = {`LM32_WORD_WIDTH{1'bx}};
|
||||
// endcase
|
||||
//end
|
||||
// end
|
||||
//endgenerate
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Sequential Logic
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
// XXX JB XXX
|
||||
//generate
|
||||
// if (interrupts > 1)
|
||||
// begin
|
||||
// IE, IM, IP - Interrupt Enable, Interrupt Mask and Interrupt Pending CSRs
|
||||
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
|
||||
begin
|
||||
if (rst_i == `TRUE)
|
||||
begin
|
||||
ie <= `FALSE;
|
||||
eie <= `FALSE;
|
||||
`ifdef CFG_DEBUG_ENABLED
|
||||
bie <= `FALSE;
|
||||
`endif
|
||||
im <= {interrupts{1'b0}};
|
||||
ip <= {interrupts{1'b0}};
|
||||
end
|
||||
else
|
||||
begin
|
||||
// Set IP bit when interrupt line is asserted
|
||||
ip <= asserted;
|
||||
`ifdef CFG_DEBUG_ENABLED
|
||||
if (non_debug_exception == `TRUE)
|
||||
begin
|
||||
// Save and then clear interrupt enable
|
||||
eie <= ie;
|
||||
ie <= `FALSE;
|
||||
end
|
||||
else if (debug_exception == `TRUE)
|
||||
begin
|
||||
// Save and then clear interrupt enable
|
||||
bie <= ie;
|
||||
ie <= `FALSE;
|
||||
end
|
||||
`else
|
||||
if (exception == `TRUE)
|
||||
begin
|
||||
// Save and then clear interrupt enable
|
||||
eie <= ie;
|
||||
ie <= `FALSE;
|
||||
end
|
||||
`endif
|
||||
else if (stall_x == `FALSE)
|
||||
begin
|
||||
if (eret_q_x == `TRUE)
|
||||
// Restore interrupt enable
|
||||
ie <= eie;
|
||||
`ifdef CFG_DEBUG_ENABLED
|
||||
else if (bret_q_x == `TRUE)
|
||||
// Restore interrupt enable
|
||||
ie <= bie;
|
||||
`endif
|
||||
else if (csr_write_enable == `TRUE)
|
||||
begin
|
||||
// Handle wcsr write
|
||||
if (csr == `LM32_CSR_IE)
|
||||
begin
|
||||
ie <= csr_write_data[0];
|
||||
eie <= csr_write_data[1];
|
||||
`ifdef CFG_DEBUG_ENABLED
|
||||
bie <= csr_write_data[2];
|
||||
`endif
|
||||
end
|
||||
if (csr == `LM32_CSR_IM)
|
||||
im <= csr_write_data[interrupts-1:0];
|
||||
if (csr == `LM32_CSR_IP)
|
||||
ip <= asserted & ~csr_write_data[interrupts-1:0];
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
// end
|
||||
//else
|
||||
// begin
|
||||
//// IE, IM, IP - Interrupt Enable, Interrupt Mask and Interrupt Pending CSRs
|
||||
//always @(posedge clk_i `CFG_RESET_SENSITIVITY)
|
||||
//begin
|
||||
// if (rst_i == `TRUE)
|
||||
// begin
|
||||
// ie <= `FALSE;
|
||||
// eie <= `FALSE;
|
||||
//`ifdef CFG_DEBUG_ENABLED
|
||||
// bie <= `FALSE;
|
||||
//`endif
|
||||
// ip <= {interrupts{1'b0}};
|
||||
// end
|
||||
// else
|
||||
// begin
|
||||
// // Set IP bit when interrupt line is asserted
|
||||
// ip <= asserted;
|
||||
//`ifdef CFG_DEBUG_ENABLED
|
||||
// if (non_debug_exception == `TRUE)
|
||||
// begin
|
||||
// // Save and then clear interrupt enable
|
||||
// eie <= ie;
|
||||
// ie <= `FALSE;
|
||||
// end
|
||||
// else if (debug_exception == `TRUE)
|
||||
// begin
|
||||
// // Save and then clear interrupt enable
|
||||
// bie <= ie;
|
||||
// ie <= `FALSE;
|
||||
// end
|
||||
//`else
|
||||
// if (exception == `TRUE)
|
||||
// begin
|
||||
// // Save and then clear interrupt enable
|
||||
// eie <= ie;
|
||||
// ie <= `FALSE;
|
||||
// end
|
||||
//`endif
|
||||
// else if (stall_x == `FALSE)
|
||||
// begin
|
||||
// if (eret_q_x == `TRUE)
|
||||
// // Restore interrupt enable
|
||||
// ie <= eie;
|
||||
//`ifdef CFG_DEBUG_ENABLED
|
||||
// else if (bret_q_x == `TRUE)
|
||||
// // Restore interrupt enable
|
||||
// ie <= bie;
|
||||
//`endif
|
||||
// else if (csr_write_enable == `TRUE)
|
||||
// begin
|
||||
// // Handle wcsr write
|
||||
// if (csr == `LM32_CSR_IE)
|
||||
// begin
|
||||
// ie <= csr_write_data[0];
|
||||
// eie <= csr_write_data[1];
|
||||
//`ifdef CFG_DEBUG_ENABLED
|
||||
// bie <= csr_write_data[2];
|
||||
//`endif
|
||||
// end
|
||||
// if (csr == `LM32_CSR_IP)
|
||||
// ip <= asserted & ~csr_write_data[interrupts-1:0];
|
||||
// end
|
||||
// end
|
||||
// end
|
||||
//end
|
||||
// end
|
||||
//endgenerate
|
||||
|
||||
endmodule
|
||||
|
491
lm32/logic/sakc/rtl/lm32/lm32_jtag.v
Normal file
491
lm32/logic/sakc/rtl/lm32/lm32_jtag.v
Normal file
@ -0,0 +1,491 @@
|
||||
// =============================================================================
|
||||
// COPYRIGHT NOTICE
|
||||
// Copyright 2006 (c) Lattice Semiconductor Corporation
|
||||
// ALL RIGHTS RESERVED
|
||||
// This confidential and proprietary software may be used only as authorised by
|
||||
// a licensing agreement from Lattice Semiconductor Corporation.
|
||||
// The entire notice above must be reproduced on all authorized copies and
|
||||
// copies may only be made to the extent permitted by a licensing agreement from
|
||||
// Lattice Semiconductor Corporation.
|
||||
//
|
||||
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
|
||||
// 5555 NE Moore Court 408-826-6000 (other locations)
|
||||
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
|
||||
// U.S.A email: techsupport@latticesemi.com
|
||||
// =============================================================================/
|
||||
// FILE DETAILS
|
||||
// Project : LatticeMico32
|
||||
// File : lm32_jtag.v
|
||||
// Title : JTAG interface
|
||||
// Dependencies : lm32_include.v
|
||||
// Version : 6.1.17
|
||||
// =============================================================================
|
||||
|
||||
`include "lm32_include.v"
|
||||
|
||||
`ifdef CFG_JTAG_ENABLED
|
||||
|
||||
`define LM32_DP 3'b000
|
||||
`define LM32_TX 3'b001
|
||||
`define LM32_RX 3'b010
|
||||
|
||||
// LM32 Debug Protocol commands IDs
|
||||
`define LM32_DP_RNG 3:0
|
||||
`define LM32_DP_READ_MEMORY 4'b0001
|
||||
`define LM32_DP_WRITE_MEMORY 4'b0010
|
||||
`define LM32_DP_READ_SEQUENTIAL 4'b0011
|
||||
`define LM32_DP_WRITE_SEQUENTIAL 4'b0100
|
||||
`define LM32_DP_WRITE_CSR 4'b0101
|
||||
`define LM32_DP_BREAK 4'b0110
|
||||
`define LM32_DP_RESET 4'b0111
|
||||
|
||||
// States for FSM
|
||||
`define LM32_JTAG_STATE_RNG 3:0
|
||||
`define LM32_JTAG_STATE_READ_COMMAND 4'h0
|
||||
`define LM32_JTAG_STATE_READ_BYTE_0 4'h1
|
||||
`define LM32_JTAG_STATE_READ_BYTE_1 4'h2
|
||||
`define LM32_JTAG_STATE_READ_BYTE_2 4'h3
|
||||
`define LM32_JTAG_STATE_READ_BYTE_3 4'h4
|
||||
`define LM32_JTAG_STATE_READ_BYTE_4 4'h5
|
||||
`define LM32_JTAG_STATE_PROCESS_COMMAND 4'h6
|
||||
`define LM32_JTAG_STATE_WAIT_FOR_MEMORY 4'h7
|
||||
`define LM32_JTAG_STATE_WAIT_FOR_CSR 4'h8
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Module interface
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
module lm32_jtag (
|
||||
// ----- Inputs -------
|
||||
clk_i,
|
||||
rst_i,
|
||||
jtag_clk,
|
||||
jtag_update,
|
||||
jtag_reg_q,
|
||||
jtag_reg_addr_q,
|
||||
`ifdef CFG_JTAG_UART_ENABLED
|
||||
csr,
|
||||
csr_write_enable,
|
||||
csr_write_data,
|
||||
stall_x,
|
||||
`endif
|
||||
`ifdef CFG_HW_DEBUG_ENABLED
|
||||
jtag_read_data,
|
||||
jtag_access_complete,
|
||||
`endif
|
||||
`ifdef CFG_DEBUG_ENABLED
|
||||
exception_q_w,
|
||||
`endif
|
||||
// ----- Outputs -------
|
||||
`ifdef CFG_JTAG_UART_ENABLED
|
||||
jtx_csr_read_data,
|
||||
jrx_csr_read_data,
|
||||
`endif
|
||||
`ifdef CFG_HW_DEBUG_ENABLED
|
||||
jtag_csr_write_enable,
|
||||
jtag_csr_write_data,
|
||||
jtag_csr,
|
||||
jtag_read_enable,
|
||||
jtag_write_enable,
|
||||
jtag_write_data,
|
||||
jtag_address,
|
||||
`endif
|
||||
`ifdef CFG_DEBUG_ENABLED
|
||||
jtag_break,
|
||||
jtag_reset,
|
||||
`endif
|
||||
jtag_reg_d,
|
||||
jtag_reg_addr_d
|
||||
);
|
||||
|
||||
parameter lat_family = `LATTICE_FAMILY;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Inputs
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
input clk_i; // Clock
|
||||
input rst_i; // Reset
|
||||
|
||||
input jtag_clk; // JTAG clock
|
||||
input jtag_update; // JTAG data register has been updated
|
||||
input [`LM32_BYTE_RNG] jtag_reg_q; // JTAG data register
|
||||
input [2:0] jtag_reg_addr_q; // JTAG data register
|
||||
|
||||
`ifdef CFG_JTAG_UART_ENABLED
|
||||
input [`LM32_CSR_RNG] csr; // CSR to write
|
||||
input csr_write_enable; // CSR write enable
|
||||
input [`LM32_WORD_RNG] csr_write_data; // Data to write to specified CSR
|
||||
input stall_x; // Stall instruction in X stage
|
||||
`endif
|
||||
`ifdef CFG_HW_DEBUG_ENABLED
|
||||
input [`LM32_BYTE_RNG] jtag_read_data; // Data read from requested address
|
||||
input jtag_access_complete; // Memory access if complete
|
||||
`endif
|
||||
`ifdef CFG_DEBUG_ENABLED
|
||||
input exception_q_w; // Indicates an exception has occured in W stage
|
||||
`endif
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Outputs
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
`ifdef CFG_JTAG_UART_ENABLED
|
||||
output [`LM32_WORD_RNG] jtx_csr_read_data; // Value of JTX CSR for rcsr instructions
|
||||
wire [`LM32_WORD_RNG] jtx_csr_read_data;
|
||||
output [`LM32_WORD_RNG] jrx_csr_read_data; // Value of JRX CSR for rcsr instructions
|
||||
wire [`LM32_WORD_RNG] jrx_csr_read_data;
|
||||
`endif
|
||||
`ifdef CFG_HW_DEBUG_ENABLED
|
||||
output jtag_csr_write_enable; // CSR write enable
|
||||
reg jtag_csr_write_enable;
|
||||
output [`LM32_WORD_RNG] jtag_csr_write_data; // Data to write to specified CSR
|
||||
wire [`LM32_WORD_RNG] jtag_csr_write_data;
|
||||
output [`LM32_CSR_RNG] jtag_csr; // CSR to write
|
||||
wire [`LM32_CSR_RNG] jtag_csr;
|
||||
output jtag_read_enable; // Memory read enable
|
||||
reg jtag_read_enable;
|
||||
output jtag_write_enable; // Memory write enable
|
||||
reg jtag_write_enable;
|
||||
output [`LM32_BYTE_RNG] jtag_write_data; // Data to write to specified address
|
||||
wire [`LM32_BYTE_RNG] jtag_write_data;
|
||||
output [`LM32_WORD_RNG] jtag_address; // Memory read/write address
|
||||
wire [`LM32_WORD_RNG] jtag_address;
|
||||
`endif
|
||||
`ifdef CFG_DEBUG_ENABLED
|
||||
output jtag_break; // Request to raise a breakpoint exception
|
||||
reg jtag_break;
|
||||
output jtag_reset; // Request to raise a reset exception
|
||||
reg jtag_reset;
|
||||
`endif
|
||||
output [`LM32_BYTE_RNG] jtag_reg_d;
|
||||
reg [`LM32_BYTE_RNG] jtag_reg_d;
|
||||
output [2:0] jtag_reg_addr_d;
|
||||
wire [2:0] jtag_reg_addr_d;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Internal nets and registers
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
reg rx_toggle; // Clock-domain crossing registers
|
||||
reg rx_toggle_r; // Registered version of rx_toggle
|
||||
reg rx_toggle_r_r; // Registered version of rx_toggle_r
|
||||
reg rx_toggle_r_r_r; // Registered version of rx_toggle_r_r
|
||||
|
||||
reg [`LM32_BYTE_RNG] rx_byte;
|
||||
reg [2:0] rx_addr;
|
||||
|
||||
`ifdef CFG_JTAG_UART_ENABLED
|
||||
reg [`LM32_BYTE_RNG] uart_tx_byte; // UART TX data
|
||||
reg uart_tx_valid; // TX data is valid
|
||||
reg [`LM32_BYTE_RNG] uart_rx_byte; // UART RX data
|
||||
reg uart_rx_valid; // RX data is valid
|
||||
`endif
|
||||
|
||||
reg [`LM32_DP_RNG] command; // The last received command
|
||||
`ifdef CFG_HW_DEBUG_ENABLED
|
||||
reg [`LM32_BYTE_RNG] jtag_byte_0; // Registers to hold command paramaters
|
||||
reg [`LM32_BYTE_RNG] jtag_byte_1;
|
||||
reg [`LM32_BYTE_RNG] jtag_byte_2;
|
||||
reg [`LM32_BYTE_RNG] jtag_byte_3;
|
||||
reg [`LM32_BYTE_RNG] jtag_byte_4;
|
||||
reg processing; // Indicates if we're still processing a memory read/write
|
||||
`endif
|
||||
|
||||
reg [`LM32_JTAG_STATE_RNG] state; // Current state of FSM
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Combinational Logic
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
`ifdef CFG_HW_DEBUG_ENABLED
|
||||
assign jtag_csr_write_data = {jtag_byte_0, jtag_byte_1, jtag_byte_2, jtag_byte_3};
|
||||
assign jtag_csr = jtag_byte_4[`LM32_CSR_RNG];
|
||||
assign jtag_address = {jtag_byte_0, jtag_byte_1, jtag_byte_2, jtag_byte_3};
|
||||
assign jtag_write_data = jtag_byte_4;
|
||||
`endif
|
||||
|
||||
// Generate status flags for reading via the JTAG interface
|
||||
`ifdef CFG_JTAG_UART_ENABLED
|
||||
assign jtag_reg_addr_d[1:0] = {uart_rx_valid, uart_tx_valid};
|
||||
`else
|
||||
assign jtag_reg_addr_d[1:0] = 2'b00;
|
||||
`endif
|
||||
`ifdef CFG_HW_DEBUG_ENABLED
|
||||
assign jtag_reg_addr_d[2] = processing;
|
||||
`else
|
||||
assign jtag_reg_addr_d[2] = 1'b0;
|
||||
`endif
|
||||
|
||||
`ifdef CFG_JTAG_UART_ENABLED
|
||||
assign jtx_csr_read_data = {{`LM32_WORD_WIDTH-9{1'b0}}, uart_tx_valid, 8'h00};
|
||||
assign jrx_csr_read_data = {{`LM32_WORD_WIDTH-9{1'b0}}, uart_rx_valid, uart_rx_byte};
|
||||
`endif
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Sequential Logic
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
// Toggle a flag when a JTAG write occurs
|
||||
generate
|
||||
if (lat_family == "EC" || lat_family == "ECP" ||
|
||||
lat_family == "XP" || lat_family == "ECP2" || lat_family == "ECP2M") begin
|
||||
|
||||
always @(posedge jtag_clk `CFG_RESET_SENSITIVITY)
|
||||
begin
|
||||
if (rst_i == `TRUE)
|
||||
rx_toggle <= 1'b0;
|
||||
else
|
||||
if (jtag_update == `TRUE)
|
||||
rx_toggle <= ~rx_toggle;
|
||||
end
|
||||
|
||||
end else begin // for SC & SCM
|
||||
|
||||
always @(negedge jtag_update `CFG_RESET_SENSITIVITY)
|
||||
begin
|
||||
if (rst_i == `TRUE)
|
||||
rx_toggle <= 1'b0;
|
||||
else
|
||||
rx_toggle <= ~rx_toggle;
|
||||
end
|
||||
|
||||
end
|
||||
endgenerate
|
||||
|
||||
always @(*)
|
||||
begin
|
||||
rx_byte = jtag_reg_q;
|
||||
rx_addr = jtag_reg_addr_q;
|
||||
end
|
||||
|
||||
// Clock domain crossing from JTAG clock domain to CPU clock domain
|
||||
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
|
||||
begin
|
||||
if (rst_i == `TRUE)
|
||||
begin
|
||||
rx_toggle_r <= 1'b0;
|
||||
rx_toggle_r_r <= 1'b0;
|
||||
rx_toggle_r_r_r <= 1'b0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
rx_toggle_r <= rx_toggle;
|
||||
rx_toggle_r_r <= rx_toggle_r;
|
||||
rx_toggle_r_r_r <= rx_toggle_r_r;
|
||||
end
|
||||
end
|
||||
|
||||
// LM32 debug protocol state machine
|
||||
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
|
||||
begin
|
||||
if (rst_i == `TRUE)
|
||||
begin
|
||||
state <= `LM32_JTAG_STATE_READ_COMMAND;
|
||||
command <= 4'b0000;
|
||||
jtag_reg_d <= 8'h00;
|
||||
`ifdef CFG_HW_DEBUG_ENABLED
|
||||
processing <= `FALSE;
|
||||
jtag_csr_write_enable <= `FALSE;
|
||||
jtag_read_enable <= `FALSE;
|
||||
jtag_write_enable <= `FALSE;
|
||||
`endif
|
||||
`ifdef CFG_DEBUG_ENABLED
|
||||
jtag_break <= `FALSE;
|
||||
jtag_reset <= `FALSE;
|
||||
`endif
|
||||
`ifdef CFG_JTAG_UART_ENABLED
|
||||
uart_tx_byte <= 8'h00;
|
||||
uart_tx_valid <= `FALSE;
|
||||
uart_rx_byte <= 8'h00;
|
||||
uart_rx_valid <= `FALSE;
|
||||
`endif
|
||||
end
|
||||
else
|
||||
begin
|
||||
`ifdef CFG_JTAG_UART_ENABLED
|
||||
if ((csr_write_enable == `TRUE) && (stall_x == `FALSE))
|
||||
begin
|
||||
case (csr)
|
||||
`LM32_CSR_JTX:
|
||||
begin
|
||||
// Set flag indicating data is available
|
||||
uart_tx_byte <= csr_write_data[`LM32_BYTE_0_RNG];
|
||||
uart_tx_valid <= `TRUE;
|
||||
end
|
||||
`LM32_CSR_JRX:
|
||||
begin
|
||||
// Clear flag indidicating data has been received
|
||||
uart_rx_valid <= `FALSE;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
`endif
|
||||
`ifdef CFG_DEBUG_ENABLED
|
||||
// When an exception has occured, clear the requests
|
||||
if (exception_q_w == `TRUE)
|
||||
begin
|
||||
jtag_break <= `FALSE;
|
||||
jtag_reset <= `FALSE;
|
||||
end
|
||||
`endif
|
||||
case (state)
|
||||
`LM32_JTAG_STATE_READ_COMMAND:
|
||||
begin
|
||||
// Wait for rx register to toggle which indicates new data is available
|
||||
if (rx_toggle_r_r != rx_toggle_r_r_r)
|
||||
begin
|
||||
command <= rx_byte[7:4];
|
||||
case (rx_addr)
|
||||
`ifdef CFG_DEBUG_ENABLED
|
||||
`LM32_DP:
|
||||
begin
|
||||
case (rx_byte[7:4])
|
||||
`ifdef CFG_HW_DEBUG_ENABLED
|
||||
`LM32_DP_READ_MEMORY:
|
||||
state <= `LM32_JTAG_STATE_READ_BYTE_0;
|
||||
`LM32_DP_READ_SEQUENTIAL:
|
||||
begin
|
||||
{jtag_byte_2, jtag_byte_3} <= {jtag_byte_2, jtag_byte_3} + 1'b1;
|
||||
state <= `LM32_JTAG_STATE_PROCESS_COMMAND;
|
||||
end
|
||||
`LM32_DP_WRITE_MEMORY:
|
||||
state <= `LM32_JTAG_STATE_READ_BYTE_0;
|
||||
`LM32_DP_WRITE_SEQUENTIAL:
|
||||
begin
|
||||
{jtag_byte_2, jtag_byte_3} <= {jtag_byte_2, jtag_byte_3} + 1'b1;
|
||||
state <= 5;
|
||||
end
|
||||
`LM32_DP_WRITE_CSR:
|
||||
state <= `LM32_JTAG_STATE_READ_BYTE_0;
|
||||
`endif
|
||||
`LM32_DP_BREAK:
|
||||
begin
|
||||
`ifdef CFG_JTAG_UART_ENABLED
|
||||
uart_rx_valid <= `FALSE;
|
||||
uart_tx_valid <= `FALSE;
|
||||
`endif
|
||||
jtag_break <= `TRUE;
|
||||
end
|
||||
`LM32_DP_RESET:
|
||||
begin
|
||||
`ifdef CFG_JTAG_UART_ENABLED
|
||||
uart_rx_valid <= `FALSE;
|
||||
uart_tx_valid <= `FALSE;
|
||||
`endif
|
||||
jtag_reset <= `TRUE;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
`endif
|
||||
`ifdef CFG_JTAG_UART_ENABLED
|
||||
`LM32_TX:
|
||||
begin
|
||||
uart_rx_byte <= rx_byte;
|
||||
uart_rx_valid <= `TRUE;
|
||||
end
|
||||
`LM32_RX:
|
||||
begin
|
||||
jtag_reg_d <= uart_tx_byte;
|
||||
uart_tx_valid <= `FALSE;
|
||||
end
|
||||
`endif
|
||||
default:
|
||||
;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
`ifdef CFG_HW_DEBUG_ENABLED
|
||||
`LM32_JTAG_STATE_READ_BYTE_0:
|
||||
begin
|
||||
if (rx_toggle_r_r != rx_toggle_r_r_r)
|
||||
begin
|
||||
jtag_byte_0 <= rx_byte;
|
||||
state <= `LM32_JTAG_STATE_READ_BYTE_1;
|
||||
end
|
||||
end
|
||||
`LM32_JTAG_STATE_READ_BYTE_1:
|
||||
begin
|
||||
if (rx_toggle_r_r != rx_toggle_r_r_r)
|
||||
begin
|
||||
jtag_byte_1 <= rx_byte;
|
||||
state <= `LM32_JTAG_STATE_READ_BYTE_2;
|
||||
end
|
||||
end
|
||||
`LM32_JTAG_STATE_READ_BYTE_2:
|
||||
begin
|
||||
if (rx_toggle_r_r != rx_toggle_r_r_r)
|
||||
begin
|
||||
jtag_byte_2 <= rx_byte;
|
||||
state <= `LM32_JTAG_STATE_READ_BYTE_3;
|
||||
end
|
||||
end
|
||||
`LM32_JTAG_STATE_READ_BYTE_3:
|
||||
begin
|
||||
if (rx_toggle_r_r != rx_toggle_r_r_r)
|
||||
begin
|
||||
jtag_byte_3 <= rx_byte;
|
||||
if (command == `LM32_DP_READ_MEMORY)
|
||||
state <= `LM32_JTAG_STATE_PROCESS_COMMAND;
|
||||
else
|
||||
state <= `LM32_JTAG_STATE_READ_BYTE_4;
|
||||
end
|
||||
end
|
||||
`LM32_JTAG_STATE_READ_BYTE_4:
|
||||
begin
|
||||
if (rx_toggle_r_r != rx_toggle_r_r_r)
|
||||
begin
|
||||
jtag_byte_4 <= rx_byte;
|
||||
state <= `LM32_JTAG_STATE_PROCESS_COMMAND;
|
||||
end
|
||||
end
|
||||
`LM32_JTAG_STATE_PROCESS_COMMAND:
|
||||
begin
|
||||
case (command)
|
||||
`LM32_DP_READ_MEMORY,
|
||||
`LM32_DP_READ_SEQUENTIAL:
|
||||
begin
|
||||
jtag_read_enable <= `TRUE;
|
||||
processing <= `TRUE;
|
||||
state <= `LM32_JTAG_STATE_WAIT_FOR_MEMORY;
|
||||
end
|
||||
`LM32_DP_WRITE_MEMORY,
|
||||
`LM32_DP_WRITE_SEQUENTIAL:
|
||||
begin
|
||||
jtag_write_enable <= `TRUE;
|
||||
processing <= `TRUE;
|
||||
state <= `LM32_JTAG_STATE_WAIT_FOR_MEMORY;
|
||||
end
|
||||
`LM32_DP_WRITE_CSR:
|
||||
begin
|
||||
jtag_csr_write_enable <= `TRUE;
|
||||
processing <= `TRUE;
|
||||
state <= `LM32_JTAG_STATE_WAIT_FOR_CSR;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
`LM32_JTAG_STATE_WAIT_FOR_MEMORY:
|
||||
begin
|
||||
if (jtag_access_complete == `TRUE)
|
||||
begin
|
||||
jtag_read_enable <= `FALSE;
|
||||
jtag_reg_d <= jtag_read_data;
|
||||
jtag_write_enable <= `FALSE;
|
||||
processing <= `FALSE;
|
||||
state <= `LM32_JTAG_STATE_READ_COMMAND;
|
||||
end
|
||||
end
|
||||
`LM32_JTAG_STATE_WAIT_FOR_CSR:
|
||||
begin
|
||||
jtag_csr_write_enable <= `FALSE;
|
||||
processing <= `FALSE;
|
||||
state <= `LM32_JTAG_STATE_READ_COMMAND;
|
||||
end
|
||||
`endif
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
`endif
|
588
lm32/logic/sakc/rtl/lm32/lm32_load_store_unit.v
Normal file
588
lm32/logic/sakc/rtl/lm32/lm32_load_store_unit.v
Normal file
@ -0,0 +1,588 @@
|
||||
// =============================================================================
|
||||
// COPYRIGHT NOTICE
|
||||
// Copyright 2006 (c) Lattice Semiconductor Corporation
|
||||
// ALL RIGHTS RESERVED
|
||||
// This confidential and proprietary software may be used only as authorised by
|
||||
// a licensing agreement from Lattice Semiconductor Corporation.
|
||||
// The entire notice above must be reproduced on all authorized copies and
|
||||
// copies may only be made to the extent permitted by a licensing agreement from
|
||||
// Lattice Semiconductor Corporation.
|
||||
//
|
||||
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
|
||||
// 5555 NE Moore Court 408-826-6000 (other locations)
|
||||
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
|
||||
// U.S.A email: techsupport@latticesemi.com
|
||||
// =============================================================================/
|
||||
// FILE DETAILS
|
||||
// Project : LatticeMico32
|
||||
// File : lm32_load_store_unit.v
|
||||
// Title : Load and store unit
|
||||
// Dependencies : lm32_include.v
|
||||
// Version : 6.0.13
|
||||
// =============================================================================
|
||||
|
||||
`include "lm32_include.v"
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Module interface
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
module lm32_load_store_unit (
|
||||
// ----- Inputs -------
|
||||
clk_i,
|
||||
rst_i,
|
||||
// From pipeline
|
||||
stall_a,
|
||||
stall_x,
|
||||
stall_m,
|
||||
kill_x,
|
||||
kill_m,
|
||||
exception_m,
|
||||
store_operand_x,
|
||||
load_store_address_x,
|
||||
load_store_address_m,
|
||||
load_store_address_w,
|
||||
load_q_x,
|
||||
load_q_m,
|
||||
store_q_m,
|
||||
sign_extend_x,
|
||||
size_x,
|
||||
`ifdef CFG_DCACHE_ENABLED
|
||||
dflush,
|
||||
`endif
|
||||
// From Wishbone
|
||||
d_dat_i,
|
||||
d_ack_i,
|
||||
d_err_i,
|
||||
d_rty_i,
|
||||
// ----- Outputs -------
|
||||
// To pipeline
|
||||
`ifdef CFG_DCACHE_ENABLED
|
||||
dcache_refill_request,
|
||||
dcache_restart_request,
|
||||
dcache_stall_request,
|
||||
dcache_refilling,
|
||||
`endif
|
||||
load_data_w,
|
||||
stall_wb_load,
|
||||
// To Wishbone
|
||||
d_dat_o,
|
||||
d_adr_o,
|
||||
d_cyc_o,
|
||||
d_sel_o,
|
||||
d_stb_o,
|
||||
d_we_o,
|
||||
d_cti_o,
|
||||
d_lock_o,
|
||||
d_bte_o
|
||||
);
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Parameters
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
parameter associativity = 1; // Associativity of the cache (Number of ways)
|
||||
parameter sets = 512; // Number of sets
|
||||
parameter bytes_per_line = 16; // Number of bytes per cache line
|
||||
parameter base_address = 0; // Base address of cachable memory
|
||||
parameter limit = 0; // Limit (highest address) of cachable memory
|
||||
|
||||
// For bytes_per_line == 4, we set 1 so part-select range isn't reversed, even though not really used
|
||||
//localparam addr_offset_width = bytes_per_line == 4 ? 1 : clogb2(bytes_per_line)-1-2;
|
||||
localparam addr_offset_width = 2;
|
||||
localparam addr_offset_lsb = 2;
|
||||
localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1);
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Inputs
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
input clk_i; // Clock
|
||||
input rst_i; // Reset
|
||||
|
||||
input stall_a; // A stage stall
|
||||
input stall_x; // X stage stall
|
||||
input stall_m; // M stage stall
|
||||
input kill_x; // Kill instruction in X stage
|
||||
input kill_m; // Kill instruction in M stage
|
||||
input exception_m; // An exception occured in the M stage
|
||||
|
||||
input [`LM32_WORD_RNG] store_operand_x; // Data read from register to store
|
||||
input [`LM32_WORD_RNG] load_store_address_x; // X stage load/store address
|
||||
input [`LM32_WORD_RNG] load_store_address_m; // M stage load/store address
|
||||
input [1:0] load_store_address_w; // W stage load/store address (only least two significant bits are needed)
|
||||
input load_q_x; // Load instruction in X stage
|
||||
input load_q_m; // Load instruction in M stage
|
||||
input store_q_m; // Store instruction in M stage
|
||||
input sign_extend_x; // Whether load instruction in X stage should sign extend or zero extend
|
||||
input [`LM32_SIZE_RNG] size_x; // Size of load or store (byte, hword, word)
|
||||
|
||||
`ifdef CFG_DCACHE_ENABLED
|
||||
input dflush; // Flush the data cache
|
||||
`endif
|
||||
|
||||
input [`LM32_WORD_RNG] d_dat_i; // Data Wishbone interface read data
|
||||
input d_ack_i; // Data Wishbone interface acknowledgement
|
||||
input d_err_i; // Data Wishbone interface error
|
||||
input d_rty_i; // Data Wishbone interface retry
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Outputs
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
`ifdef CFG_DCACHE_ENABLED
|
||||
output dcache_refill_request; // Request to refill data cache
|
||||
wire dcache_refill_request;
|
||||
output dcache_restart_request; // Request to restart the instruction that caused a data cache miss
|
||||
wire dcache_restart_request;
|
||||
output dcache_stall_request; // Data cache stall request
|
||||
wire dcache_stall_request;
|
||||
output dcache_refilling;
|
||||
wire dcache_refilling;
|
||||
`endif
|
||||
|
||||
output [`LM32_WORD_RNG] load_data_w; // Result of a load instruction
|
||||
reg [`LM32_WORD_RNG] load_data_w;
|
||||
output stall_wb_load; // Request to stall pipeline due to a load from the Wishbone interface
|
||||
reg stall_wb_load;
|
||||
|
||||
output [`LM32_WORD_RNG] d_dat_o; // Data Wishbone interface write data
|
||||
reg [`LM32_WORD_RNG] d_dat_o;
|
||||
output [`LM32_WORD_RNG] d_adr_o; // Data Wishbone interface address
|
||||
reg [`LM32_WORD_RNG] d_adr_o;
|
||||
output d_cyc_o; // Data Wishbone interface cycle
|
||||
reg d_cyc_o;
|
||||
output [`LM32_BYTE_SELECT_RNG] d_sel_o; // Data Wishbone interface byte select
|
||||
reg [`LM32_BYTE_SELECT_RNG] d_sel_o;
|
||||
output d_stb_o; // Data Wishbone interface strobe
|
||||
reg d_stb_o;
|
||||
output d_we_o; // Data Wishbone interface write enable
|
||||
reg d_we_o;
|
||||
output [`LM32_CTYPE_RNG] d_cti_o; // Data Wishbone interface cycle type
|
||||
wire [`LM32_CTYPE_RNG] d_cti_o;
|
||||
output d_lock_o; // Date Wishbone interface lock bus
|
||||
wire d_lock_o;
|
||||
output [`LM32_BTYPE_RNG] d_bte_o; // Data Wishbone interface burst type
|
||||
wire [`LM32_BTYPE_RNG] d_bte_o;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Internal nets and registers
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
// Microcode pipeline registers - See inputs for description
|
||||
reg [`LM32_SIZE_RNG] size_m;
|
||||
reg [`LM32_SIZE_RNG] size_w;
|
||||
reg sign_extend_m;
|
||||
reg sign_extend_w;
|
||||
reg [`LM32_WORD_RNG] store_data_x;
|
||||
reg [`LM32_WORD_RNG] store_data_m;
|
||||
reg [`LM32_BYTE_SELECT_RNG] byte_enable_x;
|
||||
reg [`LM32_BYTE_SELECT_RNG] byte_enable_m;
|
||||
wire [`LM32_WORD_RNG] data_m;
|
||||
reg [`LM32_WORD_RNG] data_w;
|
||||
|
||||
`ifdef CFG_DCACHE_ENABLED
|
||||
wire dcache_select_x; // Select data cache to load from / store to
|
||||
reg dcache_select_m;
|
||||
wire [`LM32_WORD_RNG] dcache_data_m; // Data read from cache
|
||||
wire [`LM32_WORD_RNG] dcache_refill_address; // Address to refill data cache from
|
||||
reg dcache_refill_ready; // Indicates the next word of refill data is ready
|
||||
wire last_word; // Indicates if this is the last word in the cache line
|
||||
wire [`LM32_WORD_RNG] first_address; // First cache refill address
|
||||
`endif
|
||||
`ifdef CFG_DRAM_ENABLED
|
||||
wire dram_select_x; // Select data RAM to load from / store to
|
||||
reg dram_select_m;
|
||||
wire [`LM32_WORD_RNG] dram_data_m; // Data read from data RAM
|
||||
wire [`LM32_WORD_RNG] dram_store_data_m; // Data to write to RAM
|
||||
`endif
|
||||
wire wb_select_x; // Select Wishbone to load from / store to
|
||||
reg wb_select_m;
|
||||
reg [`LM32_WORD_RNG] wb_data_m; // Data read from Wishbone
|
||||
reg wb_load_complete; // Indicates when a Wishbone load is complete
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Functions
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
`include "lm32_functions.v"
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Instantiations
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
`ifdef CFG_DRAM_ENABLED
|
||||
// Data RAM
|
||||
pmi_ram_dp_true #(
|
||||
// ----- Parameters -------
|
||||
.pmi_addr_depth_a (1 << (clogb2(`CFG_DRAM_LIMIT/4-`CFG_DRAM_BASE_ADDRESS/4+1)-1)),
|
||||
.pmi_addr_width_a ((clogb2(`CFG_DRAM_LIMIT/4-`CFG_DRAM_BASE_ADDRESS/4+1)-1)),
|
||||
.pmi_data_width_a (`LM32_WORD_WIDTH),
|
||||
.pmi_addr_depth_b (1 << (clogb2(`CFG_DRAM_LIMIT/4-`CFG_DRAM_BASE_ADDRESS/4+1)-1)),
|
||||
.pmi_addr_width_b ((clogb2(`CFG_DRAM_LIMIT/4-`CFG_DRAM_BASE_ADDRESS/4+1)-1)),
|
||||
.pmi_data_width_b (`LM32_WORD_WIDTH),
|
||||
.pmi_regmode_a ("noreg"),
|
||||
.pmi_regmode_b ("noreg"),
|
||||
.pmi_gsr ("enable"),
|
||||
.pmi_resetmode ("async"),
|
||||
.pmi_init_file (`CFG_DRAM_INIT_FILE),
|
||||
.pmi_init_file_format ("hex"),
|
||||
.module_type ("pmi_ram_dp")
|
||||
) ram (
|
||||
// ----- Inputs -------
|
||||
.ClockA (clk_i),
|
||||
.ClockB (clk_i),
|
||||
.ResetA (rst_i),
|
||||
.ResetB (rst_i),
|
||||
.DataInA ({32{1'b0}}),
|
||||
.DataInB (dram_store_data_m),
|
||||
.AddressA (load_store_address_x[(clogb2(`CFG_DRAM_LIMIT/4-`CFG_DRAM_BASE_ADDRESS/4+1)-1)+2-1:2]),
|
||||
.AddressB (load_store_address_m[(clogb2(`CFG_DRAM_LIMIT/4-`CFG_DRAM_BASE_ADDRESS/4+1)-1)+2-1:2]),
|
||||
.ClockEnA (!stall_x),
|
||||
.ClockEnB (!stall_m),
|
||||
.WrA (`FALSE),
|
||||
.WrB (store_q_m),
|
||||
// ----- Outputs -------
|
||||
.QA (dram_data_m),
|
||||
.QB ()
|
||||
);
|
||||
`endif
|
||||
|
||||
`ifdef CFG_DCACHE_ENABLED
|
||||
// Data cache
|
||||
lm32_dcache #(
|
||||
.associativity (associativity),
|
||||
.sets (sets),
|
||||
.bytes_per_line (bytes_per_line),
|
||||
.base_address (base_address),
|
||||
.limit (limit)
|
||||
) dcache (
|
||||
// ----- Inputs -----
|
||||
.clk_i (clk_i),
|
||||
.rst_i (rst_i),
|
||||
.stall_a (stall_a),
|
||||
.stall_x (stall_x),
|
||||
.stall_m (stall_m),
|
||||
.address_x (load_store_address_x),
|
||||
.address_m (load_store_address_m),
|
||||
.load_q_m (load_q_m & dcache_select_m),
|
||||
.store_q_m (store_q_m),
|
||||
.store_data (store_data_m),
|
||||
.store_byte_select (byte_enable_m),
|
||||
.refill_ready (dcache_refill_ready),
|
||||
.refill_data (wb_data_m),
|
||||
.dflush (dflush),
|
||||
// ----- Outputs -----
|
||||
.stall_request (dcache_stall_request),
|
||||
.restart_request (dcache_restart_request),
|
||||
.refill_request (dcache_refill_request),
|
||||
.refill_address (dcache_refill_address),
|
||||
.refilling (dcache_refilling),
|
||||
.load_data (dcache_data_m)
|
||||
);
|
||||
`endif
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Combinational Logic
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
// Select where data should be loaded from / stored to
|
||||
`ifdef CFG_DCACHE_ENABLED
|
||||
assign dcache_select_x = (load_store_address_x >= `CFG_DCACHE_BASE_ADDRESS) && (load_store_address_x <= `CFG_DCACHE_LIMIT);
|
||||
//assign dcache_select_x = (load_store_address_x >= `CFG_DCACHE_BASE_ADDRESS) && ~|load_store_address_x[`LM32_WORD_WIDTH-1:clogb2(`CFG_DCACHE_LIMIT-`CFG_DCACHE_BASE_ADDRESS)-1];
|
||||
`endif
|
||||
`ifdef CFG_DRAM_ENABLED
|
||||
assign dram_select_x = (load_store_address_x >= `CFG_DRAM_BASE_ADDRESS) && (load_store_address_x <= `CFG_DRAM_LIMIT);
|
||||
`endif
|
||||
assign wb_select_x = `TRUE
|
||||
`ifdef CFG_DCACHE_ENABLED
|
||||
&& !dcache_select_x
|
||||
`endif
|
||||
`ifdef CFG_DRAM_ENABLED
|
||||
&& !dram_select_x
|
||||
`endif
|
||||
;
|
||||
|
||||
// Make sure data to store is in correct byte lane
|
||||
always @(*)
|
||||
begin
|
||||
case (size_x)
|
||||
`LM32_SIZE_BYTE: store_data_x = {4{store_operand_x[7:0]}};
|
||||
`LM32_SIZE_HWORD: store_data_x = {2{store_operand_x[15:0]}};
|
||||
`LM32_SIZE_WORD: store_data_x = store_operand_x;
|
||||
default: store_data_x = {`LM32_WORD_WIDTH{1'bx}};
|
||||
endcase
|
||||
end
|
||||
|
||||
// Generate byte enable accoring to size of load or store and address being accessed
|
||||
always @(*)
|
||||
begin
|
||||
casez ({size_x, load_store_address_x[1:0]})
|
||||
{`LM32_SIZE_BYTE, 2'b11}: byte_enable_x = 4'b0001;
|
||||
{`LM32_SIZE_BYTE, 2'b10}: byte_enable_x = 4'b0010;
|
||||
{`LM32_SIZE_BYTE, 2'b01}: byte_enable_x = 4'b0100;
|
||||
{`LM32_SIZE_BYTE, 2'b00}: byte_enable_x = 4'b1000;
|
||||
{`LM32_SIZE_HWORD, 2'b1?}: byte_enable_x = 4'b0011;
|
||||
{`LM32_SIZE_HWORD, 2'b0?}: byte_enable_x = 4'b1100;
|
||||
{`LM32_SIZE_WORD, 2'b??}: byte_enable_x = 4'b1111;
|
||||
default: byte_enable_x = 4'bxxxx;
|
||||
endcase
|
||||
end
|
||||
|
||||
`ifdef CFG_DRAM_ENABLED
|
||||
// Only replace selected bytes
|
||||
assign dram_store_data_m[`LM32_BYTE_0_RNG] = byte_enable_m[0] ? store_data_m[`LM32_BYTE_0_RNG] : dram_data_m[`LM32_BYTE_0_RNG];
|
||||
assign dram_store_data_m[`LM32_BYTE_1_RNG] = byte_enable_m[1] ? store_data_m[`LM32_BYTE_1_RNG] : dram_data_m[`LM32_BYTE_1_RNG];
|
||||
assign dram_store_data_m[`LM32_BYTE_2_RNG] = byte_enable_m[2] ? store_data_m[`LM32_BYTE_2_RNG] : dram_data_m[`LM32_BYTE_2_RNG];
|
||||
assign dram_store_data_m[`LM32_BYTE_3_RNG] = byte_enable_m[3] ? store_data_m[`LM32_BYTE_3_RNG] : dram_data_m[`LM32_BYTE_3_RNG];
|
||||
`endif
|
||||
|
||||
// Select data from selected source
|
||||
`ifdef CFG_DCACHE_ENABLED
|
||||
`ifdef CFG_DRAM_ENABLED
|
||||
assign data_m = wb_select_m == `TRUE
|
||||
? wb_data_m
|
||||
: dram_select_m == `TRUE
|
||||
? dram_data_m
|
||||
: dcache_data_m;
|
||||
`else
|
||||
assign data_m = wb_select_m == `TRUE ? wb_data_m : dcache_data_m;
|
||||
`endif
|
||||
`else
|
||||
`ifdef CFG_DRAM_ENABLED
|
||||
assign data_m = wb_select_m == `TRUE ? wb_data_m : dram_data_m;
|
||||
`else
|
||||
assign data_m = wb_data_m;
|
||||
`endif
|
||||
`endif
|
||||
|
||||
// Sub-word selection and sign/zero-extension for loads
|
||||
always @(*)
|
||||
begin
|
||||
casez ({size_w, load_store_address_w[1:0]})
|
||||
{`LM32_SIZE_BYTE, 2'b11}: load_data_w = {{24{sign_extend_w & data_w[7]}}, data_w[7:0]};
|
||||
{`LM32_SIZE_BYTE, 2'b10}: load_data_w = {{24{sign_extend_w & data_w[15]}}, data_w[15:8]};
|
||||
{`LM32_SIZE_BYTE, 2'b01}: load_data_w = {{24{sign_extend_w & data_w[23]}}, data_w[23:16]};
|
||||
{`LM32_SIZE_BYTE, 2'b00}: load_data_w = {{24{sign_extend_w & data_w[31]}}, data_w[31:24]};
|
||||
{`LM32_SIZE_HWORD, 2'b1?}: load_data_w = {{16{sign_extend_w & data_w[15]}}, data_w[15:0]};
|
||||
{`LM32_SIZE_HWORD, 2'b0?}: load_data_w = {{16{sign_extend_w & data_w[31]}}, data_w[31:16]};
|
||||
{`LM32_SIZE_WORD, 2'b??}: load_data_w = data_w;
|
||||
default: load_data_w = {`LM32_WORD_WIDTH{1'bx}};
|
||||
endcase
|
||||
end
|
||||
|
||||
// Unused Wishbone signals
|
||||
assign d_cti_o = `LM32_CTYPE_WIDTH'd0;
|
||||
assign d_lock_o = `FALSE;
|
||||
assign d_bte_o = `LM32_BTYPE_WIDTH'd0;
|
||||
|
||||
`ifdef CFG_DCACHE_ENABLED
|
||||
// Generate signal to indicate last word in cache line
|
||||
generate
|
||||
if (bytes_per_line > 4)
|
||||
begin
|
||||
assign first_address = {dcache_refill_address[`LM32_WORD_WIDTH-1:addr_offset_msb+1], {addr_offset_width{1'b0}}, 2'b00};
|
||||
assign last_word = (&d_adr_o[addr_offset_msb:addr_offset_lsb]) == 1'b1;
|
||||
end
|
||||
else
|
||||
begin
|
||||
assign first_address = {dcache_refill_address[`LM32_WORD_WIDTH-1:2], 2'b00};
|
||||
assign last_word = `TRUE;
|
||||
end
|
||||
endgenerate
|
||||
`endif
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Sequential Logic
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
// Data Wishbone interface
|
||||
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
|
||||
begin
|
||||
if (rst_i == `TRUE)
|
||||
begin
|
||||
d_cyc_o <= `FALSE;
|
||||
d_stb_o <= `FALSE;
|
||||
d_dat_o <= {`LM32_WORD_WIDTH{1'b0}};
|
||||
d_adr_o <= {`LM32_WORD_WIDTH{1'b0}};
|
||||
d_sel_o <= {`LM32_BYTE_SELECT_WIDTH{`FALSE}};
|
||||
d_we_o <= `FALSE;
|
||||
wb_data_m <= {`LM32_WORD_WIDTH{1'b0}};
|
||||
wb_load_complete <= `FALSE;
|
||||
stall_wb_load <= `FALSE;
|
||||
`ifdef CFG_DCACHE_ENABLED
|
||||
dcache_refill_ready <= `FALSE;
|
||||
`endif
|
||||
end
|
||||
else
|
||||
begin
|
||||
`ifdef CFG_DCACHE_ENABLED
|
||||
// Refill ready should only be asserted for a single cycle
|
||||
dcache_refill_ready <= `FALSE;
|
||||
`endif
|
||||
// Is a Wishbone cycle already in progress?
|
||||
if (d_cyc_o == `TRUE)
|
||||
begin
|
||||
// Is the cycle complete?
|
||||
if ((d_ack_i == `TRUE) || (d_err_i == `TRUE))
|
||||
begin
|
||||
`ifdef CFG_DCACHE_ENABLED
|
||||
if ((dcache_refilling == `TRUE) && (!last_word))
|
||||
begin
|
||||
// Fetch next word of cache line
|
||||
d_adr_o[addr_offset_msb:addr_offset_lsb] <= d_adr_o[addr_offset_msb:addr_offset_lsb] + 1'b1;
|
||||
end
|
||||
else
|
||||
`endif
|
||||
begin
|
||||
// Refill/access complete
|
||||
d_cyc_o <= `FALSE;
|
||||
d_stb_o <= `FALSE;
|
||||
end
|
||||
`ifdef CFG_DCACHE_ENABLED
|
||||
// If we are performing a refill, indicate to cache next word of data is ready
|
||||
dcache_refill_ready <= dcache_refilling;
|
||||
`endif
|
||||
// Register data read from Wishbone interface
|
||||
wb_data_m <= d_dat_i;
|
||||
// Don't set when stores complete - otherwise we'll deadlock if load in m stage
|
||||
wb_load_complete <= !d_we_o;
|
||||
end
|
||||
// synthesis translate_off
|
||||
if (d_err_i == `TRUE)
|
||||
$display ("Data bus error. Address: %x", d_adr_o);
|
||||
// synthesis translate_on
|
||||
end
|
||||
else
|
||||
begin
|
||||
`ifdef CFG_DCACHE_ENABLED
|
||||
if (dcache_refill_request == `TRUE)
|
||||
begin
|
||||
// Start cache refill
|
||||
d_adr_o <= first_address;
|
||||
d_cyc_o <= `TRUE;
|
||||
d_sel_o <= {`LM32_WORD_WIDTH/8{`TRUE}};
|
||||
d_stb_o <= `TRUE;
|
||||
d_we_o <= `FALSE;
|
||||
end
|
||||
else
|
||||
`endif
|
||||
if ( (store_q_m == `TRUE)
|
||||
&& (stall_m == `FALSE)
|
||||
`ifdef CFG_DRAM_ENABLED
|
||||
&& !dram_select_m
|
||||
`endif
|
||||
)
|
||||
begin
|
||||
// Data cache is write through, so all stores go to memory
|
||||
d_dat_o <= store_data_m;
|
||||
d_adr_o <= load_store_address_m;
|
||||
d_cyc_o <= `TRUE;
|
||||
d_sel_o <= byte_enable_m;
|
||||
d_stb_o <= `TRUE;
|
||||
d_we_o <= `TRUE;
|
||||
end
|
||||
else if ( (load_q_m == `TRUE)
|
||||
&& (wb_select_m == `TRUE)
|
||||
&& (wb_load_complete == `FALSE)
|
||||
/* stall_m will be TRUE, because stall_wb_load will be TRUE */
|
||||
)
|
||||
begin
|
||||
// Read requested address
|
||||
stall_wb_load <= `FALSE;
|
||||
d_adr_o <= load_store_address_m;
|
||||
d_cyc_o <= `TRUE;
|
||||
d_sel_o <= byte_enable_m;
|
||||
d_stb_o <= `TRUE;
|
||||
d_we_o <= `FALSE;
|
||||
end
|
||||
end
|
||||
// Clear load/store complete flag when instruction leaves M stage
|
||||
if (stall_m == `FALSE)
|
||||
wb_load_complete <= `FALSE;
|
||||
// When a Wishbone load first enters the M stage, we need to stall it
|
||||
if ((load_q_x == `TRUE) && (wb_select_x == `TRUE) && (stall_x == `FALSE))
|
||||
stall_wb_load <= `TRUE;
|
||||
// Clear stall request if load instruction is killed
|
||||
if ((kill_m == `TRUE) || (exception_m == `TRUE))
|
||||
stall_wb_load <= `FALSE;
|
||||
end
|
||||
end
|
||||
|
||||
// Pipeline registers
|
||||
|
||||
// X/M stage pipeline registers
|
||||
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
|
||||
begin
|
||||
if (rst_i == `TRUE)
|
||||
begin
|
||||
sign_extend_m <= `FALSE;
|
||||
size_m <= 2'b00;
|
||||
byte_enable_m <= `FALSE;
|
||||
store_data_m <= {`LM32_WORD_WIDTH{1'b0}};
|
||||
`ifdef CFG_DCACHE_ENABLED
|
||||
dcache_select_m <= `FALSE;
|
||||
`endif
|
||||
`ifdef CFG_DRAM_ENABLED
|
||||
dram_select_m <= `FALSE;
|
||||
`endif
|
||||
wb_select_m <= `FALSE;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if (stall_m == `FALSE)
|
||||
begin
|
||||
sign_extend_m <= sign_extend_x;
|
||||
size_m <= size_x;
|
||||
byte_enable_m <= byte_enable_x;
|
||||
store_data_m <= store_data_x;
|
||||
`ifdef CFG_DCACHE_ENABLED
|
||||
dcache_select_m <= dcache_select_x;
|
||||
`endif
|
||||
`ifdef CFG_DRAM_ENABLED
|
||||
dram_select_m <= dram_select_x;
|
||||
`endif
|
||||
wb_select_m <= wb_select_x;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// M/W stage pipeline registers
|
||||
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
|
||||
begin
|
||||
if (rst_i == `TRUE)
|
||||
begin
|
||||
size_w <= 2'b00;
|
||||
data_w <= {`LM32_WORD_WIDTH{1'b0}};
|
||||
sign_extend_w <= `FALSE;
|
||||
end
|
||||
else
|
||||
begin
|
||||
size_w <= size_m;
|
||||
data_w <= data_m;
|
||||
sign_extend_w <= sign_extend_m;
|
||||
end
|
||||
end
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Behavioural Logic
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
// synthesis translate_off
|
||||
|
||||
// Check for non-aligned loads or stores
|
||||
always @(posedge clk_i)
|
||||
begin
|
||||
if (((load_q_m == `TRUE) || (store_q_m == `TRUE)) && (stall_m == `FALSE))
|
||||
begin
|
||||
if ((size_m === `LM32_SIZE_HWORD) && (load_store_address_m[0] !== 1'b0))
|
||||
$display ("Warning: Non-aligned halfword access. Address: 0x%0x Time: %0t.", load_store_address_m, $time);
|
||||
if ((size_m === `LM32_SIZE_WORD) && (load_store_address_m[1:0] !== 2'b00))
|
||||
$display ("Warning: Non-aligned word access. Address: 0x%0x Time: %0t.", load_store_address_m, $time);
|
||||
end
|
||||
end
|
||||
|
||||
// synthesis translate_on
|
||||
|
||||
endmodule
|
||||
|
71
lm32/logic/sakc/rtl/lm32/lm32_logic_op.v
Normal file
71
lm32/logic/sakc/rtl/lm32/lm32_logic_op.v
Normal file
@ -0,0 +1,71 @@
|
||||
// =============================================================================
|
||||
// COPYRIGHT NOTICE
|
||||
// Copyright 2006 (c) Lattice Semiconductor Corporation
|
||||
// ALL RIGHTS RESERVED
|
||||
// This confidential and proprietary software may be used only as authorised by
|
||||
// a licensing agreement from Lattice Semiconductor Corporation.
|
||||
// The entire notice above must be reproduced on all authorized copies and
|
||||
// copies may only be made to the extent permitted by a licensing agreement from
|
||||
// Lattice Semiconductor Corporation.
|
||||
//
|
||||
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
|
||||
// 5555 NE Moore Court 408-826-6000 (other locations)
|
||||
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
|
||||
// U.S.A email: techsupport@latticesemi.com
|
||||
// =============================================================================/
|
||||
// FILE DETAILS
|
||||
// Project : LatticeMico32
|
||||
// File : lm32_logic_op.v
|
||||
// Title : Logic operations (and / or / not etc)
|
||||
// Dependencies : lm32_include.v
|
||||
// Version : 6.1.17
|
||||
// =============================================================================
|
||||
|
||||
`include "lm32_include.v"
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Module interface
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
module lm32_logic_op (
|
||||
// ----- Inputs -------
|
||||
logic_op_x,
|
||||
operand_0_x,
|
||||
operand_1_x,
|
||||
// ----- Outputs -------
|
||||
logic_result_x
|
||||
);
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Inputs
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
input [`LM32_LOGIC_OP_RNG] logic_op_x;
|
||||
input [`LM32_WORD_RNG] operand_0_x;
|
||||
input [`LM32_WORD_RNG] operand_1_x;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Outputs
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
output [`LM32_WORD_RNG] logic_result_x;
|
||||
reg [`LM32_WORD_RNG] logic_result_x;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Internal nets and registers
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
integer logic_idx;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Combinational Logic
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
always @*
|
||||
begin
|
||||
for(logic_idx = 0; logic_idx < `LM32_WORD_WIDTH; logic_idx = logic_idx + 1)
|
||||
logic_result_x[logic_idx] = logic_op_x[{operand_1_x[logic_idx], operand_0_x[logic_idx]}];
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
283
lm32/logic/sakc/rtl/lm32/lm32_mc_arithmetic.v
Normal file
283
lm32/logic/sakc/rtl/lm32/lm32_mc_arithmetic.v
Normal file
@ -0,0 +1,283 @@
|
||||
// =============================================================================
|
||||
// COPYRIGHT NOTICE
|
||||
// Copyright 2006 (c) Lattice Semiconductor Corporation
|
||||
// ALL RIGHTS RESERVED
|
||||
// This confidential and proprietary software may be used only as authorised by
|
||||
// a licensing agreement from Lattice Semiconductor Corporation.
|
||||
// The entire notice above must be reproduced on all authorized copies and
|
||||
// copies may only be made to the extent permitted by a licensing agreement from
|
||||
// Lattice Semiconductor Corporation.
|
||||
//
|
||||
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
|
||||
// 5555 NE Moore Court 408-826-6000 (other locations)
|
||||
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
|
||||
// U.S.A email: techsupport@latticesemi.com
|
||||
// =============================================================================/
|
||||
// FILE DETAILS
|
||||
// Project : LatticeMico32
|
||||
// File : lm_mc_arithmetic.v
|
||||
// Title : Multi-cycle arithmetic unit.
|
||||
// Dependencies : lm32_include.v
|
||||
// Version : 6.1.17
|
||||
// =============================================================================
|
||||
|
||||
`include "lm32_include.v"
|
||||
|
||||
`define LM32_MC_STATE_RNG 2:0
|
||||
`define LM32_MC_STATE_IDLE 3'b000
|
||||
`define LM32_MC_STATE_MULTIPLY 3'b001
|
||||
`define LM32_MC_STATE_MODULUS 3'b010
|
||||
`define LM32_MC_STATE_DIVIDE 3'b011
|
||||
`define LM32_MC_STATE_SHIFT_LEFT 3'b100
|
||||
`define LM32_MC_STATE_SHIFT_RIGHT 3'b101
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Module interface
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
module lm32_mc_arithmetic (
|
||||
// ----- Inputs -----
|
||||
clk_i,
|
||||
rst_i,
|
||||
stall_d,
|
||||
kill_x,
|
||||
`ifdef CFG_MC_DIVIDE_ENABLED
|
||||
divide_d,
|
||||
modulus_d,
|
||||
`endif
|
||||
`ifdef CFG_MC_MULTIPLY_ENABLED
|
||||
multiply_d,
|
||||
`endif
|
||||
`ifdef CFG_MC_BARREL_SHIFT_ENABLED
|
||||
shift_left_d,
|
||||
shift_right_d,
|
||||
sign_extend_d,
|
||||
`endif
|
||||
operand_0_d,
|
||||
operand_1_d,
|
||||
// ----- Ouputs -----
|
||||
result_x,
|
||||
`ifdef CFG_MC_DIVIDE_ENABLED
|
||||
divide_by_zero_x,
|
||||
`endif
|
||||
stall_request_x
|
||||
);
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Inputs
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
input clk_i; // Clock
|
||||
input rst_i; // Reset
|
||||
input stall_d; // Stall instruction in D stage
|
||||
input kill_x; // Kill instruction in X stage
|
||||
`ifdef CFG_MC_DIVIDE_ENABLED
|
||||
input divide_d; // Perform divide
|
||||
input modulus_d; // Perform modulus
|
||||
`endif
|
||||
`ifdef CFG_MC_MULTIPLY_ENABLED
|
||||
input multiply_d; // Perform multiply
|
||||
`endif
|
||||
`ifdef CFG_MC_BARREL_SHIFT_ENABLED
|
||||
input shift_left_d; // Perform left shift
|
||||
input shift_right_d; // Perform right shift
|
||||
input sign_extend_d; // Whether to sign-extend (arithmetic) or zero-extend (logical)
|
||||
`endif
|
||||
input [`LM32_WORD_RNG] operand_0_d;
|
||||
input [`LM32_WORD_RNG] operand_1_d;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Outputs
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
output [`LM32_WORD_RNG] result_x; // Result of operation
|
||||
reg [`LM32_WORD_RNG] result_x;
|
||||
`ifdef CFG_MC_DIVIDE_ENABLED
|
||||
output divide_by_zero_x; // A divide by zero was attempted
|
||||
reg divide_by_zero_x;
|
||||
`endif
|
||||
output stall_request_x; // Request to stall pipeline from X stage back
|
||||
wire stall_request_x;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Internal nets and registers
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
reg [`LM32_WORD_RNG] p; // Temporary registers
|
||||
reg [`LM32_WORD_RNG] a;
|
||||
reg [`LM32_WORD_RNG] b;
|
||||
`ifdef CFG_MC_DIVIDE_ENABLED
|
||||
wire [32:0] t;
|
||||
`endif
|
||||
|
||||
reg [`LM32_MC_STATE_RNG] state; // Current state of FSM
|
||||
reg [5:0] cycles; // Number of cycles remaining in the operation
|
||||
|
||||
`ifdef CFG_MC_BARREL_SHIFT_ENABLED
|
||||
reg sign_extend_x; // Whether to sign extend of zero extend right shifts
|
||||
wire fill_value; // Value to fill with for right barrel-shifts
|
||||
`endif
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Combinational logic
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
// Stall pipeline while any operation is being performed
|
||||
assign stall_request_x = state != `LM32_MC_STATE_IDLE;
|
||||
|
||||
`ifdef CFG_MC_DIVIDE_ENABLED
|
||||
// Subtraction
|
||||
assign t = {p[`LM32_WORD_WIDTH-2:0], a[`LM32_WORD_WIDTH-1]} - b;
|
||||
`endif
|
||||
|
||||
`ifdef CFG_MC_BARREL_SHIFT_ENABLED
|
||||
// Determine fill value for right shift - Sign bit for arithmetic shift, or zero for logical shift
|
||||
assign fill_value = (sign_extend_x == `TRUE) & b[`LM32_WORD_WIDTH-1];
|
||||
`endif
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Sequential logic
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
// Perform right shift
|
||||
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
|
||||
begin
|
||||
if (rst_i == `TRUE)
|
||||
begin
|
||||
cycles <= {6{1'b0}};
|
||||
p <= {`LM32_WORD_WIDTH{1'b0}};
|
||||
a <= {`LM32_WORD_WIDTH{1'b0}};
|
||||
b <= {`LM32_WORD_WIDTH{1'b0}};
|
||||
`ifdef CFG_MC_BARREL_SHIFT_ENABLED
|
||||
sign_extend_x <= 1'b0;
|
||||
`endif
|
||||
`ifdef CFG_MC_DIVIDE_ENABLED
|
||||
divide_by_zero_x <= `FALSE;
|
||||
`endif
|
||||
result_x <= {`LM32_WORD_WIDTH{1'b0}};
|
||||
state <= `LM32_MC_STATE_IDLE;
|
||||
end
|
||||
else
|
||||
begin
|
||||
`ifdef CFG_MC_DIVIDE_ENABLED
|
||||
divide_by_zero_x <= `FALSE;
|
||||
`endif
|
||||
case (state)
|
||||
`LM32_MC_STATE_IDLE:
|
||||
begin
|
||||
if (stall_d == `FALSE)
|
||||
begin
|
||||
cycles <= `LM32_WORD_WIDTH;
|
||||
p <= 32'b0;
|
||||
a <= operand_0_d;
|
||||
b <= operand_1_d;
|
||||
`ifdef CFG_MC_DIVIDE_ENABLED
|
||||
if (divide_d == `TRUE)
|
||||
state <= `LM32_MC_STATE_DIVIDE;
|
||||
if (modulus_d == `TRUE)
|
||||
state <= `LM32_MC_STATE_MODULUS;
|
||||
`endif
|
||||
`ifdef CFG_MC_MULTIPLY_ENABLED
|
||||
if (multiply_d == `TRUE)
|
||||
state <= `LM32_MC_STATE_MULTIPLY;
|
||||
`endif
|
||||
`ifdef CFG_MC_BARREL_SHIFT_ENABLED
|
||||
if (shift_left_d == `TRUE)
|
||||
begin
|
||||
state <= `LM32_MC_STATE_SHIFT_LEFT;
|
||||
sign_extend_x <= sign_extend_d;
|
||||
cycles <= operand_1_d[4:0];
|
||||
a <= operand_0_d;
|
||||
b <= operand_0_d;
|
||||
end
|
||||
if (shift_right_d == `TRUE)
|
||||
begin
|
||||
state <= `LM32_MC_STATE_SHIFT_RIGHT;
|
||||
sign_extend_x <= sign_extend_d;
|
||||
cycles <= operand_1_d[4:0];
|
||||
a <= operand_0_d;
|
||||
b <= operand_0_d;
|
||||
end
|
||||
`endif
|
||||
end
|
||||
end
|
||||
`ifdef CFG_MC_DIVIDE_ENABLED
|
||||
`LM32_MC_STATE_DIVIDE:
|
||||
begin
|
||||
if (t[32] == 1'b0)
|
||||
begin
|
||||
p <= t[31:0];
|
||||
a <= {a[`LM32_WORD_WIDTH-2:0], 1'b1};
|
||||
end
|
||||
else
|
||||
begin
|
||||
p <= {p[`LM32_WORD_WIDTH-2:0], a[`LM32_WORD_WIDTH-1]};
|
||||
a <= {a[`LM32_WORD_WIDTH-2:0], 1'b0};
|
||||
end
|
||||
result_x <= a;
|
||||
if ((cycles == `LM32_WORD_WIDTH'd0) || (kill_x == `TRUE))
|
||||
begin
|
||||
// Check for divide by zero
|
||||
divide_by_zero_x <= b == {`LM32_WORD_WIDTH{1'b0}};
|
||||
state <= `LM32_MC_STATE_IDLE;
|
||||
end
|
||||
cycles <= cycles - 1'b1;
|
||||
end
|
||||
`LM32_MC_STATE_MODULUS:
|
||||
begin
|
||||
if (t[32] == 1'b0)
|
||||
begin
|
||||
p <= t[31:0];
|
||||
a <= {a[`LM32_WORD_WIDTH-2:0], 1'b1};
|
||||
end
|
||||
else
|
||||
begin
|
||||
p <= {p[`LM32_WORD_WIDTH-2:0], a[`LM32_WORD_WIDTH-1]};
|
||||
a <= {a[`LM32_WORD_WIDTH-2:0], 1'b0};
|
||||
end
|
||||
result_x <= p;
|
||||
if ((cycles == `LM32_WORD_WIDTH'd0) || (kill_x == `TRUE))
|
||||
begin
|
||||
// Check for divide by zero
|
||||
divide_by_zero_x <= b == {`LM32_WORD_WIDTH{1'b0}};
|
||||
state <= `LM32_MC_STATE_IDLE;
|
||||
end
|
||||
cycles <= cycles - 1'b1;
|
||||
end
|
||||
`endif
|
||||
`ifdef CFG_MC_MULTIPLY_ENABLED
|
||||
`LM32_MC_STATE_MULTIPLY:
|
||||
begin
|
||||
if (b[0] == 1'b1)
|
||||
p <= p + a;
|
||||
b <= {1'b0, b[`LM32_WORD_WIDTH-1:1]};
|
||||
a <= {a[`LM32_WORD_WIDTH-2:0], 1'b0};
|
||||
result_x <= p;
|
||||
if ((cycles == `LM32_WORD_WIDTH'd0) || (kill_x == `TRUE))
|
||||
state <= `LM32_MC_STATE_IDLE;
|
||||
cycles <= cycles - 1'b1;
|
||||
end
|
||||
`endif
|
||||
`ifdef CFG_MC_BARREL_SHIFT_ENABLED
|
||||
`LM32_MC_STATE_SHIFT_LEFT:
|
||||
begin
|
||||
a <= {a[`LM32_WORD_WIDTH-2:0], 1'b0};
|
||||
result_x <= a;
|
||||
if ((cycles == `LM32_WORD_WIDTH'd0) || (kill_x == `TRUE))
|
||||
state <= `LM32_MC_STATE_IDLE;
|
||||
cycles <= cycles - 1'b1;
|
||||
end
|
||||
`LM32_MC_STATE_SHIFT_RIGHT:
|
||||
begin
|
||||
b <= {fill_value, b[`LM32_WORD_WIDTH-1:1]};
|
||||
result_x <= b;
|
||||
if ((cycles == `LM32_WORD_WIDTH'd0) || (kill_x == `TRUE))
|
||||
state <= `LM32_MC_STATE_IDLE;
|
||||
cycles <= cycles - 1'b1;
|
||||
end
|
||||
`endif
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
164
lm32/logic/sakc/rtl/lm32/lm32_monitor.v
Normal file
164
lm32/logic/sakc/rtl/lm32/lm32_monitor.v
Normal file
@ -0,0 +1,164 @@
|
||||
// =============================================================================
|
||||
// COPYRIGHT NOTICE
|
||||
// Copyright 2006 (c) Lattice Semiconductor Corporation
|
||||
// ALL RIGHTS RESERVED
|
||||
// This confidential and proprietary software may be used only as authorised by
|
||||
// a licensing agreement from Lattice Semiconductor Corporation.
|
||||
// The entire notice above must be reproduced on all authorized copies and
|
||||
// copies may only be made to the extent permitted by a licensing agreement from
|
||||
// Lattice Semiconductor Corporation.
|
||||
//
|
||||
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
|
||||
// 5555 NE Moore Court 408-826-6000 (other locations)
|
||||
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
|
||||
// U.S.A email: techsupport@latticesemi.com
|
||||
// =============================================================================/
|
||||
// FILE DETAILS
|
||||
// Project : LatticeMico32
|
||||
// File : lm32_monitor.v
|
||||
// Title : Debug monitor memory Wishbone interface
|
||||
// Version : 6.1.17
|
||||
// =============================================================================
|
||||
|
||||
`include "system_conf.v"
|
||||
`include "lm32_include.v"
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Module interface
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
module lm32_monitor (
|
||||
// ----- Inputs -------
|
||||
clk_i,
|
||||
rst_i,
|
||||
MON_ADR_I,
|
||||
MON_CYC_I,
|
||||
MON_DAT_I,
|
||||
MON_SEL_I,
|
||||
MON_STB_I,
|
||||
MON_WE_I,
|
||||
MON_LOCK_I,
|
||||
MON_CTI_I,
|
||||
MON_BTE_I,
|
||||
// ----- Outputs -------
|
||||
MON_ACK_O,
|
||||
MON_RTY_O,
|
||||
MON_DAT_O,
|
||||
MON_ERR_O
|
||||
);
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Inputs
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
input clk_i; // Wishbone clock
|
||||
input rst_i; // Wishbone reset
|
||||
input [`LM32_WORD_RNG] MON_ADR_I; // Wishbone address
|
||||
input MON_STB_I; // Wishbone strobe
|
||||
input MON_CYC_I; // Wishbone cycle
|
||||
input [`LM32_WORD_RNG] MON_DAT_I; // Wishbone write data
|
||||
input [`LM32_BYTE_SELECT_RNG] MON_SEL_I; // Wishbone byte select
|
||||
input MON_WE_I; // Wishbone write enable
|
||||
input MON_LOCK_I; // Wishbone locked transfer
|
||||
input [`LM32_CTYPE_RNG] MON_CTI_I; // Wishbone cycle type
|
||||
input [`LM32_BTYPE_RNG] MON_BTE_I; // Wishbone burst type
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Outputs
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
output MON_ACK_O; // Wishbone acknowlege
|
||||
reg MON_ACK_O;
|
||||
output [`LM32_WORD_RNG] MON_DAT_O; // Wishbone data output
|
||||
reg [`LM32_WORD_RNG] MON_DAT_O;
|
||||
output MON_RTY_O; // Wishbone retry
|
||||
wire MON_RTY_O;
|
||||
output MON_ERR_O; // Wishbone error
|
||||
wire MON_ERR_O;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Internal nets and registers
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
reg [1:0] state; // Current state of FSM
|
||||
wire [`LM32_WORD_RNG] data; // Data read from RAM
|
||||
reg write_enable; // RAM write enable
|
||||
reg [`LM32_WORD_RNG] write_data; // RAM write data
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Instantiations
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
lm32_monitor_ram ram (
|
||||
// ----- Inputs -------
|
||||
.ClockA (clk_i),
|
||||
.ClockB (clk_i),
|
||||
.ResetA (rst_i),
|
||||
.ResetB (rst_i),
|
||||
.ClockEnA (`TRUE),
|
||||
.ClockEnB (`FALSE),
|
||||
.AddressA (MON_ADR_I[10:2]),
|
||||
.DataInA (write_data),
|
||||
.WrA (write_enable),
|
||||
.WrB (`FALSE),
|
||||
// ----- Outputs -------
|
||||
.QA (data)
|
||||
);
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Combinational Logic
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
assign MON_RTY_O = `FALSE;
|
||||
assign MON_ERR_O = `FALSE;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Sequential Logic
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
|
||||
begin
|
||||
if (rst_i == `TRUE)
|
||||
begin
|
||||
write_enable <= `FALSE;
|
||||
MON_ACK_O <= `FALSE;
|
||||
MON_DAT_O <= {`LM32_WORD_WIDTH{1'bx}};
|
||||
state <= 2'b00;
|
||||
end
|
||||
else
|
||||
begin
|
||||
case (state)
|
||||
2'b00:
|
||||
begin
|
||||
// Wait for a Wishbone access
|
||||
if ((MON_STB_I == `TRUE) && (MON_CYC_I == `TRUE))
|
||||
state <= 2'b01;
|
||||
end
|
||||
2'b01:
|
||||
begin
|
||||
// Output read data to Wishbone
|
||||
MON_ACK_O <= `TRUE;
|
||||
MON_DAT_O <= data;
|
||||
// Sub-word writes are performed using read-modify-write
|
||||
// as the Lattice EBRs don't support byte enables
|
||||
if (MON_WE_I == `TRUE)
|
||||
write_enable <= `TRUE;
|
||||
write_data[7:0] <= MON_SEL_I[0] ? MON_DAT_I[7:0] : data[7:0];
|
||||
write_data[15:8] <= MON_SEL_I[1] ? MON_DAT_I[15:8] : data[15:8];
|
||||
write_data[23:16] <= MON_SEL_I[2] ? MON_DAT_I[23:16] : data[23:16];
|
||||
write_data[31:24] <= MON_SEL_I[3] ? MON_DAT_I[31:24] : data[31:24];
|
||||
state <= 2'b10;
|
||||
end
|
||||
2'b10:
|
||||
begin
|
||||
// Wishbone access occurs in this cycle
|
||||
write_enable <= `FALSE;
|
||||
MON_ACK_O <= `FALSE;
|
||||
MON_DAT_O <= {`LM32_WORD_WIDTH{1'bx}};
|
||||
state <= 2'b00;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
1397
lm32/logic/sakc/rtl/lm32/lm32_monitor_ram.v
Normal file
1397
lm32/logic/sakc/rtl/lm32/lm32_monitor_ram.v
Normal file
File diff suppressed because it is too large
Load Diff
94
lm32/logic/sakc/rtl/lm32/lm32_multiplier.v
Normal file
94
lm32/logic/sakc/rtl/lm32/lm32_multiplier.v
Normal file
@ -0,0 +1,94 @@
|
||||
// =============================================================================
|
||||
// COPYRIGHT NOTICE
|
||||
// Copyright 2006 (c) Lattice Semiconductor Corporation
|
||||
// ALL RIGHTS RESERVED
|
||||
// This confidential and proprietary software may be used only as authorised by
|
||||
// a licensing agreement from Lattice Semiconductor Corporation.
|
||||
// The entire notice above must be reproduced on all authorized copies and
|
||||
// copies may only be made to the extent permitted by a licensing agreement from
|
||||
// Lattice Semiconductor Corporation.
|
||||
//
|
||||
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
|
||||
// 5555 NE Moore Court 408-826-6000 (other locations)
|
||||
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
|
||||
// U.S.A email: techsupport@latticesemi.com
|
||||
// =============================================================================/
|
||||
// FILE DETAILS
|
||||
// Project : LatticeMico32
|
||||
// File : lm32_multiplier.v
|
||||
// Title : Pipelined multiplier.
|
||||
// Dependencies : lm32_include.v
|
||||
// Version : 6.1.17
|
||||
// =============================================================================
|
||||
|
||||
`include "lm32_include.v"
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Module interface
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
module lm32_multiplier (
|
||||
// ----- Inputs -----
|
||||
clk_i,
|
||||
rst_i,
|
||||
stall_x,
|
||||
stall_m,
|
||||
operand_0,
|
||||
operand_1,
|
||||
// ----- Ouputs -----
|
||||
result
|
||||
);
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Inputs
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
input clk_i; // Clock
|
||||
input rst_i; // Reset
|
||||
input stall_x; // Stall instruction in X stage
|
||||
input stall_m; // Stall instruction in M stage
|
||||
input [`LM32_WORD_RNG] operand_0; // Muliplicand
|
||||
input [`LM32_WORD_RNG] operand_1; // Multiplier
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Outputs
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
output [`LM32_WORD_RNG] result; // Product of multiplication
|
||||
reg [`LM32_WORD_RNG] result;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Internal nets and registers
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
reg [`LM32_WORD_RNG] muliplicand;
|
||||
reg [`LM32_WORD_RNG] multiplier;
|
||||
reg [`LM32_WORD_RNG] product;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Sequential logic
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
|
||||
begin
|
||||
if (rst_i == `TRUE)
|
||||
begin
|
||||
muliplicand <= {`LM32_WORD_WIDTH{1'b0}};
|
||||
multiplier <= {`LM32_WORD_WIDTH{1'b0}};
|
||||
product <= {`LM32_WORD_WIDTH{1'b0}};
|
||||
result <= {`LM32_WORD_WIDTH{1'b0}};
|
||||
end
|
||||
else
|
||||
begin
|
||||
if (stall_x == `FALSE)
|
||||
begin
|
||||
muliplicand <= operand_0;
|
||||
multiplier <= operand_1;
|
||||
end
|
||||
if (stall_m == `FALSE)
|
||||
product <= muliplicand * multiplier;
|
||||
result <= product;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
105
lm32/logic/sakc/rtl/lm32/lm32_ram.v
Normal file
105
lm32/logic/sakc/rtl/lm32/lm32_ram.v
Normal file
@ -0,0 +1,105 @@
|
||||
// =============================================================================
|
||||
// COPYRIGHT NOTICE
|
||||
// Copyright 2006 (c) Lattice Semiconductor Corporation
|
||||
// ALL RIGHTS RESERVED
|
||||
// This confidential and proprietary software may be used only as authorised by
|
||||
// a licensing agreement from Lattice Semiconductor Corporation.
|
||||
// The entire notice above must be reproduced on all authorized copies and
|
||||
// copies may only be made to the extent permitted by a licensing agreement from
|
||||
// Lattice Semiconductor Corporation.
|
||||
//
|
||||
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
|
||||
// 5555 NE Moore Court 408-826-6000 (other locations)
|
||||
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
|
||||
// U.S.A email: techsupport@latticesemi.com
|
||||
// =============================================================================/
|
||||
// FILE DETAILS
|
||||
// Project : LatticeMico32
|
||||
// File : lm32_ram.v
|
||||
// Title : Pseudo dual-port RAM.
|
||||
// Version : 6.1.17
|
||||
// =============================================================================
|
||||
|
||||
`include "lm32_include.v"
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Module interface
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
module lm32_ram (
|
||||
// ----- Inputs -------
|
||||
read_clk,
|
||||
write_clk,
|
||||
reset,
|
||||
enable_read,
|
||||
read_address,
|
||||
enable_write,
|
||||
write_address,
|
||||
write_data,
|
||||
write_enable,
|
||||
// ----- Outputs -------
|
||||
read_data
|
||||
);
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Parameters
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
parameter data_width = 1; // Width of the data ports
|
||||
parameter address_width = 1; // Width of the address ports
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Inputs
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
input read_clk; // Read clock
|
||||
input write_clk; // Write clock
|
||||
input reset; // Reset
|
||||
|
||||
input enable_read; // Access enable
|
||||
input [address_width-1:0] read_address; // Read/write address
|
||||
input enable_write; // Access enable
|
||||
input [address_width-1:0] write_address;// Read/write address
|
||||
input [data_width-1:0] write_data; // Data to write to specified address
|
||||
input write_enable; // Write enable
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Outputs
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
output [data_width-1:0] read_data; // Data read from specified addess
|
||||
wire [data_width-1:0] read_data;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Internal nets and registers
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
reg [data_width-1:0] mem[0:(1<<address_width)-1]; // The RAM
|
||||
reg [address_width-1:0] ra; // Registered read address
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Combinational Logic
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
// Read port
|
||||
assign read_data = mem[ra];
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Sequential Logic
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
// Write port
|
||||
always @(posedge write_clk)
|
||||
begin
|
||||
if ((write_enable == `TRUE) && (enable_write == `TRUE))
|
||||
mem[write_address] <= write_data;
|
||||
end
|
||||
|
||||
// Register read address for use on next cycle
|
||||
always @(posedge read_clk)
|
||||
begin
|
||||
if (enable_read)
|
||||
ra <= read_address;
|
||||
end
|
||||
|
||||
endmodule
|
129
lm32/logic/sakc/rtl/lm32/lm32_shifter.v
Normal file
129
lm32/logic/sakc/rtl/lm32/lm32_shifter.v
Normal file
@ -0,0 +1,129 @@
|
||||
// =============================================================================
|
||||
// COPYRIGHT NOTICE
|
||||
// Copyright 2006 (c) Lattice Semiconductor Corporation
|
||||
// ALL RIGHTS RESERVED
|
||||
// This confidential and proprietary software may be used only as authorised by
|
||||
// a licensing agreement from Lattice Semiconductor Corporation.
|
||||
// The entire notice above must be reproduced on all authorized copies and
|
||||
// copies may only be made to the extent permitted by a licensing agreement from
|
||||
// Lattice Semiconductor Corporation.
|
||||
//
|
||||
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
|
||||
// 5555 NE Moore Court 408-826-6000 (other locations)
|
||||
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
|
||||
// U.S.A email: techsupport@latticesemi.com
|
||||
// =============================================================================/
|
||||
// FILE DETAILS
|
||||
// Project : LatticeMico32
|
||||
// File : lm32_shifter.v
|
||||
// Title : Barrel shifter
|
||||
// Dependencies : lm32_include.v
|
||||
// Version : 6.1.17
|
||||
// =============================================================================
|
||||
|
||||
`include "lm32_include.v"
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Module interface
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
module lm32_shifter (
|
||||
// ----- Inputs -------
|
||||
clk_i,
|
||||
rst_i,
|
||||
stall_x,
|
||||
direction_x,
|
||||
sign_extend_x,
|
||||
operand_0_x,
|
||||
operand_1_x,
|
||||
// ----- Outputs -------
|
||||
shifter_result_m
|
||||
);
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Inputs
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
input clk_i; // Clock
|
||||
input rst_i; // Reset
|
||||
input stall_x; // Stall instruction in X stage
|
||||
input direction_x; // Direction to shift
|
||||
input sign_extend_x; // Whether shift is arithmetic (1'b1) or logical (1'b0)
|
||||
input [`LM32_WORD_RNG] operand_0_x; // Operand to shift
|
||||
input [`LM32_WORD_RNG] operand_1_x; // Operand that specifies how many bits to shift by
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Outputs
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
output [`LM32_WORD_RNG] shifter_result_m; // Result of shift
|
||||
wire [`LM32_WORD_RNG] shifter_result_m;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Internal nets and registers
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
reg direction_m;
|
||||
reg [`LM32_WORD_RNG] left_shift_result;
|
||||
reg [`LM32_WORD_RNG] right_shift_result;
|
||||
reg [`LM32_WORD_RNG] left_shift_operand;
|
||||
wire [`LM32_WORD_RNG] right_shift_operand;
|
||||
wire fill_value;
|
||||
wire [`LM32_WORD_RNG] right_shift_in;
|
||||
|
||||
integer shift_idx_0;
|
||||
integer shift_idx_1;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Combinational Logic
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
// Select operands - To perform a left shift, we reverse the bits and perform a right shift
|
||||
always @*
|
||||
begin
|
||||
for (shift_idx_0 = 0; shift_idx_0 < `LM32_WORD_WIDTH; shift_idx_0 = shift_idx_0 + 1)
|
||||
left_shift_operand[`LM32_WORD_WIDTH-1-shift_idx_0] = operand_0_x[shift_idx_0];
|
||||
end
|
||||
assign right_shift_operand = direction_x == `LM32_SHIFT_OP_LEFT ? left_shift_operand : operand_0_x;
|
||||
|
||||
// Determine fill value for right shift - Sign bit for arithmetic shift, or zero for logical shift
|
||||
assign fill_value = (sign_extend_x == `TRUE) && (direction_x == `LM32_SHIFT_OP_RIGHT)
|
||||
? operand_0_x[`LM32_WORD_WIDTH-1]
|
||||
: 1'b0;
|
||||
|
||||
// Determine bits to shift in for right shift or rotate
|
||||
assign right_shift_in = {`LM32_WORD_WIDTH{fill_value}};
|
||||
|
||||
// Reverse bits to get left shift result
|
||||
always @*
|
||||
begin
|
||||
for (shift_idx_1 = 0; shift_idx_1 < `LM32_WORD_WIDTH; shift_idx_1 = shift_idx_1 + 1)
|
||||
left_shift_result[`LM32_WORD_WIDTH-1-shift_idx_1] = right_shift_result[shift_idx_1];
|
||||
end
|
||||
|
||||
// Select result
|
||||
assign shifter_result_m = direction_m == `LM32_SHIFT_OP_LEFT ? left_shift_result : right_shift_result;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Sequential Logic
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
// Perform right shift
|
||||
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
|
||||
begin
|
||||
if (rst_i == `TRUE)
|
||||
begin
|
||||
right_shift_result <= {`LM32_WORD_WIDTH{1'b0}};
|
||||
direction_m <= `FALSE;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if (stall_x == `FALSE)
|
||||
begin
|
||||
right_shift_result <= {right_shift_in, right_shift_operand} >> operand_1_x[`LM32_SHIFT_RNG];
|
||||
direction_m <= direction_x;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
165
lm32/logic/sakc/rtl/lm32/lm32_simtrace.v
Normal file
165
lm32/logic/sakc/rtl/lm32/lm32_simtrace.v
Normal file
@ -0,0 +1,165 @@
|
||||
// =============================================================================/
|
||||
// FILE DETAILS
|
||||
// Project : LatticeMico32
|
||||
// File : lm32_simtrace.v
|
||||
// Title : Trace excecution in simulation
|
||||
// Dependencies : lm32_include.v
|
||||
// Version : soc-lm32 only
|
||||
// =============================================================================
|
||||
|
||||
`include "lm32_include.v"
|
||||
|
||||
// Index of opcode field in an instruction
|
||||
`define LM32_OPCODE_RNG 31:26
|
||||
`define LM32_OP_RNG 30:26
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Module interface
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
module lm32_simtrace (
|
||||
// ----- Inputs -------
|
||||
clk_i,
|
||||
rst_i,
|
||||
// From pipeline
|
||||
stall_x,
|
||||
stall_m,
|
||||
valid_w,
|
||||
kill_w,
|
||||
instruction_d,
|
||||
pc_w
|
||||
);
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Inputs
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
input clk_i;
|
||||
input rst_i;
|
||||
input stall_x; //
|
||||
input stall_m; //
|
||||
input valid_w; //
|
||||
input kill_w; //
|
||||
input [`LM32_INSTRUCTION_RNG] instruction_d; // Instruction to decode
|
||||
input [`LM32_PC_RNG] pc_w; // PC of instruction in D stage
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Internal nets and registers
|
||||
/////////////////////////////////////////////////////
|
||||
reg [`LM32_INSTRUCTION_RNG] instruction_x; // Instruction to decode
|
||||
reg [`LM32_INSTRUCTION_RNG] instruction_m; // Instruction to decode
|
||||
reg [`LM32_INSTRUCTION_RNG] instruction; // Instruction to decode
|
||||
|
||||
wire [`LM32_WORD_RNG] extended_immediate; // Zero or sign extended immediate
|
||||
wire [`LM32_WORD_RNG] high_immediate; // Immedate as high 16 bits
|
||||
wire [`LM32_WORD_RNG] immediate; // Immedate as high 16 bits
|
||||
wire [`LM32_WORD_RNG] call_immediate; // Call immediate
|
||||
wire [`LM32_WORD_RNG] branch_immediate; // Conditional branch immediate
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Functions
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
`include "lm32_functions.v"
|
||||
|
||||
|
||||
wire [4:0] r3 = instruction[25:21];
|
||||
wire [4:0] r2 = instruction[20:16];
|
||||
wire [4:0] r1 = instruction[15:11];
|
||||
|
||||
wire [ 4:0] imm5 = instruction[ 4:0];
|
||||
wire [15:0] imm16 = instruction[15:0];
|
||||
wire [26:0] imm27 = instruction[26:0];
|
||||
|
||||
//assign high_imm = {instruction[15:0], 16'h0000};
|
||||
wire [`LM32_PC_RNG] call_imm = {{ 4{instruction[25]}}, instruction[25:0]};
|
||||
wire [`LM32_PC_RNG] branch_imm = {{14{instruction[15]}}, instruction[15:0] };
|
||||
|
||||
// synopsys translate_off
|
||||
|
||||
always @(posedge clk_i)
|
||||
begin
|
||||
if (stall_x == `FALSE)
|
||||
instruction_x <= instruction_d;
|
||||
if (stall_m == `FALSE)
|
||||
instruction_m <= instruction_x;
|
||||
instruction <= instruction_m;
|
||||
|
||||
if ((valid_w == `TRUE) && (!kill_w)) begin
|
||||
// $write ( $stime/10 );
|
||||
$writeh( " [", pc_w << 2);
|
||||
$writeh( "]\t" );
|
||||
|
||||
case ( instruction[`LM32_OPCODE_RNG] )
|
||||
6'h00: $display( "srui r%0d, r%0d, 0x%0x", r2, r3, imm5 );
|
||||
6'h01: $display( "nori r%0d, r%0d, 0x%0x", r2, r3, imm16 );
|
||||
6'h02: $display( "muli r%0d, r%0d, 0x%0x", r2, r3, imm16 );
|
||||
6'h03: $display( "sh (r%0d + 0x%0x), r%0d", r3, r2, imm16 );
|
||||
6'h04: $display( "lb r%0d, (r%0d + 0x%0x)", r2, r3, imm16 );
|
||||
6'h05: $display( "sri r%0d, r%0d, 0x%0x", r2, r3, imm16 );
|
||||
6'h06: $display( "xori r%0d, r%0d, 0x%0x", r2, r3, imm16 );
|
||||
6'h07: $display( "lh r%0d, (r%0d + 0x%0x)", r2, r3, imm16 );
|
||||
6'h08: $display( "andi r%0d, r%0d, 0x%0x", r2, r3, imm16 );
|
||||
6'h09: $display( "xnori r%0d, r%0d, 0x%0x", r2, r3, imm16 );
|
||||
6'h0a: $display( "lw r%0d, (r%0d + 0x%0x)", r2, r3, imm16 );
|
||||
6'h0b: $display( "lhu r%0d, (r%0d + 0x%0x)", r2, r3, imm16 );
|
||||
6'h0c: $display( "sb (r%0d + 0x%0x), r%0d", r3, r2, imm16 );
|
||||
6'h0d: $display( "addi r%0d, r%0d, 0x%0x", r2, r3, imm16 );
|
||||
6'h0e: $display( "ori r%0d, r%0d, 0x%0x", r2, r3, imm16 );
|
||||
6'h0f: $display( "sli r%0d, r%0d, 0x%0x", r2, r3, imm5 );
|
||||
6'h10: $display( "lbu r%0d, (r%0d + 0x%0x)", r2, r3, imm16 );
|
||||
6'h11: $display( "be r%0d, r%0d, 0x%x", r2, r3, (pc_w + branch_imm ) << 2 );
|
||||
6'h12: $display( "bg r%0d, r%0d, 0x%x", r2, r3, (pc_w + branch_imm ) << 2 );
|
||||
6'h13: $display( "bge r%0d, r%0d, 0x%x", r2, r3, (pc_w + branch_imm ) << 2 );
|
||||
6'h14: $display( "bgeu r%0d, r%0d, 0x%x", r2, r3, (pc_w + branch_imm ) << 2 );
|
||||
6'h15: $display( "bgu r%0d, r%0d, 0x%x", r2, r3, (pc_w + branch_imm ) << 2 );
|
||||
6'h16: $display( "sw (r%0d + 0x%0x), r%0d", r3, r2, imm16 );
|
||||
6'h17: $display( "bne r%0d, r%0d, 0x%x", r2, r3, (pc_w + branch_imm ) << 2 );
|
||||
6'h18: $display( "andhi r%0d, r%0d, 0x%0x", r2, r3, imm16 );
|
||||
6'h19: $display( "cmpei r%0d, r%0d, 0x%0x", r2, r3, imm16 );
|
||||
6'h1a: $display( "cmpgi r%0d, r%0d, 0x%0x", r2, r3, imm16 );
|
||||
6'h1b: $display( "cmpgei r%0d, r%0d, 0x%0x", r2, r3, imm16 );
|
||||
6'h1c: $display( "cmpgeui r%0d, r%0d, 0x%0x", r2, r3, imm16 );
|
||||
6'h1d: $display( "cmpgui r%0d, r%0d, 0x%0x", r2, r3, imm16 );
|
||||
6'h1e: $display( "orhi r%0d, r%0d, 0x%0x", r2, r3, imm16 );
|
||||
6'h1f: $display( "cmpnei r%0d, r%0d, 0x%0x", r2, r3, imm16 );
|
||||
6'h20: $display( "sru r%0d, r%0d, r%0d", r1, r3, r2 );
|
||||
6'h21: $display( "nor r%0d, r%0d, r%0d", r1, r3, r2 );
|
||||
6'h22: $display( "mul r%0d, r%0d, r%0d", r1, r3, r2 );
|
||||
6'h23: $display( "divu r%0d, r%0d, r%0d", r1, r3, r2 );
|
||||
6'h24: $display( "rcsr r%0d, csr%0d", r1, r3 );
|
||||
6'h25: $display( "sr r%0d, r%0d, r%0d", r1, r3, r2 );
|
||||
6'h26: $display( "xor r%0d, r%0d, r%0d", r1, r3, r2 );
|
||||
6'h27: $display( "div (XXX not documented XXX)" );
|
||||
6'h28: $display( "and r%0d, r%0d, r%0d", r1, r3, r2 );
|
||||
6'h29: $display( "xnor r%0d, r%0d, r%0d", r1, r3, r2 );
|
||||
6'h2a: $display( "XXX" );
|
||||
6'h2b: $display( "raise (XXX: scall or break)" );
|
||||
6'h2c: $display( "sextb r%0d, r%0d", r1, r3 );
|
||||
6'h2d: $display( "add r%0d, r%0d, r%0d", r1, r3, r2 );
|
||||
6'h2e: $display( "or r%0d, r%0d, r%0d", r1, r3, r2 );
|
||||
6'h2f: $display( "sl r%0d, r%0d, r%0d", r1, r3, r2 );
|
||||
6'h30: $display( "b r%0d", r3 );
|
||||
6'h31: $display( "modu r%0d, r%0d, r%0d", r1, r3, r2 );
|
||||
6'h32: $display( "sub r%0d, r%0d, r%0d", r1, r3, r2 );
|
||||
6'h33: $display( "XXX" );
|
||||
6'h34: $display( "wcsr csr%0d, r%0d", r3, r2 );
|
||||
6'h35: $display( "modu r%0d, r%0d, r%0d", r1, r3, r2 );
|
||||
6'h36: $display( "call r%0d", r3 );
|
||||
6'h37: $display( "sexth r%0d, r%0d", r1, r3 );
|
||||
6'h38: $display( "bi 0x%x", (pc_w + call_imm) << 2 );
|
||||
6'h39: $display( "cmpe r%0d, r%0d, r%0d", r1, r3, r2 );
|
||||
6'h3a: $display( "cmpg r%0d, r%0d, r%0d", r1, r3, r2 );
|
||||
6'h3b: $display( "cmpge r%0d, r%0d, r%0d", r1, r3, r2 );
|
||||
6'h3c: $display( "cmpgeu r%0d, r%0d, r%0d", r1, r3, r2 );
|
||||
6'h3d: $display( "cmpgu r%0d, r%0d, r%0d", r1, r3, r2 );
|
||||
6'h3e: $display( "calli 0x%x", (pc_w + call_imm) << 2 );
|
||||
6'h3f: $display( "cmpne r%0d, r%0d, r%0d", r1, r3, r2 );
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
// synopsys translate_on
|
||||
|
||||
endmodule
|
||||
|
370
lm32/logic/sakc/rtl/lm32/lm32_top.v
Normal file
370
lm32/logic/sakc/rtl/lm32/lm32_top.v
Normal file
@ -0,0 +1,370 @@
|
||||
// =============================================================================
|
||||
// COPYRIGHT NOTICE
|
||||
// Copyright 2006 (c) Lattice Semiconductor Corporation
|
||||
// ALL RIGHTS RESERVED
|
||||
// This confidential and proprietary software may be used only as authorised by
|
||||
// a licensing agreement from Lattice Semiconductor Corporation.
|
||||
// The entire notice above must be reproduced on all authorized copies and
|
||||
// copies may only be made to the extent permitted by a licensing agreement from
|
||||
// Lattice Semiconductor Corporation.
|
||||
//
|
||||
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
|
||||
// 5555 NE Moore Court 408-826-6000 (other locations)
|
||||
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
|
||||
// U.S.A email: techsupport@latticesemi.com
|
||||
// =============================================================================/
|
||||
// FILE DETAILS
|
||||
// Project : LatticeMico32
|
||||
// File : lm32_top.v
|
||||
// Title : Top-level of CPU.
|
||||
// Dependencies : lm32_include.v
|
||||
// Version : 6.1.17
|
||||
// =============================================================================
|
||||
|
||||
`include "lm32_include.v"
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Module interface
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
module lm32_top (
|
||||
// ----- Inputs -------
|
||||
clk_i,
|
||||
rst_i,
|
||||
// From external devices
|
||||
`ifdef CFG_INTERRUPTS_ENABLED
|
||||
interrupt_n,
|
||||
`endif
|
||||
// From user logic
|
||||
`ifdef CFG_USER_ENABLED
|
||||
user_result,
|
||||
user_complete,
|
||||
`endif
|
||||
`ifdef CFG_IWB_ENABLED
|
||||
// Instruction Wishbone master
|
||||
I_DAT_I,
|
||||
I_ACK_I,
|
||||
I_ERR_I,
|
||||
I_RTY_I,
|
||||
`endif
|
||||
// Data Wishbone master
|
||||
D_DAT_I,
|
||||
D_ACK_I,
|
||||
D_ERR_I,
|
||||
D_RTY_I,
|
||||
// Debug Slave port WishboneInterface
|
||||
DEBUG_ADR_I,
|
||||
DEBUG_DAT_I,
|
||||
DEBUG_SEL_I,
|
||||
DEBUG_WE_I,
|
||||
DEBUG_CTI_I,
|
||||
DEBUG_BTE_I,
|
||||
DEBUG_LOCK_I,
|
||||
DEBUG_CYC_I,
|
||||
DEBUG_STB_I,
|
||||
// ----- Outputs -------
|
||||
`ifdef CFG_USER_ENABLED
|
||||
user_valid,
|
||||
user_opcode,
|
||||
user_operand_0,
|
||||
user_operand_1,
|
||||
`endif
|
||||
`ifdef CFG_IWB_ENABLED
|
||||
// Instruction Wishbone master
|
||||
I_DAT_O,
|
||||
I_ADR_O,
|
||||
I_CYC_O,
|
||||
I_SEL_O,
|
||||
I_STB_O,
|
||||
I_WE_O,
|
||||
I_CTI_O,
|
||||
I_LOCK_O,
|
||||
I_BTE_O,
|
||||
`endif
|
||||
// Data Wishbone master
|
||||
D_DAT_O,
|
||||
D_ADR_O,
|
||||
D_CYC_O,
|
||||
D_SEL_O,
|
||||
D_STB_O,
|
||||
D_WE_O,
|
||||
D_CTI_O,
|
||||
D_LOCK_O,
|
||||
D_BTE_O,
|
||||
// Debug Slave port WishboneInterface
|
||||
DEBUG_ACK_O,
|
||||
DEBUG_ERR_O,
|
||||
DEBUG_RTY_O,
|
||||
DEBUG_DAT_O
|
||||
);
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Inputs
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
input clk_i; // Clock
|
||||
input rst_i; // Reset
|
||||
|
||||
`ifdef CFG_INTERRUPTS_ENABLED
|
||||
input [`LM32_INTERRUPT_RNG] interrupt_n; // Interrupt pins, active-low
|
||||
`endif
|
||||
|
||||
`ifdef CFG_USER_ENABLED
|
||||
input [`LM32_WORD_RNG] user_result; // User-defined instruction result
|
||||
input user_complete; // Indicates the user-defined instruction result is valid
|
||||
`endif
|
||||
|
||||
`ifdef CFG_IWB_ENABLED
|
||||
input [`LM32_WORD_RNG] I_DAT_I; // Instruction Wishbone interface read data
|
||||
input I_ACK_I; // Instruction Wishbone interface acknowledgement
|
||||
input I_ERR_I; // Instruction Wishbone interface error
|
||||
input I_RTY_I; // Instruction Wishbone interface retry
|
||||
`endif
|
||||
|
||||
input [`LM32_WORD_RNG] D_DAT_I; // Data Wishbone interface read data
|
||||
input D_ACK_I; // Data Wishbone interface acknowledgement
|
||||
input D_ERR_I; // Data Wishbone interface error
|
||||
input D_RTY_I; // Data Wishbone interface retry
|
||||
|
||||
input [`LM32_WORD_RNG] DEBUG_ADR_I; // Debug monitor Wishbone interface address
|
||||
input [`LM32_WORD_RNG] DEBUG_DAT_I; // Debug monitor Wishbone interface write data
|
||||
input [`LM32_BYTE_SELECT_RNG] DEBUG_SEL_I; // Debug monitor Wishbone interface byte select
|
||||
input DEBUG_WE_I; // Debug monitor Wishbone interface write enable
|
||||
input [`LM32_CTYPE_RNG] DEBUG_CTI_I; // Debug monitor Wishbone interface cycle type
|
||||
input [`LM32_BTYPE_RNG] DEBUG_BTE_I; // Debug monitor Wishbone interface burst type
|
||||
input DEBUG_LOCK_I; // Debug monitor Wishbone interface locked transfer
|
||||
input DEBUG_CYC_I; // Debug monitor Wishbone interface cycle
|
||||
input DEBUG_STB_I; // Debug monitor Wishbone interface strobe
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Outputs
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
`ifdef CFG_USER_ENABLED
|
||||
output user_valid; // Indicates that user_opcode and user_operand_* are valid
|
||||
wire user_valid;
|
||||
output [`LM32_USER_OPCODE_RNG] user_opcode; // User-defined instruction opcode
|
||||
reg [`LM32_USER_OPCODE_RNG] user_opcode;
|
||||
output [`LM32_WORD_RNG] user_operand_0; // First operand for user-defined instruction
|
||||
wire [`LM32_WORD_RNG] user_operand_0;
|
||||
output [`LM32_WORD_RNG] user_operand_1; // Second operand for user-defined instruction
|
||||
wire [`LM32_WORD_RNG] user_operand_1;
|
||||
`endif
|
||||
|
||||
`ifdef CFG_IWB_ENABLED
|
||||
output [`LM32_WORD_RNG] I_DAT_O; // Instruction Wishbone interface write data
|
||||
wire [`LM32_WORD_RNG] I_DAT_O;
|
||||
output [`LM32_WORD_RNG] I_ADR_O; // Instruction Wishbone interface address
|
||||
wire [`LM32_WORD_RNG] I_ADR_O;
|
||||
output I_CYC_O; // Instruction Wishbone interface cycle
|
||||
wire I_CYC_O;
|
||||
output [`LM32_BYTE_SELECT_RNG] I_SEL_O; // Instruction Wishbone interface byte select
|
||||
wire [`LM32_BYTE_SELECT_RNG] I_SEL_O;
|
||||
output I_STB_O; // Instruction Wishbone interface strobe
|
||||
wire I_STB_O;
|
||||
output I_WE_O; // Instruction Wishbone interface write enable
|
||||
wire I_WE_O;
|
||||
output [`LM32_CTYPE_RNG] I_CTI_O; // Instruction Wishbone interface cycle type
|
||||
wire [`LM32_CTYPE_RNG] I_CTI_O;
|
||||
output I_LOCK_O; // Instruction Wishbone interface lock bus
|
||||
wire I_LOCK_O;
|
||||
output [`LM32_BTYPE_RNG] I_BTE_O; // Instruction Wishbone interface burst type
|
||||
wire [`LM32_BTYPE_RNG] I_BTE_O;
|
||||
`endif
|
||||
|
||||
output [`LM32_WORD_RNG] D_DAT_O; // Data Wishbone interface write data
|
||||
wire [`LM32_WORD_RNG] D_DAT_O;
|
||||
output [`LM32_WORD_RNG] D_ADR_O; // Data Wishbone interface address
|
||||
wire [`LM32_WORD_RNG] D_ADR_O;
|
||||
output D_CYC_O; // Data Wishbone interface cycle
|
||||
wire D_CYC_O;
|
||||
output [`LM32_BYTE_SELECT_RNG] D_SEL_O; // Data Wishbone interface byte select
|
||||
wire [`LM32_BYTE_SELECT_RNG] D_SEL_O;
|
||||
output D_STB_O; // Data Wishbone interface strobe
|
||||
wire D_STB_O;
|
||||
output D_WE_O; // Data Wishbone interface write enable
|
||||
wire D_WE_O;
|
||||
output [`LM32_CTYPE_RNG] D_CTI_O; // Data Wishbone interface cycle type
|
||||
wire [`LM32_CTYPE_RNG] D_CTI_O;
|
||||
output D_LOCK_O; // Date Wishbone interface lock bus
|
||||
wire D_LOCK_O;
|
||||
output [`LM32_BTYPE_RNG] D_BTE_O; // Data Wishbone interface burst type
|
||||
wire [`LM32_BTYPE_RNG] D_BTE_O;
|
||||
|
||||
output DEBUG_ACK_O; // Debug monitor Wishbone ack
|
||||
wire DEBUG_ACK_O;
|
||||
output DEBUG_ERR_O; // Debug monitor Wishbone error
|
||||
wire DEBUG_ERR_O;
|
||||
output DEBUG_RTY_O; // Debug monitor Wishbone retry
|
||||
wire DEBUG_RTY_O;
|
||||
output [`LM32_WORD_RNG] DEBUG_DAT_O; // Debug monitor Wishbone read data
|
||||
wire [`LM32_WORD_RNG] DEBUG_DAT_O;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Internal nets and registers
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
`ifdef CFG_JTAG_ENABLED
|
||||
// Signals between JTAG interface and CPU
|
||||
wire [`LM32_BYTE_RNG] jtag_reg_d;
|
||||
wire [`LM32_BYTE_RNG] jtag_reg_q;
|
||||
wire jtag_update;
|
||||
wire [2:0] jtag_reg_addr_d;
|
||||
wire [2:0] jtag_reg_addr_q;
|
||||
wire jtck;
|
||||
wire jrstn;
|
||||
`endif
|
||||
|
||||
`ifdef CFG_TRACE_ENABLED
|
||||
// PC trace signals
|
||||
wire [`LM32_PC_RNG] trace_pc; // PC to trace (address of next non-sequential instruction)
|
||||
wire trace_pc_valid; // Indicates that a new trace PC is valid
|
||||
wire trace_exception; // Indicates an exception has occured
|
||||
wire [`LM32_EID_RNG] trace_eid; // Indicates what type of exception has occured
|
||||
wire trace_eret; // Indicates an eret instruction has been executed
|
||||
`ifdef CFG_DEBUG_ENABLED
|
||||
wire trace_bret; // Indicates a bret instruction has been executed
|
||||
`endif
|
||||
`endif
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Functions
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
`include "lm32_functions.v"
|
||||
/////////////////////////////////////////////////////
|
||||
// Instantiations
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
// LM32 CPU
|
||||
lm32_cpu cpu (
|
||||
// ----- Inputs -------
|
||||
.clk_i (clk_i),
|
||||
`ifdef CFG_EBR_NEGEDGE_REGISTER_FILE
|
||||
.clk_n_i (clk_n),
|
||||
`endif
|
||||
.rst_i (rst_i),
|
||||
// From external devices
|
||||
`ifdef CFG_INTERRUPTS_ENABLED
|
||||
.interrupt_n (interrupt_n),
|
||||
`endif
|
||||
// From user logic
|
||||
`ifdef CFG_USER_ENABLED
|
||||
.user_result (user_result),
|
||||
.user_complete (user_complete),
|
||||
`endif
|
||||
`ifdef CFG_JTAG_ENABLED
|
||||
// From JTAG
|
||||
.jtag_clk (jtck),
|
||||
.jtag_update (jtag_update),
|
||||
.jtag_reg_q (jtag_reg_q),
|
||||
.jtag_reg_addr_q (jtag_reg_addr_q),
|
||||
`endif
|
||||
`ifdef CFG_IWB_ENABLED
|
||||
// Instruction Wishbone master
|
||||
.I_DAT_I (I_DAT_I),
|
||||
.I_ACK_I (I_ACK_I),
|
||||
.I_ERR_I (I_ERR_I),
|
||||
.I_RTY_I (I_RTY_I),
|
||||
`endif
|
||||
// Data Wishbone master
|
||||
.D_DAT_I (D_DAT_I),
|
||||
.D_ACK_I (D_ACK_I),
|
||||
.D_ERR_I (D_ERR_I),
|
||||
.D_RTY_I (D_RTY_I),
|
||||
// ----- Outputs -------
|
||||
`ifdef CFG_TRACE_ENABLED
|
||||
.trace_pc (trace_pc),
|
||||
.trace_pc_valid (trace_pc_valid),
|
||||
.trace_exception (trace_exception),
|
||||
.trace_eid (trace_eid),
|
||||
.trace_eret (trace_eret),
|
||||
`ifdef CFG_DEBUG_ENABLED
|
||||
.trace_bret (trace_bret),
|
||||
`endif
|
||||
`endif
|
||||
`ifdef CFG_JTAG_ENABLED
|
||||
.jtag_reg_d (jtag_reg_d),
|
||||
.jtag_reg_addr_d (jtag_reg_addr_d),
|
||||
`endif
|
||||
`ifdef CFG_USER_ENABLED
|
||||
.user_valid (user_valid),
|
||||
.user_opcode (user_opcode),
|
||||
.user_operand_0 (user_operand_0),
|
||||
.user_operand_1 (user_operand_1),
|
||||
`endif
|
||||
`ifdef CFG_IWB_ENABLED
|
||||
// Instruction Wishbone master
|
||||
.I_DAT_O (I_DAT_O),
|
||||
.I_ADR_O (I_ADR_O),
|
||||
.I_CYC_O (I_CYC_O),
|
||||
.I_SEL_O (I_SEL_O),
|
||||
.I_STB_O (I_STB_O),
|
||||
.I_WE_O (I_WE_O),
|
||||
.I_CTI_O (I_CTI_O),
|
||||
.I_LOCK_O (I_LOCK_O),
|
||||
.I_BTE_O (I_BTE_O),
|
||||
`endif
|
||||
// Data Wishbone master
|
||||
.D_DAT_O (D_DAT_O),
|
||||
.D_ADR_O (D_ADR_O),
|
||||
.D_CYC_O (D_CYC_O),
|
||||
.D_SEL_O (D_SEL_O),
|
||||
.D_STB_O (D_STB_O),
|
||||
.D_WE_O (D_WE_O),
|
||||
.D_CTI_O (D_CTI_O),
|
||||
.D_LOCK_O (D_LOCK_O),
|
||||
.D_BTE_O (D_BTE_O)
|
||||
);
|
||||
|
||||
`ifdef DEBUG_ROM
|
||||
// ROM monitor
|
||||
lm32_monitor debug_rom (
|
||||
// ----- Inputs -------
|
||||
.clk_i (clk_i),
|
||||
.rst_i (rst_i),
|
||||
.MON_ADR_I (DEBUG_ADR_I),
|
||||
.MON_STB_I (DEBUG_STB_I),
|
||||
.MON_CYC_I (DEBUG_CYC_I),
|
||||
.MON_WE_I (DEBUG_WE_I),
|
||||
.MON_SEL_I (DEBUG_SEL_I),
|
||||
.MON_DAT_I (DEBUG_DAT_I),
|
||||
.MON_CTI_I (DEBUG_CTI_I),
|
||||
.MON_BTE_I (DEBUG_BTE_I),
|
||||
.MON_LOCK_I (DEBUG_LOCK_I),
|
||||
// ----- Outputs ------
|
||||
.MON_RTY_O (DEBUG_RTY_O),
|
||||
.MON_ERR_O (DEBUG_ERR_O),
|
||||
.MON_ACK_O (DEBUG_ACK_O),
|
||||
.MON_DAT_O (DEBUG_DAT_O)
|
||||
);
|
||||
`endif
|
||||
|
||||
`ifdef CFG_JTAG_ENABLED
|
||||
// JTAG cores
|
||||
jtag_cores jtag_cores (
|
||||
// ----- Inputs -----
|
||||
`ifdef INCLUDE_LM32
|
||||
.reg_d (jtag_reg_d),
|
||||
.reg_addr_d (jtag_reg_addr_d),
|
||||
`endif
|
||||
`ifdef INCLUDE_SPI
|
||||
.spi_q (spi_q),
|
||||
`endif
|
||||
// ----- Outputs -----
|
||||
`ifdef INCLUDE_LM32
|
||||
.reg_update (jtag_update),
|
||||
.reg_q (jtag_reg_q),
|
||||
.reg_addr_q (jtag_reg_addr_q),
|
||||
`endif
|
||||
`ifdef INCLUDE_SPI
|
||||
.spi_c (spi_c),
|
||||
.spi_d (spi_d),
|
||||
.spi_sn (spi_sn),
|
||||
`endif
|
||||
.jtck (jtck),
|
||||
.jrstn (jrstn)
|
||||
);
|
||||
`endif
|
||||
|
||||
endmodule
|
159
lm32/logic/sakc/rtl/lm32/spiprog.v
Normal file
159
lm32/logic/sakc/rtl/lm32/spiprog.v
Normal file
@ -0,0 +1,159 @@
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//Name : SPIPROG.v
|
||||
//
|
||||
//Description:
|
||||
//
|
||||
// This module contains the ER2 regsiters of SPI Serial FLASH programmer IP
|
||||
// core. There are only three ER2 registers, one control register and two
|
||||
// data registers, in this IP core. The control register is a 8-bit wide
|
||||
// register for selecting which data register will be accessed when the
|
||||
// Control/Data# bit in ER1 register is low. Data register 0 is a readonly
|
||||
// ID register. It is composed of three register fields -- an 8-bit
|
||||
// "implementer", a 16-bit "IP_functionality", and a 12-bit "revision".
|
||||
// Data register 1 is a variable length register for sending commands to or
|
||||
// receiving readback data from the SPI Serial FLASH device.
|
||||
//
|
||||
//$Log: spiprog.vhd,v $
|
||||
//Revision 1.2 2004-09-09 11:43:26-07 jhsin
|
||||
//1. Reduced the the ID register (DR0) length from 36 bits to 8 bits.
|
||||
//2. Same as TYPEA and TYPEB modules, use falling edge clock
|
||||
// for all TCK Flip-Flops.
|
||||
//
|
||||
//Revision 1.1 2004-08-12 13:22:05-07 jhsin
|
||||
//Added 7 delay Flip-Flops so that the DR1 readback data from SPI Serial FLASH is in the byte boundary.
|
||||
//
|
||||
//Revision 1.0 2004-08-03 18:35:56-07 jhsin
|
||||
//Initial revision
|
||||
//
|
||||
//
|
||||
//$Header: \\\\hqfs2\\ip\040cores\\rcs\\hqfs2\\ip\040cores\\rcswork\\isptracy\\VHDL\\Implementation\\spiprog.vhd,v 1.2 2004-09-09 11:43:26-07 jhsin Exp $
|
||||
//
|
||||
//Copyright (C) 2004 Lattice Semiconductor Corp. All rights reserved.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
module SPIPROG (input JTCK ,
|
||||
input JTDI ,
|
||||
output JTDO2 ,
|
||||
input JSHIFT ,
|
||||
input JUPDATE ,
|
||||
input JRSTN ,
|
||||
input JCE2 ,
|
||||
input SPIPROG_ENABLE ,
|
||||
input CONTROL_DATAN ,
|
||||
output SPI_C ,
|
||||
output SPI_D ,
|
||||
output SPI_SN ,
|
||||
input SPI_Q);
|
||||
|
||||
wire er2Cr_enable ;
|
||||
wire er2Dr0_enable;
|
||||
wire er2Dr1_enable;
|
||||
|
||||
wire tdo_er2Cr ;
|
||||
wire tdo_er2Dr0;
|
||||
wire tdo_er2Dr1;
|
||||
|
||||
wire [7:0] encodedDrSelBits ;
|
||||
wire [8:0] er2CrTdiBit ;
|
||||
wire [8:0] er2Dr0TdiBit ;
|
||||
|
||||
wire captureDrER2;
|
||||
reg spi_s ;
|
||||
reg [6:0] spi_q_dly;
|
||||
|
||||
wire [7:0] ip_functionality_id;
|
||||
|
||||
genvar i;
|
||||
|
||||
// ------ Control Register 0 ------
|
||||
|
||||
assign er2Cr_enable = JCE2 & SPIPROG_ENABLE & CONTROL_DATAN;
|
||||
|
||||
assign tdo_er2Cr = er2CrTdiBit[0];
|
||||
|
||||
// CR_BIT0_BIT7
|
||||
generate
|
||||
for(i=0; i<=7; i=i+1)
|
||||
begin:CR_BIT0_BIT7
|
||||
TYPEA BIT_N (.CLK (JTCK),
|
||||
.RESET_N (JRSTN),
|
||||
.CLKEN (er2Cr_enable),
|
||||
.TDI (er2CrTdiBit[i + 1]),
|
||||
.TDO (er2CrTdiBit[i]),
|
||||
.DATA_OUT (encodedDrSelBits[i]),
|
||||
.DATA_IN (encodedDrSelBits[i]),
|
||||
.CAPTURE_DR (captureDrER2),
|
||||
.UPDATE_DR (JUPDATE));
|
||||
end
|
||||
endgenerate // CR_BIT0_BIT7
|
||||
|
||||
assign er2CrTdiBit[8] = JTDI;
|
||||
|
||||
// ------ Data Register 0 ------
|
||||
assign er2Dr0_enable = (JCE2 & SPIPROG_ENABLE & ~CONTROL_DATAN & (encodedDrSelBits == 8'b00000000)) ? 1'b1 : 1'b0;
|
||||
|
||||
assign tdo_er2Dr0 = er2Dr0TdiBit[0];
|
||||
|
||||
assign ip_functionality_id = 8'b00000001; //-- SPI Serial FLASH Programmer (0x01)
|
||||
|
||||
// DR0_BIT0_BIT7
|
||||
generate
|
||||
for(i=0; i<=7; i=i+1)
|
||||
begin:DR0_BIT0_BIT7
|
||||
TYPEB BIT_N (.CLK (JTCK),
|
||||
.RESET_N (JRSTN),
|
||||
.CLKEN (er2Dr0_enable),
|
||||
.TDI (er2Dr0TdiBit[i + 1]),
|
||||
.TDO (er2Dr0TdiBit[i]),
|
||||
.DATA_IN (ip_functionality_id[i]),
|
||||
.CAPTURE_DR (captureDrER2));
|
||||
end
|
||||
endgenerate // DR0_BIT0_BIT7
|
||||
|
||||
assign er2Dr0TdiBit[8] = JTDI;
|
||||
|
||||
// ------ Data Register 1 ------
|
||||
|
||||
assign er2Dr1_enable = (JCE2 & JSHIFT & SPIPROG_ENABLE & ~CONTROL_DATAN & (encodedDrSelBits == 8'b00000001)) ? 1'b1 : 1'b0;
|
||||
|
||||
assign SPI_C = ~ (JTCK & er2Dr1_enable & spi_s);
|
||||
|
||||
assign SPI_D = JTDI & er2Dr1_enable;
|
||||
|
||||
// SPI_S_Proc
|
||||
always @(negedge JTCK or negedge JRSTN)
|
||||
begin
|
||||
if (~JRSTN)
|
||||
spi_s <= 1'b0;
|
||||
else
|
||||
if (JUPDATE)
|
||||
spi_s <= 1'b0;
|
||||
else
|
||||
spi_s <= er2Dr1_enable;
|
||||
end
|
||||
|
||||
assign SPI_SN = ~spi_s;
|
||||
|
||||
// SPI_Q_Proc
|
||||
always @(negedge JTCK or negedge JRSTN)
|
||||
begin
|
||||
if (~JRSTN)
|
||||
spi_q_dly <= 'b0;
|
||||
else
|
||||
if (er2Dr1_enable)
|
||||
spi_q_dly <= {spi_q_dly[5:0],SPI_Q};
|
||||
end
|
||||
|
||||
assign tdo_er2Dr1 = spi_q_dly[6];
|
||||
|
||||
// ------ JTDO2 MUX ------
|
||||
|
||||
assign JTDO2 = CONTROL_DATAN ? tdo_er2Cr :
|
||||
(encodedDrSelBits == 8'b00000000) ? tdo_er2Dr0 :
|
||||
(encodedDrSelBits == 8'b00000001) ? tdo_er2Dr1 : 1'b0;
|
||||
|
||||
assign captureDrER2 = ~JSHIFT & JCE2;
|
||||
|
||||
endmodule
|
58
lm32/logic/sakc/rtl/lm32/system.sdc
Executable file
58
lm32/logic/sakc/rtl/lm32/system.sdc
Executable file
@ -0,0 +1,58 @@
|
||||
# Synplicity, Inc. constraint file
|
||||
# C:\ispTOOLS6_0\micosystem\components\lm32_top\rtl\verilog\system.sdc
|
||||
# Written on Thu Apr 06 13:56:58 2006
|
||||
# by Synplify for Lattice, Synplify for Lattice 8.5D Scope Editor
|
||||
|
||||
#
|
||||
# Clocks
|
||||
#
|
||||
define_clock -name {clk_i} -freq 25.000 -clockgroup default_clkgroup_0
|
||||
|
||||
#
|
||||
# Clock to Clock
|
||||
#
|
||||
|
||||
#
|
||||
# Inputs/Outputs
|
||||
#
|
||||
|
||||
#
|
||||
# Registers
|
||||
#
|
||||
|
||||
#
|
||||
# Multicycle Path
|
||||
#
|
||||
|
||||
#
|
||||
# False Path
|
||||
#
|
||||
|
||||
#
|
||||
# Path Delay
|
||||
#
|
||||
|
||||
#
|
||||
# Attributes
|
||||
#
|
||||
define_attribute {clk_i} loc {a10}
|
||||
define_attribute {reset_n} loc {h6}
|
||||
define_attribute {uartSIN} loc {m2}
|
||||
define_attribute {uartSOUT} loc {l1}
|
||||
define_attribute {sramsram_csn} loc {y4}
|
||||
define_attribute {sramsram_oen} loc {aa6}
|
||||
define_attribute {sramsram_wen} loc {ab6}
|
||||
define_attribute {sramsram_be[3:0]} loc {aa3,ab3,aa4,ab4}
|
||||
define_attribute {sramsram_data[31:0]} loc {v7,w7,y7,aa7,ab7,v8,w8,y8,aa8,ab8,v9,w9,y9,aa9,ab9,v10,w10,y10,aa10,w11,y11,aa11,y13,aa13,w14,y14,aa14,ab14,u15,v15,w15,y15}
|
||||
define_attribute {sramsram_addr[22:0]} loc {u16,v16,w16,y16,aa16,ab16,u17,v17,w17,y17,aa17,ab17,w18,y18,aa18,ab18,y19,aa19,ab19,aa20,ab20,y20,w20}
|
||||
define_attribute {gpio_LCDPIO_OUT[15:0]} loc {h5,t13,t17,u13,v13,p5,p3,p4,n5,n4,n3,n2,n1,m5,m4,m3}
|
||||
define_attribute {gpio_LEDPIO_OUT[9:0]} loc {u11,v5,u6,u4,g5,g4,f5,f4,e5,e4}
|
||||
define_attribute {gpio_KeypadPIO_IN[3:0]} loc {R1,T3,T2,T1}
|
||||
|
||||
#
|
||||
# I/O standards
|
||||
#
|
||||
|
||||
#
|
||||
# Other Constraints
|
||||
#
|
74
lm32/logic/sakc/rtl/lm32/typea.v
Normal file
74
lm32/logic/sakc/rtl/lm32/typea.v
Normal file
@ -0,0 +1,74 @@
|
||||
/*-- ---------------------------------------------------------------------------
|
||||
--
|
||||
-- Name : TYPEA.v
|
||||
--
|
||||
-- Description:
|
||||
--
|
||||
-- This is one of the two types of cells that are used to create ER1/ER2
|
||||
-- register bits.
|
||||
--
|
||||
-- $Log: typea.vhd,v $
|
||||
-- Revision 1.2 2002-11-13 18:33:59-08 jhsin
|
||||
-- The SHIFT_DR_CAPTURE_DR and ENABLE_ER1/2 signals of the
|
||||
-- dedicate logic JTAG_PORT didn't act as what their names implied.
|
||||
-- The SHIFT_DR_CAPTURE_DR actually acts as SHIFT_DR.
|
||||
-- The ENABLE_ER1/2 actually acts as SHIFT_DR_CAPTURE_DR.
|
||||
-- These had caused a lot of headaches for a long time and now they are
|
||||
-- fixed by:
|
||||
-- (1) Use SHIFT_DR_CAPTURE_DR and ENABLE_ER1/2 to create
|
||||
-- CAPTURE_DR for all typeA, typeB bits in the ER1, ER2 registers.
|
||||
-- (2) Use ENABLE_ER1 or the enESR, enCSR, enBAR (these 3 signals
|
||||
-- have the same waveform of ENABLE_ER2) directly to be the CLKEN
|
||||
-- of all typeA, typeB bits in the ER1, ER2 registers.
|
||||
-- (3) Modify typea.vhd to use only UPDATE_DR signal for the clock enable
|
||||
-- of the holding flip-flop.
|
||||
-- These changes caused ispTracy.vhd and cge.dat changes and the new
|
||||
-- CGE.exe version will be 1.3.5.
|
||||
--
|
||||
-- Revision 1.1 2002-05-01 18:13:51-07 jhsin
|
||||
-- Added RCS version control header to file. No code changes.
|
||||
--
|
||||
-- $Header: \\\\hqfile2\\ipcores\\rcs\\hqfile2\\ipcores\\rcswork\\isptracy\\VHDL\\Implementation\\typea.vhd,v 1.2 2002-11-13 18:33:59-08 jhsin Exp $
|
||||
--
|
||||
-- Copyright (C) 2002 Lattice Semiconductor Corp. All rights reserved.
|
||||
--
|
||||
-- ---------------------------------------------------------------------------*/
|
||||
|
||||
module TYPEA(
|
||||
input CLK,
|
||||
input RESET_N,
|
||||
input CLKEN,
|
||||
input TDI,
|
||||
output TDO,
|
||||
output reg DATA_OUT,
|
||||
input DATA_IN,
|
||||
input CAPTURE_DR,
|
||||
input UPDATE_DR
|
||||
);
|
||||
|
||||
reg tdoInt;
|
||||
|
||||
|
||||
always @ (negedge CLK or negedge RESET_N)
|
||||
begin
|
||||
if (RESET_N == 1'b0)
|
||||
tdoInt <= 1'b0;
|
||||
else if (CLK == 1'b0)
|
||||
if (CLKEN == 1'b1)
|
||||
if (CAPTURE_DR == 1'b0)
|
||||
tdoInt <= TDI;
|
||||
else
|
||||
tdoInt <= DATA_IN;
|
||||
end
|
||||
|
||||
assign TDO = tdoInt;
|
||||
|
||||
always @ (negedge CLK or negedge RESET_N)
|
||||
begin
|
||||
if (RESET_N == 1'b0)
|
||||
DATA_OUT <= 1'b0;
|
||||
else if (CLK == 1'b0)
|
||||
if (UPDATE_DR == 1'b1)
|
||||
DATA_OUT <= tdoInt;
|
||||
end
|
||||
endmodule
|
50
lm32/logic/sakc/rtl/lm32/typeb.v
Normal file
50
lm32/logic/sakc/rtl/lm32/typeb.v
Normal file
@ -0,0 +1,50 @@
|
||||
/*-- ---------------------------------------------------------------------------
|
||||
--
|
||||
-- Name : TYPEB.vhd
|
||||
--
|
||||
-- Description:
|
||||
--
|
||||
-- This is one of the two types of cells that are used to create ER1/ER2
|
||||
-- register bits.
|
||||
--
|
||||
-- $Log: typeb.vhd,v $
|
||||
-- Revision 1.2 2002-08-01 16:39:33-07 jhsin
|
||||
-- Modified typeb module to remove redundant DATA_OUT port.
|
||||
--
|
||||
-- Revision 1.1 2002-05-01 18:13:51-07 jhsin
|
||||
-- Added RCS version control header to file. No code changes.
|
||||
--
|
||||
-- $Header: \\\\hqfile2\\ipcores\\rcs\\hqfile2\\ipcores\\rcswork\\isptracy\\VHDL\\Implementation\\typeb.vhd,v 1.2 2002-08-01 16:39:33-07 jhsin Exp $
|
||||
--
|
||||
-- Copyright (C) 2002 Lattice Semiconductor Corp. All rights reserved.
|
||||
--
|
||||
-- ---------------------------------------------------------------------------*/
|
||||
module TYPEB
|
||||
(
|
||||
input CLK,
|
||||
input RESET_N,
|
||||
input CLKEN,
|
||||
input TDI,
|
||||
output TDO,
|
||||
input DATA_IN,
|
||||
input CAPTURE_DR
|
||||
);
|
||||
|
||||
reg tdoInt;
|
||||
|
||||
always @ (negedge CLK or negedge RESET_N)
|
||||
begin
|
||||
if (RESET_N== 1'b0)
|
||||
tdoInt <= 1'b0;
|
||||
else if (CLK == 1'b0)
|
||||
if (CLKEN==1'b1)
|
||||
if (CAPTURE_DR==1'b0)
|
||||
tdoInt <= TDI;
|
||||
else
|
||||
tdoInt <= DATA_IN;
|
||||
end
|
||||
|
||||
assign TDO = tdoInt;
|
||||
|
||||
endmodule
|
||||
|
62
lm32/logic/sakc/rtl/wb_bram/wb_bram.v
Normal file
62
lm32/logic/sakc/rtl/wb_bram/wb_bram.v
Normal file
@ -0,0 +1,62 @@
|
||||
//-----------------------------------------------------------------
|
||||
// Wishbone BlockRAM
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
module wb_bram #(
|
||||
parameter mem_file_name = "none",
|
||||
parameter adr_width = 11
|
||||
) (
|
||||
input clk_i,
|
||||
input rst_i,
|
||||
//
|
||||
input wb_stb_i,
|
||||
input wb_cyc_i,
|
||||
input wb_we_i,
|
||||
output wb_ack_o,
|
||||
input [31:0] wb_adr_i,
|
||||
output reg [31:0] wb_dat_o,
|
||||
input [31:0] wb_dat_i,
|
||||
input [ 3:0] wb_sel_i
|
||||
);
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// Storage depth in 32 bit words
|
||||
//-----------------------------------------------------------------
|
||||
parameter word_width = adr_width - 2;
|
||||
parameter word_depth = (1 << word_width);
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------
|
||||
reg [31:0] ram [0:word_depth-1]; // actual RAM
|
||||
reg ack;
|
||||
wire [word_width-1:0] adr;
|
||||
|
||||
|
||||
assign adr = wb_adr_i[adr_width-1:2]; //
|
||||
assign wb_ack_o = wb_stb_i & ack;
|
||||
|
||||
always @(posedge clk_i)
|
||||
begin
|
||||
if (wb_stb_i && wb_cyc_i)
|
||||
begin
|
||||
if (wb_we_i)
|
||||
ram[ adr ] <= wb_dat_i;
|
||||
|
||||
wb_dat_o <= ram[ adr ];
|
||||
ack <= ~ack;
|
||||
end else
|
||||
ack <= 0;
|
||||
|
||||
end
|
||||
|
||||
initial
|
||||
begin
|
||||
if (mem_file_name != "none")
|
||||
begin
|
||||
$readmemh(mem_file_name, ram);
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
252
lm32/logic/sakc/rtl/wb_conbus/wb_conbus_arb.v
Normal file
252
lm32/logic/sakc/rtl/wb_conbus/wb_conbus_arb.v
Normal file
@ -0,0 +1,252 @@
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
//// ////
|
||||
//// General Round Robin Arbiter ////
|
||||
//// ////
|
||||
//// ////
|
||||
//// Author: Rudolf Usselmann ////
|
||||
//// rudi@asics.ws ////
|
||||
//// ////
|
||||
//// ////
|
||||
//// Downloaded from: http://www.opencores.org/cores/wb_conmax/ ////
|
||||
//// ////
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
//// ////
|
||||
//// Copyright (C) 2000-2002 Rudolf Usselmann ////
|
||||
//// www.asics.ws ////
|
||||
//// rudi@asics.ws ////
|
||||
//// ////
|
||||
//// This source file may be used and distributed without ////
|
||||
//// restriction provided that this copyright statement is not ////
|
||||
//// removed from the file and that any derivative work contains ////
|
||||
//// the original copyright notice and the associated disclaimer.////
|
||||
//// ////
|
||||
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
|
||||
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
|
||||
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
|
||||
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
|
||||
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
|
||||
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
|
||||
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
|
||||
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
|
||||
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
|
||||
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
|
||||
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
|
||||
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
|
||||
//// POSSIBILITY OF SUCH DAMAGE. ////
|
||||
//// ////
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
//
|
||||
// copy from wb_conmax
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
`include "wb_conbus_defines.v"
|
||||
|
||||
module wb_conbus_arb(clk, rst, req, gnt);
|
||||
|
||||
input clk;
|
||||
input rst;
|
||||
input [7:0] req; // Req input
|
||||
output [2:0] gnt; // Grant output
|
||||
//input next; // Next Target
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Parameters
|
||||
//
|
||||
|
||||
|
||||
parameter [2:0]
|
||||
grant0 = 3'h0,
|
||||
grant1 = 3'h1,
|
||||
grant2 = 3'h2,
|
||||
grant3 = 3'h3,
|
||||
grant4 = 3'h4,
|
||||
grant5 = 3'h5,
|
||||
grant6 = 3'h6,
|
||||
grant7 = 3'h7;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Local Registers and Wires
|
||||
//
|
||||
|
||||
reg [2:0] state, next_state;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Misc Logic
|
||||
//
|
||||
|
||||
assign gnt = state;
|
||||
|
||||
always@(posedge clk or posedge rst)
|
||||
if(rst) state <= grant0;
|
||||
else state <= next_state;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Next State Logic
|
||||
// - implements round robin arbitration algorithm
|
||||
// - switches grant if current req is dropped or next is asserted
|
||||
// - parks at last grant
|
||||
//
|
||||
|
||||
always@(state or req )
|
||||
begin
|
||||
next_state = state; // Default Keep State
|
||||
case(state) // synopsys parallel_case full_case
|
||||
grant0:
|
||||
// if this req is dropped or next is asserted, check for other req's
|
||||
if(!req[0] )
|
||||
begin
|
||||
if(req[1]) next_state = grant1;
|
||||
else
|
||||
if(req[2]) next_state = grant2;
|
||||
else
|
||||
if(req[3]) next_state = grant3;
|
||||
else
|
||||
if(req[4]) next_state = grant4;
|
||||
else
|
||||
if(req[5]) next_state = grant5;
|
||||
else
|
||||
if(req[6]) next_state = grant6;
|
||||
else
|
||||
if(req[7]) next_state = grant7;
|
||||
end
|
||||
grant1:
|
||||
// if this req is dropped or next is asserted, check for other req's
|
||||
if(!req[1] )
|
||||
begin
|
||||
if(req[2]) next_state = grant2;
|
||||
else
|
||||
if(req[3]) next_state = grant3;
|
||||
else
|
||||
if(req[4]) next_state = grant4;
|
||||
else
|
||||
if(req[5]) next_state = grant5;
|
||||
else
|
||||
if(req[6]) next_state = grant6;
|
||||
else
|
||||
if(req[7]) next_state = grant7;
|
||||
else
|
||||
if(req[0]) next_state = grant0;
|
||||
end
|
||||
grant2:
|
||||
// if this req is dropped or next is asserted, check for other req's
|
||||
if(!req[2] )
|
||||
begin
|
||||
if(req[3]) next_state = grant3;
|
||||
else
|
||||
if(req[4]) next_state = grant4;
|
||||
else
|
||||
if(req[5]) next_state = grant5;
|
||||
else
|
||||
if(req[6]) next_state = grant6;
|
||||
else
|
||||
if(req[7]) next_state = grant7;
|
||||
else
|
||||
if(req[0]) next_state = grant0;
|
||||
else
|
||||
if(req[1]) next_state = grant1;
|
||||
end
|
||||
grant3:
|
||||
// if this req is dropped or next is asserted, check for other req's
|
||||
if(!req[3] )
|
||||
begin
|
||||
if(req[4]) next_state = grant4;
|
||||
else
|
||||
if(req[5]) next_state = grant5;
|
||||
else
|
||||
if(req[6]) next_state = grant6;
|
||||
else
|
||||
if(req[7]) next_state = grant7;
|
||||
else
|
||||
if(req[0]) next_state = grant0;
|
||||
else
|
||||
if(req[1]) next_state = grant1;
|
||||
else
|
||||
if(req[2]) next_state = grant2;
|
||||
end
|
||||
grant4:
|
||||
// if this req is dropped or next is asserted, check for other req's
|
||||
if(!req[4] )
|
||||
begin
|
||||
if(req[5]) next_state = grant5;
|
||||
else
|
||||
if(req[6]) next_state = grant6;
|
||||
else
|
||||
if(req[7]) next_state = grant7;
|
||||
else
|
||||
if(req[0]) next_state = grant0;
|
||||
else
|
||||
if(req[1]) next_state = grant1;
|
||||
else
|
||||
if(req[2]) next_state = grant2;
|
||||
else
|
||||
if(req[3]) next_state = grant3;
|
||||
end
|
||||
grant5:
|
||||
// if this req is dropped or next is asserted, check for other req's
|
||||
if(!req[5] )
|
||||
begin
|
||||
if(req[6]) next_state = grant6;
|
||||
else
|
||||
if(req[7]) next_state = grant7;
|
||||
else
|
||||
if(req[0]) next_state = grant0;
|
||||
else
|
||||
if(req[1]) next_state = grant1;
|
||||
else
|
||||
if(req[2]) next_state = grant2;
|
||||
else
|
||||
if(req[3]) next_state = grant3;
|
||||
else
|
||||
if(req[4]) next_state = grant4;
|
||||
end
|
||||
grant6:
|
||||
// if this req is dropped or next is asserted, check for other req's
|
||||
if(!req[6] )
|
||||
begin
|
||||
if(req[7]) next_state = grant7;
|
||||
else
|
||||
if(req[0]) next_state = grant0;
|
||||
else
|
||||
if(req[1]) next_state = grant1;
|
||||
else
|
||||
if(req[2]) next_state = grant2;
|
||||
else
|
||||
if(req[3]) next_state = grant3;
|
||||
else
|
||||
if(req[4]) next_state = grant4;
|
||||
else
|
||||
if(req[5]) next_state = grant5;
|
||||
end
|
||||
grant7:
|
||||
// if this req is dropped or next is asserted, check for other req's
|
||||
if(!req[7] )
|
||||
begin
|
||||
if(req[0]) next_state = grant0;
|
||||
else
|
||||
if(req[1]) next_state = grant1;
|
||||
else
|
||||
if(req[2]) next_state = grant2;
|
||||
else
|
||||
if(req[3]) next_state = grant3;
|
||||
else
|
||||
if(req[4]) next_state = grant4;
|
||||
else
|
||||
if(req[5]) next_state = grant5;
|
||||
else
|
||||
if(req[6]) next_state = grant6;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
42
lm32/logic/sakc/rtl/wb_conbus/wb_conbus_defines.v
Normal file
42
lm32/logic/sakc/rtl/wb_conbus/wb_conbus_defines.v
Normal file
@ -0,0 +1,42 @@
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
//// ////
|
||||
//// WISHBONE Connection ShareBus Definitions ////
|
||||
//// ////
|
||||
//// ////
|
||||
//// Author: Johny Chi ////
|
||||
//// chisuhua@yahoo.com.cn ////
|
||||
//// ////
|
||||
//// ////
|
||||
//// Downloaded from: http://www.opencores.org/cores/wb_conmax/ ////
|
||||
//// ////
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
/// ////
|
||||
//// Copyright (C) 2000 Authors and OPENCORES.ORG ////
|
||||
//// ////
|
||||
//// This source file may be used and distributed without ////
|
||||
//// restriction provided that this copyright statement is not ////
|
||||
//// removed from the file and that any derivative work contains ////
|
||||
//// the original copyright notice and the associated disclaimer. ////
|
||||
//// ////
|
||||
//// This source file is free software; you can redistribute it ////
|
||||
//// and/or modify it under the terms of the GNU Lesser General ////
|
||||
//// Public License as published by the Free Software Foundation; ////
|
||||
//// either version 2.1 of the License, or (at your option) any ////
|
||||
//// later version. ////
|
||||
//// ////
|
||||
//// This source is distributed in the hope that it will be ////
|
||||
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
|
||||
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
|
||||
//// PURPOSE. See the GNU Lesser General Public License for more ////
|
||||
//// details. ////
|
||||
//// ////
|
||||
//// You should have received a copy of the GNU Lesser General ////
|
||||
//// Public License along with this source; if not, download it ////
|
||||
//// from http://www.opencores.org/lgpl.shtml ////
|
||||
//// ////
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
`timescale 1ns / 10ps
|
||||
|
655
lm32/logic/sakc/rtl/wb_conbus/wb_conbus_top.v
Normal file
655
lm32/logic/sakc/rtl/wb_conbus/wb_conbus_top.v
Normal file
@ -0,0 +1,655 @@
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
//// ////
|
||||
//// WISHBONE Connection Bus Top Level ////
|
||||
//// ////
|
||||
//// ////
|
||||
//// Author: Johny Chi ////
|
||||
//// chisuhua@yahoo.com.cn ////
|
||||
//// ////
|
||||
//// ////
|
||||
//// ////
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
//// ////
|
||||
//// Copyright (C) 2000 Authors and OPENCORES.ORG ////
|
||||
//// ////
|
||||
//// This source file may be used and distributed without ////
|
||||
//// restriction provided that this copyright statement is not ////
|
||||
//// removed from the file and that any derivative work contains ////
|
||||
//// the original copyright notice and the associated disclaimer. ////
|
||||
//// ////
|
||||
//// This source file is free software; you can redistribute it ////
|
||||
//// and/or modify it under the terms of the GNU Lesser General ////
|
||||
//// Public License as published by the Free Software Foundation; ////
|
||||
//// either version 2.1 of the License, or (at your option) any ////
|
||||
//// later version. ////
|
||||
//// ////
|
||||
//// This source is distributed in the hope that it will be ////
|
||||
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
|
||||
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
|
||||
//// PURPOSE. See the GNU Lesser General Public License for more ////
|
||||
//// details. ////
|
||||
//// ////
|
||||
//// You should have received a copy of the GNU Lesser General ////
|
||||
//// Public License along with this source; if not, download it ////
|
||||
//// from http://www.opencores.org/lgpl.shtml ////
|
||||
//// ////
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Description
|
||||
// 1. Up to 8 masters and 8 slaves share bus Wishbone connection
|
||||
// 2. no priorty arbitor , 8 masters are processed in a round
|
||||
// robin way,
|
||||
// 3. if WB_USE_TRISTATE was defined, the share bus is a tristate
|
||||
// bus, and use less logic resource.
|
||||
// 4. wb_conbus was synthesis to XC2S100-5-PQ208 using synplify,
|
||||
// Max speed >60M , and 374 SLICE if using Multiplexor bus
|
||||
// or 150 SLICE if using tri-state bus.
|
||||
//
|
||||
`include "wb_conbus_defines.v"
|
||||
`define dw 32 // Data bus Width
|
||||
`define aw 32 // Address bus Width
|
||||
`define sw `dw / 8 // Number of Select Lines
|
||||
`define mbusw `aw + `sw + `dw +4 //address width + byte select width + dat width + cyc + we + stb +cab , input from master interface
|
||||
`define sbusw 3 // ack + err + rty, input from slave interface
|
||||
`define mselectw 8 // number of masters
|
||||
`define sselectw 8 // number of slavers
|
||||
|
||||
//`define WB_USE_TRISTATE
|
||||
|
||||
|
||||
module wb_conbus_top #(
|
||||
parameter s0_addr_w = 4 , // slave 0 address decode width -- bit 31 is always ignored!
|
||||
parameter s0_addr = 4'h0, // slave 0 address
|
||||
parameter s1_addr_w = 4 , // slave 1 address decode width -- bit 31 is always ignored!
|
||||
parameter s1_addr = 4'h1, // slave 1 address
|
||||
parameter s27_addr_w = 8 , // slave 2 to slave 7 address decode width -- bit 31 is always ignored!
|
||||
parameter s2_addr = 8'h92, // slave 2 address
|
||||
parameter s3_addr = 8'h93, // slave 3 address
|
||||
parameter s4_addr = 8'h94, // slave 4 address
|
||||
parameter s5_addr = 8'h95, // slave 5 address
|
||||
parameter s6_addr = 8'h96, // slave 6 address
|
||||
parameter s7_addr = 8'h97 // slave 7 address
|
||||
) (
|
||||
clk_i, rst_i,
|
||||
|
||||
// Master 0 Interface
|
||||
m0_dat_i, m0_dat_o, m0_adr_i, m0_sel_i, m0_we_i, m0_cyc_i,
|
||||
m0_stb_i, m0_ack_o, m0_err_o, m0_rty_o, m0_cab_i,
|
||||
|
||||
// Master 1 Interface
|
||||
m1_dat_i, m1_dat_o, m1_adr_i, m1_sel_i, m1_we_i, m1_cyc_i,
|
||||
m1_stb_i, m1_ack_o, m1_err_o, m1_rty_o, m1_cab_i,
|
||||
|
||||
// Master 2 Interface
|
||||
m2_dat_i, m2_dat_o, m2_adr_i, m2_sel_i, m2_we_i, m2_cyc_i,
|
||||
m2_stb_i, m2_ack_o, m2_err_o, m2_rty_o, m2_cab_i,
|
||||
|
||||
// Master 3 Interface
|
||||
m3_dat_i, m3_dat_o, m3_adr_i, m3_sel_i, m3_we_i, m3_cyc_i,
|
||||
m3_stb_i, m3_ack_o, m3_err_o, m3_rty_o, m3_cab_i,
|
||||
|
||||
// Master 4 Interface
|
||||
m4_dat_i, m4_dat_o, m4_adr_i, m4_sel_i, m4_we_i, m4_cyc_i,
|
||||
m4_stb_i, m4_ack_o, m4_err_o, m4_rty_o, m4_cab_i,
|
||||
|
||||
// Master 5 Interface
|
||||
m5_dat_i, m5_dat_o, m5_adr_i, m5_sel_i, m5_we_i, m5_cyc_i,
|
||||
m5_stb_i, m5_ack_o, m5_err_o, m5_rty_o, m5_cab_i,
|
||||
|
||||
// Master 6 Interface
|
||||
m6_dat_i, m6_dat_o, m6_adr_i, m6_sel_i, m6_we_i, m6_cyc_i,
|
||||
m6_stb_i, m6_ack_o, m6_err_o, m6_rty_o, m6_cab_i,
|
||||
|
||||
// Master 7 Interface
|
||||
m7_dat_i, m7_dat_o, m7_adr_i, m7_sel_i, m7_we_i, m7_cyc_i,
|
||||
m7_stb_i, m7_ack_o, m7_err_o, m7_rty_o, m7_cab_i,
|
||||
|
||||
// Slave 0 Interface
|
||||
s0_dat_i, s0_dat_o, s0_adr_o, s0_sel_o, s0_we_o, s0_cyc_o,
|
||||
s0_stb_o, s0_ack_i, s0_err_i, s0_rty_i, s0_cab_o,
|
||||
|
||||
// Slave 1 Interface
|
||||
s1_dat_i, s1_dat_o, s1_adr_o, s1_sel_o, s1_we_o, s1_cyc_o,
|
||||
s1_stb_o, s1_ack_i, s1_err_i, s1_rty_i, s1_cab_o,
|
||||
|
||||
// Slave 2 Interface
|
||||
s2_dat_i, s2_dat_o, s2_adr_o, s2_sel_o, s2_we_o, s2_cyc_o,
|
||||
s2_stb_o, s2_ack_i, s2_err_i, s2_rty_i, s2_cab_o,
|
||||
|
||||
// Slave 3 Interface
|
||||
s3_dat_i, s3_dat_o, s3_adr_o, s3_sel_o, s3_we_o, s3_cyc_o,
|
||||
s3_stb_o, s3_ack_i, s3_err_i, s3_rty_i, s3_cab_o,
|
||||
|
||||
// Slave 4 Interface
|
||||
s4_dat_i, s4_dat_o, s4_adr_o, s4_sel_o, s4_we_o, s4_cyc_o,
|
||||
s4_stb_o, s4_ack_i, s4_err_i, s4_rty_i, s4_cab_o,
|
||||
|
||||
// Slave 5 Interface
|
||||
s5_dat_i, s5_dat_o, s5_adr_o, s5_sel_o, s5_we_o, s5_cyc_o,
|
||||
s5_stb_o, s5_ack_i, s5_err_i, s5_rty_i, s5_cab_o,
|
||||
|
||||
// Slave 6 Interface
|
||||
s6_dat_i, s6_dat_o, s6_adr_o, s6_sel_o, s6_we_o, s6_cyc_o,
|
||||
s6_stb_o, s6_ack_i, s6_err_i, s6_rty_i, s6_cab_o,
|
||||
|
||||
// Slave 7 Interface
|
||||
s7_dat_i, s7_dat_o, s7_adr_o, s7_sel_o, s7_we_o, s7_cyc_o,
|
||||
s7_stb_o, s7_ack_i, s7_err_i, s7_rty_i, s7_cab_o
|
||||
|
||||
);
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Module Parameters
|
||||
//
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Module IOs
|
||||
//
|
||||
|
||||
input clk_i, rst_i;
|
||||
|
||||
// Master 0 Interface
|
||||
input [`dw-1:0] m0_dat_i;
|
||||
output [`dw-1:0] m0_dat_o;
|
||||
input [`aw-1:0] m0_adr_i;
|
||||
input [`sw-1:0] m0_sel_i;
|
||||
input m0_we_i;
|
||||
input m0_cyc_i;
|
||||
input m0_stb_i;
|
||||
input m0_cab_i;
|
||||
output m0_ack_o;
|
||||
output m0_err_o;
|
||||
output m0_rty_o;
|
||||
|
||||
// Master 1 Interface
|
||||
input [`dw-1:0] m1_dat_i;
|
||||
output [`dw-1:0] m1_dat_o;
|
||||
input [`aw-1:0] m1_adr_i;
|
||||
input [`sw-1:0] m1_sel_i;
|
||||
input m1_we_i;
|
||||
input m1_cyc_i;
|
||||
input m1_stb_i;
|
||||
input m1_cab_i;
|
||||
output m1_ack_o;
|
||||
output m1_err_o;
|
||||
output m1_rty_o;
|
||||
|
||||
// Master 2 Interface
|
||||
input [`dw-1:0] m2_dat_i;
|
||||
output [`dw-1:0] m2_dat_o;
|
||||
input [`aw-1:0] m2_adr_i;
|
||||
input [`sw-1:0] m2_sel_i;
|
||||
input m2_we_i;
|
||||
input m2_cyc_i;
|
||||
input m2_stb_i;
|
||||
input m2_cab_i;
|
||||
output m2_ack_o;
|
||||
output m2_err_o;
|
||||
output m2_rty_o;
|
||||
|
||||
// Master 3 Interface
|
||||
input [`dw-1:0] m3_dat_i;
|
||||
output [`dw-1:0] m3_dat_o;
|
||||
input [`aw-1:0] m3_adr_i;
|
||||
input [`sw-1:0] m3_sel_i;
|
||||
input m3_we_i;
|
||||
input m3_cyc_i;
|
||||
input m3_stb_i;
|
||||
input m3_cab_i;
|
||||
output m3_ack_o;
|
||||
output m3_err_o;
|
||||
output m3_rty_o;
|
||||
|
||||
// Master 4 Interface
|
||||
input [`dw-1:0] m4_dat_i;
|
||||
output [`dw-1:0] m4_dat_o;
|
||||
input [`aw-1:0] m4_adr_i;
|
||||
input [`sw-1:0] m4_sel_i;
|
||||
input m4_we_i;
|
||||
input m4_cyc_i;
|
||||
input m4_stb_i;
|
||||
input m4_cab_i;
|
||||
output m4_ack_o;
|
||||
output m4_err_o;
|
||||
output m4_rty_o;
|
||||
|
||||
// Master 5 Interface
|
||||
input [`dw-1:0] m5_dat_i;
|
||||
output [`dw-1:0] m5_dat_o;
|
||||
input [`aw-1:0] m5_adr_i;
|
||||
input [`sw-1:0] m5_sel_i;
|
||||
input m5_we_i;
|
||||
input m5_cyc_i;
|
||||
input m5_stb_i;
|
||||
input m5_cab_i;
|
||||
output m5_ack_o;
|
||||
output m5_err_o;
|
||||
output m5_rty_o;
|
||||
|
||||
// Master 6 Interface
|
||||
input [`dw-1:0] m6_dat_i;
|
||||
output [`dw-1:0] m6_dat_o;
|
||||
input [`aw-1:0] m6_adr_i;
|
||||
input [`sw-1:0] m6_sel_i;
|
||||
input m6_we_i;
|
||||
input m6_cyc_i;
|
||||
input m6_stb_i;
|
||||
input m6_cab_i;
|
||||
output m6_ack_o;
|
||||
output m6_err_o;
|
||||
output m6_rty_o;
|
||||
|
||||
// Master 7 Interface
|
||||
input [`dw-1:0] m7_dat_i;
|
||||
output [`dw-1:0] m7_dat_o;
|
||||
input [`aw-1:0] m7_adr_i;
|
||||
input [`sw-1:0] m7_sel_i;
|
||||
input m7_we_i;
|
||||
input m7_cyc_i;
|
||||
input m7_stb_i;
|
||||
input m7_cab_i;
|
||||
output m7_ack_o;
|
||||
output m7_err_o;
|
||||
output m7_rty_o;
|
||||
|
||||
// Slave 0 Interface
|
||||
input [`dw-1:0] s0_dat_i;
|
||||
output [`dw-1:0] s0_dat_o;
|
||||
output [`aw-1:0] s0_adr_o;
|
||||
output [`sw-1:0] s0_sel_o;
|
||||
output s0_we_o;
|
||||
output s0_cyc_o;
|
||||
output s0_stb_o;
|
||||
output s0_cab_o;
|
||||
input s0_ack_i;
|
||||
input s0_err_i;
|
||||
input s0_rty_i;
|
||||
|
||||
// Slave 1 Interface
|
||||
input [`dw-1:0] s1_dat_i;
|
||||
output [`dw-1:0] s1_dat_o;
|
||||
output [`aw-1:0] s1_adr_o;
|
||||
output [`sw-1:0] s1_sel_o;
|
||||
output s1_we_o;
|
||||
output s1_cyc_o;
|
||||
output s1_stb_o;
|
||||
output s1_cab_o;
|
||||
input s1_ack_i;
|
||||
input s1_err_i;
|
||||
input s1_rty_i;
|
||||
|
||||
// Slave 2 Interface
|
||||
input [`dw-1:0] s2_dat_i;
|
||||
output [`dw-1:0] s2_dat_o;
|
||||
output [`aw-1:0] s2_adr_o;
|
||||
output [`sw-1:0] s2_sel_o;
|
||||
output s2_we_o;
|
||||
output s2_cyc_o;
|
||||
output s2_stb_o;
|
||||
output s2_cab_o;
|
||||
input s2_ack_i;
|
||||
input s2_err_i;
|
||||
input s2_rty_i;
|
||||
|
||||
// Slave 3 Interface
|
||||
input [`dw-1:0] s3_dat_i;
|
||||
output [`dw-1:0] s3_dat_o;
|
||||
output [`aw-1:0] s3_adr_o;
|
||||
output [`sw-1:0] s3_sel_o;
|
||||
output s3_we_o;
|
||||
output s3_cyc_o;
|
||||
output s3_stb_o;
|
||||
output s3_cab_o;
|
||||
input s3_ack_i;
|
||||
input s3_err_i;
|
||||
input s3_rty_i;
|
||||
|
||||
// Slave 4 Interface
|
||||
input [`dw-1:0] s4_dat_i;
|
||||
output [`dw-1:0] s4_dat_o;
|
||||
output [`aw-1:0] s4_adr_o;
|
||||
output [`sw-1:0] s4_sel_o;
|
||||
output s4_we_o;
|
||||
output s4_cyc_o;
|
||||
output s4_stb_o;
|
||||
output s4_cab_o;
|
||||
input s4_ack_i;
|
||||
input s4_err_i;
|
||||
input s4_rty_i;
|
||||
|
||||
// Slave 5 Interface
|
||||
input [`dw-1:0] s5_dat_i;
|
||||
output [`dw-1:0] s5_dat_o;
|
||||
output [`aw-1:0] s5_adr_o;
|
||||
output [`sw-1:0] s5_sel_o;
|
||||
output s5_we_o;
|
||||
output s5_cyc_o;
|
||||
output s5_stb_o;
|
||||
output s5_cab_o;
|
||||
input s5_ack_i;
|
||||
input s5_err_i;
|
||||
input s5_rty_i;
|
||||
|
||||
// Slave 6 Interface
|
||||
input [`dw-1:0] s6_dat_i;
|
||||
output [`dw-1:0] s6_dat_o;
|
||||
output [`aw-1:0] s6_adr_o;
|
||||
output [`sw-1:0] s6_sel_o;
|
||||
output s6_we_o;
|
||||
output s6_cyc_o;
|
||||
output s6_stb_o;
|
||||
output s6_cab_o;
|
||||
input s6_ack_i;
|
||||
input s6_err_i;
|
||||
input s6_rty_i;
|
||||
|
||||
// Slave 7 Interface
|
||||
input [`dw-1:0] s7_dat_i;
|
||||
output [`dw-1:0] s7_dat_o;
|
||||
output [`aw-1:0] s7_adr_o;
|
||||
output [`sw-1:0] s7_sel_o;
|
||||
output s7_we_o;
|
||||
output s7_cyc_o;
|
||||
output s7_stb_o;
|
||||
output s7_cab_o;
|
||||
input s7_ack_i;
|
||||
input s7_err_i;
|
||||
input s7_rty_i;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Local wires
|
||||
//
|
||||
|
||||
wire [`mselectw -1:0] i_gnt_arb;
|
||||
wire [2:0] gnt;
|
||||
reg [`sselectw -1:0] i_ssel_dec;
|
||||
`ifdef WB_USE_TRISTATE
|
||||
wire [`mbusw -1:0] i_bus_m;
|
||||
`else
|
||||
reg [`mbusw -1:0] i_bus_m; // internal share bus, master data and control to slave
|
||||
`endif
|
||||
wire [`dw -1:0] i_dat_s; // internal share bus , slave data to master
|
||||
wire [`sbusw -1:0] i_bus_s; // internal share bus , slave control to master
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Master output Interfaces
|
||||
//
|
||||
|
||||
// master0
|
||||
assign m0_dat_o = i_dat_s;
|
||||
assign {m0_ack_o, m0_err_o, m0_rty_o} = i_bus_s & {3{i_gnt_arb[0]}};
|
||||
|
||||
// master1
|
||||
assign m1_dat_o = i_dat_s;
|
||||
assign {m1_ack_o, m1_err_o, m1_rty_o} = i_bus_s & {3{i_gnt_arb[1]}};
|
||||
|
||||
// master2
|
||||
|
||||
assign m2_dat_o = i_dat_s;
|
||||
assign {m2_ack_o, m2_err_o, m2_rty_o} = i_bus_s & {3{i_gnt_arb[2]}};
|
||||
|
||||
// master3
|
||||
|
||||
assign m3_dat_o = i_dat_s;
|
||||
assign {m3_ack_o, m3_err_o, m3_rty_o} = i_bus_s & {3{i_gnt_arb[3]}};
|
||||
|
||||
// master4
|
||||
|
||||
assign m4_dat_o = i_dat_s;
|
||||
assign {m4_ack_o, m4_err_o, m4_rty_o} = i_bus_s & {3{i_gnt_arb[4]}};
|
||||
|
||||
// master5
|
||||
|
||||
assign m5_dat_o = i_dat_s;
|
||||
assign {m5_ack_o, m5_err_o, m5_rty_o} = i_bus_s & {3{i_gnt_arb[5]}};
|
||||
|
||||
// master6
|
||||
|
||||
assign m6_dat_o = i_dat_s;
|
||||
assign {m6_ack_o, m6_err_o, m6_rty_o} = i_bus_s & {3{i_gnt_arb[6]}};
|
||||
|
||||
// master7
|
||||
|
||||
assign m7_dat_o = i_dat_s;
|
||||
assign {m7_ack_o, m7_err_o, m7_rty_o} = i_bus_s & {3{i_gnt_arb[7]}};
|
||||
|
||||
|
||||
assign i_bus_s = {s0_ack_i | s1_ack_i | s2_ack_i | s3_ack_i | s4_ack_i | s5_ack_i | s6_ack_i | s7_ack_i ,
|
||||
s0_err_i | s1_err_i | s2_err_i | s3_err_i | s4_err_i | s5_err_i | s6_err_i | s7_err_i ,
|
||||
s0_rty_i | s1_rty_i | s2_rty_i | s3_rty_i | s4_rty_i | s5_rty_i | s6_rty_i | s7_rty_i };
|
||||
|
||||
////////////////////////////////
|
||||
// Slave output interface
|
||||
//
|
||||
// slave0
|
||||
assign {s0_adr_o, s0_sel_o, s0_dat_o, s0_we_o, s0_cab_o,s0_cyc_o} = i_bus_m[`mbusw -1:1];
|
||||
assign s0_stb_o = i_bus_m[1] & i_bus_m[0] & i_ssel_dec[0]; // stb_o = cyc_i & stb_i & i_ssel_dec
|
||||
|
||||
// slave1
|
||||
|
||||
assign {s1_adr_o, s1_sel_o, s1_dat_o, s1_we_o, s1_cab_o, s1_cyc_o} = i_bus_m[`mbusw -1:1];
|
||||
assign s1_stb_o = i_bus_m[1] & i_bus_m[0] & i_ssel_dec[1];
|
||||
|
||||
// slave2
|
||||
|
||||
assign {s2_adr_o, s2_sel_o, s2_dat_o, s2_we_o, s2_cab_o, s2_cyc_o} = i_bus_m[`mbusw -1:1];
|
||||
assign s2_stb_o = i_bus_m[1] & i_bus_m[0] & i_ssel_dec[2];
|
||||
|
||||
// slave3
|
||||
|
||||
assign {s3_adr_o, s3_sel_o, s3_dat_o, s3_we_o, s3_cab_o, s3_cyc_o} = i_bus_m[`mbusw -1:1];
|
||||
assign s3_stb_o = i_bus_m[1] & i_bus_m[0] & i_ssel_dec[3];
|
||||
|
||||
// slave4
|
||||
|
||||
assign {s4_adr_o, s4_sel_o, s4_dat_o, s4_we_o, s4_cab_o, s4_cyc_o} = i_bus_m[`mbusw -1:1];
|
||||
assign s4_stb_o = i_bus_m[1] & i_bus_m[0] & i_ssel_dec[4];
|
||||
|
||||
// slave5
|
||||
|
||||
assign {s5_adr_o, s5_sel_o, s5_dat_o, s5_we_o, s5_cab_o, s5_cyc_o} = i_bus_m[`mbusw -1:1];
|
||||
assign s5_stb_o = i_bus_m[1] & i_bus_m[0] & i_ssel_dec[5];
|
||||
|
||||
// slave6
|
||||
|
||||
assign {s6_adr_o, s6_sel_o, s6_dat_o, s6_we_o, s6_cab_o, s6_cyc_o} = i_bus_m[`mbusw -1:1];
|
||||
assign s6_stb_o = i_bus_m[1] & i_bus_m[0] & i_ssel_dec[6];
|
||||
|
||||
// slave7
|
||||
|
||||
assign {s7_adr_o, s7_sel_o, s7_dat_o, s7_we_o, s7_cab_o, s7_cyc_o} = i_bus_m[`mbusw -1:1];
|
||||
assign s7_stb_o = i_bus_m[1] & i_bus_m[0] & i_ssel_dec[7];
|
||||
|
||||
///////////////////////////////////////
|
||||
// Master and Slave input interface
|
||||
//
|
||||
|
||||
`ifdef WB_USE_TRISTATE
|
||||
// input from master interface
|
||||
assign i_bus_m = i_gnt_arb[0] ? {m0_adr_i, m0_sel_i, m0_dat_i, m0_we_i, m0_cab_i, m0_cyc_i, m0_stb_i} : 72'bz ;
|
||||
assign i_bus_m = i_gnt_arb[1] ? {m1_adr_i, m1_sel_i, m1_dat_i, m1_we_i, m1_cab_i,m1_cyc_i, m1_stb_i} : 72'bz ;
|
||||
assign i_bus_m = i_gnt_arb[2] ? {m2_adr_i, m2_sel_i, m2_dat_i, m2_we_i, m2_cab_i, m2_cyc_i, m2_stb_i} : 72'bz ;
|
||||
assign i_bus_m = i_gnt_arb[3] ? {m3_adr_i, m3_sel_i, m3_dat_i, m3_we_i, m3_cab_i, m3_cyc_i, m3_stb_i} : 72'bz ;
|
||||
assign i_bus_m = i_gnt_arb[4] ? {m4_adr_i, m4_sel_i, m4_dat_i, m4_we_i, m4_cab_i, m4_cyc_i, m4_stb_i} : 72'bz ;
|
||||
assign i_bus_m = i_gnt_arb[5] ? {m5_adr_i, m5_sel_i, m5_dat_i, m5_we_i, m5_cab_i, m5_cyc_i, m5_stb_i} : 72'bz ;
|
||||
assign i_bus_m = i_gnt_arb[6] ? {m6_adr_i, m6_sel_i, m6_dat_i, m6_we_i, m6_cab_i, m6_cyc_i, m6_stb_i} : 72'bz ;
|
||||
assign i_bus_m = i_gnt_arb[7] ? {m7_adr_i, m7_sel_i, m7_dat_i, m7_we_i, m7_cab_i, m7_cyc_i,m7_stb_i} : 72'bz ;
|
||||
// input from slave interface
|
||||
assign i_dat_s = i_ssel_dec[0] ? s0_dat_i: 32'bz;
|
||||
assign i_dat_s = i_ssel_dec[1] ? s1_dat_i: 32'bz;
|
||||
assign i_dat_s = i_ssel_dec[2] ? s2_dat_i: 32'bz;
|
||||
assign i_dat_s = i_ssel_dec[3] ? s3_dat_i: 32'bz;
|
||||
assign i_dat_s = i_ssel_dec[4] ? s4_dat_i: 32'bz;
|
||||
assign i_dat_s = i_ssel_dec[5] ? s5_dat_i: 32'bz;
|
||||
assign i_dat_s = i_ssel_dec[6] ? s6_dat_i: 32'bz;
|
||||
assign i_dat_s = i_ssel_dec[7] ? s7_dat_i: 32'bz;
|
||||
|
||||
`else
|
||||
|
||||
always @(gnt , m0_adr_i, m0_sel_i, m0_dat_i, m0_we_i, m0_cab_i, m0_cyc_i,m0_stb_i,
|
||||
m1_adr_i, m1_sel_i, m1_dat_i, m1_we_i, m1_cab_i, m1_cyc_i,m1_stb_i,
|
||||
m2_adr_i, m2_sel_i, m2_dat_i, m2_we_i, m2_cab_i, m2_cyc_i,m2_stb_i,
|
||||
m3_adr_i, m3_sel_i, m3_dat_i, m3_we_i, m3_cab_i, m3_cyc_i,m3_stb_i,
|
||||
m4_adr_i, m4_sel_i, m4_dat_i, m4_we_i, m4_cab_i, m4_cyc_i,m4_stb_i,
|
||||
m5_adr_i, m5_sel_i, m5_dat_i, m5_we_i, m5_cab_i, m5_cyc_i,m5_stb_i,
|
||||
m6_adr_i, m6_sel_i, m6_dat_i, m6_we_i, m6_cab_i, m6_cyc_i,m6_stb_i,
|
||||
m7_adr_i, m7_sel_i, m7_dat_i, m7_we_i, m7_cab_i, m7_cyc_i,m7_stb_i)
|
||||
case(gnt)
|
||||
3'h0: i_bus_m = {m0_adr_i, m0_sel_i, m0_dat_i, m0_we_i, m0_cab_i, m0_cyc_i,m0_stb_i};
|
||||
3'h1: i_bus_m = {m1_adr_i, m1_sel_i, m1_dat_i, m1_we_i, m1_cab_i, m1_cyc_i,m1_stb_i};
|
||||
3'h2: i_bus_m = {m2_adr_i, m2_sel_i, m2_dat_i, m2_we_i, m2_cab_i, m2_cyc_i,m2_stb_i};
|
||||
3'h3: i_bus_m = {m3_adr_i, m3_sel_i, m3_dat_i, m3_we_i, m3_cab_i, m3_cyc_i,m3_stb_i};
|
||||
3'h4: i_bus_m = {m4_adr_i, m4_sel_i, m4_dat_i, m4_we_i, m4_cab_i, m4_cyc_i,m4_stb_i};
|
||||
3'h5: i_bus_m = {m5_adr_i, m5_sel_i, m5_dat_i, m5_we_i, m5_cab_i, m5_cyc_i,m5_stb_i};
|
||||
3'h6: i_bus_m = {m6_adr_i, m6_sel_i, m6_dat_i, m6_we_i, m6_cab_i, m6_cyc_i,m6_stb_i};
|
||||
3'h7: i_bus_m = {m7_adr_i, m7_sel_i, m7_dat_i, m7_we_i, m7_cab_i, m7_cyc_i,m7_stb_i};
|
||||
default:i_bus_m = 72'b0;//{m0_adr_i, m0_sel_i, m0_dat_i, m0_we_i, m0_cab_i, m0_cyc_i,m0_stb_i};
|
||||
endcase
|
||||
|
||||
assign i_dat_s = i_ssel_dec[0] ? s0_dat_i :
|
||||
i_ssel_dec[1] ? s1_dat_i :
|
||||
i_ssel_dec[2] ? s2_dat_i :
|
||||
i_ssel_dec[3] ? s3_dat_i :
|
||||
i_ssel_dec[4] ? s4_dat_i :
|
||||
i_ssel_dec[5] ? s5_dat_i :
|
||||
i_ssel_dec[6] ? s6_dat_i :
|
||||
i_ssel_dec[7] ? s7_dat_i : {`dw{1'b0}};
|
||||
`endif
|
||||
//
|
||||
// arbitor
|
||||
//
|
||||
assign i_gnt_arb[0] = (gnt == 3'd0);
|
||||
assign i_gnt_arb[1] = (gnt == 3'd1);
|
||||
assign i_gnt_arb[2] = (gnt == 3'd2);
|
||||
assign i_gnt_arb[3] = (gnt == 3'd3);
|
||||
assign i_gnt_arb[4] = (gnt == 3'd4);
|
||||
assign i_gnt_arb[5] = (gnt == 3'd5);
|
||||
assign i_gnt_arb[6] = (gnt == 3'd6);
|
||||
assign i_gnt_arb[7] = (gnt == 3'd7);
|
||||
|
||||
wb_conbus_arb wb_conbus_arb(
|
||||
.clk(clk_i),
|
||||
.rst(rst_i),
|
||||
.req({ m7_cyc_i,
|
||||
m6_cyc_i,
|
||||
m5_cyc_i,
|
||||
m4_cyc_i,
|
||||
m3_cyc_i,
|
||||
m2_cyc_i,
|
||||
m1_cyc_i,
|
||||
m0_cyc_i}),
|
||||
.gnt(gnt)
|
||||
);
|
||||
|
||||
//////////////////////////////////
|
||||
// address decode logic
|
||||
//
|
||||
wire [7:0] m0_ssel_dec, m1_ssel_dec, m2_ssel_dec, m3_ssel_dec, m4_ssel_dec, m5_ssel_dec, m6_ssel_dec, m7_ssel_dec;
|
||||
always @(gnt, m0_ssel_dec, m1_ssel_dec, m2_ssel_dec, m3_ssel_dec, m4_ssel_dec, m5_ssel_dec, m6_ssel_dec, m7_ssel_dec)
|
||||
case(gnt)
|
||||
3'h0: i_ssel_dec = m0_ssel_dec;
|
||||
3'h1: i_ssel_dec = m1_ssel_dec;
|
||||
3'h2: i_ssel_dec = m2_ssel_dec;
|
||||
3'h3: i_ssel_dec = m3_ssel_dec;
|
||||
3'h4: i_ssel_dec = m4_ssel_dec;
|
||||
3'h5: i_ssel_dec = m5_ssel_dec;
|
||||
3'h6: i_ssel_dec = m6_ssel_dec;
|
||||
3'h7: i_ssel_dec = m7_ssel_dec;
|
||||
default: i_ssel_dec = 7'b0;
|
||||
endcase
|
||||
//
|
||||
// decode all master address before arbitor for running faster
|
||||
//
|
||||
assign m0_ssel_dec[0] = (m0_adr_i[`aw -2 : `aw -1 - s0_addr_w ] == s0_addr);
|
||||
assign m0_ssel_dec[1] = (m0_adr_i[`aw -2 : `aw -1 - s1_addr_w ] == s1_addr);
|
||||
assign m0_ssel_dec[2] = (m0_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s2_addr);
|
||||
assign m0_ssel_dec[3] = (m0_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s3_addr);
|
||||
assign m0_ssel_dec[4] = (m0_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s4_addr);
|
||||
assign m0_ssel_dec[5] = (m0_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s5_addr);
|
||||
assign m0_ssel_dec[6] = (m0_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s6_addr);
|
||||
assign m0_ssel_dec[7] = (m0_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s7_addr);
|
||||
|
||||
assign m1_ssel_dec[0] = (m1_adr_i[`aw -2 : `aw -1 - s0_addr_w ] == s0_addr);
|
||||
assign m1_ssel_dec[1] = (m1_adr_i[`aw -2 : `aw -1 - s1_addr_w ] == s1_addr);
|
||||
assign m1_ssel_dec[2] = (m1_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s2_addr);
|
||||
assign m1_ssel_dec[3] = (m1_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s3_addr);
|
||||
assign m1_ssel_dec[4] = (m1_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s4_addr);
|
||||
assign m1_ssel_dec[5] = (m1_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s5_addr);
|
||||
assign m1_ssel_dec[6] = (m1_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s6_addr);
|
||||
assign m1_ssel_dec[7] = (m1_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s7_addr);
|
||||
|
||||
assign m2_ssel_dec[0] = (m2_adr_i[`aw -2 : `aw -1 - s0_addr_w ] == s0_addr);
|
||||
assign m2_ssel_dec[1] = (m2_adr_i[`aw -2 : `aw -1 - s1_addr_w ] == s1_addr);
|
||||
assign m2_ssel_dec[2] = (m2_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s2_addr);
|
||||
assign m2_ssel_dec[3] = (m2_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s3_addr);
|
||||
assign m2_ssel_dec[4] = (m2_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s4_addr);
|
||||
assign m2_ssel_dec[5] = (m2_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s5_addr);
|
||||
assign m2_ssel_dec[6] = (m2_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s6_addr);
|
||||
assign m2_ssel_dec[7] = (m2_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s7_addr);
|
||||
|
||||
assign m3_ssel_dec[0] = (m3_adr_i[`aw -2 : `aw -1 - s0_addr_w ] == s0_addr);
|
||||
assign m3_ssel_dec[1] = (m3_adr_i[`aw -2 : `aw -1 - s1_addr_w ] == s1_addr);
|
||||
assign m3_ssel_dec[2] = (m3_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s2_addr);
|
||||
assign m3_ssel_dec[3] = (m3_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s3_addr);
|
||||
assign m3_ssel_dec[4] = (m3_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s4_addr);
|
||||
assign m3_ssel_dec[5] = (m3_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s5_addr);
|
||||
assign m3_ssel_dec[6] = (m3_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s6_addr);
|
||||
assign m3_ssel_dec[7] = (m3_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s7_addr);
|
||||
|
||||
assign m4_ssel_dec[0] = (m4_adr_i[`aw -2 : `aw -1 - s0_addr_w ] == s0_addr);
|
||||
assign m4_ssel_dec[1] = (m4_adr_i[`aw -2 : `aw -1 - s1_addr_w ] == s1_addr);
|
||||
assign m4_ssel_dec[2] = (m4_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s2_addr);
|
||||
assign m4_ssel_dec[3] = (m4_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s3_addr);
|
||||
assign m4_ssel_dec[4] = (m4_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s4_addr);
|
||||
assign m4_ssel_dec[5] = (m4_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s5_addr);
|
||||
assign m4_ssel_dec[6] = (m4_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s6_addr);
|
||||
assign m4_ssel_dec[7] = (m4_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s7_addr);
|
||||
|
||||
assign m5_ssel_dec[0] = (m5_adr_i[`aw -2 : `aw -1 - s0_addr_w ] == s0_addr);
|
||||
assign m5_ssel_dec[1] = (m5_adr_i[`aw -2 : `aw -1 - s1_addr_w ] == s1_addr);
|
||||
assign m5_ssel_dec[2] = (m5_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s2_addr);
|
||||
assign m5_ssel_dec[3] = (m5_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s3_addr);
|
||||
assign m5_ssel_dec[4] = (m5_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s4_addr);
|
||||
assign m5_ssel_dec[5] = (m5_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s5_addr);
|
||||
assign m5_ssel_dec[6] = (m5_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s6_addr);
|
||||
assign m5_ssel_dec[7] = (m5_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s7_addr);
|
||||
|
||||
assign m6_ssel_dec[0] = (m6_adr_i[`aw -2 : `aw -1 - s0_addr_w ] == s0_addr);
|
||||
assign m6_ssel_dec[1] = (m6_adr_i[`aw -2 : `aw -1 - s1_addr_w ] == s1_addr);
|
||||
assign m6_ssel_dec[2] = (m6_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s2_addr);
|
||||
assign m6_ssel_dec[3] = (m6_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s3_addr);
|
||||
assign m6_ssel_dec[4] = (m6_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s4_addr);
|
||||
assign m6_ssel_dec[5] = (m6_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s5_addr);
|
||||
assign m6_ssel_dec[6] = (m6_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s6_addr);
|
||||
assign m6_ssel_dec[7] = (m6_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s7_addr);
|
||||
|
||||
assign m7_ssel_dec[0] = (m7_adr_i[`aw -2 : `aw -1 - s0_addr_w ] == s0_addr);
|
||||
assign m7_ssel_dec[1] = (m7_adr_i[`aw -2 : `aw -1 - s1_addr_w ] == s1_addr);
|
||||
assign m7_ssel_dec[2] = (m7_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s2_addr);
|
||||
assign m7_ssel_dec[3] = (m7_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s3_addr);
|
||||
assign m7_ssel_dec[4] = (m7_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s4_addr);
|
||||
assign m7_ssel_dec[5] = (m7_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s5_addr);
|
||||
assign m7_ssel_dec[6] = (m7_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s6_addr);
|
||||
assign m7_ssel_dec[7] = (m7_adr_i[`aw -2 : `aw -1 - s27_addr_w ] == s7_addr);
|
||||
|
||||
//assign i_ssel_dec[0] = (i_bus_m[`mbusw -1 : `mbusw - s0_addr_w ] == s0_addr);
|
||||
//assign i_ssel_dec[1] = (i_bus_m[`mbusw -1 : `mbusw - s1_addr_w ] == s1_addr);
|
||||
//assign i_ssel_dec[2] = (i_bus_m[`mbusw -1 : `mbusw - s27_addr_w ] == s2_addr);
|
||||
//assign i_ssel_dec[3] = (i_bus_m[`mbusw -1 : `mbusw - s27_addr_w ] == s3_addr);
|
||||
//assign i_ssel_dec[4] = (i_bus_m[`mbusw -1 : `mbusw - s27_addr_w ] == s4_addr);
|
||||
//assign i_ssel_dec[5] = (i_bus_m[`mbusw -1 : `mbusw - s27_addr_w ] == s5_addr);
|
||||
//assign i_ssel_dec[6] = (i_bus_m[`mbusw -1 : `mbusw - s27_addr_w ] == s6_addr);
|
||||
//assign i_ssel_dec[7] = (i_bus_m[`mbusw -1 : `mbusw - s27_addr_w ] == s7_addr);
|
||||
|
||||
|
||||
endmodule
|
||||
|
116
lm32/logic/sakc/rtl/wb_ddr/async_fifo.v
Normal file
116
lm32/logic/sakc/rtl/wb_ddr/async_fifo.v
Normal file
@ -0,0 +1,116 @@
|
||||
//==========================================
|
||||
// Function : Asynchronous FIFO (w/ 2 asynchronous clocks).
|
||||
// Coder : Alex Claros F.
|
||||
// Date : 15/May/2005.
|
||||
// Notes : This implementation is based on the article
|
||||
// 'Asynchronous FIFO in Virtex-II FPGAs'
|
||||
// writen by Peter Alfke. This TechXclusive
|
||||
// article can be downloaded from the
|
||||
// Xilinx website. It has some minor modifications.
|
||||
//=========================================
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module async_fifo
|
||||
#(parameter DATA_WIDTH = 8,
|
||||
ADDRESS_WIDTH = 4,
|
||||
FIFO_DEPTH = (1 << ADDRESS_WIDTH))
|
||||
//Reading port
|
||||
(output wire [DATA_WIDTH-1:0] Data_out,
|
||||
output reg Empty_out,
|
||||
input wire ReadEn_in,
|
||||
input wire RClk,
|
||||
//Writing port.
|
||||
input wire [DATA_WIDTH-1:0] Data_in,
|
||||
output reg Full_out,
|
||||
input wire WriteEn_in,
|
||||
input wire WClk,
|
||||
|
||||
input wire Clear_in);
|
||||
|
||||
/////Internal connections & variables//////
|
||||
reg [DATA_WIDTH-1:0] Mem [FIFO_DEPTH-1:0];
|
||||
wire [ADDRESS_WIDTH-1:0] pNextWordToWrite, pNextWordToRead;
|
||||
wire EqualAddresses;
|
||||
wire NextWriteAddressEn, NextReadAddressEn;
|
||||
wire Set_Status, Rst_Status;
|
||||
reg Status;
|
||||
wire PresetFull, PresetEmpty;
|
||||
|
||||
//////////////Code///////////////
|
||||
//Data ports logic:
|
||||
//(Uses a dual-port RAM).
|
||||
//'Data_out' logic:
|
||||
assign Data_out = Mem[pNextWordToRead];
|
||||
// always @ (posedge RClk)
|
||||
// if (!PresetEmpty)
|
||||
// Data_out <= Mem[pNextWordToRead];
|
||||
// if (ReadEn_in & !Empty_out)
|
||||
|
||||
//'Data_in' logic:
|
||||
always @ (posedge WClk)
|
||||
if (WriteEn_in & !Full_out)
|
||||
Mem[pNextWordToWrite] <= Data_in;
|
||||
|
||||
//Fifo addresses support logic:
|
||||
//'Next Addresses' enable logic:
|
||||
assign NextWriteAddressEn = WriteEn_in & ~Full_out;
|
||||
assign NextReadAddressEn = ReadEn_in & ~Empty_out;
|
||||
|
||||
//Addreses (Gray counters) logic:
|
||||
GrayCounter #(
|
||||
.COUNTER_WIDTH( ADDRESS_WIDTH )
|
||||
) GrayCounter_pWr (
|
||||
.GrayCount_out(pNextWordToWrite),
|
||||
.Enable_in(NextWriteAddressEn),
|
||||
.Clear_in(Clear_in),
|
||||
|
||||
.Clk(WClk)
|
||||
);
|
||||
|
||||
GrayCounter #(
|
||||
.COUNTER_WIDTH( ADDRESS_WIDTH )
|
||||
) GrayCounter_pRd (
|
||||
.GrayCount_out(pNextWordToRead),
|
||||
.Enable_in(NextReadAddressEn),
|
||||
.Clear_in(Clear_in),
|
||||
.Clk(RClk)
|
||||
);
|
||||
|
||||
|
||||
//'EqualAddresses' logic:
|
||||
assign EqualAddresses = (pNextWordToWrite == pNextWordToRead);
|
||||
|
||||
//'Quadrant selectors' logic:
|
||||
assign Set_Status = (pNextWordToWrite[ADDRESS_WIDTH-2] ~^ pNextWordToRead[ADDRESS_WIDTH-1]) &
|
||||
(pNextWordToWrite[ADDRESS_WIDTH-1] ^ pNextWordToRead[ADDRESS_WIDTH-2]);
|
||||
|
||||
assign Rst_Status = (pNextWordToWrite[ADDRESS_WIDTH-2] ^ pNextWordToRead[ADDRESS_WIDTH-1]) &
|
||||
(pNextWordToWrite[ADDRESS_WIDTH-1] ~^ pNextWordToRead[ADDRESS_WIDTH-2]);
|
||||
|
||||
//'Status' latch logic:
|
||||
always @ (Set_Status, Rst_Status, Clear_in) //D Latch w/ Asynchronous Clear & Preset.
|
||||
if (Rst_Status | Clear_in)
|
||||
Status = 0; //Going 'Empty'.
|
||||
else if (Set_Status)
|
||||
Status = 1; //Going 'Full'.
|
||||
|
||||
//'Full_out' logic for the writing port:
|
||||
assign PresetFull = Status & EqualAddresses; //'Full' Fifo.
|
||||
|
||||
always @ (posedge WClk, posedge PresetFull) //D Flip-Flop w/ Asynchronous Preset.
|
||||
if (PresetFull)
|
||||
Full_out <= 1;
|
||||
else
|
||||
Full_out <= 0;
|
||||
|
||||
//'Empty_out' logic for the reading port:
|
||||
assign PresetEmpty = ~Status & EqualAddresses; //'Empty' Fifo.
|
||||
|
||||
always @ (posedge RClk, posedge PresetEmpty) //D Flip-Flop w/ Asynchronous Preset.
|
||||
if (PresetEmpty)
|
||||
Empty_out <= 1;
|
||||
else
|
||||
Empty_out <= 0;
|
||||
|
||||
endmodule
|
224
lm32/logic/sakc/rtl/wb_ddr/ddr_clkgen.v
Normal file
224
lm32/logic/sakc/rtl/wb_ddr/ddr_clkgen.v
Normal file
@ -0,0 +1,224 @@
|
||||
//---------------------------------------------------------------------------
|
||||
// Wishbone DDR Controller
|
||||
//
|
||||
// (c) Joerg Bornschein (<jb@capsec.org>)
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
`include "ddr_include.v"
|
||||
|
||||
module ddr_clkgen
|
||||
#(
|
||||
parameter phase_shift = 0,
|
||||
parameter clk_multiply = 13,
|
||||
parameter clk_divide = 5
|
||||
) (
|
||||
input clk,
|
||||
input reset,
|
||||
output locked,
|
||||
//
|
||||
output read_clk,
|
||||
output write_clk,
|
||||
output write_clk90,
|
||||
// DCM phase shift control
|
||||
output reg ps_ready,
|
||||
input ps_up,
|
||||
input ps_down
|
||||
);
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// ~133 MHz DDR Clock generator
|
||||
//----------------------------------------------------------------------------
|
||||
wire read_clk_u;
|
||||
wire dcm_fx_locked;
|
||||
|
||||
DCM #(
|
||||
.CLKDV_DIVIDE(2.0), // Divide by: 1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0,5.5,6.0,6.5
|
||||
// 7.0,7.5,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0 or 16.0
|
||||
.CLKFX_DIVIDE(clk_divide), // Can be any integer from 1 to 32
|
||||
.CLKFX_MULTIPLY(clk_multiply), // Can be any integer from 2 to 32
|
||||
.CLKIN_DIVIDE_BY_2("FALSE"), // TRUE/FALSE to enable CLKIN divide by two feature
|
||||
.CLKIN_PERIOD(), // Specify period of input clock
|
||||
.CLKOUT_PHASE_SHIFT("NONE"), // Specify phase shift of NONE, FIXED or VARIABLE
|
||||
.CLK_FEEDBACK("NONE"), // Specify clock feedback of NONE, 1X or 2X
|
||||
.DESKEW_ADJUST("SOURCE_SYNCHRONOUS"), // SOURCE_SYNCHRONOUS, SYSTEM_SYNCHRONOUS or
|
||||
// an integer from 0 to 15
|
||||
.DFS_FREQUENCY_MODE("LOW"), // HIGH or LOW frequency mode for frequency synthesis
|
||||
.DLL_FREQUENCY_MODE("LOW"), // HIGH or LOW frequency mode for DLL
|
||||
.DUTY_CYCLE_CORRECTION("TRUE"), // Duty cycle correction, TRUE or FALSE
|
||||
.FACTORY_JF(16'hC080), // FACTORY JF values
|
||||
.PHASE_SHIFT(0), // Amount of fixed phase shift from -255 to 255
|
||||
.STARTUP_WAIT("FALSE") // Delay configuration DONE until DCM LOCK, TRUE/FALSE
|
||||
) dcm_fx (
|
||||
.DSSEN(),
|
||||
.CLK0(), // 0 degree DCM CLK output
|
||||
.CLK180(), // 180 degree DCM CLK output
|
||||
.CLK270(), // 270 degree DCM CLK output
|
||||
.CLK2X(), // 2X DCM CLK output
|
||||
.CLK2X180(), // 2X, 180 degree DCM CLK out
|
||||
.CLK90(), // 90 degree DCM CLK output
|
||||
.CLKDV(), // Divided DCM CLK out (CLKDV_DIVIDE)
|
||||
.CLKFX( read_clk_u ), // DCM CLK synthesis out (M/D)
|
||||
.CLKFX180(), // 180 degree CLK synthesis out
|
||||
.LOCKED( dcm_fx_locked), // DCM LOCK status output
|
||||
.PSDONE(), // Dynamic phase adjust done output
|
||||
.STATUS(), // 8-bit DCM status bits output
|
||||
.CLKFB(), // DCM clock feedback
|
||||
.CLKIN( clk ), // Clock input (from IBUFG, BUFG or DCM)
|
||||
.PSCLK( gnd ), // Dynamic phase adjust clock input
|
||||
.PSEN( gnd ), // Dynamic phase adjust enable input
|
||||
.PSINCDEC( gnd ), // Dynamic phase adjust increment/decrement
|
||||
.RST( reset ) // DCM asynchronous reset input
|
||||
);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// BUFG read clock
|
||||
//----------------------------------------------------------------------------
|
||||
BUFG bufg_fx_clk (
|
||||
.O(read_clk), // Clock buffer output
|
||||
.I(read_clk_u) // Clock buffer input
|
||||
);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Phase shifted clock for write path
|
||||
//----------------------------------------------------------------------------
|
||||
wire phase_dcm_reset;
|
||||
wire phase_dcm_locked;
|
||||
wire write_clk_u, write_clk90_u, write_clk180_u, write_clk270_u;
|
||||
reg psen, psincdec;
|
||||
wire psdone;
|
||||
|
||||
DCM #(
|
||||
.CLKDV_DIVIDE(2.0), // Divide by: 1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0,5.5,6.0,6.5
|
||||
// 7.0,7.5,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0 or 16.0
|
||||
.CLKFX_DIVIDE(2), // Can be any integer from 1 to 32
|
||||
.CLKFX_MULTIPLY(2), // Can be any integer from 2 to 32
|
||||
.CLKIN_DIVIDE_BY_2("FALSE"), // TRUE/FALSE to enable CLKIN divide by two feature
|
||||
.CLKIN_PERIOD(), // Specify period of input clock
|
||||
.CLK_FEEDBACK("1X"), // Specify clock feedback of NONE, 1X or 2X
|
||||
.DESKEW_ADJUST("SYSTEM_SYNCHRONOUS"), // SOURCE_SYNCHRONOUS, SYSTEM_SYNCHRONOUS or
|
||||
// an integer from 0 to 15
|
||||
.DFS_FREQUENCY_MODE("LOW"), // HIGH or LOW frequency mode for frequency synthesis
|
||||
.DLL_FREQUENCY_MODE("LOW"), // HIGH or LOW frequency mode for DLL
|
||||
.DUTY_CYCLE_CORRECTION("TRUE"), // Duty cycle correction, TRUE or FALSE
|
||||
.FACTORY_JF(16'hC080), // FACTORY JF values
|
||||
.CLKOUT_PHASE_SHIFT("VARIABLE"), // Specify phase shift of NONE, FIXED or VARIABLE
|
||||
.PHASE_SHIFT( phase_shift ), // Amount of fixed phase shift from -255 to 255
|
||||
.STARTUP_WAIT("FALSE") // Delay configuration DONE until DCM LOCK, TRUE/FALSE
|
||||
) dcm_phase (
|
||||
.DSSEN(),
|
||||
.CLK0( write_clk_u ), // 0 degree DCM CLK output
|
||||
.CLK90( write_clk90_u ), // 90 degree DCM CLK output
|
||||
.CLK180( write_clk180_u ), // 180 degree DCM CLK output
|
||||
.CLK270( write_clk270_u ), // 270 degree DCM CLK output
|
||||
.CLK2X(), // 2X DCM CLK output
|
||||
.CLK2X180(), // 2X, 180 degree DCM CLK out
|
||||
.CLKDV(), // Divided DCM CLK out (CLKDV_DIVIDE)
|
||||
.CLKFX(), // DCM CLK synthesis out (M/D)
|
||||
.CLKFX180(), // 180 degree CLK synthesis out
|
||||
.LOCKED( phase_dcm_locked ), // DCM LOCK status output
|
||||
.STATUS(), // 8-bit DCM status bits output
|
||||
.CLKFB( write_clk ), // DCM clock feedback
|
||||
.CLKIN( read_clk ), // Clock input (from IBUFG, BUFG or DCM)
|
||||
.PSCLK( clk ), // Dynamic phase adjust clock input
|
||||
.PSEN( psen ), // Dynamic phase adjust enable input
|
||||
.PSINCDEC( psincdec ), // Dynamic phase adjust increment/decrement
|
||||
.PSDONE( psdone ), // Dynamic phase adjust done output
|
||||
.RST( phase_dcm_reset ) // DCM asynchronous reset input
|
||||
);
|
||||
|
||||
// delayed reset for phase shifting DCM
|
||||
reg [3:0] reset_counter;
|
||||
assign phase_dcm_reset = reset | (reset_counter != 0);
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
if (reset)
|
||||
reset_counter <= 1;
|
||||
else begin
|
||||
if (dcm_fx_locked & (reset_counter != 0))
|
||||
reset_counter <= reset_counter + 1;
|
||||
end
|
||||
end
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// DCM phase shifting state machine
|
||||
//----------------------------------------------------------------------------
|
||||
parameter s_init = 0;
|
||||
parameter s_idle = 1;
|
||||
parameter s_waitdone = 2;
|
||||
parameter s_waitdone2= 3;
|
||||
|
||||
reg [1:0] state;
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
if (reset) begin
|
||||
state <= s_init;
|
||||
psen <= 0;
|
||||
ps_ready <= 0;
|
||||
end else begin
|
||||
case (state)
|
||||
s_init: begin
|
||||
if (phase_dcm_locked) begin
|
||||
ps_ready <= 1;
|
||||
state <= s_idle;
|
||||
end
|
||||
end
|
||||
s_idle: begin
|
||||
if (ps_up) begin
|
||||
ps_ready <= 0;
|
||||
psen <= 1;
|
||||
psincdec <= 1;
|
||||
state <= s_waitdone;
|
||||
end else if (ps_down) begin
|
||||
ps_ready <= 0;
|
||||
psen <= 1;
|
||||
psincdec <= 0;
|
||||
state <= s_waitdone;
|
||||
end
|
||||
end
|
||||
s_waitdone: begin
|
||||
psen <= 0;
|
||||
if (psdone) begin
|
||||
state <= s_waitdone2;
|
||||
end
|
||||
end
|
||||
s_waitdone2: begin
|
||||
if (~ps_up && ~ps_down) begin
|
||||
ps_ready <= 1;
|
||||
state <= s_idle;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// BUFG write clock
|
||||
//----------------------------------------------------------------------------
|
||||
BUFG bufg_write_clk (
|
||||
.O(write_clk ), // Clock buffer output
|
||||
.I(write_clk_u) // Clock buffer input
|
||||
);
|
||||
|
||||
BUFG bufg_write_clk90 (
|
||||
.O(write_clk90 ), // Clock buffer output
|
||||
.I(write_clk90_u) // Clock buffer input
|
||||
);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// LOCKED logic
|
||||
//----------------------------------------------------------------------------
|
||||
reg phase_dcm_locked_delayed;
|
||||
|
||||
always @(posedge write_clk)
|
||||
begin
|
||||
phase_dcm_locked_delayed <= phase_dcm_locked;
|
||||
end
|
||||
|
||||
assign locked = ~reset & phase_dcm_locked_delayed;
|
||||
|
||||
|
||||
endmodule
|
370
lm32/logic/sakc/rtl/wb_ddr/ddr_ctrl.v
Normal file
370
lm32/logic/sakc/rtl/wb_ddr/ddr_ctrl.v
Normal file
@ -0,0 +1,370 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// Pipelined, asyncronous DDR Controller
|
||||
//
|
||||
// (c) Joerg Bornschein (<jb@capsec.org>)
|
||||
//----------------------------------------------------------------------------
|
||||
module ddr_ctrl
|
||||
#(
|
||||
parameter phase_shift = 0,
|
||||
parameter clk_freq = 100000000,
|
||||
parameter clk_multiply = 12,
|
||||
parameter clk_divide = 5,
|
||||
parameter wait200_init = 26
|
||||
) (
|
||||
input clk,
|
||||
input reset,
|
||||
// DDR ports
|
||||
output [2:0] ddr_clk,
|
||||
output [2:0] ddr_clk_n,
|
||||
input ddr_clk_fb,
|
||||
output ddr_ras_n,
|
||||
output ddr_cas_n,
|
||||
output ddr_we_n,
|
||||
output [1:0] ddr_cke,
|
||||
output [1:0] ddr_cs_n,
|
||||
output [ `A_RNG] ddr_a,
|
||||
output [ `BA_RNG] ddr_ba,
|
||||
inout [ `DQ_RNG] ddr_dq,
|
||||
inout [`DQS_RNG] ddr_dqs,
|
||||
output [ `DM_RNG] ddr_dm,
|
||||
// FML (FastMemoryLink)
|
||||
output reg fml_done,
|
||||
input [`FML_ADR_RNG] fml_adr,
|
||||
input fml_rd,
|
||||
input fml_wr,
|
||||
input [`FML_DAT_RNG] fml_wdat,
|
||||
input [`FML_BE_RNG] fml_wbe,
|
||||
input fml_wnext,
|
||||
output fml_rempty,
|
||||
input fml_rnext,
|
||||
output [`FML_DAT_RNG] fml_rdat,
|
||||
// DCM phase shift control
|
||||
output ps_ready,
|
||||
input ps_up,
|
||||
input ps_down,
|
||||
// Logic Probe
|
||||
output probe_clk,
|
||||
input [7:0] probe_sel,
|
||||
output reg [7:0] probe
|
||||
);
|
||||
|
||||
wire [ `DQ_RNG] ddr_dq_i, ddr_dq_o;
|
||||
wire [`DQS_RNG] ddr_dqs_i, ddr_dqs_o;
|
||||
wire ddr_dqs_oe;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// clock generator
|
||||
//----------------------------------------------------------------------------
|
||||
wire clk_locked;
|
||||
wire write_clk, write_clk90;
|
||||
wire read_clk;
|
||||
|
||||
wire reset_int = reset | ~clk_locked;
|
||||
|
||||
ddr_clkgen #(
|
||||
.phase_shift( phase_shift ),
|
||||
.clk_multiply( clk_multiply ),
|
||||
.clk_divide( clk_divide )
|
||||
) clkgen (
|
||||
.clk( clk ),
|
||||
.reset( reset ),
|
||||
.locked( clk_locked ),
|
||||
// ddr-clk
|
||||
.read_clk( read_clk ),
|
||||
.write_clk( write_clk ),
|
||||
.write_clk90( write_clk90 ),
|
||||
// phase shift control
|
||||
.ps_ready( ps_ready ),
|
||||
.ps_up( ps_up ),
|
||||
.ps_down( ps_down )
|
||||
);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// async_fifos (cmd, wdata, rdata)
|
||||
//----------------------------------------------------------------------------
|
||||
wire cba_fifo_full;
|
||||
reg [`CBA_RNG] cba_fifo_din;
|
||||
reg cba_fifo_we;
|
||||
|
||||
wire wfifo_full;
|
||||
wire [`WFIFO_RNG] wfifo_din;
|
||||
wire wfifo_we;
|
||||
|
||||
wire [`RFIFO_RNG] rfifo_dout;
|
||||
wire rfifo_empty;
|
||||
wire rfifo_next;
|
||||
|
||||
assign wfifo_din = { ~fml_wbe, fml_wdat };
|
||||
assign wfifo_we = fml_wnext;
|
||||
|
||||
assign fml_rdat = rfifo_dout;
|
||||
assign fml_rempty = rfifo_empty;
|
||||
assign rfifo_next = fml_rnext;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// High-speed cmd, write and read datapath
|
||||
//----------------------------------------------------------------------------
|
||||
ddr_wpath wpath0 (
|
||||
.clk( write_clk ),
|
||||
.clk90( write_clk90 ),
|
||||
.reset( reset_int ),
|
||||
// CBA async fifo
|
||||
.cba_clk( clk ),
|
||||
.cba_din( cba_fifo_din ),
|
||||
.cba_wr( cba_fifo_we ),
|
||||
.cba_full( cba_fifo_full ),
|
||||
// WDATA async fifo
|
||||
.wdata_clk( clk ),
|
||||
.wdata_din( wfifo_din ),
|
||||
.wdata_wr( wfifo_we ),
|
||||
.wdata_full( wfifo_full ),
|
||||
//
|
||||
.sample( sample ),
|
||||
// DDR
|
||||
.ddr_clk( ddr_clk ),
|
||||
.ddr_clk_n( ddr_clk_n ),
|
||||
.ddr_ras_n( ddr_ras_n ),
|
||||
.ddr_cas_n( ddr_cas_n ),
|
||||
.ddr_we_n( ddr_we_n ),
|
||||
.ddr_a( ddr_a ),
|
||||
.ddr_ba( ddr_ba ),
|
||||
.ddr_dm( ddr_dm ),
|
||||
.ddr_dq( ddr_dq_o ),
|
||||
.ddr_dqs( ddr_dqs_o ),
|
||||
.ddr_dqs_oe( ddr_dqs_oe )
|
||||
);
|
||||
|
||||
ddr_rpath rpath0 (
|
||||
.clk( read_clk ),
|
||||
.reset( reset_int ),
|
||||
//
|
||||
.sample( sample ),
|
||||
//
|
||||
.rfifo_clk( clk ),
|
||||
.rfifo_empty( rfifo_empty),
|
||||
.rfifo_dout( rfifo_dout ),
|
||||
.rfifo_next( rfifo_next ),
|
||||
// DDR
|
||||
.ddr_dq( ddr_dq_i ),
|
||||
.ddr_dqs( ddr_dqs_i )
|
||||
);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// 7.8 us pulse generator
|
||||
//----------------------------------------------------------------------------
|
||||
wire pulse78;
|
||||
reg ar_req;
|
||||
reg ar_done;
|
||||
|
||||
ddr_pulse78 #(
|
||||
.clk_freq( clk_freq )
|
||||
) pulse78_gen (
|
||||
.clk( clk ),
|
||||
.reset( reset_int ),
|
||||
.pulse78( pulse78 )
|
||||
);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Auto Refresh request generator
|
||||
//----------------------------------------------------------------------------
|
||||
always @(posedge clk)
|
||||
if (reset_int)
|
||||
ar_req <= 0;
|
||||
else
|
||||
ar_req <= pulse78 | (ar_req & ~ar_done);
|
||||
|
||||
// operations we might want to submit
|
||||
wire [`CBA_RNG] ar_pre_cba;
|
||||
wire [`CBA_RNG] ar_ar_cba;
|
||||
|
||||
assign ar_pre_cba = { `DDR_CMD_PRE, 2'b00, 13'b1111111111111 };
|
||||
assign ar_ar_cba = { `DDR_CMD_AR, 2'b00, 13'b0000000000000 };
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Init & management
|
||||
//----------------------------------------------------------------------------
|
||||
wire init_req;
|
||||
reg init_ack;
|
||||
wire [`CBA_RNG] init_cba;
|
||||
wire init_done;
|
||||
wire wait200;
|
||||
|
||||
ddr_init #(
|
||||
.wait200_init( wait200_init )
|
||||
) init (
|
||||
.clk( clk ),
|
||||
.reset( reset_int ),
|
||||
.pulse78( pulse78 ),
|
||||
.wait200( wait200 ),
|
||||
.init_done( init_done ),
|
||||
//
|
||||
.mngt_req( init_req ),
|
||||
.mngt_ack( init_ack ),
|
||||
.mngt_cba( init_cba )
|
||||
);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Active Bank Information
|
||||
//----------------------------------------------------------------------------
|
||||
reg [`ROW_RNG] ba_row [3:0];
|
||||
reg [3:0] ba_active;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// FML decoding
|
||||
//----------------------------------------------------------------------------
|
||||
wire [`FML_ADR_BA_RNG] fml_ba = fml_adr[`FML_ADR_BA_RNG];
|
||||
wire [`FML_ADR_ROW_RNG] fml_row = fml_adr[`FML_ADR_ROW_RNG];
|
||||
wire [`FML_ADR_COL_RNG] fml_col = fml_adr[`FML_ADR_COL_RNG];
|
||||
|
||||
wire [`FML_ADR_ROW_RNG] fml_cur_row; // current active row in sel. bank
|
||||
assign fml_cur_row = ba_row[fml_ba];
|
||||
|
||||
wire fml_row_active; // is row in selected ba really active?
|
||||
assign fml_row_active = ba_active[fml_ba];
|
||||
|
||||
|
||||
/*
|
||||
wire fml_row_active = (fml_ba == 0) ? ba0_active : // is row in selected
|
||||
(fml_ba == 1) ? ba1_active : // bank really active?
|
||||
(fml_ba == 2) ? ba2_active :
|
||||
ba3_active ;
|
||||
*/
|
||||
|
||||
// request operation iff correct bank is active
|
||||
wire fml_req = fml_rd | fml_wr;
|
||||
wire fml_row_match = (fml_row == fml_cur_row) & fml_row_active;
|
||||
wire fml_pre_req = fml_req & ~fml_row_match & fml_row_active;
|
||||
wire fml_act_req = fml_req & ~fml_row_active;
|
||||
wire fml_read_req = fml_rd & fml_row_match & ~fml_done;
|
||||
wire fml_write_req = fml_wr & fml_row_match & ~fml_done;
|
||||
|
||||
// actual operations we might want to submit
|
||||
wire [`CBA_RNG] fml_pre_cba;
|
||||
wire [`CBA_RNG] fml_act_cba;
|
||||
wire [`CBA_RNG] fml_read_cba;
|
||||
wire [`CBA_RNG] fml_write_cba;
|
||||
|
||||
assign fml_pre_cba = { `DDR_CMD_PRE, fml_ba, 13'b0 };
|
||||
assign fml_act_cba = { `DDR_CMD_ACT, fml_ba, fml_row };
|
||||
assign fml_read_cba = { `DDR_CMD_READ, fml_ba, {3'b000}, fml_col, {3'b000} };
|
||||
assign fml_write_cba = { `DDR_CMD_WRITE, fml_ba, {3'b000}, fml_col, {3'b000} };
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Schedule and issue commands
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
parameter s_init = 0;
|
||||
parameter s_idle = 1;
|
||||
parameter s_ar = 2;
|
||||
parameter s_reading = 3;
|
||||
|
||||
reg [1:0] state;
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
if (reset_int) begin
|
||||
state <= s_init;
|
||||
ba_active <= 0;
|
||||
ba_row[0] <= 0;
|
||||
ba_row[1] <= 0;
|
||||
ba_row[2] <= 0;
|
||||
ba_row[3] <= 0;
|
||||
|
||||
fml_done <= 0;
|
||||
init_ack <= 0;
|
||||
cba_fifo_we <= 0;
|
||||
ar_done <= 0;
|
||||
end else begin
|
||||
fml_done <= 0;
|
||||
init_ack <= 0;
|
||||
cba_fifo_we <= 0;
|
||||
ar_done <= 0;
|
||||
|
||||
case (state)
|
||||
s_init: begin
|
||||
if (init_done)
|
||||
state <= s_idle;
|
||||
|
||||
if (init_req & ~cba_fifo_full) begin
|
||||
cba_fifo_we <= 1;
|
||||
cba_fifo_din <= init_cba;
|
||||
init_ack <= 1;
|
||||
end
|
||||
end
|
||||
s_idle: begin
|
||||
if (fml_read_req & ~cba_fifo_full) begin
|
||||
cba_fifo_we <= 1;
|
||||
cba_fifo_din <= fml_read_cba;
|
||||
fml_done <= 1;
|
||||
end else if (fml_write_req & ~cba_fifo_full) begin
|
||||
cba_fifo_we <= 1;
|
||||
cba_fifo_din <= fml_write_cba;
|
||||
fml_done <= 1;
|
||||
end else if (ar_req & ~cba_fifo_full) begin
|
||||
cba_fifo_we <= 1;
|
||||
cba_fifo_din <= ar_pre_cba;
|
||||
ar_done <= 1;
|
||||
ba_active <= 'b0;
|
||||
state <= s_ar;
|
||||
end else if (fml_pre_req & ~cba_fifo_full) begin
|
||||
cba_fifo_we <= 1;
|
||||
cba_fifo_din <= fml_pre_cba;
|
||||
ba_active[fml_ba] <= 0;
|
||||
end else if (fml_act_req & ~cba_fifo_full) begin
|
||||
cba_fifo_we <= 1;
|
||||
cba_fifo_din <= fml_act_cba;
|
||||
ba_active[fml_ba] <= 1;
|
||||
ba_row[fml_ba] <= fml_row;
|
||||
end
|
||||
end
|
||||
s_ar: begin
|
||||
if (~cba_fifo_full) begin
|
||||
cba_fifo_we <= 1;
|
||||
cba_fifo_din <= ar_ar_cba;
|
||||
state <= s_idle;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Demux dqs and dq
|
||||
//----------------------------------------------------------------------------
|
||||
assign ddr_cke = {~wait200, ~wait200}; // bring up CKE as soon 200us wait is finished
|
||||
|
||||
assign ddr_dqs = ddr_dqs_oe!=1'b0 ? ddr_dqs_o : 'bz;
|
||||
assign ddr_dq = ddr_dqs_oe!=1'b0 ? ddr_dq_o : 'bz;
|
||||
|
||||
assign ddr_dqs_i = ddr_dqs;
|
||||
assign ddr_dq_i = ddr_dq;
|
||||
|
||||
assign ddr_cs_n = 2'b00;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Probes
|
||||
//----------------------------------------------------------------------------
|
||||
assign probe_clk = clk;
|
||||
|
||||
always @(*)
|
||||
begin
|
||||
case (probe_sel)
|
||||
8'h00: probe <= { cba_fifo_we, wfifo_we, rfifo_next, 1'b0, cba_fifo_full, wfifo_full, rfifo_empty, 1'b0 };
|
||||
8'h01: probe <= { write_clk, write_clk90, read_clk, 5'b00000 };
|
||||
8'h10: probe <= { rfifo_empty, rfifo_next, rfifo_dout[ 5: 0] };
|
||||
8'h11: probe <= { rfifo_empty, rfifo_next, rfifo_dout[13: 8] };
|
||||
8'h12: probe <= { rfifo_empty, rfifo_next, rfifo_dout[21:16] };
|
||||
8'h13: probe <= { rfifo_empty, rfifo_next, rfifo_dout[29:24] };
|
||||
8'h20: probe <= wfifo_din[ 7:0];
|
||||
8'h21: probe <= wfifo_din[15:8];
|
||||
8'h20: probe <= wfifo_din[23:16];
|
||||
8'h21: probe <= wfifo_din[31:24];
|
||||
8'h30: probe <= cba_fifo_din[17:10];
|
||||
8'h31: probe <= cba_fifo_din[ 9:2];
|
||||
default: probe <= 0'b0;
|
||||
endcase
|
||||
end
|
||||
|
||||
|
||||
endmodule
|
||||
|
122
lm32/logic/sakc/rtl/wb_ddr/ddr_include.v
Normal file
122
lm32/logic/sakc/rtl/wb_ddr/ddr_include.v
Normal file
@ -0,0 +1,122 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// Wishbone DDR Controller
|
||||
//
|
||||
// (c) Joerg Bornschein (<jb@capsec.org>)
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
`ifdef WBDDR_INCLUDE_V
|
||||
`else
|
||||
`define WBDDR_INCLUDE_V
|
||||
|
||||
`timescale 1ns/10ps
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Frequency and timeouts
|
||||
//----------------------------------------------------------------------------
|
||||
`define SYS_CLK_FREQUENCY 50000 // in kHz
|
||||
`define DDR_CLK_MULTIPLY 5
|
||||
`define DDR_CLK_DIVIDE 2
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Width
|
||||
//----------------------------------------------------------------------------
|
||||
`define CMD_WIDTH 3
|
||||
`define A_WIDTH 13
|
||||
`define BA_WIDTH 2
|
||||
`define DQ_WIDTH 16
|
||||
`define DQS_WIDTH 2
|
||||
`define DM_WIDTH 2
|
||||
|
||||
`define RFIFO_WIDTH (2 * `DQ_WIDTH )
|
||||
`define WFIFO_WIDTH (2 * (`DQ_WIDTH + `DM_WIDTH))
|
||||
`define CBA_WIDTH (`CMD_WIDTH+`BA_WIDTH+`A_WIDTH)
|
||||
|
||||
// Ranges
|
||||
`define CMD_RNG (`CMD_WIDTH-1):0
|
||||
`define A_RNG (`A_WIDTH-1):0
|
||||
`define BA_RNG (`BA_WIDTH-1):0
|
||||
`define DQ_RNG (`DQ_WIDTH-1):0
|
||||
`define DQS_RNG (`DQS_WIDTH-1):0
|
||||
`define DM_RNG (`DM_WIDTH-1):0
|
||||
|
||||
`define RFIFO_RNG (`RFIFO_WIDTH-1):0
|
||||
`define WFIFO_RNG (`WFIFO_WIDTH-1):0
|
||||
`define WFIFO_D0_RNG (1*`DQ_WIDTH-1):0
|
||||
`define WFIFO_D1_RNG (2*`DQ_WIDTH-1):(`DQ_WIDTH)
|
||||
`define WFIFO_M0_RNG (2*`DQ_WIDTH+1*`DM_WIDTH-1):(2*`DQ_WIDTH+0*`DM_WIDTH)
|
||||
`define WFIFO_M1_RNG (2*`DQ_WIDTH+2*`DM_WIDTH-1):(2*`DQ_WIDTH+1*`DM_WIDTH)
|
||||
`define CBA_RNG (`CBA_WIDTH-1):0
|
||||
`define CBA_CMD_RNG (`CBA_WIDTH-1):(`CBA_WIDTH-3)
|
||||
`define CBA_BA_RNG (`CBA_WIDTH-4):(`CBA_WIDTH-5)
|
||||
`define CBA_A_RNG (`CBA_WIDTH-6):0
|
||||
|
||||
`define ROW_RNG 12:0
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Configuration registers
|
||||
//----------------------------------------------------------------------------
|
||||
`define DDR_INIT_EMRS `A_WIDTH'b0000000000000 // DLL enable
|
||||
`define DDR_INIT_MRS1 `A_WIDTH'b0000101100011 // BURST=8, CL=2.5, DLL RESET
|
||||
`define DDR_INIT_MRS2 `A_WIDTH'b0000001100011 // BURST=8, CL=2.5
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// FML constants
|
||||
//----------------------------------------------------------------------------
|
||||
`define FML_ADR_RNG 25:4
|
||||
`define FML_ADR_BA_RNG 25:24
|
||||
`define FML_ADR_ROW_RNG 23:11
|
||||
`define FML_ADR_COL_RNG 10:4
|
||||
`define FML_DAT_RNG 31:0
|
||||
`define FML_BE_RNG 3:0
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// DDR constants
|
||||
//----------------------------------------------------------------------------
|
||||
`define DDR_CMD_NOP 3'b111
|
||||
`define DDR_CMD_ACT 3'b011
|
||||
`define DDR_CMD_READ 3'b101
|
||||
`define DDR_CMD_WRITE 3'b100
|
||||
`define DDR_CMD_TERM 3'b110
|
||||
`define DDR_CMD_PRE 3'b010
|
||||
`define DDR_CMD_AR 3'b001
|
||||
`define DDR_CMD_MRS 3'b000
|
||||
|
||||
`define ADR_BA_RNG 25:24
|
||||
`define ADR_ROW_RNG 23:11
|
||||
`define ADR_COL_RNG 10:4
|
||||
|
||||
`define T_MRD 2 // Mode register set
|
||||
`define T_RP 2 // Precharge Command Period
|
||||
`define T_RFC 8 // Precharge Command Period
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Buffer Cache
|
||||
//----------------------------------------------------------------------------
|
||||
`define WAY_WIDTH (`WB_DAT_WIDTH + `WB_SEL_WIDTH)
|
||||
`define WAY_LINE_RNG (`WAY_WIDTH-1):0
|
||||
`define WAY_DAT_RNG 31:0
|
||||
`define WAY_VALID_RNG 35:32
|
||||
|
||||
`define TAG_LINE_RNG 32:0
|
||||
`define TAG_LINE_TAG0_RNG 14:0
|
||||
`define TAG_LINE_TAG1_RNG 29:15
|
||||
`define TAG_LINE_DIRTY0_RNG 30
|
||||
`define TAG_LINE_DIRTY1_RNG 31
|
||||
`define TAG_LINE_LRU_RNG 32
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Whishbone constants
|
||||
//----------------------------------------------------------------------------
|
||||
`define WB_ADR_WIDTH 32
|
||||
`define WB_DAT_WIDTH 32
|
||||
`define WB_SEL_WIDTH 4
|
||||
|
||||
`define WB_ADR_RNG (`WB_ADR_WIDTH-1):0
|
||||
`define WB_DAT_RNG (`WB_DAT_WIDTH-1):0
|
||||
`define WB_SEL_RNG (`WB_SEL_WIDTH-1):0
|
||||
|
||||
`define WB_WORD_RNG 3:2
|
||||
`define WB_SET_RNG 10:4
|
||||
`define WB_TAG_RNG 25:11
|
||||
|
||||
`endif
|
164
lm32/logic/sakc/rtl/wb_ddr/ddr_init.v
Normal file
164
lm32/logic/sakc/rtl/wb_ddr/ddr_init.v
Normal file
@ -0,0 +1,164 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// Wishbone DDR Controller
|
||||
//
|
||||
// (c) Joerg Bornschein (<jb@capsec.org>)
|
||||
//----------------------------------------------------------------------------
|
||||
`include "ddr_include.v"
|
||||
|
||||
module ddr_init
|
||||
#(
|
||||
parameter wait200_init = 26
|
||||
) (
|
||||
input clk,
|
||||
input reset,
|
||||
input pulse78,
|
||||
output wait200,
|
||||
output init_done,
|
||||
//
|
||||
output mngt_req,
|
||||
input mngt_ack,
|
||||
output [`CBA_RNG] mngt_cba // CMD, BA and ADDRESS
|
||||
);
|
||||
|
||||
reg cmd_req_reg;
|
||||
reg [`CMD_RNG] cmd_cmd_reg;
|
||||
reg [ `BA_RNG] cmd_ba_reg;
|
||||
reg [ `A_RNG] cmd_a_reg;
|
||||
reg [7:0] cmd_idle_reg;
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Initial 200us delay
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
// `define WAIT200_INIT 26
|
||||
// `define WAIT200_INIT 1
|
||||
|
||||
reg [4:0] wait200_counter;
|
||||
reg wait200_reg;
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
if (reset) begin
|
||||
wait200_reg <= 1;
|
||||
wait200_counter <= wait200_init;
|
||||
end else begin
|
||||
if (wait200_counter == 0)
|
||||
wait200_reg <= 0;
|
||||
|
||||
if (wait200_reg & pulse78)
|
||||
wait200_counter <= wait200_counter - 1;
|
||||
end
|
||||
end
|
||||
|
||||
assign wait200 = wait200_reg;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// DDR Initialization State Machine
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
parameter s_wait200 = 0;
|
||||
parameter s_init1 = 1;
|
||||
parameter s_init2 = 2;
|
||||
parameter s_init3 = 3;
|
||||
parameter s_init4 = 4;
|
||||
parameter s_init5 = 5;
|
||||
parameter s_init6 = 6;
|
||||
parameter s_waitack = 7;
|
||||
parameter s_idle = 8;
|
||||
|
||||
reg [3:0] state;
|
||||
reg init_done_reg;
|
||||
|
||||
assign mngt_cba = {cmd_cmd_reg, cmd_ba_reg, cmd_a_reg};
|
||||
assign mngt_req = cmd_req_reg;
|
||||
assign mngt_pri_req = ~init_done_reg;
|
||||
assign init_done = init_done_reg;
|
||||
|
||||
always @(posedge clk or posedge reset)
|
||||
begin
|
||||
if (reset) begin
|
||||
init_done_reg <= 0;
|
||||
state <= s_wait200;
|
||||
cmd_idle_reg <= 0;
|
||||
cmd_req_reg <= 0;
|
||||
cmd_cmd_reg <= 'b0;
|
||||
cmd_ba_reg <= 'b0;
|
||||
cmd_a_reg <= 'b0;
|
||||
end else begin
|
||||
case (state)
|
||||
s_wait200: begin
|
||||
if (~wait200_reg) begin
|
||||
state <= s_init1;
|
||||
cmd_req_reg <= 1;
|
||||
cmd_cmd_reg <= `DDR_CMD_PRE; // PRE ALL
|
||||
cmd_a_reg[10] <= 1'b1;
|
||||
end
|
||||
end
|
||||
s_init1: begin
|
||||
if (mngt_ack) begin
|
||||
state <= s_init2;
|
||||
cmd_req_reg <= 1;
|
||||
cmd_cmd_reg <= `DDR_CMD_MRS; // EMRS
|
||||
cmd_ba_reg <= 2'b01;
|
||||
cmd_a_reg <= `DDR_INIT_EMRS;
|
||||
end
|
||||
end
|
||||
s_init2: begin
|
||||
if (mngt_ack) begin
|
||||
state <= s_init3;
|
||||
cmd_req_reg <= 1;
|
||||
cmd_cmd_reg <= `DDR_CMD_MRS; // MRS
|
||||
cmd_ba_reg <= 2'b00;
|
||||
cmd_a_reg <= `DDR_INIT_MRS1;
|
||||
end
|
||||
end
|
||||
s_init3: begin
|
||||
if (mngt_ack) begin
|
||||
state <= s_init4;
|
||||
cmd_req_reg <= 1;
|
||||
cmd_cmd_reg <= `DDR_CMD_PRE; // PRE ALL
|
||||
cmd_a_reg[10] <= 1'b1;
|
||||
end
|
||||
end
|
||||
s_init4: begin
|
||||
if (mngt_ack) begin
|
||||
state <= s_init5;
|
||||
cmd_req_reg <= 1;
|
||||
cmd_cmd_reg <= `DDR_CMD_AR; // AR
|
||||
end
|
||||
end
|
||||
s_init5: begin
|
||||
if (mngt_ack) begin
|
||||
state <= s_init6;
|
||||
cmd_req_reg <= 1;
|
||||
cmd_cmd_reg <= `DDR_CMD_AR; // AR
|
||||
end
|
||||
end
|
||||
s_init6: begin
|
||||
if (mngt_ack) begin
|
||||
init_done_reg <= 1;
|
||||
state <= s_waitack;
|
||||
cmd_req_reg <= 1;
|
||||
cmd_cmd_reg <= `DDR_CMD_MRS; // MRS
|
||||
cmd_ba_reg <= 2'b00;
|
||||
cmd_a_reg <= `DDR_INIT_MRS2;
|
||||
end
|
||||
end
|
||||
s_waitack: begin
|
||||
if (mngt_ack) begin
|
||||
state <= s_idle;
|
||||
cmd_req_reg <= 0;
|
||||
cmd_cmd_reg <= 'b0;
|
||||
cmd_ba_reg <= 'b0;
|
||||
cmd_a_reg <= 'b0;
|
||||
end
|
||||
end
|
||||
s_idle: begin
|
||||
end
|
||||
endcase ///////////////////////////////////////// INIT STATE MACHINE ///
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
endmodule
|
||||
|
43
lm32/logic/sakc/rtl/wb_ddr/ddr_pulse78.v
Normal file
43
lm32/logic/sakc/rtl/wb_ddr/ddr_pulse78.v
Normal file
@ -0,0 +1,43 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// Wishbone DDR Controller
|
||||
//
|
||||
// (c) Joerg Bornschein (<jb@capsec.org>)
|
||||
//----------------------------------------------------------------------------
|
||||
`include "ddr_include.v"
|
||||
|
||||
module ddr_pulse78 #(
|
||||
parameter clk_freq = 50000000
|
||||
) (
|
||||
input clk,
|
||||
input reset,
|
||||
//
|
||||
output reg pulse78
|
||||
);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
`define PULSE78_RNG 10:0
|
||||
|
||||
parameter pulse78_init = 78 * (clk_freq/10000000);
|
||||
|
||||
reg [`PULSE78_RNG] counter;
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
if (reset) begin
|
||||
counter <= pulse78_init;
|
||||
pulse78 <= 0;
|
||||
end else begin
|
||||
if (counter == 0) begin
|
||||
counter <= pulse78_init;
|
||||
pulse78 <= 1'b1;
|
||||
end else begin
|
||||
counter <= counter - 1;
|
||||
pulse78 <= 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
112
lm32/logic/sakc/rtl/wb_ddr/ddr_rpath.v
Normal file
112
lm32/logic/sakc/rtl/wb_ddr/ddr_rpath.v
Normal file
@ -0,0 +1,112 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// Wishbone DDR Controller
|
||||
//
|
||||
// (c) Joerg Bornschein (<jb@capsec.org>)
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
`include "ddr_include.v"
|
||||
|
||||
module ddr_rpath
|
||||
(
|
||||
input clk,
|
||||
input reset,
|
||||
// sample activate
|
||||
input sample,
|
||||
// RDATA async fifo
|
||||
input rfifo_clk,
|
||||
output rfifo_empty,
|
||||
output [`RFIFO_RNG] rfifo_dout,
|
||||
input rfifo_next,
|
||||
// DDR
|
||||
input [ `DQ_RNG] ddr_dq,
|
||||
input [`DQS_RNG] ddr_dqs
|
||||
);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// RDATA async. fifo
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
wire [`RFIFO_RNG] rfifo_din;
|
||||
wire rfifo_wr;
|
||||
wire rfifo_full;
|
||||
|
||||
async_fifo #(
|
||||
.DATA_WIDTH( `RFIFO_WIDTH ),
|
||||
.ADDRESS_WIDTH( 4 )
|
||||
) rfifo (
|
||||
.Data_out( rfifo_dout ),
|
||||
.Empty_out( rfifo_empty ),
|
||||
.ReadEn_in( rfifo_next ),
|
||||
.RClk( rfifo_clk ),
|
||||
//
|
||||
.Data_in( rfifo_din ),
|
||||
.WriteEn_in( rfifo_wr ),
|
||||
.Full_out( rfifo_full ),
|
||||
.WClk( ~clk ),
|
||||
.Clear_in( reset )
|
||||
);
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Clean up incoming 'sample' signal and generate sample_dq
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
// anti-meta-state
|
||||
//reg sample180;
|
||||
//always @(negedge clk) sample180 <= sample;
|
||||
wire sample180 = sample;
|
||||
|
||||
|
||||
reg sample_dq; // authoritive sample flag (after cleanup)
|
||||
reg sample_dq_delayed; // write to rfifo?
|
||||
reg [3:0] sample_count; // make sure sample_dq is up exactly
|
||||
// BURSTLENGTH/2 cycles
|
||||
|
||||
always @(posedge clk or posedge reset)
|
||||
begin
|
||||
if (reset) begin
|
||||
sample_dq <= 0;
|
||||
sample_dq_delayed <= 0;
|
||||
sample_count <= 0;
|
||||
end else begin
|
||||
sample_dq_delayed <= sample_dq;
|
||||
if (sample_count == 0) begin
|
||||
if (sample180) begin
|
||||
sample_dq <= 1;
|
||||
sample_count <= 1;
|
||||
end
|
||||
end else if (sample_count == 4) begin
|
||||
sample_dq <= 0;
|
||||
sample_count <= 0;
|
||||
end else
|
||||
sample_count <= sample_count + 1;
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Sampe DQ and fill RFIFO
|
||||
//----------------------------------------------------------------------------
|
||||
reg [15:0] ddr_dq_low, ddr_dq_high;
|
||||
|
||||
always @(negedge clk )
|
||||
begin
|
||||
if (reset)
|
||||
ddr_dq_low <= 'b0;
|
||||
else
|
||||
ddr_dq_low <= ddr_dq;
|
||||
end
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
if (reset)
|
||||
ddr_dq_high <= 'b0;
|
||||
else
|
||||
ddr_dq_high <= ddr_dq;
|
||||
end
|
||||
|
||||
assign rfifo_wr = sample_dq_delayed;
|
||||
assign rfifo_din = { ddr_dq_high, ddr_dq_low };
|
||||
|
||||
endmodule
|
||||
|
286
lm32/logic/sakc/rtl/wb_ddr/ddr_wpath.v
Normal file
286
lm32/logic/sakc/rtl/wb_ddr/ddr_wpath.v
Normal file
@ -0,0 +1,286 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// Wishbone DDR Controller -- fast write data-path
|
||||
//
|
||||
// (c) Joerg Bornschein (<jb@capsec.org>)
|
||||
//----------------------------------------------------------------------------
|
||||
`include "ddr_include.v"
|
||||
|
||||
module ddr_wpath (
|
||||
input clk,
|
||||
input clk90,
|
||||
input reset,
|
||||
// CBA async fifo
|
||||
input cba_clk,
|
||||
input [`CBA_RNG] cba_din,
|
||||
input cba_wr,
|
||||
output cba_full,
|
||||
// WDATA async fifo
|
||||
input wdata_clk,
|
||||
input [`WFIFO_RNG] wdata_din,
|
||||
input wdata_wr,
|
||||
output wdata_full,
|
||||
// sample to rdata
|
||||
output sample,
|
||||
// DDR
|
||||
output [2:0] ddr_clk,
|
||||
output [2:0] ddr_clk_n,
|
||||
output ddr_ras_n,
|
||||
output ddr_cas_n,
|
||||
output ddr_we_n,
|
||||
output [ `A_RNG] ddr_a,
|
||||
output [ `BA_RNG] ddr_ba,
|
||||
output [ `DM_RNG] ddr_dm,
|
||||
output [ `DQ_RNG] ddr_dq,
|
||||
output [`DQS_RNG] ddr_dqs,
|
||||
output ddr_dqs_oe
|
||||
);
|
||||
|
||||
wire gnd = 1'b0;
|
||||
wire vcc = 1'b1;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// CBA async. fifo
|
||||
//----------------------------------------------------------------------------
|
||||
wire [`CBA_RNG] cba_data;
|
||||
wire cba_empty;
|
||||
wire cba_ack;
|
||||
|
||||
wire cba_avail = ~cba_empty;
|
||||
|
||||
async_fifo #(
|
||||
.DATA_WIDTH( `CBA_WIDTH ),
|
||||
.ADDRESS_WIDTH( 4 )
|
||||
) cba_fifo (
|
||||
.Data_out( cba_data ),
|
||||
.Empty_out( cba_empty ),
|
||||
.ReadEn_in( cba_ack ),
|
||||
.RClk( clk ),
|
||||
//
|
||||
.Data_in( cba_din ),
|
||||
.WriteEn_in( cba_wr ),
|
||||
.Full_out( cba_full ),
|
||||
.WClk( cba_clk ),
|
||||
.Clear_in( reset )
|
||||
);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// WDATA async. fifo
|
||||
//----------------------------------------------------------------------------
|
||||
wire [`WFIFO_RNG] wdata_data;
|
||||
wire wdata_empty;
|
||||
wire wdata_ack;
|
||||
|
||||
wire wdata_avail = ~wdata_empty;
|
||||
|
||||
async_fifo #(
|
||||
.DATA_WIDTH( `WFIFO_WIDTH ),
|
||||
.ADDRESS_WIDTH( 4 )
|
||||
) wdata_fifo (
|
||||
.Data_out( wdata_data ),
|
||||
.Empty_out( wdata_empty ),
|
||||
.ReadEn_in( wdata_ack ),
|
||||
.RClk( ~clk90 ),
|
||||
//
|
||||
.Data_in( wdata_din ),
|
||||
.WriteEn_in( wdata_wr ),
|
||||
.Full_out( wdata_full ),
|
||||
.WClk( wdata_clk ),
|
||||
.Clear_in( reset )
|
||||
);
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Handle CBA
|
||||
//----------------------------------------------------------------------------
|
||||
reg [3:0] delay_count;
|
||||
|
||||
reg [`CBA_RNG] ddr_cba;
|
||||
wire [`CBA_RNG] CBA_NOP = { `DDR_CMD_NOP, 15'b0 };
|
||||
|
||||
assign cba_ack = cba_avail & (delay_count == 0);
|
||||
|
||||
wire [`CMD_RNG] cba_cmd = cba_data[(`CBA_WIDTH-1):(`CBA_WIDTH-3)];
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
if (reset) begin
|
||||
delay_count <= 0;
|
||||
ddr_cba <= CBA_NOP;
|
||||
end else begin
|
||||
if (delay_count != 0) begin
|
||||
delay_count <= delay_count - 1;
|
||||
ddr_cba <= CBA_NOP;
|
||||
end
|
||||
|
||||
if (!cba_ack) begin
|
||||
ddr_cba <= CBA_NOP;
|
||||
end else begin
|
||||
ddr_cba <= cba_data;
|
||||
|
||||
case (cba_cmd)
|
||||
`DDR_CMD_MRS : delay_count <= 2;
|
||||
`DDR_CMD_AR : delay_count <= 14;
|
||||
`DDR_CMD_ACT : delay_count <= 4;
|
||||
`DDR_CMD_PRE : delay_count <= 2;
|
||||
`DDR_CMD_READ : delay_count <= 6; // XXX
|
||||
`DDR_CMD_WRITE : delay_count <= 8; // XXX
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// READ-SHIFT-REGISTER
|
||||
//----------------------------------------------------------------------------
|
||||
reg [7:0] read_shr;
|
||||
wire read_cmd = (cba_cmd == `DDR_CMD_READ) & cba_ack;
|
||||
assign sample = read_shr[6];
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
if (reset)
|
||||
read_shr <= 'b0;
|
||||
else begin
|
||||
if (read_cmd)
|
||||
read_shr <= { 8'b00011000 };
|
||||
else
|
||||
read_shr <= { read_shr[6:0], 1'b0 };
|
||||
end
|
||||
end
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// WRITE-SHIFT-REGISTER
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
reg [0:4] write_shr;
|
||||
wire write_cmd = (cba_cmd == `DDR_CMD_WRITE) & cba_ack;
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
if (reset)
|
||||
write_shr <= 'b0;
|
||||
else begin
|
||||
if (write_cmd)
|
||||
write_shr <= { 5'b11111 };
|
||||
else
|
||||
write_shr <= { write_shr[1:4], 1'b0 };
|
||||
end
|
||||
end
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// DDR_DQS, DDR_DQS_OE
|
||||
//----------------------------------------------------------------------------
|
||||
genvar i;
|
||||
|
||||
reg ddr_dqs_oe_reg;
|
||||
assign ddr_dqs_oe = ddr_dqs_oe_reg;
|
||||
|
||||
always @(negedge clk)
|
||||
begin
|
||||
ddr_dqs_oe_reg <= write_shr[0];
|
||||
end
|
||||
|
||||
generate
|
||||
for (i=0; i<3; i=i+1) begin : CLK
|
||||
FDDRRSE ddr_clk_reg (
|
||||
.Q( ddr_clk[i] ),
|
||||
.C0( clk90 ),
|
||||
.C1( ~clk90 ),
|
||||
.CE( vcc ),
|
||||
.D0( vcc ),
|
||||
.D1( gnd ),
|
||||
.R( gnd ),
|
||||
.S( gnd )
|
||||
);
|
||||
|
||||
FDDRRSE ddr_clk_n_reg (
|
||||
.Q( ddr_clk_n[i] ),
|
||||
.C0( clk90 ),
|
||||
.C1( ~clk90 ),
|
||||
.CE( vcc ),
|
||||
.D0( gnd ),
|
||||
.D1( vcc ),
|
||||
.R( gnd ),
|
||||
.S( gnd )
|
||||
);
|
||||
end
|
||||
endgenerate
|
||||
|
||||
generate
|
||||
for (i=0; i<`DQS_WIDTH; i=i+1) begin : DQS
|
||||
FDDRRSE ddr_dqs_reg (
|
||||
.Q( ddr_dqs[i] ),
|
||||
.C0( clk ),
|
||||
.C1( ~clk ),
|
||||
.CE( vcc ),
|
||||
.D0( write_shr[1] ),
|
||||
.D1( gnd ),
|
||||
.R( gnd ),
|
||||
.S( gnd )
|
||||
);
|
||||
end
|
||||
endgenerate
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// DQ data output
|
||||
//----------------------------------------------------------------------------
|
||||
wire [`DQ_RNG] buf_d0;
|
||||
wire [`DM_RNG] buf_m0;
|
||||
reg [`DQ_RNG] buf_d1; // pipleine high word data
|
||||
reg [`DM_RNG] buf_m1; // pipleine high word mask
|
||||
|
||||
assign buf_d0 = wdata_data[`WFIFO_D0_RNG];
|
||||
assign buf_m0 = wdata_data[`WFIFO_M0_RNG];
|
||||
|
||||
always @(negedge clk90)
|
||||
begin
|
||||
buf_d1 <= wdata_data[`WFIFO_D1_RNG];
|
||||
buf_m1 <= wdata_data[`WFIFO_M1_RNG];
|
||||
end
|
||||
|
||||
assign wdata_ack = write_shr[1];
|
||||
|
||||
// generate DDR_DQ register
|
||||
generate
|
||||
for (i=0; i<`DQ_WIDTH; i=i+1) begin : DQ_REG
|
||||
FDDRRSE ddr_dq_reg (
|
||||
.Q( ddr_dq[i] ),
|
||||
.C0( ~clk90 ),
|
||||
.C1( clk90 ),
|
||||
.CE( vcc ),
|
||||
.D0( buf_d0[i] ),
|
||||
.D1( buf_d1[i] ),
|
||||
.R( gnd ),
|
||||
.S( gnd )
|
||||
);
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// generate DDR_DM register
|
||||
generate
|
||||
for (i=0; i<`DM_WIDTH; i=i+1) begin : DM_REG
|
||||
FDDRRSE ddr_dm_reg (
|
||||
.Q( ddr_dm[i] ),
|
||||
.C0( ~clk90 ),
|
||||
.C1( clk90 ),
|
||||
.CE( vcc ),
|
||||
.D0( buf_m0[i] ),
|
||||
.D1( buf_m1[i] ),
|
||||
.R( gnd ),
|
||||
.S( gnd )
|
||||
);
|
||||
end
|
||||
endgenerate
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Connect ddr_cba to actual DDR pins
|
||||
//----------------------------------------------------------------------------
|
||||
assign ddr_a = ddr_cba[(`A_WIDTH-1):0];
|
||||
assign ddr_ba = ddr_cba[(`A_WIDTH+`BA_WIDTH-1):(`A_WIDTH)];
|
||||
assign ddr_ras_n = ddr_cba[(`CBA_WIDTH-1)];
|
||||
assign ddr_cas_n = ddr_cba[(`CBA_WIDTH-2)];
|
||||
assign ddr_we_n = ddr_cba[(`CBA_WIDTH-3)];
|
||||
|
||||
endmodule
|
64
lm32/logic/sakc/rtl/wb_ddr/dpram.v
Normal file
64
lm32/logic/sakc/rtl/wb_ddr/dpram.v
Normal file
@ -0,0 +1,64 @@
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Wishbone DDR Controller
|
||||
//
|
||||
// (c) Joerg Bornschein (<jb@capsec.org>)
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
module dpram
|
||||
#(
|
||||
parameter adr_width = 9,
|
||||
parameter dat_width = 36
|
||||
) (
|
||||
input clk,
|
||||
// Port 0
|
||||
input [adr_width-1:0] adr0,
|
||||
input we0,
|
||||
input [dat_width-1:0] din0,
|
||||
output reg [dat_width-1:0] dout0,
|
||||
// Port 1
|
||||
input [adr_width-1:0] adr1,
|
||||
input we1,
|
||||
input [dat_width-1:0] din1,
|
||||
output reg [dat_width-1:0] dout1
|
||||
);
|
||||
|
||||
parameter depth = (1 << adr_width);
|
||||
|
||||
// actual ram
|
||||
reg [dat_width-1:0] ram [0:depth-1];
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Syncronous Dual Port RAM Access
|
||||
//------------------------------------------------------------------
|
||||
always @(posedge clk)
|
||||
begin
|
||||
// Frst port
|
||||
if (we0)
|
||||
ram[adr0] <= din0;
|
||||
|
||||
dout0 <= ram[adr0];
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
// Second port
|
||||
if (we1)
|
||||
ram[adr1] <= din1;
|
||||
|
||||
dout1 <= ram[adr1];
|
||||
end
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Initialize content to Zero
|
||||
//------------------------------------------------------------------
|
||||
integer i;
|
||||
|
||||
initial
|
||||
begin
|
||||
for(i=0; i<depth; i=i+1)
|
||||
ram[i] <= 'b0;
|
||||
end
|
||||
|
||||
endmodule
|
35
lm32/logic/sakc/rtl/wb_ddr/gray_counter.v
Normal file
35
lm32/logic/sakc/rtl/wb_ddr/gray_counter.v
Normal file
@ -0,0 +1,35 @@
|
||||
//==========================================
|
||||
// Function : Code Gray counter.
|
||||
// Coder : Alex Claros F.
|
||||
// Date : 15/May/2005.
|
||||
//=======================================
|
||||
|
||||
`timescale 1ns/1ps
|
||||
|
||||
module GrayCounter
|
||||
#(parameter COUNTER_WIDTH = 2)
|
||||
|
||||
(output reg [COUNTER_WIDTH-1:0] GrayCount_out, //'Gray' code count output.
|
||||
|
||||
input wire Enable_in, //Count enable.
|
||||
input wire Clear_in, //Count reset.
|
||||
|
||||
input wire Clk);
|
||||
|
||||
/////////Internal connections & variables///////
|
||||
reg [COUNTER_WIDTH-1:0] BinaryCount;
|
||||
|
||||
/////////Code///////////////////////
|
||||
|
||||
always @ (posedge Clk)
|
||||
if (Clear_in) begin
|
||||
BinaryCount <= {COUNTER_WIDTH{1'b 0}} + 1; //Gray count begins @ '1' with
|
||||
GrayCount_out <= {COUNTER_WIDTH{1'b 0}}; // first 'Enable_in'.
|
||||
end
|
||||
else if (Enable_in) begin
|
||||
BinaryCount <= BinaryCount + 1;
|
||||
GrayCount_out <= {BinaryCount[COUNTER_WIDTH-1],
|
||||
BinaryCount[COUNTER_WIDTH-2:0] ^ BinaryCount[COUNTER_WIDTH-1:1]};
|
||||
end
|
||||
|
||||
endmodule
|
621
lm32/logic/sakc/rtl/wb_ddr/wb_ddr.v
Normal file
621
lm32/logic/sakc/rtl/wb_ddr/wb_ddr.v
Normal file
@ -0,0 +1,621 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// Wishbone DDR Controller
|
||||
//
|
||||
// (c) Joerg Bornschein (<jb@capsec.org>)
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
`include "ddr_include.v"
|
||||
|
||||
module wb_ddr
|
||||
#(
|
||||
parameter clk_freq = 100000000,
|
||||
parameter clk_multiply = 12,
|
||||
parameter clk_divide = 5,
|
||||
parameter phase_shift = 0,
|
||||
parameter wait200_init = 26
|
||||
) (
|
||||
input clk,
|
||||
input reset,
|
||||
// DDR ports
|
||||
output [2:0] ddr_clk,
|
||||
output [2:0] ddr_clk_n,
|
||||
input ddr_clk_fb,
|
||||
output ddr_ras_n,
|
||||
output ddr_cas_n,
|
||||
output ddr_we_n,
|
||||
output [1:0] ddr_cke,
|
||||
output [1:0] ddr_cs_n,
|
||||
output [ `A_RNG] ddr_a,
|
||||
output [ `BA_RNG] ddr_ba,
|
||||
inout [ `DQ_RNG] ddr_dq,
|
||||
inout [`DQS_RNG] ddr_dqs,
|
||||
output [ `DM_RNG] ddr_dm,
|
||||
// Wishbone Slave Interface
|
||||
input [`WB_ADR_RNG] wb_adr_i,
|
||||
input [`WB_DAT_RNG] wb_dat_i,
|
||||
output reg [`WB_DAT_RNG] wb_dat_o,
|
||||
input [`WB_SEL_RNG] wb_sel_i,
|
||||
input wb_cyc_i,
|
||||
input wb_stb_i,
|
||||
input wb_we_i,
|
||||
output reg wb_ack_o,
|
||||
// XXX Temporary DCM control input XXX
|
||||
output ps_ready,
|
||||
input ps_up,
|
||||
input ps_down,
|
||||
// XXX probe wires XXX
|
||||
output probe_clk,
|
||||
input [7:0] probe_sel,
|
||||
output reg [7:0] probe
|
||||
);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Wishbone handling
|
||||
//----------------------------------------------------------------------------
|
||||
wire wb_rd = wb_stb_i & wb_cyc_i & ~wb_we_i;
|
||||
wire wb_wr = wb_stb_i & wb_cyc_i & wb_we_i;
|
||||
|
||||
wire [`WB_WORD_RNG] wb_adr_word = wb_adr_i[`WB_WORD_RNG]; // word in bufferline
|
||||
wire [`WB_SET_RNG] wb_adr_set = wb_adr_i[`WB_SET_RNG]; // index into wayX_ram
|
||||
wire [`WB_TAG_RNG] wb_adr_tag = wb_adr_i[`WB_TAG_RNG]; // more significant bits
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// TAG RAM (2-way set assioziative)
|
||||
//----------------------------------------------------------------------------
|
||||
wire [`TAG_LINE_RNG] tag_load;
|
||||
wire [`TAG_LINE_RNG] tag_store;
|
||||
wire tag_we;
|
||||
|
||||
wire [`WB_TAG_RNG] tag_load_set0 = tag_load[`TAG_LINE_TAG0_RNG];
|
||||
wire [`WB_TAG_RNG] tag_load_set1 = tag_load[`TAG_LINE_TAG1_RNG];
|
||||
wire tag_load_dirty0 = tag_load[`TAG_LINE_DIRTY0_RNG];
|
||||
wire tag_load_dirty1 = tag_load[`TAG_LINE_DIRTY1_RNG];
|
||||
wire tag_load_lru = tag_load[`TAG_LINE_LRU_RNG];
|
||||
|
||||
reg [`WB_TAG_RNG] tag_store_set0;
|
||||
reg [`WB_TAG_RNG] tag_store_set1;
|
||||
reg tag_store_dirty0;
|
||||
reg tag_store_dirty1;
|
||||
reg tag_store_lru;
|
||||
|
||||
assign tag_store[`TAG_LINE_TAG0_RNG] = tag_store_set0;
|
||||
assign tag_store[`TAG_LINE_TAG1_RNG] = tag_store_set1;
|
||||
assign tag_store[`TAG_LINE_DIRTY0_RNG] = tag_store_dirty0;
|
||||
assign tag_store[`TAG_LINE_DIRTY1_RNG] = tag_store_dirty1;
|
||||
assign tag_store[`TAG_LINE_LRU_RNG] = tag_store_lru;
|
||||
|
||||
wire [`WB_SET_RNG] ls_tag_adr;
|
||||
wire [`TAG_LINE_RNG] ls_tag_load;
|
||||
reg [`TAG_LINE_RNG] ls_tag_store;
|
||||
reg ls_tag_we;
|
||||
|
||||
dpram #(
|
||||
.adr_width( 7 ),
|
||||
.dat_width( 33 )
|
||||
) tag_ram (
|
||||
.clk ( clk ),
|
||||
//
|
||||
.adr0( wb_adr_set ),
|
||||
.dout0( tag_load ),
|
||||
.din0( tag_store ),
|
||||
.we0( tag_we ),
|
||||
//
|
||||
.adr1( ls_tag_adr ),
|
||||
.dout1( ls_tag_load ),
|
||||
.din1( ls_tag_store ),
|
||||
.we1( ls_tag_we )
|
||||
);
|
||||
|
||||
wire tag_load_match0 = (tag_load_set0 == wb_adr_tag);
|
||||
wire tag_load_match1 = (tag_load_set1 == wb_adr_tag);
|
||||
wire tag_load_match = tag_load_match0 | tag_load_match1;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Buffer cache ram (2 ways)
|
||||
//----------------------------------------------------------------------------
|
||||
wire [8:0] wayX_adr = { wb_adr_set, wb_adr_word };
|
||||
|
||||
wire [`WAY_LINE_RNG] way0_load, way1_load;
|
||||
wire [`WAY_LINE_RNG] wayX_store;
|
||||
|
||||
wire [31:0] way0_load_dat = way0_load[`WAY_DAT_RNG];
|
||||
wire [31:0] way1_load_dat = way1_load[`WAY_DAT_RNG];
|
||||
wire [3:0] way0_load_valid = way0_load[`WAY_VALID_RNG];
|
||||
wire [3:0] way1_load_valid = way1_load[`WAY_VALID_RNG];
|
||||
|
||||
wire way0_we;
|
||||
wire way1_we;
|
||||
reg [31:0] wayX_store_dat;
|
||||
reg [3:0] wayX_store_valid;
|
||||
|
||||
assign wayX_store[`WAY_DAT_RNG] = wayX_store_dat;
|
||||
assign wayX_store[`WAY_VALID_RNG] = wayX_store_valid;
|
||||
|
||||
wire [8:0] ls_wayX_adr;
|
||||
wire [`WAY_LINE_RNG] ls_way0_load;
|
||||
wire [`WAY_LINE_RNG] ls_way1_load;
|
||||
wire [`WAY_LINE_RNG] ls_wayX_store;
|
||||
wire ls_way0_we;
|
||||
wire ls_way1_we;
|
||||
reg ls_wayX_we;
|
||||
|
||||
wire way0_sel_valid = ( (~way0_load_valid & wb_sel_i) == 'b0);
|
||||
wire way1_sel_valid = ( (~way1_load_valid & wb_sel_i) == 'b0);
|
||||
wire wayX_sel_valid = (tag_load_match0) ? way0_sel_valid : way1_sel_valid;
|
||||
|
||||
// synthesis attribute ram_style of way0_ram is block
|
||||
dpram #(
|
||||
.adr_width( 9 ),
|
||||
.dat_width( 36 )
|
||||
) way0_ram (
|
||||
.clk( clk ),
|
||||
//
|
||||
.adr0( wayX_adr ),
|
||||
.dout0( way0_load ),
|
||||
.din0( wayX_store ),
|
||||
.we0( way0_we ),
|
||||
//
|
||||
.adr1( ls_wayX_adr ),
|
||||
.dout1( ls_way0_load ),
|
||||
.we1( ls_way0_we ),
|
||||
.din1( ls_wayX_store )
|
||||
);
|
||||
|
||||
// synthesis attribute ram_style of way1_ram is block
|
||||
dpram #(
|
||||
.adr_width( 9 ),
|
||||
.dat_width( 36 )
|
||||
) way1_ram (
|
||||
.clk( clk ),
|
||||
//
|
||||
.adr0( wayX_adr ),
|
||||
.dout0( way1_load ),
|
||||
.din0( wayX_store ),
|
||||
.we0( way1_we ),
|
||||
//
|
||||
.adr1( ls_wayX_adr ),
|
||||
.dout1( ls_way1_load ),
|
||||
.we1( ls_way1_we ),
|
||||
.din1( ls_wayX_store )
|
||||
);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Write/update buffer cache from wishbone side
|
||||
//----------------------------------------------------------------------------
|
||||
wire store_to_way0 = tag_load_lru & ~tag_load_dirty0; // store new data into way0? XXX spill_done XXX
|
||||
wire store_to_way1 = ~tag_load_lru & ~tag_load_dirty1; // store new data into way1? XXX spill_done XXX
|
||||
wire store_to_way = store_to_way0 | store_to_way1;
|
||||
|
||||
reg update_lru0; //
|
||||
reg update_lru1;
|
||||
|
||||
reg update_way0; //
|
||||
reg update_way1;
|
||||
|
||||
assign way0_we = update_way0;
|
||||
assign way1_we = update_way1;
|
||||
assign tag_we = way0_we | way1_we | update_lru0 | update_lru1;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// MUX wayX_store input
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
integer i;
|
||||
always @(*)
|
||||
begin
|
||||
/*
|
||||
for(i=0; i<4; i=i+1) begin
|
||||
if (wb_sel_i[i]) begin
|
||||
wayX_store_dat[8*i+7:8*i] = wb_dat_i[8*i+7:8*i];
|
||||
wayX_store_valid[i] = 1;
|
||||
end else if (update_way0) begin
|
||||
wayX_store_dat[8*i+7:8*i] = way0_load_dat[8*i+7:8*i];
|
||||
wayX_store_valid[i] = way0_load_valid[i];
|
||||
end else begin
|
||||
wayX_store_dat[8*i+7:8*i] = way1_load_dat[8*i+7:8*i];
|
||||
wayX_store_valid[i] = way1_load_valid[i];
|
||||
end
|
||||
end
|
||||
*/
|
||||
|
||||
if (wb_sel_i[0]) begin
|
||||
wayX_store_dat[8*0+7:8*0] = wb_dat_i[8*0+7:8*0];
|
||||
wayX_store_valid[0] = 1;
|
||||
end else if (update_way0) begin
|
||||
wayX_store_dat[8*0+7:8*0] = way0_load_dat[8*0+7:8*0];
|
||||
wayX_store_valid[0] = way0_load_valid[0];
|
||||
end else begin
|
||||
wayX_store_dat[8*0+7:8*0] = way1_load_dat[8*0+7:8*0];
|
||||
wayX_store_valid[0] = way1_load_valid[0];
|
||||
end
|
||||
|
||||
if (wb_sel_i[1]) begin
|
||||
wayX_store_dat[8*1+7:8*1] = wb_dat_i[8*1+7:8*1];
|
||||
wayX_store_valid[1] = 1;
|
||||
end else if (update_way0) begin
|
||||
wayX_store_dat[8*1+7:8*1] = way0_load_dat[8*1+7:8*1];
|
||||
wayX_store_valid[1] = way0_load_valid[1];
|
||||
end else begin
|
||||
wayX_store_dat[8*1+7:8*1] = way1_load_dat[8*1+7:8*1];
|
||||
wayX_store_valid[1] = way1_load_valid[1];
|
||||
end
|
||||
|
||||
if (wb_sel_i[2]) begin
|
||||
wayX_store_dat[8*2+7:8*2] = wb_dat_i[8*2+7:8*2];
|
||||
wayX_store_valid[2] = 1;
|
||||
end else if (update_way0) begin
|
||||
wayX_store_dat[8*2+7:8*2] = way0_load_dat[8*2+7:8*2];
|
||||
wayX_store_valid[2] = way0_load_valid[2];
|
||||
end else begin
|
||||
wayX_store_dat[8*2+7:8*2] = way1_load_dat[8*2+7:8*2];
|
||||
wayX_store_valid[2] = way1_load_valid[2];
|
||||
end
|
||||
|
||||
if (wb_sel_i[3]) begin
|
||||
wayX_store_dat[8*3+7:8*3] = wb_dat_i[8*3+7:8*3];
|
||||
wayX_store_valid[3] = 1;
|
||||
end else if (update_way0) begin
|
||||
wayX_store_dat[8*3+7:8*3] = way0_load_dat[8*3+7:8*3];
|
||||
wayX_store_valid[3] = way0_load_valid[3];
|
||||
end else begin
|
||||
wayX_store_dat[8*3+7:8*3] = way1_load_dat[8*3+7:8*3];
|
||||
wayX_store_valid[3] = way1_load_valid[3];
|
||||
end
|
||||
end
|
||||
|
||||
always @(*)
|
||||
begin
|
||||
if (update_way0) begin
|
||||
tag_store_set0 = wb_adr_tag;
|
||||
tag_store_dirty0 = 1;
|
||||
end else begin
|
||||
tag_store_set0 = tag_load_set0;
|
||||
tag_store_dirty0 = tag_load_dirty0;
|
||||
end
|
||||
|
||||
if (update_way1) begin
|
||||
tag_store_set1 = wb_adr_tag;
|
||||
tag_store_dirty1 = 1;
|
||||
end else begin
|
||||
tag_store_set1 = tag_load_set1;
|
||||
tag_store_dirty1 = tag_load_dirty1;
|
||||
end
|
||||
|
||||
if (update_lru0)
|
||||
tag_store_lru = 0;
|
||||
else if (update_lru1)
|
||||
tag_store_lru = 1;
|
||||
else
|
||||
tag_store_lru = tag_load_lru;
|
||||
end
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Wishbone FSM
|
||||
//----------------------------------------------------------------------------
|
||||
reg ls_fill;
|
||||
reg ls_spill;
|
||||
reg ls_way;
|
||||
wire ls_busy;
|
||||
|
||||
reg [`WB_TAG_RNG] ls_adr_tag;
|
||||
reg [`WB_SET_RNG] ls_adr_set;
|
||||
reg [`WB_WORD_RNG] ls_adr_word;
|
||||
|
||||
reg [2:0] state;
|
||||
|
||||
parameter s_idle = 0;
|
||||
parameter s_read = 1;
|
||||
parameter s_rspill = 2;
|
||||
parameter s_rfill = 3;
|
||||
parameter s_write = 4;
|
||||
parameter s_wspill = 5;
|
||||
|
||||
// Syncronous part of FSM
|
||||
always @(posedge clk)
|
||||
begin
|
||||
if (reset) begin
|
||||
state <= s_idle;
|
||||
ls_spill <= 0;
|
||||
ls_fill <= 0;
|
||||
ls_way <= 0;
|
||||
end else begin
|
||||
ls_fill <= 0;
|
||||
ls_spill <= 0;
|
||||
|
||||
case (state)
|
||||
s_idle: begin
|
||||
if (wb_rd)
|
||||
state <= s_read;
|
||||
|
||||
if (wb_wr)
|
||||
state <= s_write;
|
||||
end
|
||||
s_read: begin
|
||||
if ((tag_load_match0 & way0_sel_valid) | (tag_load_match1 & way1_sel_valid)) begin
|
||||
state <= s_idle;
|
||||
end else if (store_to_way & ~ls_busy) begin
|
||||
state <= s_rfill;
|
||||
ls_fill <= 1;
|
||||
ls_way <= ~tag_load_lru;
|
||||
ls_adr_tag <= wb_adr_tag;
|
||||
ls_adr_set <= wb_adr_set;
|
||||
end else if (~ls_busy) begin
|
||||
state <= s_rspill;
|
||||
ls_spill <= 1;
|
||||
ls_way <= ~tag_load_lru;
|
||||
ls_adr_set <= wb_adr_set;
|
||||
if (tag_load_lru == 1)
|
||||
ls_adr_tag <= tag_load_set0;
|
||||
else
|
||||
ls_adr_tag <= tag_load_set1;
|
||||
end
|
||||
end
|
||||
s_rspill: begin
|
||||
if (~ls_busy) begin
|
||||
state <= s_rfill;
|
||||
ls_fill <= 1;
|
||||
ls_way <= ~tag_load_lru;
|
||||
ls_adr_tag <= wb_adr_tag;
|
||||
ls_adr_set <= wb_adr_set;
|
||||
end
|
||||
end
|
||||
s_rfill: begin
|
||||
if (tag_load_match & wayX_sel_valid)
|
||||
state <= s_idle;
|
||||
end
|
||||
s_write: begin
|
||||
if (tag_load_match | store_to_way) begin
|
||||
state <= s_idle;
|
||||
end else if (~ls_busy) begin
|
||||
state <= s_wspill;
|
||||
ls_spill <= 1;
|
||||
ls_way <= ~tag_load_lru;
|
||||
ls_adr_set <= wb_adr_set;
|
||||
if (tag_load_lru == 1)
|
||||
ls_adr_tag <= tag_load_set0;
|
||||
else
|
||||
ls_adr_tag <= tag_load_set1;
|
||||
end
|
||||
end
|
||||
s_wspill: begin
|
||||
if (tag_load_match | store_to_way) begin
|
||||
state <= s_idle;
|
||||
end
|
||||
end
|
||||
default:
|
||||
state <= s_idle;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
// Asyncronous part of FSM
|
||||
always @(*)
|
||||
begin
|
||||
update_lru0 <= 0;
|
||||
update_lru1 <= 0;
|
||||
update_way0 <= 0;
|
||||
update_way1 <= 0;
|
||||
wb_dat_o <= 0;
|
||||
wb_ack_o <= 0;
|
||||
|
||||
case (state)
|
||||
s_idle: begin end
|
||||
s_read: begin
|
||||
if (tag_load_match0 & way0_sel_valid) begin
|
||||
update_lru0 <= 1;
|
||||
wb_dat_o <= way0_load_dat;
|
||||
wb_ack_o <= 1;
|
||||
end else if (tag_load_match1 & way1_sel_valid) begin
|
||||
update_lru1 <= 1;
|
||||
wb_dat_o <= way1_load_dat;
|
||||
wb_ack_o <= 1;
|
||||
end
|
||||
end
|
||||
s_write: begin
|
||||
if (tag_load_match0 | store_to_way0) begin
|
||||
update_lru0 <= 1;
|
||||
update_way0 <= 1;
|
||||
wb_ack_o <= 1;
|
||||
end else if (tag_load_match1 | store_to_way1) begin
|
||||
update_lru1 <= 1;
|
||||
update_way1 <= 1;
|
||||
wb_ack_o <= 1;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// DDR Controller Engine (including clkgen, [rw]-path)
|
||||
//----------------------------------------------------------------------------
|
||||
reg fml_rd;
|
||||
reg fml_wr;
|
||||
wire fml_done;
|
||||
wire [`FML_ADR_RNG] fml_adr;
|
||||
wire [`FML_DAT_RNG] fml_wdat;
|
||||
wire [`FML_BE_RNG] fml_wbe;
|
||||
reg fml_wnext;
|
||||
reg fml_wnext2;
|
||||
wire fml_rempty;
|
||||
reg fml_rnext;
|
||||
wire [`FML_DAT_RNG] fml_rdat;
|
||||
|
||||
ddr_ctrl #(
|
||||
.phase_shift( phase_shift ),
|
||||
.clk_multiply( clk_multiply ),
|
||||
.clk_divide( clk_divide ),
|
||||
.wait200_init( wait200_init )
|
||||
) ctrl0 (
|
||||
.clk( clk ),
|
||||
.reset( reset ),
|
||||
// DDR Ports
|
||||
.ddr_clk( ddr_clk ),
|
||||
.ddr_clk_n( ddr_clk_n ),
|
||||
.ddr_clk_fb( ddr_clk_fb ),
|
||||
.ddr_ras_n( ddr_ras_n ),
|
||||
.ddr_cas_n( ddr_cas_n ),
|
||||
.ddr_we_n( ddr_we_n ),
|
||||
.ddr_cke( ddr_cke ),
|
||||
.ddr_cs_n( ddr_cs_n ),
|
||||
.ddr_a( ddr_a ),
|
||||
.ddr_ba( ddr_ba ),
|
||||
.ddr_dq( ddr_dq ),
|
||||
.ddr_dqs( ddr_dqs ),
|
||||
.ddr_dm( ddr_dm ),
|
||||
// FML (FastMemoryLink)
|
||||
.fml_rd( fml_rd ),
|
||||
.fml_wr( fml_wr ),
|
||||
.fml_done( fml_done ),
|
||||
.fml_adr( fml_adr ),
|
||||
.fml_wdat( fml_wdat ),
|
||||
.fml_wbe( fml_wbe ),
|
||||
.fml_wnext( fml_wnext2 ),
|
||||
.fml_rempty( fml_rempty ),
|
||||
.fml_rdat( fml_rdat ),
|
||||
.fml_rnext( fml_rnext ),
|
||||
// DCM phase shift control
|
||||
.ps_ready( ps_ready ),
|
||||
.ps_up( ps_up ),
|
||||
.ps_down( ps_down )
|
||||
);
|
||||
|
||||
assign fml_adr = { ls_adr_tag, ls_adr_set };
|
||||
|
||||
assign fml_wdat = (ls_way) ? ls_way1_load[`WAY_DAT_RNG] :
|
||||
ls_way0_load[`WAY_DAT_RNG];
|
||||
|
||||
assign fml_wbe = (ls_way) ? ls_way1_load[`WAY_VALID_RNG] :
|
||||
ls_way0_load[`WAY_VALID_RNG];
|
||||
|
||||
assign ls_tag_adr = { ls_adr_set };
|
||||
assign ls_wayX_adr = { ls_adr_set, ls_adr_word };
|
||||
assign ls_way0_we = ls_wayX_we & ~ls_way;
|
||||
assign ls_way1_we = ls_wayX_we & ls_way;
|
||||
|
||||
assign ls_wayX_store[`WAY_DAT_RNG] = fml_rdat;
|
||||
assign ls_wayX_store[`WAY_VALID_RNG] = 4'b1111;
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// LS (Load and Store) Engine
|
||||
//----------------------------------------------------------------------------
|
||||
parameter l_idle = 0;
|
||||
parameter l_fill = 1;
|
||||
parameter l_spill = 2;
|
||||
parameter l_waitdone = 3;
|
||||
|
||||
reg [2:0] ls_state;
|
||||
assign ls_busy = (ls_state != l_idle) || ls_fill || ls_spill;
|
||||
|
||||
// Syncronous part FSM
|
||||
always @(posedge clk)
|
||||
begin
|
||||
if (reset) begin
|
||||
ls_state <= l_idle;
|
||||
ls_adr_word <= 0;
|
||||
fml_wr <= 0;
|
||||
fml_rd <= 0;
|
||||
end else begin
|
||||
fml_wnext2 <= fml_wnext;
|
||||
|
||||
case (ls_state)
|
||||
l_idle: begin
|
||||
ls_adr_word <= 0;
|
||||
|
||||
if (ls_spill) begin
|
||||
ls_state <= l_spill;
|
||||
ls_adr_word <= ls_adr_word + 1;
|
||||
end
|
||||
if (ls_fill) begin
|
||||
ls_state <= l_fill;
|
||||
fml_rd <= 1;
|
||||
end
|
||||
end
|
||||
l_spill: begin
|
||||
ls_adr_word <= ls_adr_word + 1;
|
||||
|
||||
if (ls_adr_word == 3) begin
|
||||
ls_state <= l_waitdone;
|
||||
fml_wr <= 1;
|
||||
end
|
||||
end
|
||||
l_waitdone: begin
|
||||
ls_adr_word <= 0;
|
||||
|
||||
if (fml_done) begin
|
||||
ls_state <= l_idle;
|
||||
fml_wr <= 0;
|
||||
end
|
||||
end
|
||||
l_fill: begin
|
||||
if (fml_done)
|
||||
fml_rd <= 0;
|
||||
|
||||
if (~fml_rempty)
|
||||
ls_adr_word <= ls_adr_word + 1;
|
||||
|
||||
if (~fml_rempty & (ls_adr_word == 3))
|
||||
ls_state <= l_idle;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
always @(*)
|
||||
begin
|
||||
fml_wnext <= 0;
|
||||
fml_rnext <= 0;
|
||||
ls_tag_we <= 0;
|
||||
ls_tag_store <= ls_tag_load;
|
||||
ls_wayX_we <= 0;
|
||||
|
||||
case (ls_state)
|
||||
l_idle: begin
|
||||
if (ls_spill) begin
|
||||
fml_wnext <= 1;
|
||||
end
|
||||
end
|
||||
l_spill: begin
|
||||
fml_wnext <= 1;
|
||||
end
|
||||
l_waitdone: begin
|
||||
if (ls_way == 0)
|
||||
ls_tag_store[`TAG_LINE_DIRTY0_RNG] <= 0;
|
||||
else
|
||||
ls_tag_store[`TAG_LINE_DIRTY1_RNG] <= 0;
|
||||
|
||||
if (fml_done)
|
||||
ls_tag_we <= 1;
|
||||
end
|
||||
l_fill: begin
|
||||
if (ls_way == 0) begin
|
||||
ls_tag_store[`TAG_LINE_DIRTY0_RNG] <= 0;
|
||||
ls_tag_store[`TAG_LINE_TAG0_RNG] <= ls_adr_tag;
|
||||
end else begin
|
||||
ls_tag_store[`TAG_LINE_DIRTY1_RNG] <= 0;
|
||||
ls_tag_store[`TAG_LINE_TAG1_RNG] <= ls_adr_tag;
|
||||
end
|
||||
|
||||
if (~fml_rempty) begin
|
||||
ls_wayX_we <= 1;
|
||||
fml_rnext <= 1;
|
||||
end
|
||||
|
||||
if (~fml_rempty & (ls_adr_word == 3))
|
||||
ls_tag_we <= 1;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
if (ls_fill)
|
||||
$display ("At time %t WB_DDR fill cacheline: TAG = %h, SET = %h)", $time, ls_adr_tag, ls_adr_set);
|
||||
|
||||
if (ls_spill)
|
||||
$display ("At time %t WB_DDR spill cacheline: TAG = %h, SET = %h)", $time, ls_adr_tag, ls_adr_set);
|
||||
end
|
||||
|
||||
endmodule
|
77
lm32/logic/sakc/rtl/wb_gpio/wb_gpio.v
Normal file
77
lm32/logic/sakc/rtl/wb_gpio/wb_gpio.v
Normal file
@ -0,0 +1,77 @@
|
||||
//---------------------------------------------------------------------------
|
||||
// Wishbone General Pupose IO Component
|
||||
//
|
||||
// 0x00
|
||||
// 0x10 gpio_in (read-only)
|
||||
// 0x14 gpio_out (read/write)
|
||||
// 0x18 gpio_oe (read/write)
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
module wb_gpio (
|
||||
input clk,
|
||||
input reset,
|
||||
// Wishbone interface
|
||||
input wb_stb_i,
|
||||
input wb_cyc_i,
|
||||
output wb_ack_o,
|
||||
input wb_we_i,
|
||||
input [31:0] wb_adr_i,
|
||||
input [3:0] wb_sel_i,
|
||||
input [31:0] wb_dat_i,
|
||||
output reg [31:0] wb_dat_o,
|
||||
//
|
||||
output intr,
|
||||
// IO Wires
|
||||
input [31:0] gpio_in,
|
||||
output reg [31:0] gpio_out,
|
||||
output reg [31:0] gpio_oe
|
||||
);
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
wire [31:0] gpiocr = 32'b0;
|
||||
|
||||
// Wishbone
|
||||
reg ack;
|
||||
assign wb_ack_o = wb_stb_i & wb_cyc_i & ack;
|
||||
|
||||
wire wb_rd = wb_stb_i & wb_cyc_i & ~wb_we_i;
|
||||
wire wb_wr = wb_stb_i & wb_cyc_i & wb_we_i;
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
if (reset) begin
|
||||
ack <= 0;
|
||||
gpio_out <= 'b0;
|
||||
end else begin
|
||||
// Handle WISHBONE access
|
||||
ack <= 0;
|
||||
|
||||
if (wb_rd & ~ack) begin // read cycle
|
||||
ack <= 1;
|
||||
|
||||
case (wb_adr_i[7:0])
|
||||
'h00: wb_dat_o <= gpiocr;
|
||||
'h10: wb_dat_o <= gpio_in;
|
||||
'h14: wb_dat_o <= gpio_out;
|
||||
'h18: wb_dat_o <= gpio_oe;
|
||||
default: wb_dat_o <= 32'b0;
|
||||
endcase
|
||||
end else if (wb_wr & ~ack ) begin // write cycle
|
||||
ack <= 1;
|
||||
|
||||
case (wb_adr_i[7:0])
|
||||
'h00: begin
|
||||
end
|
||||
'h14: gpio_out <= wb_dat_i;
|
||||
'h18: gpio_oe <= wb_dat_i;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
endmodule
|
101
lm32/logic/sakc/rtl/wb_spi/wb_spi.v
Normal file
101
lm32/logic/sakc/rtl/wb_spi/wb_spi.v
Normal file
@ -0,0 +1,101 @@
|
||||
//-----------------------------------------------------------------
|
||||
// SPI Master
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
module wb_spi(
|
||||
input clk;
|
||||
input reset;
|
||||
// Wishbone bus
|
||||
input [31:0] wb_adr_i;
|
||||
input [31:0] wb_dat_i;
|
||||
output reg [31:0] wb_dat_o;
|
||||
input [ 3:0] wb_sel_i;
|
||||
input wb_cyc_i;
|
||||
input wb_stb_i;
|
||||
output wb_ack_o;
|
||||
input wb_we_i;
|
||||
// SPI
|
||||
output spi_sck;
|
||||
output spi_mosi;
|
||||
input spi_miso;
|
||||
output reg [7:0] spi_cs;
|
||||
);
|
||||
|
||||
|
||||
reg ack;
|
||||
assign wb_ack_o = wb_stb_i & wb_cyc_i & ack;
|
||||
|
||||
wire wb_rd = wb_stb_i & wb_cyc_i & ~ack & ~wb_we_i;
|
||||
wire wb_wr = wb_stb_i & wb_cyc_i & ~ack & wb_we_i;
|
||||
|
||||
|
||||
reg [2:0] bitcount;
|
||||
reg ilatch;
|
||||
reg run;
|
||||
|
||||
reg sck;
|
||||
|
||||
//prescaler registers for sclk
|
||||
reg [7:0] prescaler;
|
||||
reg [7:0] divisor;
|
||||
|
||||
//data shift register
|
||||
reg [7:0] sreg;
|
||||
|
||||
assign spi_sck = sck;
|
||||
assign spi_mosi = sreg[7];
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (reset == 1'b1) begin
|
||||
ack <= 0;
|
||||
sck <= 1'b0;
|
||||
bitcount <= 3'b000;
|
||||
run <= 1'b0;
|
||||
prescaler <= 8'h00;
|
||||
divisor <= 8'hff;
|
||||
end else begin
|
||||
prescaler <= prescaler + 1;
|
||||
if (prescaler == divisor) begin
|
||||
prescaler <= 8'h00;
|
||||
if (run == 1'b1) begin
|
||||
sck <= ~sck;
|
||||
if(sck == 1'b1) begin
|
||||
bitcount <= bitcount + 1;
|
||||
if(bitcount == 3'b111) begin
|
||||
run <= 1'b0;
|
||||
end
|
||||
|
||||
sreg [7:0] <= {sreg[6:0], ilatch};
|
||||
end else begin
|
||||
ilatch <= spi_miso;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
ack <= wb_stb_i & wb_cyc_i;
|
||||
|
||||
if (wb_rd) begin // read cycle
|
||||
case (wb_adr_i[5:2])
|
||||
4'b0000: wb_dat_o <= sreg;
|
||||
4'b0001: wb_dat_o <= {7'b0000000 , run};
|
||||
endcase
|
||||
end
|
||||
|
||||
|
||||
if (wb_wr) begin // write cycle
|
||||
case (wb_adr_i[5:2])
|
||||
4'b0000: begin
|
||||
sreg <= wb_dat_i[7:0];
|
||||
run <= 1'b1;
|
||||
end
|
||||
4'b0010:
|
||||
spi_cs <= wb_dat_i[7:0];
|
||||
4'b0100:
|
||||
divisor <= wb_dat_i[7:0];
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
endmodule
|
163
lm32/logic/sakc/rtl/wb_sram/wb_sram16.v
Normal file
163
lm32/logic/sakc/rtl/wb_sram/wb_sram16.v
Normal file
@ -0,0 +1,163 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// Wishbone SRAM controller
|
||||
//----------------------------------------------------------------------------
|
||||
module wb_sram16 #(
|
||||
parameter adr_width = 18,
|
||||
parameter latency = 0 // 0 .. 7
|
||||
) (
|
||||
input clk,
|
||||
input reset,
|
||||
// Wishbone interface
|
||||
input wb_stb_i,
|
||||
input wb_cyc_i,
|
||||
output reg wb_ack_o,
|
||||
input wb_we_i,
|
||||
input [31:0] wb_adr_i,
|
||||
input [3:0] wb_sel_i,
|
||||
input [31:0] wb_dat_i,
|
||||
output reg [31:0] wb_dat_o,
|
||||
// SRAM connection
|
||||
output reg [adr_width-1:0] sram_adr,
|
||||
inout [15:0] sram_dat,
|
||||
output reg [1:0] sram_be_n, // Byte Enable
|
||||
output reg sram_ce_n, // Chip Enable
|
||||
output reg sram_oe_n, // Output Enable
|
||||
output reg sram_we_n // Write Enable
|
||||
);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
// Wishbone handling
|
||||
wire wb_rd = wb_stb_i & wb_cyc_i & ~wb_we_i & ~wb_ack_o;
|
||||
wire wb_wr = wb_stb_i & wb_cyc_i & wb_we_i & ~wb_ack_o;
|
||||
|
||||
// Translate wishbone address to sram address
|
||||
wire [adr_width-1:0] adr1 = { wb_adr_i[adr_width:2], 1'b0 };
|
||||
wire [adr_width-1:0] adr2 = { wb_adr_i[adr_width:2], 1'b1 };
|
||||
|
||||
// Tri-State-Driver
|
||||
reg [15:0] wdat;
|
||||
reg wdat_oe;
|
||||
|
||||
assign sram_dat = wdat_oe ? wdat : 16'bz;
|
||||
|
||||
|
||||
// Latency countdown
|
||||
reg [2:0] lcount;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// State Machine
|
||||
//----------------------------------------------------------------------------
|
||||
parameter s_idle = 0;
|
||||
parameter s_read1 = 1;
|
||||
parameter s_read2 = 2;
|
||||
parameter s_write1 = 3;
|
||||
parameter s_write2 = 4;
|
||||
parameter s_write3 = 5;
|
||||
|
||||
reg [2:0] state;
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
if (reset) begin
|
||||
state <= s_idle;
|
||||
lcount <= 0;
|
||||
wb_ack_o <= 0;
|
||||
end else begin
|
||||
case (state)
|
||||
s_idle: begin
|
||||
wb_ack_o <= 0;
|
||||
|
||||
if (wb_rd) begin
|
||||
sram_ce_n <= 0;
|
||||
sram_oe_n <= 0;
|
||||
sram_we_n <= 1;
|
||||
sram_adr <= adr1;
|
||||
sram_be_n <= 2'b00;
|
||||
wdat_oe <= 0;
|
||||
lcount <= latency;
|
||||
state <= s_read1;
|
||||
end else if (wb_wr) begin
|
||||
sram_ce_n <= 0;
|
||||
sram_oe_n <= 1;
|
||||
sram_we_n <= 0;
|
||||
sram_adr <= adr1;
|
||||
sram_be_n <= ~wb_sel_i[1:0];
|
||||
wdat <= wb_dat_i[15:0];
|
||||
wdat_oe <= 1;
|
||||
lcount <= latency;
|
||||
state <= s_write1;
|
||||
end else begin
|
||||
sram_ce_n <= 1;
|
||||
sram_oe_n <= 1;
|
||||
sram_we_n <= 1;
|
||||
end
|
||||
end
|
||||
s_read1: begin
|
||||
if (lcount != 0) begin
|
||||
lcount <= lcount - 1;
|
||||
end else begin
|
||||
wb_dat_o[15:0] <= sram_dat;
|
||||
sram_ce_n <= 0;
|
||||
sram_oe_n <= 0;
|
||||
sram_we_n <= 1;
|
||||
sram_adr <= adr2;
|
||||
sram_be_n <= 2'b00;
|
||||
wdat_oe <= 0;
|
||||
lcount <= latency;
|
||||
state <= s_read2;
|
||||
end
|
||||
end
|
||||
s_read2: begin
|
||||
if (lcount != 0) begin
|
||||
lcount <= lcount - 1;
|
||||
end else begin
|
||||
wb_dat_o[31:16] <= sram_dat;
|
||||
wb_ack_o <= 1;
|
||||
sram_ce_n <= 1;
|
||||
sram_oe_n <= 1;
|
||||
sram_we_n <= 1;
|
||||
state <= s_idle;
|
||||
end
|
||||
end
|
||||
s_write1: begin
|
||||
if (lcount != 0) begin
|
||||
lcount <= lcount - 1;
|
||||
end else begin
|
||||
sram_ce_n <= 0;
|
||||
sram_oe_n <= 1;
|
||||
sram_we_n <= 1;
|
||||
state <= s_write2;
|
||||
end
|
||||
end
|
||||
s_write2: begin
|
||||
sram_ce_n <= 0;
|
||||
sram_oe_n <= 1;
|
||||
sram_we_n <= 0;
|
||||
sram_adr <= adr2;
|
||||
sram_be_n <= ~wb_sel_i[3:2];
|
||||
wdat <= wb_dat_i[31:16];
|
||||
wdat_oe <= 1;
|
||||
lcount <= latency;
|
||||
wb_ack_o <= 1;
|
||||
state <= s_write3;
|
||||
end
|
||||
s_write3: begin
|
||||
wb_ack_o <= 0;
|
||||
if (lcount != 0) begin
|
||||
lcount <= lcount - 1;
|
||||
end else begin
|
||||
sram_ce_n <= 1;
|
||||
sram_oe_n <= 1;
|
||||
sram_we_n <= 1;
|
||||
wdat_oe <= 0;
|
||||
state <= s_idle;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
122
lm32/logic/sakc/rtl/wb_sram/wb_sram32.v
Normal file
122
lm32/logic/sakc/rtl/wb_sram/wb_sram32.v
Normal file
@ -0,0 +1,122 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// Wishbone SRAM controller
|
||||
//----------------------------------------------------------------------------
|
||||
module wb_sram32 #(
|
||||
parameter adr_width = 18,
|
||||
parameter latency = 0 // 0 .. 7
|
||||
) (
|
||||
input clk,
|
||||
input reset,
|
||||
// Wishbone interface
|
||||
input wb_stb_i,
|
||||
input wb_cyc_i,
|
||||
output reg wb_ack_o,
|
||||
input wb_we_i,
|
||||
input [31:0] wb_adr_i,
|
||||
input [3:0] wb_sel_i,
|
||||
input [31:0] wb_dat_i,
|
||||
output reg [31:0] wb_dat_o,
|
||||
// SRAM connection
|
||||
output reg [adr_width-1:0] sram_adr,
|
||||
inout [31:0] sram_dat,
|
||||
output reg [3:0] sram_be_n, // Byte Enable
|
||||
output reg sram_ce_n, // Chip Enable
|
||||
output reg sram_oe_n, // Output Enable
|
||||
output reg sram_we_n // Write Enable
|
||||
);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
// Wishbone handling
|
||||
wire wb_rd = wb_stb_i & wb_cyc_i & ~wb_we_i & ~wb_ack_o;
|
||||
wire wb_wr = wb_stb_i & wb_cyc_i & wb_we_i & ~wb_ack_o;
|
||||
|
||||
// Translate wishbone address to sram address
|
||||
wire [adr_width-1:0] adr = wb_adr_i[adr_width+1:2];
|
||||
|
||||
// Tri-State-Driver
|
||||
reg [31:0] wdat;
|
||||
reg wdat_oe;
|
||||
|
||||
assign sram_dat = wdat_oe ? wdat : 32'bz;
|
||||
|
||||
|
||||
// Latency countdown
|
||||
reg [2:0] lcount;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// State Machine
|
||||
//----------------------------------------------------------------------------
|
||||
parameter s_idle = 0;
|
||||
parameter s_read = 1;
|
||||
parameter s_write = 2;
|
||||
|
||||
reg [2:0] state;
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
if (reset) begin
|
||||
state <= s_idle;
|
||||
lcount <= 0;
|
||||
wb_ack_o <= 0;
|
||||
end else begin
|
||||
case (state)
|
||||
s_idle: begin
|
||||
wb_ack_o <= 0;
|
||||
|
||||
if (wb_rd) begin
|
||||
sram_ce_n <= 0;
|
||||
sram_oe_n <= 0;
|
||||
sram_we_n <= 1;
|
||||
sram_adr <= adr;
|
||||
sram_be_n <= 4'b0000;
|
||||
wdat_oe <= 0;
|
||||
lcount <= latency;
|
||||
state <= s_read;
|
||||
end else if (wb_wr) begin
|
||||
sram_ce_n <= 0;
|
||||
sram_oe_n <= 1;
|
||||
sram_we_n <= 0;
|
||||
sram_adr <= adr;
|
||||
sram_be_n <= ~wb_sel_i;
|
||||
wdat <= wb_dat_i;
|
||||
wdat_oe <= 1;
|
||||
lcount <= latency;
|
||||
state <= s_write;
|
||||
end else begin
|
||||
sram_ce_n <= 1;
|
||||
sram_oe_n <= 1;
|
||||
sram_we_n <= 1;
|
||||
wdat_oe <= 0;
|
||||
end
|
||||
end
|
||||
s_read: begin
|
||||
if (lcount != 0) begin
|
||||
lcount <= lcount - 1;
|
||||
end else begin
|
||||
sram_ce_n <= 1;
|
||||
sram_oe_n <= 1;
|
||||
sram_we_n <= 1;
|
||||
wb_dat_o <= sram_dat;
|
||||
wb_ack_o <= 1;
|
||||
state <= s_idle;
|
||||
end
|
||||
end
|
||||
s_write: begin
|
||||
if (lcount != 0) begin
|
||||
lcount <= lcount - 1;
|
||||
end else begin
|
||||
sram_ce_n <= 1;
|
||||
sram_oe_n <= 1;
|
||||
sram_we_n <= 1;
|
||||
wb_ack_o <= 1; // XXX We could acknoledge write XXX
|
||||
state <= s_idle; // XXX requests 1 cycle ahead XXX
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
144
lm32/logic/sakc/rtl/wb_timer/wb_timer.v
Normal file
144
lm32/logic/sakc/rtl/wb_timer/wb_timer.v
Normal file
@ -0,0 +1,144 @@
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Wishbone Timer
|
||||
//
|
||||
// Register Description:
|
||||
//
|
||||
// 0x00 TCR0
|
||||
// 0x04 COMPARE0
|
||||
// 0x08 COUNTER0
|
||||
// 0x0C TCR1
|
||||
// 0x10 COMPARE1
|
||||
// 0x14 COUNTER1
|
||||
//
|
||||
// TCRx:
|
||||
// +-------------------+-------+-------+-------+-------+
|
||||
// | 28'b0 | EN | AR | IRQEN | TRIG |
|
||||
// +-------------------+-------+-------+-------+-------+
|
||||
//
|
||||
// EN i (rw) if set to '1', COUNTERX counts upwards until it reaches
|
||||
// COMPAREX
|
||||
// AR (rw) AutoRecwstartload -- if COUNTER reaches COMPAREX, shall we
|
||||
// restart at 1, or disable this counter?
|
||||
// IRQEN (rw) Indicate interrupt condition when triggered?
|
||||
// TRIG (ro)
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
module wb_timer #(
|
||||
parameter clk_freq = 50000000
|
||||
) (
|
||||
input clk,
|
||||
input reset,
|
||||
// Wishbone interface
|
||||
input wb_stb_i,
|
||||
input wb_cyc_i,
|
||||
output wb_ack_o,
|
||||
input wb_we_i,
|
||||
input [31:0] wb_adr_i,
|
||||
input [3:0] wb_sel_i,
|
||||
input [31:0] wb_dat_i,
|
||||
output reg [31:0] wb_dat_o,
|
||||
//
|
||||
output [1:0] intr
|
||||
);
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
reg irqen0, irqen1;
|
||||
reg trig0, trig1;
|
||||
reg en0, en1;
|
||||
reg ar0, ar1;
|
||||
|
||||
wire [31:0] tcr0 = { 28'b0, en0, ar0, irqen0, trig0 };
|
||||
wire [31:0] tcr1 = { 28'b0, en1, ar1, irqen1, trig1 };
|
||||
|
||||
reg [31:0] counter0;
|
||||
reg [31:0] counter1;
|
||||
|
||||
reg [31:0] compare0;
|
||||
reg [31:0] compare1;
|
||||
|
||||
wire match0 = (counter0 == compare0);
|
||||
wire match1 = (counter1 == compare1);
|
||||
|
||||
assign intr = { trig1, trig0 };
|
||||
|
||||
reg ack;
|
||||
assign wb_ack_o = wb_stb_i & wb_cyc_i & ack;
|
||||
|
||||
wire wb_rd = wb_stb_i & wb_cyc_i & ~wb_we_i;
|
||||
wire wb_wr = wb_stb_i & wb_cyc_i & wb_we_i;
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
if (reset) begin
|
||||
ack <= 0;
|
||||
en0 <= 0;
|
||||
en1 <= 0;
|
||||
ar0 <= 0;
|
||||
ar1 <= 0;
|
||||
trig0 <= 0;
|
||||
trig1 <= 0;
|
||||
counter0 <= 0;
|
||||
counter1 <= 0;
|
||||
compare0 <= 32'hFFFFFFFF;
|
||||
compare1 <= 32'hFFFFFFFF;
|
||||
end else begin
|
||||
|
||||
// Handle counter 0
|
||||
if ( en0 & ~match0) counter0 <= counter0 + 1;
|
||||
if ( en0 & match0) trig0 <= 1;
|
||||
if ( ar0 & match0) counter0 <= 1;
|
||||
if (~ar0 & match0) en0 <= 0;
|
||||
|
||||
// Handle counter 1
|
||||
if ( en1 & ~match1) counter1 <= counter1 + 1;
|
||||
if ( en1 & match1) trig1 <= 1;
|
||||
if ( ar1 & match1) counter1 <= 1;
|
||||
if (~ar1 & match1) en1 <= 0;
|
||||
|
||||
// Handle WISHBONE access
|
||||
ack <= 0;
|
||||
|
||||
if (wb_rd & ~ack) begin // read cycle
|
||||
ack <= 1;
|
||||
|
||||
case (wb_adr_i[7:0])
|
||||
'h00: wb_dat_o <= tcr0;
|
||||
'h04: wb_dat_o <= compare0;
|
||||
'h08: wb_dat_o <= counter0;
|
||||
'h0c: wb_dat_o <= tcr1;
|
||||
'h10: wb_dat_o <= compare1;
|
||||
'h14: wb_dat_o <= counter1;
|
||||
default: wb_dat_o <= 32'b0;
|
||||
endcase
|
||||
end else if (wb_wr & ~ack ) begin // write cycle
|
||||
ack <= 1;
|
||||
|
||||
case (wb_adr_i[7:0])
|
||||
'h00: begin
|
||||
trig0 <= 0;
|
||||
irqen0 <= wb_dat_i[1];
|
||||
ar0 <= wb_dat_i[2];
|
||||
en0 <= wb_dat_i[3];
|
||||
end
|
||||
'h04: compare0 <= wb_dat_i;
|
||||
'h08: counter0 <= wb_dat_i;
|
||||
'h0c: begin
|
||||
trig1 <= 0;
|
||||
irqen1 <= wb_dat_i[1];
|
||||
ar1 <= wb_dat_i[2];
|
||||
en1 <= wb_dat_i[3];
|
||||
end
|
||||
'h10: compare1 <= wb_dat_i;
|
||||
'h14: counter1 <= wb_dat_i;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
endmodule
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user