1
0
mirror of git://projects.qi-hardware.com/nn-usb-fpga.git synced 2025-01-06 15:20:14 +02:00

Adding lm32 demo to SAKC project

This commit is contained in:
Carlos Camargo 2010-05-25 21:49:58 -05:00
parent 26b0c73a84
commit 61d4408f2a
145 changed files with 27924 additions and 1501 deletions

View File

@ -1,6 +1,6 @@
CC = mipsel-openwrt-linux-gcc
all: jz_init_sram jz_test_gpio
all: jz_init_sram jz_test_gpio enable_rx
DEBUG = -O3 -g0
@ -26,6 +26,9 @@ jz_init_sram: $(COMMON_OBJECTS)
jz_test_gpio: $(COMMON_OBJECTS)
$(CC) $(LDFLAGS) $(COMMON_OBJECTS) jz_test_gpio.c -o jz_test_gpio
enable_rx: $(COMMON_OBJECTS)
$(CC) $(LDFLAGS) $(COMMON_OBJECTS) enable_rx.c -o enable_rx
.c.o:
$(CC) -c $(CCFLAGS) $< -o $@
@ -33,7 +36,7 @@ upload: jz_init_sram jz_test_gpio
scp jz_test_gpio jz_init_sram root@$(NANO_IP):
clean:
rm -f *.o jz_init_sram jz_test_gpio ${EXEC} *~
rm -f *.o jz_init_sram jz_test_gpio enable_rx ${EXEC} *~
indent:
indent -bad -bap -nbc -bl -nce -i2 --no-tabs --line-length120 $(COMMON_SOURCES) $(H_SOURCES)

View File

@ -0,0 +1,40 @@
/*
JZ47xx test gpio
Copyright (C) 2010 Andres Calderon andres.calderon@emqbit.com
Carlos Camargo cicamargoba@unal.edu.co
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <stdio.h>
#include <unistd.h>
#include "jz47xx_gpio.h"
#define RXD_PORT JZ_GPIO_PORT_D
#define RXD_PIN 26
int
main ()
{
JZ_PIO *pio = jz_gpio_map (RXD_PORT);
if (!pio)
return -1;
jz_gpio_as_func (pio, RXD_PIN, 1);
return 0;
}

View File

@ -79,18 +79,21 @@ jz_gpio_as_func (JZ_PIO * pio, unsigned int o, int func)
pio->PXFUNS = (1 << o);
pio->PXTRGC = (1 << o);
pio->PXSELC = (1 << o);
pio->PXPES = (1 << o);
return 1;
case 1:
pio->PXFUNS = (1 << o);
pio->PXTRGC = (1 << o);
pio->PXSELS = (1 << o);
pio->PXPES = (1 << o);
return 1;
case 2:
pio->PXFUNS = (1 << o);
pio->PXTRGS = (1 << o);
pio->PXSELC = (1 << o);
pio->PXPES = (1 << o);
return 1;
}
return 0;

131
lm32/logic/sakc/Makefile Normal file
View 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

View 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

View 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

View File

@ -0,0 +1 @@
crt0ram.o: crt0ram.S

Binary file not shown.

Binary file not shown.

View 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

View 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

View 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

File diff suppressed because it is too large Load Diff

View 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

View 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);

View 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();
}
}

View File

@ -0,0 +1 @@
main.o: main.c soc-hw.h

Binary file not shown.

View 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++;
}
}

View File

@ -0,0 +1 @@
soc-hw.o: soc-hw.c soc-hw.h

View 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

Binary file not shown.

View 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

View 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

File diff suppressed because it is too large Load Diff

View 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);

View 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;
}
}
}

View 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++;
}
}

View 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

View 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

View 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

File diff suppressed because it is too large Load Diff

View 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 */

View 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));*/
}

View File

@ -0,0 +1,5 @@
void _gdb_write_char (char c);
char _gdb_read_char (void);
void _gdb_ack_interrupt (void) ;

View 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);

View 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);
}
}
}

View 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++;
}
}

View 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

View File

@ -0,0 +1,6 @@
#!/bin/sh
lm32-elf-gdb image << ENDL
target remote /dev/ttyUSB0
ENDL

View 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

View 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

View 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);

View 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());
}
}

View 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++;
}
}

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

File diff suppressed because it is too large Load Diff

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

File diff suppressed because it is too large Load Diff

View 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

View 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

