mirror of
git://projects.qi-hardware.com/nn-usb-fpga.git
synced 2025-04-21 12:27:27 +03:00
Adding lm32 demo to SAKC project
This commit is contained in:
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
|
||||
160
lm32/logic/sakc/rtl/wb_uart/uart.v
Normal file
160
lm32/logic/sakc/rtl/wb_uart/uart.v
Normal file
@@ -0,0 +1,160 @@
|
||||
//-----------------------------------------------------
|
||||
// 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;
|
||||
tx_count16 <= 0;
|
||||
end else begin
|
||||
if (tx_wr && !tx_busy) begin
|
||||
txd_reg <= tx_data;
|
||||
tx_bitcount <= 0;
|
||||
tx_count16 <= 0;
|
||||
tx_busy <= 1;
|
||||
end
|
||||
|
||||
if (enable16) begin
|
||||
tx_count16 <= tx_count16 + 1;
|
||||
|
||||
if ((tx_count16 == 0) && tx_busy) begin
|
||||
tx_bitcount <= tx_bitcount + 1;
|
||||
|
||||
if (tx_bitcount == 0) begin
|
||||
uart_txd <= 'b0;
|
||||
end else if (tx_bitcount == 9) begin
|
||||
uart_txd <= 'b1;
|
||||
end else if (tx_bitcount == 10) begin
|
||||
tx_bitcount <= 0;
|
||||
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
|
||||
114
lm32/logic/sakc/rtl/wb_uart/wb_uart.v
Normal file
114
lm32/logic/sakc/rtl/wb_uart/wb_uart.v
Normal file
@@ -0,0 +1,114 @@
|
||||
//---------------------------------------------------------------------------
|
||||
// Wishbone UART
|
||||
//
|
||||
// Register Description:
|
||||
//
|
||||
// 0x00 UCR [ 0 | 0 | 0 | tx_busy | 0 | 0 | rx_error | rx_avail ]
|
||||
// 0x04 DATA
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
module wb_uart #(
|
||||
parameter clk_freq = 50000000,
|
||||
parameter baud = 115200
|
||||
) (
|
||||
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,
|
||||
// Serial Wires
|
||||
input uart_rxd,
|
||||
output uart_txd
|
||||
);
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Actual UART engine
|
||||
//---------------------------------------------------------------------------
|
||||
wire [7:0] rx_data;
|
||||
wire rx_avail;
|
||||
wire rx_error;
|
||||
reg rx_ack;
|
||||
wire [7:0] tx_data;
|
||||
reg tx_wr;
|
||||
wire tx_busy;
|
||||
|
||||
uart #(
|
||||
.freq_hz( clk_freq ),
|
||||
.baud( baud )
|
||||
) uart0 (
|
||||
.clk( clk ),
|
||||
.reset( reset ),
|
||||
//
|
||||
.uart_rxd( uart_rxd ),
|
||||
.uart_txd( uart_txd ),
|
||||
//
|
||||
.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 )
|
||||
);
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
wire [7:0] ucr = { 3'b0, tx_busy, 2'b0, rx_error, rx_avail };
|
||||
|
||||
wire wb_rd = wb_stb_i & wb_cyc_i & ~wb_we_i;
|
||||
wire wb_wr = wb_stb_i & wb_cyc_i & wb_we_i & wb_sel_i[0];
|
||||
|
||||
reg ack;
|
||||
|
||||
assign wb_ack_o = wb_stb_i & wb_cyc_i & ack;
|
||||
|
||||
assign tx_data = wb_dat_i[7:0];
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
if (reset) begin
|
||||
wb_dat_o[31:8] <= 24'b0;
|
||||
tx_wr <= 0;
|
||||
rx_ack <= 0;
|
||||
ack <= 0;
|
||||
end else begin
|
||||
wb_dat_o[31:8] <= 24'b0;
|
||||
tx_wr <= 0;
|
||||
rx_ack <= 0;
|
||||
ack <= 0;
|
||||
|
||||
if (wb_rd & ~ack) begin
|
||||
ack <= 1;
|
||||
|
||||
case (wb_adr_i[3:2])
|
||||
2'b00: begin
|
||||
wb_dat_o[7:0] <= ucr;
|
||||
end
|
||||
2'b01: begin
|
||||
wb_dat_o[7:0] <= rx_data;
|
||||
rx_ack <= 1;
|
||||
end
|
||||
default: begin
|
||||
wb_dat_o[7:0] <= 8'b0;
|
||||
end
|
||||
endcase
|
||||
end else if (wb_wr & ~ack ) begin
|
||||
ack <= 1;
|
||||
|
||||
if ((wb_adr_i[3:2] == 2'b01) && ~tx_busy) begin
|
||||
tx_wr <= 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
endmodule
|
||||
1379
lm32/logic/sakc/sim/ddr/ddr.v
Normal file
1379
lm32/logic/sakc/sim/ddr/ddr.v
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user