View 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

View 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

View 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

View 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

View 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
#

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View File

@ -0,0 +1,144 @@
//---------------------------------------------------------------------------
//
// Wishbone Timer
//
// Register Description:
//
// 0x00 TCR0
// 0x04 COMPARE0
// 0x08 COUNTER0
// 0x0C TCR1
// 0x10 COMPARE1
// 0x14 COUNTER1
//
// TCRx:
// +-------------------+-------+-------+-------+-------+
// | 28'b0 | EN | AR | IRQEN | TRIG |
// +-------------------+-------+-------+-------+-------+
//
// EN i (rw) if set to '1', COUNTERX counts upwards until it reaches
// COMPAREX
// AR (rw) AutoRecwstartload -- if COUNTER reaches COMPAREX, shall we
// restart at 1, or disable this counter?
// IRQEN (rw) Indicate interrupt condition when triggered?
// TRIG (ro)
//
//---------------------------------------------------------------------------
module wb_timer #(
parameter clk_freq = 50000000
) (
input clk,
input reset,
// Wishbone interface
input wb_stb_i,
input wb_cyc_i,
output wb_ack_o,
input wb_we_i,
input [31:0] wb_adr_i,
input [3:0] wb_sel_i,
input [31:0] wb_dat_i,
output reg [31:0] wb_dat_o,
//
output [1:0] intr
);
//---------------------------------------------------------------------------
//
//---------------------------------------------------------------------------
reg irqen0, irqen1;
reg trig0, trig1;
reg en0, en1;
reg ar0, ar1;
wire [31:0] tcr0 = { 28'b0, en0, ar0, irqen0, trig0 };
wire [31:0] tcr1 = { 28'b0, en1, ar1, irqen1, trig1 };
reg [31:0] counter0;
reg [31:0] counter1;
reg [31:0] compare0;
reg [31:0] compare1;
wire match0 = (counter0 == compare0);
wire match1 = (counter1 == compare1);
assign intr = { trig1, trig0 };
reg ack;
assign wb_ack_o = wb_stb_i & wb_cyc_i & ack;
wire wb_rd = wb_stb_i & wb_cyc_i & ~wb_we_i;
wire wb_wr = wb_stb_i & wb_cyc_i & wb_we_i;
always @(posedge clk)
begin
if (reset) begin
ack <= 0;
en0 <= 0;
en1 <= 0;
ar0 <= 0;
ar1 <= 0;
trig0 <= 0;
trig1 <= 0;
counter0 <= 0;
counter1 <= 0;
compare0 <= 32'hFFFFFFFF;
compare1 <= 32'hFFFFFFFF;
end else begin
// Handle counter 0
if ( en0 & ~match0) counter0 <= counter0 + 1;
if ( en0 & match0) trig0 <= 1;
if ( ar0 & match0) counter0 <= 1;
if (~ar0 & match0) en0 <= 0;
// Handle counter 1
if ( en1 & ~match1) counter1 <= counter1 + 1;
if ( en1 & match1) trig1 <= 1;
if ( ar1 & match1) counter1 <= 1;
if (~ar1 & match1) en1 <= 0;
// Handle WISHBONE access
ack <= 0;
if (wb_rd & ~ack) begin // read cycle
ack <= 1;
case (wb_adr_i[7:0])
'h00: wb_dat_o <= tcr0;
'h04: wb_dat_o <= compare0;
'h08: wb_dat_o <= counter0;
'h0c: wb_dat_o <= tcr1;
'h10: wb_dat_o <= compare1;
'h14: wb_dat_o <= counter1;
default: wb_dat_o <= 32'b0;
endcase
end else if (wb_wr & ~ack ) begin // write cycle
ack <= 1;
case (wb_adr_i[7:0])
'h00: begin
trig0 <= 0;
irqen0 <= wb_dat_i[1];
ar0 <= wb_dat_i[2];
en0 <= wb_dat_i[3];
end
'h04: compare0 <= wb_dat_i;
'h08: counter0 <= wb_dat_i;
'h0c: begin
trig1 <= 0;
irqen1 <= wb_dat_i[1];
ar1 <= wb_dat_i[2];
en1 <= wb_dat_i[3];
end
'h10: compare1 <= wb_dat_i;
'h14: counter1 <= wb_dat_i;
endcase
end
end
end
endmodule

Some files were not shown because too many files have changed in this diff Show More