init repo

This commit is contained in:
TOKISAKIX\21168
2023-12-11 21:50:22 +08:00
commit 910ee11168
449 changed files with 41705 additions and 0 deletions

358
lab2/.gitignore vendored Normal file
View File

@@ -0,0 +1,358 @@
### Project Specific stuff
test_run_dir/*
### XilinxISE template
# intermediate build files
*.bgn
*.bit
*.bld
*.cmd_log
*.drc
*.ll
*.lso
*.msd
*.msk
*.ncd
*.ngc
*.ngd
*.ngr
*.pad
*.par
*.pcf
*.prj
*.ptwx
*.rbb
*.rbd
*.stx
*.syr
*.twr
*.twx
*.unroutes
*.ut
*.xpi
*.xst
*_bitgen.xwbt
*_envsettings.html
*_map.map
*_map.mrp
*_map.ngm
*_map.xrpt
*_ngdbuild.xrpt
*_pad.csv
*_pad.txt
*_par.xrpt
*_summary.html
*_summary.xml
*_usage.xml
*_xst.xrpt
# project-wide generated files
*.gise
par_usage_statistics.html
usage_statistics_webtalk.html
webtalk.log
webtalk_pn.xml
# generated folders
iseconfig/
xlnx_auto_0_xdb/
xst/
_ngo/
_xmsgs/
### Eclipse template
*.pydevproject
.metadata
.gradle
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.settings/
.loadpath
# Eclipse Core
.project
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# CDT-specific
.cproject
# JDT-specific (Eclipse Java Development Tools)
.classpath
# Java annotation processor (APT)
.factorypath
# PDT-specific
.buildpath
# sbteclipse plugin
.target
# TeXlipse plugin
.texlipse
### C template
# Object files
*.o
*.ko
*.obj
*.elf
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
### SBT template
# Simple Build Tool
# http://www.scala-sbt.org/release/docs/Getting-Started/Directories.html#configuring-version-control
target/
lib_managed/
src_managed/
project/boot/
.history
.cache
### Emacs template
# -*- mode: gitignore; -*-
*~
\#*\#
/.emacs.desktop
/.emacs.desktop.lock
*.elc
auto-save-list
tramp
.\#*
# Org-mode
.org-id-locations
*_archive
# flymake-mode
*_flymake.*
# eshell files
/eshell/history
/eshell/lastdir
# elpa packages
/elpa/
# reftex files
*.rel
# AUCTeX auto folder
/auto/
# cask packages
.cask/
### Vim template
[._]*.s[a-w][a-z]
[._]s[a-w][a-z]
*.un~
Session.vim
.netrwhist
*~
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio
*.iml
## Directory-based project format:
.idea/
# if you remove the above rule, at least ignore the following:
# User-specific stuff:
# .idea/workspace.xml
# .idea/tasks.xml
# .idea/dictionaries
# Sensitive or high-churn files:
# .idea/dataSources.ids
# .idea/dataSources.xml
# .idea/sqlDataSources.xml
# .idea/dynamic.xml
# .idea/uiDesigner.xml
# Gradle:
# .idea/gradle.xml
# .idea/libraries
# Mongo Explorer plugin:
# .idea/mongoSettings.xml
## File-based project format:
*.ipr
*.iws
## Plugin-specific files:
# IntelliJ
/out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
### C++ template
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
### OSX template
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
### Xcode template
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
## Build generated
build/
DerivedData
## Various settings
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
## Other
*.xccheckout
*.moved-aside
*.xcuserstate
### Scala template
*.class
*.log
/.bsp
# sbt specific
.cache
.history
.lib/
dist/*
target/
lib_managed/
src_managed/
project/boot/
project/plugins/project/
# Scala-IDE specific
.scala_dependencies
.worksheet
### Java template
*.class
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.ear
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
verilog/*.txt
verilog/basys3/*
verilog/pynq/*
verilog/verilator/*
!verilog/basys3/test.v
!verilog/pynq/design_1_wrapper.v
!verilog/pynq/test.v
!verilog/pynq/TMDS_PLLVR.v
!verilog/verilator/sim_main.cpp
*.jou
*.log
.Xil
vivado/basys3/riscv-basys3
vivado/pynq/riscv-pynq
vivado/pynq/NA
.vscode
.metals

47
lab2/Makefile Normal file
View File

@@ -0,0 +1,47 @@
# Copyright 2021 Howard Lau
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
test:
sbt test
verilator:
sbt "runMain board.verilator.VerilogGenerator"
cd verilog/verilator && verilator --trace --exe --cc sim_main.cpp Top.v && make -C obj_dir -f VTop.mk
verilator-sim: verilator
cd verilog/verilator && obj_dir/VTop $(SIM_TIME)
basys3:
sbt "runMain board.basys3.VerilogGenerator"
pynq:
sbt "runMain board.pynq.VerilogGenerator"
bitstream-basys3: basys3
cd vivado/basys3 && vivado -mode batch -source generate_bitstream.tcl
program-basys3: bitstream-basys3
cd vivado/basys3 && vivado -mode batch -source program_device.tcl
vivado-sim-basys3: basys3
cd vivado/basys3 && vivado -mode batch -source run_simulation.tcl
bitstream-pynq: pynq
cd vivado/pynq && vivado -mode batch -source generate_bitstream.tcl
program-pynq: bitstream-pynq
cd vivado/pynq && vivado -mode batch -source program_device.tcl
vivado-sim-pynq: pynq
cd vivado/pynq && vivado -mode batch -source run_simulation.tcl
.PHONY: basys3 verilator test bitstream program verilator-sim vivado-sim

24
lab2/build.sbt Normal file
View File

@@ -0,0 +1,24 @@
import sbt.Keys.libraryDependencies
// See README.md for license details.
ThisBuild / scalaVersion := "2.13.10"
ThisBuild / version := "0.1.0"
ThisBuild / organization := "io.github.howardlau1999"
val chiselVersion = "3.6.0"
lazy val root = (project in file("."))
.settings(
name := "yatcpu",
libraryDependencies ++= Seq(
"edu.berkeley.cs" %% "chisel3" % chiselVersion,
"edu.berkeley.cs" %% "chiseltest" % "0.6.0" % "test",
),
scalacOptions ++= Seq(
"-language:reflectiveCalls",
"-deprecation",
"-feature",
"-Xcheckinit",
),
addCompilerPlugin("edu.berkeley.cs" % "chisel3-plugin" % chiselVersion cross CrossVersion.full),
)

View File

@@ -0,0 +1,169 @@
/*
Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Original Author: Shay Gal-on
*/
#include "coremark.h"
#include "core_portme.h"
#if VALIDATION_RUN
volatile ee_s32 seed1_volatile = 0x3415;
volatile ee_s32 seed2_volatile = 0x3415;
volatile ee_s32 seed3_volatile = 0x66;
#endif
#if PERFORMANCE_RUN
volatile ee_s32 seed1_volatile = 0x0;
volatile ee_s32 seed2_volatile = 0x0;
volatile ee_s32 seed3_volatile = 0x66;
#endif
#if PROFILE_RUN
volatile ee_s32 seed1_volatile = 0x8;
volatile ee_s32 seed2_volatile = 0x8;
volatile ee_s32 seed3_volatile = 0x8;
#endif
volatile ee_s32 seed4_volatile = ITERATIONS;
volatile ee_s32 seed5_volatile = 0;
/* Porting : Timing functions
How to capture time and convert to seconds must be ported to whatever is
supported by the platform. e.g. Read value from on board RTC, read value from
cpu clock cycles performance counter etc. Sample implementation for standard
time.h and windows.h definitions included.
*/
CORETIMETYPE
barebones_clock()
{
ee_u32 cyclel;
__asm__ __volatile__ (
"rdcycle %0" : "=r"(cyclel) : :
);
return cyclel;
}
/* Define : TIMER_RES_DIVIDER
Divider to trade off timer resolution and total time that can be
measured.
Use lower values to increase resolution, but make sure that overflow
does not occur. If there are issues with the return value overflowing,
increase this value.
*/
#define GETMYTIME(_t) (*_t = barebones_clock())
#define MYTIMEDIFF(fin, ini) ((fin) - (ini))
#define TIMER_RES_DIVIDER 1
#define SAMPLE_TIME_IMPLEMENTATION 1
#define EE_TICKS_PER_SEC (CLOCKS_PER_SEC / TIMER_RES_DIVIDER)
/** Define Host specific (POSIX), or target specific global time variables. */
static CORETIMETYPE start_time_val, stop_time_val;
/* Function : start_time
This function will be called right before starting the timed portion of
the benchmark.
Implementation may be capturing a system timer (as implemented in the
example code) or zeroing some system parameters - e.g. setting the cpu clocks
cycles to 0.
*/
void
start_time(void)
{
GETMYTIME(&start_time_val);
}
/* Function : stop_time
This function will be called right after ending the timed portion of the
benchmark.
Implementation may be capturing a system timer (as implemented in the
example code) or other system parameters - e.g. reading the current value of
cpu cycles counter.
*/
void
stop_time(void)
{
GETMYTIME(&stop_time_val);
}
/* Function : get_time
Return an abstract "ticks" number that signifies time on the system.
Actual value returned may be cpu cycles, milliseconds or any other
value, as long as it can be converted to seconds by <time_in_secs>. This
methodology is taken to accommodate any hardware or simulated platform. The
sample implementation returns millisecs by default, and the resolution is
controlled by <TIMER_RES_DIVIDER>
*/
CORE_TICKS
get_time(void)
{
CORE_TICKS elapsed
= (CORE_TICKS)(MYTIMEDIFF(stop_time_val, start_time_val));
return elapsed;
}
/* Function : time_in_secs
Convert the value returned by get_time to seconds.
The <secs_ret> type is used to accommodate systems with no support for
floating point. Default implementation implemented by the EE_TICKS_PER_SEC
macro above.
*/
secs_ret
time_in_secs(CORE_TICKS ticks)
{
secs_ret retval = ((secs_ret)ticks) / (secs_ret)EE_TICKS_PER_SEC;
return retval;
}
ee_u32 default_num_contexts = 1;
/* Function : portable_init
Target specific initialization code
Test for some common mistakes.
*/
void
portable_init(core_portable *p, int *argc, char *argv[])
{
if (sizeof(ee_ptr_int) != sizeof(ee_u8 *))
{
ee_printf(
"ERROR! Please define ee_ptr_int to a type that holds a "
"pointer!\n");
}
if (sizeof(ee_u32) != 4)
{
ee_printf("ERROR! Please define ee_u32 to a 32b unsigned type!\n");
}
p->portable_id = 1;
}
/* Function : portable_fini
Target specific final code
*/
void
portable_fini(core_portable *p)
{
p->portable_id = 0;
}
unsigned int
__mulsi3 (unsigned int a, unsigned int b)
{
unsigned int r = 0;
while (a)
{
if (a & 1)
r += b;
a >>= 1;
b <<= 1;
}
return r;
}

View File

@@ -0,0 +1,211 @@
/*
Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Original Author: Shay Gal-on
*/
/* Topic : Description
This file contains configuration constants required to execute on
different platforms
*/
#ifndef CORE_PORTME_H
#define CORE_PORTME_H
/************************/
/* Data types and settings */
/************************/
/* Configuration : HAS_FLOAT
Define to 1 if the platform supports floating point.
*/
#ifndef HAS_FLOAT
#define HAS_FLOAT 0
#endif
/* Configuration : HAS_TIME_H
Define to 1 if platform has the time.h header file,
and implementation of functions thereof.
*/
#ifndef HAS_TIME_H
#define HAS_TIME_H 0
#define CLOCKS_PER_SEC 100000000
#endif
/* Configuration : USE_CLOCK
Define to 1 if platform has the time.h header file,
and implementation of functions thereof.
*/
#ifndef USE_CLOCK
#define USE_CLOCK 0
#endif
/* Configuration : HAS_STDIO
Define to 1 if the platform has stdio.h.
*/
#ifndef HAS_STDIO
#define HAS_STDIO 0
#endif
/* Configuration : HAS_PRINTF
Define to 1 if the platform has stdio.h and implements the printf
function.
*/
#ifndef HAS_PRINTF
#define HAS_PRINTF 0
#endif
/* Definitions : COMPILER_VERSION, COMPILER_FLAGS, MEM_LOCATION
Initialize these strings per platform
*/
#ifndef COMPILER_VERSION
#ifdef __GNUC__
#define COMPILER_VERSION "GCC"__VERSION__
#else
#define COMPILER_VERSION "Please put compiler version here (e.g. gcc 4.1)"
#endif
#endif
#ifndef COMPILER_FLAGS
#define COMPILER_FLAGS \
FLAGS_STR /* "Please put compiler flags here (e.g. -o3)" */
#endif
#ifndef MEM_LOCATION
#define MEM_LOCATION "STACK"
#endif
/* Data Types :
To avoid compiler issues, define the data types that need ot be used for
8b, 16b and 32b in <core_portme.h>.
*Imprtant* :
ee_ptr_int needs to be the data type used to hold pointers, otherwise
coremark may fail!!!
*/
typedef signed short ee_s16;
typedef unsigned short ee_u16;
typedef signed int ee_s32;
typedef double ee_f32;
typedef unsigned char ee_u8;
typedef unsigned int ee_u32;
typedef ee_u32 ee_ptr_int;
typedef ee_u32 ee_size_t;
#define NULL ((void *)0)
/* align_mem :
This macro is used to align an offset to point to a 32b value. It is
used in the Matrix algorithm to initialize the input memory blocks.
*/
#define align_mem(x) (void *)(4 + (((ee_ptr_int)(x)-1) & ~3))
/* Configuration : CORE_TICKS
Define type of return from the timing functions.
*/
#define CORETIMETYPE ee_u32
typedef ee_u32 CORE_TICKS;
/* Configuration : SEED_METHOD
Defines method to get seed values that cannot be computed at compile
time.
Valid values :
SEED_ARG - from command line.
SEED_FUNC - from a system function.
SEED_VOLATILE - from volatile variables.
*/
#ifndef SEED_METHOD
#define SEED_METHOD SEED_VOLATILE
#endif
/* Configuration : MEM_METHOD
Defines method to get a block of memry.
Valid values :
MEM_MALLOC - for platforms that implement malloc and have malloc.h.
MEM_STATIC - to use a static memory array.
MEM_STACK - to allocate the data block on the stack (NYI).
*/
#ifndef MEM_METHOD
#define MEM_METHOD MEM_STATIC
#endif
/* Configuration : MULTITHREAD
Define for parallel execution
Valid values :
1 - only one context (default).
N>1 - will execute N copies in parallel.
Note :
If this flag is defined to more then 1, an implementation for launching
parallel contexts must be defined.
Two sample implementations are provided. Use <USE_PTHREAD> or <USE_FORK>
to enable them.
It is valid to have a different implementation of <core_start_parallel>
and <core_end_parallel> in <core_portme.c>, to fit a particular architecture.
*/
#ifndef MULTITHREAD
#define MULTITHREAD 1
#define USE_PTHREAD 0
#define USE_FORK 0
#define USE_SOCKET 0
#endif
/* Configuration : MAIN_HAS_NOARGC
Needed if platform does not support getting arguments to main.
Valid values :
0 - argc/argv to main is supported
1 - argc/argv to main is not supported
Note :
This flag only matters if MULTITHREAD has been defined to a value
greater then 1.
*/
#ifndef MAIN_HAS_NOARGC
#define MAIN_HAS_NOARGC 1
#endif
/* Configuration : MAIN_HAS_NORETURN
Needed if platform does not support returning a value from main.
Valid values :
0 - main returns an int, and return value will be 0.
1 - platform does not support returning a value from main
*/
#ifndef MAIN_HAS_NORETURN
#define MAIN_HAS_NORETURN 0
#endif
/* Variable : default_num_contexts
Not used for this simple port, must contain the value 1.
*/
extern ee_u32 default_num_contexts;
typedef struct CORE_PORTABLE_S
{
ee_u8 portable_id;
} core_portable;
/* target specific init/fini */
void portable_init(core_portable *p, int *argc, char *argv[]);
void portable_fini(core_portable *p);
#if !defined(PROFILE_RUN) && !defined(PERFORMANCE_RUN) \
&& !defined(VALIDATION_RUN)
#if (TOTAL_DATA_SIZE == 1200)
#define PROFILE_RUN 1
#elif (TOTAL_DATA_SIZE == 2000)
#define PERFORMANCE_RUN 1
#else
#define VALIDATION_RUN 1
#endif
#endif
int ee_printf(const char *fmt, ...);
#endif /* CORE_PORTME_H */

View File

@@ -0,0 +1,92 @@
# Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Original Author: Shay Gal-on
#File : core_portme.mak
# Flag : OUTFLAG
# Use this flag to define how to to get an executable (e.g -o)
OUTFLAG= -o
# Flag : CC
# Use this flag to define compiler to use
CC = clang
# Flag : LD
# Use this flag to define compiler to use
LD = ld.lld
# Flag : AS
# Use this flag to define compiler to use
AS = clang
# Flag : CFLAGS
# Use this flag to define compiler options. Note, you can add compiler options from the command line using XCFLAGS="other flags"
PORT_CFLAGS = -O0 -g --target=riscv32-unknown-elf -march=rv32i -mabi=ilp32
FLAGS_STR = "$(PORT_CFLAGS) $(XCFLAGS) $(XLFLAGS) $(LFLAGS_END)"
CFLAGS = $(PORT_CFLAGS) -I$(PORT_DIR) -I. -DFLAGS_STR=\"$(FLAGS_STR)\"
#Flag : LFLAGS_END
# Define any libraries needed for linking or other flags that should come at the end of the link line (e.g. linker scripts).
# Note : On certain platforms, the default clock_gettime implementation is supported but requires linking of librt.
SEPARATE_COMPILE=1
# Flag : SEPARATE_COMPILE
# You must also define below how to create an object file, and how to link.
OBJOUT = -o
LFLAGS = -T $(PORT_DIR)/link.ld
ASFLAGS = -c --target=riscv32-unknown-elf -march=rv32i -mabi=ilp32
OFLAG = -o
COUT = -c
LFLAGS_END =
# Flag : PORT_SRCS
# Port specific source files can be added here
# You may also need cvt.c if the fcvt functions are not provided as intrinsics by your compiler!
PORT_SRCS = $(PORT_DIR)/core_portme.c $(PORT_DIR)/ee_printf.c $(PORT_DIR)/div.s $(PORT_DIR)/init.s
vpath %.c $(PORT_DIR)
vpath %.s $(PORT_DIR)
PORT_OBJS = $(PORT_DIR)/init$(OEXT) $(PORT_DIR)/core_portme$(OEXT) $(PORT_DIR)/ee_printf$(OEXT) $(PORT_DIR)/div$(OEXT)
PORT_CLEAN = *$(OEXT) $(OUTFILE).asmbin
# Flag : LOAD
# For a simple port, we assume self hosted compile and run, no load needed.
# Flag : RUN
# For a simple port, we assume self hosted compile and run, simple invocation of the executable
LOAD = echo "Please set LOAD to the process of loading the executable to the flash"
RUN = echo "Please set LOAD to the process of running the executable (e.g. via jtag, or board reset)"
OEXT = .o
EXE = .bin
$(OPATH)$(PORT_DIR)/%$(OEXT) : %.c
$(CC) $(CFLAGS) $(XCFLAGS) $(COUT) $< $(OBJOUT) $@
$(OPATH)%$(OEXT) : %.c
$(CC) $(CFLAGS) $(XCFLAGS) $(COUT) $< $(OBJOUT) $@
$(OPATH)$(PORT_DIR)/%$(OEXT) : %.s
$(AS) $(ASFLAGS) $< $(OBJOUT) $@
# Target : port_pre% and port_post%
# For the purpose of this simple port, no pre or post steps needed.
.PHONY : port_prebuild port_postbuild port_prerun port_postrun port_preload port_postload
port_postbuild: $(OUTFILE)
llvm-objcopy -O binary -j .text -j .data $(OUTFILE) $(OUTFILE).asmbin
port_pre% port_post% :
# FLAG : OPATH
# Path to the output folder. Default - current folder.
OPATH = ./
MKDIR = mkdir -p

127
lab2/coremark/yatcpu/cvt.c Normal file
View File

@@ -0,0 +1,127 @@
/*
Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include <math.h>
#define CVTBUFSIZE 80
static char CVTBUF[CVTBUFSIZE];
static char *
cvt(double arg, int ndigits, int *decpt, int *sign, char *buf, int eflag)
{
int r2;
double fi, fj;
char * p, *p1;
if (ndigits < 0)
ndigits = 0;
if (ndigits >= CVTBUFSIZE - 1)
ndigits = CVTBUFSIZE - 2;
r2 = 0;
*sign = 0;
p = &buf[0];
if (arg < 0)
{
*sign = 1;
arg = -arg;
}
arg = modf(arg, &fi);
p1 = &buf[CVTBUFSIZE];
if (fi != 0)
{
p1 = &buf[CVTBUFSIZE];
while (fi != 0)
{
fj = modf(fi / 10, &fi);
*--p1 = (int)((fj + .03) * 10) + '0';
r2++;
}
while (p1 < &buf[CVTBUFSIZE])
*p++ = *p1++;
}
else if (arg > 0)
{
while ((fj = arg * 10) < 1)
{
arg = fj;
r2--;
}
}
p1 = &buf[ndigits];
if (eflag == 0)
p1 += r2;
*decpt = r2;
if (p1 < &buf[0])
{
buf[0] = '\0';
return buf;
}
while (p <= p1 && p < &buf[CVTBUFSIZE])
{
arg *= 10;
arg = modf(arg, &fj);
*p++ = (int)fj + '0';
}
if (p1 >= &buf[CVTBUFSIZE])
{
buf[CVTBUFSIZE - 1] = '\0';
return buf;
}
p = p1;
*p1 += 5;
while (*p1 > '9')
{
*p1 = '0';
if (p1 > buf)
++*--p1;
else
{
*p1 = '1';
(*decpt)++;
if (eflag == 0)
{
if (p > buf)
*p = '0';
p++;
}
}
}
*p = '\0';
return buf;
}
char *
ecvt(double arg, int ndigits, int *decpt, int *sign)
{
return cvt(arg, ndigits, decpt, sign, CVTBUF, 1);
}
char *
ecvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf)
{
return cvt(arg, ndigits, decpt, sign, buf, 1);
}
char *
fcvt(double arg, int ndigits, int *decpt, int *sign)
{
return cvt(arg, ndigits, decpt, sign, CVTBUF, 0);
}
char *
fcvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf)
{
return cvt(arg, ndigits, decpt, sign, buf, 0);
}

View File

@@ -0,0 +1,71 @@
.text
.globl __divsi3
__divsi3:
bltz a0, .L10
bltz a1, .L11
.globl __udivsi3
__udivsi3:
mv a2, a1
mv a1, a0
li a0, -1
beqz a2, .L5
li a3, 1
bgeu a2, a1, .L2
.L1:
blez a2, .L2
slli a2, a2, 1
slli a3, a3, 1
bgtu a1, a2, .L1
.L2:
li a0, 0
.L3:
bltu a1, a2, .L4
sub a1, a1, a2
or a0, a0, a3
.L4:
srli a3, a3, 1
srli a2, a2, 1
bnez a3, .L3
.L5:
ret
.globl __umodsi3
__umodsi3:
move t0, ra
jal __udivsi3
move a0, a1
jr t0
.L10:
neg a0, a0
bgtz a1, .L12
neg a1, a1
j __udivsi3
.L11:
neg a1, a1
.L12:
move t0, ra
jal __udivsi3
neg a0, a0
jr t0
.globl __modsi3
__modsi3:
move t0, ra
bltz a1, .L31
bltz a0, .L32
.L30:
jal __udivsi3
move a0, a1
jr t0
.L31:
neg a1, a1
bgez a0, .L30
.L32:
neg a0, a0
jal __udivsi3
neg a0, a1
jr t0

View File

@@ -0,0 +1,687 @@
/*
Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include <coremark.h>
#include <stdarg.h>
#define ZEROPAD (1 << 0) /* Pad with zero */
#define SIGN (1 << 1) /* Unsigned/signed long */
#define PLUS (1 << 2) /* Show plus */
#define SPACE (1 << 3) /* Spacer */
#define LEFT (1 << 4) /* Left justified */
#define HEX_PREP (1 << 5) /* 0x */
#define UPPERCASE (1 << 6) /* 'ABCDEF' */
#define is_digit(c) ((c) >= '0' && (c) <= '9')
static char * digits = "0123456789abcdefghijklmnopqrstuvwxyz";
static char * upper_digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
static ee_size_t strnlen(const char *s, ee_size_t count);
static ee_size_t
strnlen(const char *s, ee_size_t count)
{
const char *sc;
for (sc = s; *sc != '\0' && count--; ++sc)
;
return sc - s;
}
static int
skip_atoi(const char **s)
{
int i = 0;
while (is_digit(**s))
i = i * 10 + *((*s)++) - '0';
return i;
}
static char *
number(char *str, long num, int base, int size, int precision, int type)
{
char c, sign, tmp[66];
char *dig = digits;
int i;
if (type & UPPERCASE)
dig = upper_digits;
if (type & LEFT)
type &= ~ZEROPAD;
if (base < 2 || base > 36)
return 0;
c = (type & ZEROPAD) ? '0' : ' ';
sign = 0;
if (type & SIGN)
{
if (num < 0)
{
sign = '-';
num = -num;
size--;
}
else if (type & PLUS)
{
sign = '+';
size--;
}
else if (type & SPACE)
{
sign = ' ';
size--;
}
}
if (type & HEX_PREP)
{
if (base == 16)
size -= 2;
else if (base == 8)
size--;
}
i = 0;
if (num == 0)
tmp[i++] = '0';
else
{
while (num != 0)
{
tmp[i++] = dig[((unsigned long)num) % (unsigned)base];
num = ((unsigned long)num) / (unsigned)base;
}
}
if (i > precision)
precision = i;
size -= precision;
if (!(type & (ZEROPAD | LEFT)))
while (size-- > 0)
*str++ = ' ';
if (sign)
*str++ = sign;
if (type & HEX_PREP)
{
if (base == 8)
*str++ = '0';
else if (base == 16)
{
*str++ = '0';
*str++ = digits[33];
}
}
if (!(type & LEFT))
while (size-- > 0)
*str++ = c;
while (i < precision--)
*str++ = '0';
while (i-- > 0)
*str++ = tmp[i];
while (size-- > 0)
*str++ = ' ';
return str;
}
static char *
eaddr(char *str, unsigned char *addr, int size, int precision, int type)
{
char tmp[24];
char *dig = digits;
int i, len;
if (type & UPPERCASE)
dig = upper_digits;
len = 0;
for (i = 0; i < 6; i++)
{
if (i != 0)
tmp[len++] = ':';
tmp[len++] = dig[addr[i] >> 4];
tmp[len++] = dig[addr[i] & 0x0F];
}
if (!(type & LEFT))
while (len < size--)
*str++ = ' ';
for (i = 0; i < len; ++i)
*str++ = tmp[i];
while (len < size--)
*str++ = ' ';
return str;
}
static char *
iaddr(char *str, unsigned char *addr, int size, int precision, int type)
{
char tmp[24];
int i, n, len;
len = 0;
for (i = 0; i < 4; i++)
{
if (i != 0)
tmp[len++] = '.';
n = addr[i];
if (n == 0)
tmp[len++] = digits[0];
else
{
if (n >= 100)
{
tmp[len++] = digits[n / 100];
n = n % 100;
tmp[len++] = digits[n / 10];
n = n % 10;
}
else if (n >= 10)
{
tmp[len++] = digits[n / 10];
n = n % 10;
}
tmp[len++] = digits[n];
}
}
if (!(type & LEFT))
while (len < size--)
*str++ = ' ';
for (i = 0; i < len; ++i)
*str++ = tmp[i];
while (len < size--)
*str++ = ' ';
return str;
}
#if HAS_FLOAT
char * ecvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf);
char * fcvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf);
static void ee_bufcpy(char *d, char *s, int count);
void
ee_bufcpy(char *pd, char *ps, int count)
{
char *pe = ps + count;
while (ps != pe)
*pd++ = *ps++;
}
static void
parse_float(double value, char *buffer, char fmt, int precision)
{
int decpt, sign, exp, pos;
char *digits = NULL;
char cvtbuf[80];
int capexp = 0;
int magnitude;
if (fmt == 'G' || fmt == 'E')
{
capexp = 1;
fmt += 'a' - 'A';
}
if (fmt == 'g')
{
digits = ecvtbuf(value, precision, &decpt, &sign, cvtbuf);
magnitude = decpt - 1;
if (magnitude < -4 || magnitude > precision - 1)
{
fmt = 'e';
precision -= 1;
}
else
{
fmt = 'f';
precision -= decpt;
}
}
if (fmt == 'e')
{
digits = ecvtbuf(value, precision + 1, &decpt, &sign, cvtbuf);
if (sign)
*buffer++ = '-';
*buffer++ = *digits;
if (precision > 0)
*buffer++ = '.';
ee_bufcpy(buffer, digits + 1, precision);
buffer += precision;
*buffer++ = capexp ? 'E' : 'e';
if (decpt == 0)
{
if (value == 0.0)
exp = 0;
else
exp = -1;
}
else
exp = decpt - 1;
if (exp < 0)
{
*buffer++ = '-';
exp = -exp;
}
else
*buffer++ = '+';
buffer[2] = (exp % 10) + '0';
exp = exp / 10;
buffer[1] = (exp % 10) + '0';
exp = exp / 10;
buffer[0] = (exp % 10) + '0';
buffer += 3;
}
else if (fmt == 'f')
{
digits = fcvtbuf(value, precision, &decpt, &sign, cvtbuf);
if (sign)
*buffer++ = '-';
if (*digits)
{
if (decpt <= 0)
{
*buffer++ = '0';
*buffer++ = '.';
for (pos = 0; pos < -decpt; pos++)
*buffer++ = '0';
while (*digits)
*buffer++ = *digits++;
}
else
{
pos = 0;
while (*digits)
{
if (pos++ == decpt)
*buffer++ = '.';
*buffer++ = *digits++;
}
}
}
else
{
*buffer++ = '0';
if (precision > 0)
{
*buffer++ = '.';
for (pos = 0; pos < precision; pos++)
*buffer++ = '0';
}
}
}
*buffer = '\0';
}
static void
decimal_point(char *buffer)
{
while (*buffer)
{
if (*buffer == '.')
return;
if (*buffer == 'e' || *buffer == 'E')
break;
buffer++;
}
if (*buffer)
{
int n = strnlen(buffer, 256);
while (n > 0)
{
buffer[n + 1] = buffer[n];
n--;
}
*buffer = '.';
}
else
{
*buffer++ = '.';
*buffer = '\0';
}
}
static void
cropzeros(char *buffer)
{
char *stop;
while (*buffer && *buffer != '.')
buffer++;
if (*buffer++)
{
while (*buffer && *buffer != 'e' && *buffer != 'E')
buffer++;
stop = buffer--;
while (*buffer == '0')
buffer--;
if (*buffer == '.')
buffer--;
while (buffer != stop)
*++buffer = 0;
}
}
static char *
flt(char *str, double num, int size, int precision, char fmt, int flags)
{
char tmp[80];
char c, sign;
int n, i;
// Left align means no zero padding
if (flags & LEFT)
flags &= ~ZEROPAD;
// Determine padding and sign char
c = (flags & ZEROPAD) ? '0' : ' ';
sign = 0;
if (flags & SIGN)
{
if (num < 0.0)
{
sign = '-';
num = -num;
size--;
}
else if (flags & PLUS)
{
sign = '+';
size--;
}
else if (flags & SPACE)
{
sign = ' ';
size--;
}
}
// Compute the precision value
if (precision < 0)
precision = 6; // Default precision: 6
// Convert floating point number to text
parse_float(num, tmp, fmt, precision);
if ((flags & HEX_PREP) && precision == 0)
decimal_point(tmp);
if (fmt == 'g' && !(flags & HEX_PREP))
cropzeros(tmp);
n = strnlen(tmp, 256);
// Output number with alignment and padding
size -= n;
if (!(flags & (ZEROPAD | LEFT)))
while (size-- > 0)
*str++ = ' ';
if (sign)
*str++ = sign;
if (!(flags & LEFT))
while (size-- > 0)
*str++ = c;
for (i = 0; i < n; i++)
*str++ = tmp[i];
while (size-- > 0)
*str++ = ' ';
return str;
}
#endif
static int
ee_vsprintf(char *buf, const char *fmt, va_list args)
{
int len;
unsigned long num;
int i, base;
char * str;
char * s;
int flags; // Flags to number()
int field_width; // Width of output field
int precision; // Min. # of digits for integers; max number of chars for
// from string
int qualifier; // 'h', 'l', or 'L' for integer fields
for (str = buf; *fmt; fmt++)
{
if (*fmt != '%')
{
*str++ = *fmt;
continue;
}
// Process flags
flags = 0;
repeat:
fmt++; // This also skips first '%'
switch (*fmt)
{
case '-':
flags |= LEFT;
goto repeat;
case '+':
flags |= PLUS;
goto repeat;
case ' ':
flags |= SPACE;
goto repeat;
case '#':
flags |= HEX_PREP;
goto repeat;
case '0':
flags |= ZEROPAD;
goto repeat;
}
// Get field width
field_width = -1;
if (is_digit(*fmt))
field_width = skip_atoi(&fmt);
else if (*fmt == '*')
{
fmt++;
field_width = va_arg(args, int);
if (field_width < 0)
{
field_width = -field_width;
flags |= LEFT;
}
}
// Get the precision
precision = -1;
if (*fmt == '.')
{
++fmt;
if (is_digit(*fmt))
precision = skip_atoi(&fmt);
else if (*fmt == '*')
{
++fmt;
precision = va_arg(args, int);
}
if (precision < 0)
precision = 0;
}
// Get the conversion qualifier
qualifier = -1;
if (*fmt == 'l' || *fmt == 'L')
{
qualifier = *fmt;
fmt++;
}
// Default base
base = 10;
switch (*fmt)
{
case 'c':
if (!(flags & LEFT))
while (--field_width > 0)
*str++ = ' ';
*str++ = (unsigned char)va_arg(args, int);
while (--field_width > 0)
*str++ = ' ';
continue;
case 's':
s = va_arg(args, char *);
if (!s)
s = "<NULL>";
len = strnlen(s, precision);
if (!(flags & LEFT))
while (len < field_width--)
*str++ = ' ';
for (i = 0; i < len; ++i)
*str++ = *s++;
while (len < field_width--)
*str++ = ' ';
continue;
case 'p':
if (field_width == -1)
{
field_width = 2 * sizeof(void *);
flags |= ZEROPAD;
}
str = number(str,
(unsigned long)va_arg(args, void *),
16,
field_width,
precision,
flags);
continue;
case 'A':
flags |= UPPERCASE;
case 'a':
if (qualifier == 'l')
str = eaddr(str,
va_arg(args, unsigned char *),
field_width,
precision,
flags);
else
str = iaddr(str,
va_arg(args, unsigned char *),
field_width,
precision,
flags);
continue;
// Integer number formats - set up the flags and "break"
case 'o':
base = 8;
break;
case 'X':
flags |= UPPERCASE;
case 'x':
base = 16;
break;
case 'd':
case 'i':
flags |= SIGN;
case 'u':
break;
#if HAS_FLOAT
case 'f':
str = flt(str,
va_arg(args, double),
field_width,
precision,
*fmt,
flags | SIGN);
continue;
#endif
default:
if (*fmt != '%')
*str++ = '%';
if (*fmt)
*str++ = *fmt;
else
--fmt;
continue;
}
if (qualifier == 'l')
num = va_arg(args, unsigned long);
else if (flags & SIGN)
num = va_arg(args, int);
else
num = va_arg(args, unsigned int);
str = number(str, num, base, field_width, precision, flags);
}
*str = '\0';
return str - buf;
}
void
uart_send_char(char c)
{
*((volatile unsigned int *) (0x40000010)) = c;
}
int
ee_printf(const char *fmt, ...)
{
char buf[1024], *p;
va_list args;
int n = 0;
va_start(args, fmt);
ee_vsprintf(buf, fmt, args);
va_end(args);
p = buf;
while (*p)
{
uart_send_char(*p);
n++;
p++;
}
return n;
}

View File

@@ -0,0 +1,16 @@
.section .text.init
.globl _start
_start:
li sp, 4092
call main
li x1, 0xBABECAFE
write_tohost:
sw x1, tohost, x0
loop:
j loop
.pushsection .tohost,"aw",@progbits
.align 4
.global tohost
tohost: .word 0
.popsection

View File

@@ -0,0 +1,12 @@
OUTPUT_ARCH( "riscv" )
ENTRY(_start)
SECTIONS
{
. = 0x00001000;
.text : { *(.text.init) *(.text.startup) *(.text) }
.data ALIGN(0x1000) : { *(.data*) *(.rodata*) *(.sdata*) }
.tohost ALIGN(0x1000) : { *(.tohost) }
.bss : { *(.bss) }
_end = .;
}

43
lab2/csrc/CMakeLists.txt Normal file
View File

@@ -0,0 +1,43 @@
# Make CMake happy
cmake_minimum_required(VERSION 3.18)
project(yatcpu-programs C CXX ASM)
# Setting variables
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 --target=riscv32-unknown-elf -march=rv32i -mabi=ilp32")
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -O0 --target=riscv32-unknown-elf -march=rv32i -mabi=ilp32")
set(C_PROGRAMS tetris hello fibonacci quicksort simpletest)
set(ASM_PROGRAMS mmio sb)
set(LINKER_SCRIPT ${CMAKE_SOURCE_DIR}/link.lds)
set(LINKER_FLAGS -T ${LINKER_SCRIPT})
set(OBJCOPY_ARGS -O binary -j .text -j .data)
if(NOT DEST_DIR)
set(DEST_DIR "../src/main/resources")
endif()
# Let CMake know that there exists header files
include_directories("${CMAKE_SOURCE_DIR}")
add_library(prelude init.S)
set_target_properties(prelude PROPERTIES LINK_DEPENDS ${LINKER_SCRIPT})
# Let's build our executables
foreach(program IN LISTS C_PROGRAMS)
add_executable(${program} ${program}.c)
set_target_properties(${program} PROPERTIES LINK_DEPENDS ${LINKER_SCRIPT})
target_link_libraries(${program} prelude ${LINKER_FLAGS})
endforeach()
foreach(program IN LISTS ASM_PROGRAMS)
add_executable(${program} ${program}.S)
set_target_properties(${program} PROPERTIES LINK_DEPENDS ${LINKER_SCRIPT})
endforeach()
# Copy the .text section to .asmbin files
foreach(program IN LISTS C_PROGRAMS ASM_PROGRAMS)
add_custom_command(
TARGET ${program}
POST_BUILD
COMMAND ${CMAKE_OBJCOPY} ARGS ${OBJCOPY_ARGS} $<TARGET_FILE:${program}> ${CMAKE_SOURCE_DIR}/${DEST_DIR}/${program}.asmbin
)
endforeach()

3
lab2/csrc/build.bat Normal file
View File

@@ -0,0 +1,3 @@
rmdir /Q /S build
cmake -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake -G"NMake Makefiles" -B build .
cmake --build build

3
lab2/csrc/build.sh Normal file
View File

@@ -0,0 +1,3 @@
#!/bin/sh
rm -rf build
cmake -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake -B build . && cmake --build build --parallel `nproc`

22
lab2/csrc/fibonacci.c Normal file
View File

@@ -0,0 +1,22 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
int fib(int a) {
if (a == 1 || a == 2) return 1;
return fib(a - 1) + fib(a - 2);
}
int main() {
*(int *)(4) = fib(10);
}

175
lab2/csrc/hello.c Normal file
View File

@@ -0,0 +1,175 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "mmio.h"
#define MUL80(x) (((x) << 6) + ((x) << 4))
struct screen {
unsigned char row, col;
} scr;
void copy_line(int prev, int cur) {
int *prev_vram_start = ((int *) (MUL80(prev) + VRAM_BASE));
int *cur_vram_start = ((int *) (MUL80(cur) + VRAM_BASE));
for (int i = 0; i < 20; ++i) {
prev_vram_start[i] = cur_vram_start[i];
}
}
void write_char(int row, int col, unsigned char ch) {
VRAM[MUL80(row) + col] = ch;
}
void move_to(int row, int col) {
scr.row = row;
scr.col = col;
}
void new_line() {
scr.col = 0;
if (scr.row == 29) {
for (int i = 0; i < 29; ++i) {
copy_line(i, i + 1);
}
int *vram = (int *) (MUL80(29) + VRAM_BASE);
for (int i = 0; i < 20; ++i) {
vram[i] = 0x20202020;
}
} else {
++scr.row;
}
}
void putch(unsigned char ch) {
if (ch == '\n') {
new_line();
} else if (ch == '\r') {
scr.col = 0;
} else {
if (scr.col == 79) {
new_line();
}
write_char(scr.row, scr.col, ch);
++scr.col;
}
}
void clear_screen() {
scr.row = 0;
scr.col = 0;
int *vram = ((int *) VRAM_BASE);
for (int i = 0; i < 600; ++i) vram[i] = 0x20202020;
}
void print_hex(unsigned int counter) {
putch('0'); putch('x');
for (int i = 7; i >= 0; --i) {
unsigned int num = (counter >> (i << 2)) & 0xF;
if (num < 10) {
putch('0' + num);
} else {
putch('A' + num - 10);
}
}
}
void putstr(const char *s) {
while (*s) {
putch(*(s++));
}
}
int hc = 1;
int fast = 0;
void print_timer() {
putstr("Hardware timer count limit = ");
print_hex(*TIMER_LIMIT);
putstr(", enabled = ");
print_hex(*TIMER_ENABLED);
putch('\n');
}
void print_uart() {
putstr("UART Baud rate = ");
print_hex(*UART_BAUDRATE);
putch('\n');
}
void handle_timer() {
putstr("Timer trigger times = ");
print_hex(hc++);
putch('\n');
int mode = ((hc & 0x10) >> 4);
if (hc == 0x40) {
putstr("Disable timer!\n");
*TIMER_ENABLED = 0;
print_timer();
return;
}
if (fast ^ mode) {
putstr("Switch timer frequency\n");
if (fast == 0) {
*TIMER_LIMIT = 25000000;
} else {
*TIMER_LIMIT = 100000000;
}
fast = mode;
print_timer();
}
}
void handle_uart() {
unsigned int ch = *UART_RECV;
*UART_SEND = ch;
putstr("UART Recv hex = "); print_hex(ch); putstr(", ch = "); putch(ch); putch('\n');
}
void trap_handler(void *epc, unsigned int cause) {
putstr("Interrupt! EPC = ");
print_hex((unsigned int) epc);
putstr(", CAUSE = ");
print_hex(cause);
putch('\n');
switch (cause) {
case 0x8000000B:
handle_uart();
break;
default:
handle_timer();
break;
}
}
extern void enable_interrupt();
extern unsigned int get_epc();
int main() {
clear_screen();
hc = 0;
*TIMER_ENABLED = 1;
putstr("YatCPU Demo Program ");
putch(137);
putstr("2021 Howard Lau\n");
putstr("Hello, world!\n");
putstr("Last EPC = ");
print_hex(get_epc());
putch('\n');
print_timer();
print_uart();
*((int *) 0x4) = 0xDEADBEEF;
unsigned int i = 0;
enable_interrupt();
for (;;) ;
}

107
lab2/csrc/init.S Normal file
View File

@@ -0,0 +1,107 @@
# Copyright 2021 Howard Lau
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
.section .text.init
.globl _start
_start:
li sp, 4096 # Initialize stack pointer
call main # Jump to main function
loop:
j loop # Loop forever
.globl enable_interrupt
enable_interrupt:
la t0, __trap_entry
csrrw t1, mtvec, t0 # setup trap vector base
li t0, 0x1888
csrrw t1, mstatus, t0 # enable interrupt
ret
.globl get_epc
get_epc:
csrr a0, mepc
ret
.weak trap_handler
tran_handler:
ret
__trap_entry:
csrw mscratch, sp
addi sp, sp, -128
sw ra, 4(sp)
sw gp, 12(sp)
sw tp, 16(sp)
sw t0, 20(sp)
sw t1, 24(sp)
sw t2, 28(sp)
sw tp, 32(sp)
sw s1, 36(sp)
sw a0, 40(sp)
sw a1, 44(sp)
sw a2, 48(sp)
sw a3, 52(sp)
sw a4, 56(sp)
sw a5, 60(sp)
sw a6, 64(sp)
sw a7, 68(sp)
sw s2, 72(sp)
sw s3, 76(sp)
sw s4, 80(sp)
sw s5, 84(sp)
sw s6, 88(sp)
sw s7, 92(sp)
sw s8, 96(sp)
sw s9, 100(sp)
sw s10, 104(sp)
sw s11, 108(sp)
sw t3, 112(sp)
sw t4, 116(sp)
sw t5, 120(sp)
sw t6, 124(sp)
csrr a0, mepc
csrr a1, mcause
call trap_handler
lw ra, 4(sp)
lw gp, 12(sp)
lw tp, 16(sp)
lw t0, 20(sp)
lw t1, 24(sp)
lw t2, 28(sp)
lw tp, 32(sp)
lw s1, 36(sp)
lw a0, 40(sp)
lw a1, 44(sp)
lw a2, 48(sp)
lw a3, 52(sp)
lw a4, 56(sp)
lw a5, 60(sp)
lw a6, 64(sp)
lw a7, 68(sp)
lw s2, 72(sp)
lw s3, 76(sp)
lw s4, 80(sp)
lw s5, 84(sp)
lw s6, 88(sp)
lw s7, 92(sp)
lw s8, 96(sp)
lw s9, 100(sp)
lw s10, 104(sp)
lw s11, 108(sp)
lw t3, 112(sp)
lw t4, 116(sp)
lw t5, 120(sp)
lw t6, 124(sp)
csrr sp, mscratch
mret

11
lab2/csrc/link.lds Normal file
View File

@@ -0,0 +1,11 @@
OUTPUT_ARCH( "riscv" )
ENTRY(_start)
SECTIONS
{
. = 0x00001000;
.text : { *(.text.init) *(.text.startup) *(.text) }
.data ALIGN(0x1000) : { *(.data*) *(.rodata*) *(.sdata*) }
.bss : { *(.bss) }
_end = .;
}

24
lab2/csrc/mmio.S Normal file
View File

@@ -0,0 +1,24 @@
# Copyright 2021 Howard Lau
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
.globl _start
_start:
li a0, 0x80000000
lw t0, 4(a0)
li a1, 0xBEEF
sw a1, 4(a0)
nop
lw t1, 4(a0)
loop:
j loop

23
lab2/csrc/mmio.h Normal file
View File

@@ -0,0 +1,23 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#define VRAM_BASE 0x20000000
#define VRAM ((volatile unsigned char *) VRAM_BASE)
#define TIMER_BASE 0x80000000
#define TIMER_LIMIT ((volatile unsigned int *) (TIMER_BASE + 4))
#define TIMER_ENABLED ((volatile unsigned int *) (TIMER_BASE + 8))
#define UART_BASE 0x40000000
#define UART_BAUDRATE ((volatile unsigned int *) (UART_BASE + 4))
#define UART_RECV ((volatile unsigned int *) (UART_BASE + 12))
#define UART_SEND ((volatile unsigned int *) (UART_BASE + 16))

50
lab2/csrc/quicksort.c Normal file
View File

@@ -0,0 +1,50 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
void quicksort(int *arr, int l, int r) {
if (l >= r) return;
int pivot = arr[l];
int i = l, j = r;
while (i < j) {
while(arr[j] >= pivot && i < j) --j;
arr[i] = arr[j];
while(arr[i] < pivot && i < j) ++i;
arr[j] = arr[i];
}
arr[i] = pivot;
quicksort(arr, l, i - 1);
quicksort(arr, i + 1, r);
}
int main() {
int nums[10];
nums[0] = 6;
nums[1] = 2;
nums[2] = 4;
nums[3] = 5;
nums[4] = 3;
nums[5] = 1;
nums[6] = 0;
nums[7] = 9;
nums[8] = 7;
nums[9] = 8;
quicksort(nums, 0, 9);
for (int i = 1; i <= 10; ++i) {
*(int *)(i * 4) = nums[i - 1];
}
}

25
lab2/csrc/sb.S Normal file
View File

@@ -0,0 +1,25 @@
# Copyright 2021 Howard Lau
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
.globl _start
_start:
li a0, 0x4
li t0, 0xDEADBEEF
sb t0, 0(a0)
lw t1, 0(a0)
li s2, 0x15
sb s2, 1(a0)
lw ra, 0(a0)
loop:
j loop

12
lab2/csrc/simpletest.c Normal file
View File

@@ -0,0 +1,12 @@
extern void enable_interrupt();
void trap_handler(void *epc, unsigned int cause){
*((int*)0x4) = 0x2022;
}
int main(){
*((int*)0x4) = 0xDEADBEEF;
enable_interrupt();
for(;;);
}

2023
lab2/csrc/tetris.S Normal file

File diff suppressed because it is too large Load Diff

498
lab2/csrc/tetris.c Normal file
View File

@@ -0,0 +1,498 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifdef DEBUG
#include <stdio.h>
#endif
#include "mmio.h"
#define FALL_TIMER_LIMIT 50000000
#define ROWS 22
#define COLS 10
#define OFFSET_X 28
#define OFFSET_Y 3
#define SCREEN_COLS 80
#define SCREEN_ROWS 30
struct block {
unsigned int shape[3];
unsigned int xywh;
};
struct block current;
unsigned int score;
unsigned char *board;
#ifdef DEBUG
unsigned char screen[SCREEN_COLS * SCREEN_ROWS];
#endif
int wk_mul(int a, int b) {
int r = 0;
for (; b; a <<= 1, b >>= 1)
if (b & 1)
r += a;
return r;
}
unsigned int make_xywh(unsigned int x, unsigned int y, unsigned int w, unsigned int h) {
return (x << 12) | (y << 4) | (w << 2) | h;
}
void init_block(struct block *block, int type, int x, int y) {
int w = 0; int h = 0;
block->shape[0] = block->shape[1] = block->shape[2] = 0;
switch(type) {
case 0: // I
block->shape[0] = 0xF;
w = 3; h = 0;
break;
case 1: // O
block->shape[0] = 0x3;
block->shape[1] = 0x3;
w = 1; h = 1;
break;
case 2: // J
block->shape[0] = 0x4;
block->shape[1] = 0x7;
w = 2; h = 1;
break;
case 3: // T
block->shape[0] = 0x2;
block->shape[1] = 0x7;
w = 2; h = 1;
break;
case 4: // L
block->shape[0] = 0x1;
block->shape[1] = 0x7;
w = 2; h = 1;
break;
case 5: // Z
block->shape[0] = 0x6;
block->shape[1] = 0x3;
w = 2; h = 1;
break;
case 6: // S
block->shape[0] = 0x3;
block->shape[1] = 0x6;
w = 2; h = 1;
break;
}
block->xywh = make_xywh(x, y, w, h);
}
unsigned int get_shape(struct block *block, unsigned int r, unsigned int c) {
return (block->shape[r] & (1 << c)) >> c;
}
unsigned int check_bounds(struct block *block) {
unsigned int xywh = block->xywh;
unsigned int h = xywh & 0x3;
unsigned int w = (xywh & 0xC) >> 2;
unsigned int y = (xywh & 0xFF0) >> 4;
unsigned int x = (xywh & 0xF000) >> 12;
if (x < 0 || x + w >= COLS) return 0;
if (y < 0 || y + h >= ROWS) return 0;
return 1;
}
void copy_block(struct block *dst, struct block *src) {
dst->xywh = src->xywh;
dst->shape[0] = src->shape[0];
dst->shape[1] = src->shape[1];
dst->shape[2] = src->shape[2];
}
unsigned int check_collision(struct block *block) {
unsigned int xywh = block->xywh;
unsigned int h = xywh & 0x3;
unsigned int w = (xywh & 0xC) >> 2;
unsigned int y = (xywh & 0xFF0) >> 4;
unsigned int x = (xywh & 0xF000) >> 12;
for (int r = 0; r <= h; ++r) {
for (int c = 0; c <= w; ++c) {
if (get_shape(block, r, c) &&
board[wk_mul(y + r, COLS) + x + c])
return 0;
}
}
return 1;
}
void putch_at(int x, int y, unsigned char ch) {
#ifdef DEBUG
screen[wk_mul(OFFSET_Y + y, SCREEN_COLS) + x + OFFSET_X] = ch;
#else
VRAM[wk_mul(OFFSET_Y + y, SCREEN_COLS) + x + OFFSET_X] = ch;
#endif
}
void block_move(struct block *block, int dir) {
unsigned int xywh = block->xywh;
unsigned int h = xywh & 0x3;
unsigned int w = (xywh & 0xC) >> 2;
unsigned int y = (xywh & 0xFF0) >> 4;
unsigned int x = (xywh & 0xF000) >> 12;
switch(dir) {
case 0: // Left
x--;
break;
case 1: // Right
x++;
break;
case 2: // Down
y++;
break;
default:
break;
}
block->xywh = (x << 12) | (y << 4) | (w << 2) | h;
}
unsigned int move(struct block *block, int dir) {
struct block moved;
copy_block(&moved, block);
block_move(&moved, dir);
if (check_bounds(&moved) && check_collision(&moved)) {
copy_block(block, &moved);
return 1;
}
return 0;
}
void block_rotate(struct block *block, unsigned int clock) {
unsigned int xywh = block->xywh;
unsigned int h = xywh & 0x3;
unsigned int w = (xywh & 0xC) >> 2;
unsigned int y = (xywh & 0xFF0) >> 4;
unsigned int x = (xywh & 0xF000) >> 12;
unsigned int xyhw = make_xywh(x, y, h, w);
unsigned int shape[3] = {0, 0, 0};
if (clock) {
for (int r = 0; r <= h; ++r) {
for (int c = 0; c <= w; ++c) {
shape[c] = shape[c] | (get_shape(block, r, c) << (h - r));
}
}
} else {
for (int r = 0; r <= h; ++r) {
for (int c = 0; c <= w; ++c) {
shape[w - c] = shape[w - c] | (get_shape(block, r, c) << r);
}
}
}
block->shape[0] = shape[0];
block->shape[1] = shape[1];
block->shape[2] = shape[2];
block->xywh = xyhw;
}
void rotate(struct block *block, int clock) {
struct block rotated;
copy_block(&rotated, block);
block_rotate(&rotated, clock);
if (check_bounds(&rotated) && check_collision(&rotated)) {
copy_block(block, &rotated);
return;
}
unsigned int xywh = rotated.xywh;
unsigned int h = xywh & 0x3;
unsigned int w = (xywh & 0xc) >> 2;
unsigned int y = (xywh & 0xff0) >> 4;
unsigned int x = (xywh & 0xf000) >> 12;
if (x + w >= COLS) {
x = COLS - w - 1;
}
rotated.xywh = make_xywh(x, y, w, h);
if (check_bounds(&rotated) && check_collision(&rotated)) {
copy_block(block, &rotated);
}
}
void clear_board() {
for (int i = 0, s = wk_mul(ROWS, COLS); i < s; ++i) {
board[i] = 0;
}
}
void fix_block(struct block *block) {
unsigned int xywh = block->xywh;
unsigned int h = xywh & 0x3;
unsigned int w = (xywh & 0xc) >> 2;
unsigned int y = (xywh & 0xff0) >> 4;
unsigned int x = (xywh & 0xf000) >> 12;
#ifdef DEBUG
printf("%d %d %d %d\n", x, y, w, h);
#endif
for (int r = 0; r <= h; ++r) {
for (int c = 0; c <= w; ++c) {
if (get_shape(block, r, c)) {
board[wk_mul(y + r, COLS) + x + c] = 1;
}
}
}
}
void print_score() {
int c = 8;
putch_at(c++, -2, 'S');
putch_at(c++, -2, 'C');
putch_at(c++, -2, 'O');
putch_at(c++, -2, 'R');
putch_at(c++, -2, 'E');
for (int i = 0; i < 5; ++i) {
unsigned int mask = 0xF << (i * 4);
unsigned int num = (score & mask) >> (i * 4);
putch_at(12 - i, -1, num + '0');
}
}
void draw_board() {
for (int r = 0; r < ROWS; ++r) {
for (int c = 0; c < COLS; ++c) {
if (board[wk_mul(r , COLS) + c] == 1) {
putch_at((c << 1) + 1, r, '[');
putch_at((c << 1) + 2, r, ']');
} else {
putch_at((c << 1) + 1, r, ' ');
putch_at((c << 1)+ 2, r, ' ');
}
}
}
unsigned int xywh = current.xywh;
unsigned int h = xywh & 0x3;
unsigned int w = (xywh & 0xc) >> 2;
unsigned int y = (xywh & 0xff0) >> 4;
unsigned int x = (xywh & 0xf000) >> 12;
for (int r = 0; r <= h; ++r) {
for (int c = 0; c <= w; ++c) {
if (get_shape(&current, r, c)) {
putch_at(((c + x) << 1) + 1, r + y, '[');
putch_at(((c + x) << 1) + 2, r + y, ']');
}
}
}
print_score();
}
void add_score(unsigned int delta) {
score += delta;
for (unsigned int i = 0, carry = 0; i < 32; i += 4) {
unsigned int mask = 0xF << i;
unsigned int num = (score & mask) >> i;
num += carry;
if (num >= 10) {
carry = 1;
num -= 10;
} else {
carry = 0;
}
score &= ~(mask);
score |= (num << i);
}
}
void check_clear() {
unsigned int y = (current.xywh & 0xff0) >> 4;
unsigned int h = current.xywh & 0x3;
for (int r = y + h; r >= y; --r) {
unsigned int count = 0;
for (int c = 0; c < COLS; ++c) {
if (board[wk_mul(r , COLS) + c]) ++count;
}
if (count == COLS) {
add_score(1);
for (int nr = r - 1; nr > 0; --nr) {
for (int c = 0; c < COLS; ++c) {
board[wk_mul(nr + 1, COLS) + c] = board[wk_mul(nr, COLS) + c];
}
}
++r; ++y;
}
}
}
unsigned int rand() {
static unsigned int seed = 990315;
seed = (wk_mul(1103515245 , seed) + 12345) & 0x7FFFFFFF;
return seed;
}
unsigned int rand_type() {
unsigned int type = rand() & 0x7;
while (type == 7) {
type = rand() & 0x7;
}
return type;
}
void fall() {
if (move(&current, 2) == 0) {
fix_block(&current);
check_clear();
init_block(&current, rand_type(), 4, 0);
}
}
#ifdef DEBUG
void print_screen() {
for (int r = 0; r < SCREEN_ROWS; ++r) {
for (int c = 0; c < SCREEN_COLS; ++c) {
printf("%c", screen[wk_mul(r, SCREEN_COLS) + c]);
}
printf("\n");
}
printf("\n");
}
#endif
void on_input(unsigned int ch) {
switch (ch) {
case 's':
fall();
break;
case 'a':
move(&current, 0);
break;
case 'd':
move(&current, 1);
break;
case 'j':
rotate(&current, 0);
break;
case 'k':
rotate(&current, 1);
break;
}
draw_board();
#ifdef DEBUG
print_screen();
#endif
}
void on_timer() {
fall();
draw_board();
}
void trap_handler(void *epc, unsigned int cause) {
if (cause == 0x80000007) {
on_timer();
} else {
unsigned int ch = *UART_RECV;
*UART_SEND = ch;
on_input(ch);
}
}
void init() {
clear_board();
// Draw border
for (int r = 0; r < ROWS; ++r) {
putch_at(0, r, '|');
putch_at(COLS << 1 | 1, r, '|');
}
for (int c = 0; c <= (COLS << 1 | 1); ++c) {
putch_at(c, ROWS, '-');
}
int c = 8;
putch_at(c++, ROWS + 1, 'T');
putch_at(c++, ROWS + 1, 'E');
putch_at(c++, ROWS + 1, 'T');
putch_at(c++, ROWS + 1, 'R');
putch_at(c++, ROWS + 1, 'I');
putch_at(c++, ROWS + 1, 'S');
c = 6;
putch_at(c++, ROWS + 3, 'H');
putch_at(c++, ROWS + 3, 'o');
putch_at(c++, ROWS + 3, 'w');
putch_at(c++, ROWS + 3, 'a');
putch_at(c++, ROWS + 3, 'r');
putch_at(c++, ROWS + 3, 'd');
c++;
putch_at(c++, ROWS + 3, 'L');
putch_at(c++, ROWS + 3, 'a');
putch_at(c++, ROWS + 3, 'u');
c = 9;
putch_at(c++, ROWS + 4, '2');
putch_at(c++, ROWS + 4, '0');
putch_at(c++, ROWS + 4, '2');
putch_at(c++, ROWS + 4, '1');
init_block(&current, rand_type(), 4, 0);
score = 0;
draw_board();
}
void clear_screen() {
int *vram = ((int *) VRAM_BASE);
for (int i = 0; i < 600; ++i) vram[i] = 0x20202020;
}
extern void enable_interrupt();
int main() {
#ifdef DEBUG
unsigned char b[ROWS * COLS] = {0};
board = b;
for (int i = 0; i < SCREEN_ROWS * SCREEN_COLS; ++i) screen[i] = '%';
init();
#else
board = (unsigned char *) 16384;
for (int i = 0; i < 16384; i += 4) {
*((int*) (board + i)) = 0;
}
clear_screen();
init();
*((unsigned int *) 4) = 0xDEADBEEF;
enable_interrupt();
*TIMER_ENABLED = 1;
*TIMER_LIMIT = FALL_TIMER_LIMIT;
for (;;);
#endif
#ifdef DEBUG
on_input('a');
on_input('a');
on_input('s');
on_input('s');
on_input('s');
for (int i = 21; i >= 0; --i) {
on_timer();
}
on_input('d');
on_input('d');
on_input('d');
on_input('d');
for (int i = 21; i >= 0; --i) {
on_timer();
}
on_input('d');
on_input('d');
on_input('d');
on_input('d');
on_input('d');
for (int i = 21; i >= 0; --i) {
on_timer();
add_score(10);
}
print_score();
print_screen();
return 0;
#endif
}

20
lab2/csrc/toolchain.cmake Normal file
View File

@@ -0,0 +1,20 @@
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR riscv32)
set(triple riscv32-unknown-elf)
set(CMAKE_C_COMPILER clang)
set(CMAKE_C_COMPILER_TARGET ${triple})
set(CMAKE_CXX_COMPILER clang++)
set(CMAKE_CXX_COMPILER_TARGET ${triple})
set(CMAKE_ASM_COMPILER clang)
set(CMAKE_ASM_COMPILER_TARGET ${triple})
set(CMAKE_AR llvm-ar CACHE FILEPATH "Archiver")
set(CMAKE_OBJCOPY llvm-objcopy)
set(CMAKE_C_FLAGS_INIT "-mno-relax")
set(CMAKE_CXX_FLAGS_INIT "-mno-relax")
set(CMAKE_ASM_FLAGS_INIT "-mno-relax")
set(CMAKE_EXE_LINKER_FLAGS_INIT "-fuse-ld=lld -nostdlib -static -mno-relax")
set(CMAKE_MODULE_LINKER_FLAGS_INIT "-fuse-ld=lld -nostdlib -static -mno-relax")
set(CMAKE_SHARED_LINKER_FLAGS_INIT "-fuse-ld=lld -nostdlib -static -mno-relax")

View File

@@ -0,0 +1 @@
sbt.version = 1.9.6

1
lab2/project/plugins.sbt Normal file
View File

@@ -0,0 +1 @@
logLevel := Level.Warn

View File

@@ -0,0 +1,7 @@
export TARGETDIR ?= riscv-target
export XLEN = 32
export RISCV_TARGET = yatcpu
export RISCV_DEVICE =
export RISCV_TARGET_FLAGS =
export RISCV_ASSERT = 0
JOBS = -j1

View File

@@ -0,0 +1,54 @@
TARGET_SIM ?= verilog/verilator/obj_dir/VTop
TARGET_FLAGS ?= $(RISCV_TARGET_FLAGS)
ifeq ($(shell command -v $(TARGET_SIM) 2> /dev/null),)
$(error Target simulator executable '$(TARGET_SIM)` not found)
endif
RISCV_PREFIX ?= riscv64-unknown-elf-
RISCV_GCC ?= $(RISCV_PREFIX)gcc
RISCV_OBJDUMP ?= $(RISCV_PREFIX)objdump
RISCV_OBJCOPY ?= $(RISCV_PREFIX)objcopy
RISCV_GCC_OPTS ?= -g -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles $(RVTEST_DEFINES)
COMPILE_CMD = $$(RISCV_GCC) $(1) $$(RISCV_GCC_OPTS) \
-I$(ROOTDIR)/riscv-test-suite/env/ \
-I$(TARGETDIR)/$(RISCV_TARGET)/ \
-T$(TARGETDIR)/$(RISCV_TARGET)/link.ld \
$$(<) -o $$@
OBJDUMP_CMD = $$(RISCV_OBJDUMP) $$@ -D > $$@.objdump; \
$$(RISCV_OBJDUMP) $$@ --source > $$@.debug; \
$$(RISCV_OBJDUMP) -t $$@ | grep " begin_signature$$$$" | awk '{ print $$$$1 }' > $$@.begin_signature; \
$$(RISCV_OBJDUMP) -t $$@ | grep " end_signature$$$$" | awk '{ print $$$$1 }' > $$@.end_signature; \
$$(RISCV_OBJDUMP) -t $$@ | grep " tohost$$$$" | awk '{ print $$$$1 }' > $$@.halt \
OBJCOPY_CMD = $$(RISCV_OBJCOPY) $$@ -O binary -j .text -j .data -j .tohost $$@.asmbin
COMPILE_TARGET=\
$(COMPILE_CMD); \
if [ $$$$? -ne 0 ] ; \
then \
echo "\e[31m$$(RISCV_GCC) failed for target $$(@) \e[39m" ; \
exit 1 ; \
fi ; \
$(OBJDUMP_CMD); \
if [ $$$$? -ne 0 ] ; \
then \
echo "\e[31m $$(RISCV_OBJDUMP) failed for target $$(@) \e[39m" ; \
exit 1 ; \
fi ; \
$(OBJCOPY_CMD); \
if [ $$$$? -ne 0 ] ; \
then \
echo "\e[31m $$(RISCV_OBJCOPY) failed for target $$(@) \e[39m" ; \
exit 1 ; \
fi ; \
RUN_CMD = $(TARGET_SIM) $(TARGET_FLAGS) \
-signature 0x$(shell cat $(<).begin_signature) 0x$(shell cat $(<).end_signature) $(*).signature.output \
-halt 0x$(shell cat $(<).halt) \
-time 1000000 \
-instruction $(<).asmbin
RUN_TARGET = \
$(RUN_CMD)

View File

@@ -0,0 +1,12 @@
OUTPUT_ARCH( "riscv" )
ENTRY(rvtest_entry_point)
SECTIONS
{
. = 0x00001000;
.text : { *(.text.init) *(.text.startup) *(.text) }
.data ALIGN(0x1000) : { *(.data*) *(.rodata*) *(.sdata*) }
.tohost ALIGN(0x1000) : { *(.tohost) }
.bss : { *(.bss) }
_end = .;
}

View File

@@ -0,0 +1,46 @@
#ifndef _COMPLIANCE_MODEL_H_
#define _COMPLIANCE_MODEL_H_
#define ALIGNMENT 2
#define RVMODEL_DATA_SECTION \
.pushsection .tohost,"aw",@progbits; \
.align 4; .global tohost; tohost: .word 0; \
.popsection;
#define RVMODEL_BOOT
#define RVMODEL_HALT \
li x1, 0xBABECAFE; \
write_tohost: \
sw x1, tohost, x0; \
loop: j loop
//RV_COMPLIANCE_DATA_BEGIN
#define RVMODEL_DATA_BEGIN \
.align 4; .global begin_signature; begin_signature:
//RV_COMPLIANCE_DATA_END
#define RVMODEL_DATA_END \
.align 4; .global end_signature; end_signature: \
RVMODEL_DATA_SECTION \
//RVTEST_IO_INIT
#define RVMODEL_IO_INIT
//RVTEST_IO_WRITE_STR
#define RVMODEL_IO_WRITE_STR(_R, _STR)
//RVTEST_IO_CHECK
#define RVMODEL_IO_CHECK()
//RVTEST_IO_ASSERT_GPR_EQ
#define RVMODEL_IO_ASSERT_GPR_EQ(_S, _R, _I)
//RVTEST_IO_ASSERT_SFPR_EQ
#define RVMODEL_IO_ASSERT_SFPR_EQ(_F, _R, _I)
//RVTEST_IO_ASSERT_DFPR_EQ
#define RVMODEL_IO_ASSERT_DFPR_EQ(_D, _R, _I)
#define RVMODEL_SET_MSW_INT
#define RVMODEL_CLEAR_MSW_INT
#define RVMODEL_CLEAR_MTIMER_INT
#define RVMODEL_CLEAR_MEXT_INT
#endif

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -0,0 +1,54 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package board.basys3
import chisel3._
import chisel3.util._
class BCD2Segments extends Module {
val io = IO(new Bundle {
val bcd = Input(UInt(4.W))
val segs = Output(UInt(8.W))
})
val bcd = io.bcd
val segs = Wire(UInt(8.W))
segs := MuxLookup(
bcd,
0xFF.U,
IndexedSeq(
0.U -> "b10000001".U,
1.U -> "b11001111".U,
2.U -> "b10010010".U,
3.U -> "b10000110".U,
4.U -> "b11001100".U,
5.U -> "b10100100".U,
6.U -> "b10100000".U,
7.U -> "b10001111".U,
8.U -> "b10000000".U,
9.U -> "b10000100".U,
10.U -> "b00001000".U,
11.U -> "b01100000".U,
12.U -> "b00110001".U,
13.U -> "b01000010".U,
14.U -> "b00110000".U,
15.U -> "b00111000".U,
)
)
io.segs := segs
}

View File

@@ -0,0 +1,32 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package board.basys3
import chisel3._
class OnboardDigitDisplay extends Module {
val io = IO(new Bundle {
val digit_mask = Output(UInt(4.W))
})
val counter = RegInit(UInt(16.W), 0.U)
val digit_mask = RegInit(UInt(4.W), "b0111".U)
counter := counter + 1.U
when(counter === 0.U) {
digit_mask := (digit_mask << 1.U).asUInt + digit_mask(3)
}
io.digit_mask := digit_mask
}

View File

@@ -0,0 +1,34 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package board.basys3
import chisel3._
import chisel3.util._
class SYSULogo extends Module {
val io = IO(new Bundle {
val digit_mask = Input(UInt(4.W))
val segs = Output(UInt(8.W))
})
io.segs := MuxLookup(
io.digit_mask,
"b00100100".U, // "b0111".U, "b1101".U -> S
IndexedSeq(
"b1011".U -> "b01000100".U, // Y
"b1110".U -> "b01000001".U, // U
)
)
}

View File

@@ -0,0 +1,42 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package board.basys3
import chisel3._
import chisel3.util._
class SegmentMux extends Module {
val io = IO(new Bundle {
val digit_mask = Input(UInt(4.W))
val numbers = Input(UInt(16.W))
val segs = Output(UInt(8.W))
})
val digit = RegInit(UInt(4.W), 0.U)
val bcd2segs = Module(new BCD2Segments)
bcd2segs.io.bcd := digit
io.segs := bcd2segs.io.segs
digit := MuxLookup(
io.digit_mask,
io.numbers(3, 0), // "b1110".U
IndexedSeq(
"b1101".U -> io.numbers(7, 4),
"b1011".U -> io.numbers(11, 8),
"b0111".U -> io.numbers(15, 12)
)
)
}

View File

@@ -0,0 +1,138 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package board.basys3
import chisel3._
import chisel3.experimental.ChiselEnum
import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage}
import chisel3.util._
import peripheral.{CharacterDisplay, Dummy, InstructionROM, Memory, ROMLoader, Uart, VGADisplay, Timer}
import riscv._
import riscv.core.{CPU, ProgramCounter}
object BootStates extends ChiselEnum {
val Init, Loading, Finished = Value
}
class Top extends Module {
val binaryFilename = "tetris.asmbin"
val io = IO(new Bundle {
val switch = Input(UInt(16.W))
val segs = Output(UInt(8.W))
val digit_mask = Output(UInt(4.W))
val hsync = Output(Bool())
val vsync = Output(Bool())
val rgb = Output(UInt(12.W))
val led = Output(UInt(16.W))
val tx = Output(Bool())
val rx = Input(Bool())
})
val mem = Module(new Memory(Parameters.MemorySizeInWords))
val vga_display = Module(new VGADisplay)
val display = Module(new CharacterDisplay)
val timer = Module(new Timer)
val uart = Module(new Uart(frequency = 100000000, baudRate = 115200))
val dummy = Module(new Dummy)
display.io.bundle <> dummy.io.bundle
mem.io.bundle <> dummy.io.bundle
mem.io.debug_read_address := 0.U
timer.io.bundle <> dummy.io.bundle
uart.io.bundle <> dummy.io.bundle
io.tx := uart.io.txd
uart.io.rxd := io.rx
val instruction_rom = Module(new InstructionROM(binaryFilename))
val rom_loader = Module(new ROMLoader(instruction_rom.capacity))
rom_loader.io.rom_data := instruction_rom.io.data
rom_loader.io.load_address := Parameters.EntryAddress
instruction_rom.io.address := rom_loader.io.rom_address
val CPU_clkdiv = RegInit(UInt(2.W), 0.U)
val CPU_tick = Wire(Bool())
val CPU_next = Wire(UInt(2.W))
CPU_next := Mux(CPU_clkdiv === 3.U, 0.U, CPU_clkdiv + 1.U)
CPU_tick := CPU_clkdiv === 0.U
CPU_clkdiv := CPU_next
withClock(CPU_tick.asClock) {
val cpu = Module(new CPU)
cpu.io.interrupt_flag := Cat(uart.io.signal_interrupt, timer.io.signal_interrupt)
cpu.io.csr_regs_debug_read_address := 0.U
cpu.io.regs_debug_read_address := 0.U
cpu.io.instruction_valid := rom_loader.io.load_finished
mem.io.instruction_address := cpu.io.instruction_address
cpu.io.instruction := mem.io.instruction
when(!rom_loader.io.load_finished) {
rom_loader.io.bundle <> mem.io.bundle
cpu.io.memory_bundle.read_data := 0.U
}.otherwise {
rom_loader.io.bundle.read_data := 0.U
when(cpu.io.deviceSelect === 4.U) {
cpu.io.memory_bundle <> timer.io.bundle
}.elsewhen(cpu.io.deviceSelect === 2.U) {
cpu.io.memory_bundle <> uart.io.bundle
}.elsewhen(cpu.io.deviceSelect === 1.U) {
cpu.io.memory_bundle <> display.io.bundle
}.otherwise {
cpu.io.memory_bundle <> mem.io.bundle
}
}
}
display.io.x := vga_display.io.x
display.io.y := vga_display.io.y
io.hsync := vga_display.io.hsync
io.vsync := vga_display.io.vsync
io.rgb := display.io.rgb
mem.io.debug_read_address := io.switch(15, 1).asUInt << 2
io.led := Mux(
io.switch(0),
mem.io.debug_read_data(31, 16).asUInt,
mem.io.debug_read_data(15, 0).asUInt,
)
val onboard_display = Module(new OnboardDigitDisplay)
io.digit_mask := onboard_display.io.digit_mask
val sysu_logo = Module(new SYSULogo)
sysu_logo.io.digit_mask := io.digit_mask
val seg_mux = Module(new SegmentMux)
seg_mux.io.digit_mask := io.digit_mask
seg_mux.io.numbers := io.led
io.segs := MuxLookup(
io.switch,
seg_mux.io.segs,
IndexedSeq(
0.U -> sysu_logo.io.segs
)
)
}
object VerilogGenerator extends App {
(new ChiselStage).execute(Array("-X", "verilog", "-td", "verilog/basys3"), Seq(ChiselGeneratorAnnotation(() => new Top)))
}

View File

@@ -0,0 +1,109 @@
// Copyright 2022 Canbin Huang
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package board.pynq
import chisel3._
import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage}
import chisel3.util.Cat
import peripheral._
import riscv.Parameters
import riscv.core.{CPU, ProgramCounter}
class Top extends Module {
val binaryFilename = "hello.asmbin"
val io = IO(new Bundle() {
val hdmi_clk_n = Output(Bool())
val hdmi_clk_p = Output(Bool())
val hdmi_data_n = Output(UInt(3.W))
val hdmi_data_p = Output(UInt(3.W))
val hdmi_hpdn = Output(Bool())
val tx = Output(Bool())
val rx = Input(Bool())
val led = Output(UInt(4.W))
})
val mem = Module(new Memory(Parameters.MemorySizeInWords))
val hdmi_display = Module(new HDMIDisplay)
val display = Module(new CharacterDisplay)
val timer = Module(new Timer)
val uart = Module(new Uart(frequency = 125000000, baudRate = 115200))
val dummy = Module(new Dummy)
display.io.bundle <> dummy.io.bundle
mem.io.bundle <> dummy.io.bundle
mem.io.debug_read_address := 0.U
timer.io.bundle <> dummy.io.bundle
uart.io.bundle <> dummy.io.bundle
io.tx := uart.io.txd
uart.io.rxd := io.rx
val instruction_rom = Module(new InstructionROM(binaryFilename))
val rom_loader = Module(new ROMLoader(instruction_rom.capacity))
rom_loader.io.rom_data := instruction_rom.io.data
rom_loader.io.load_address := Parameters.EntryAddress
instruction_rom.io.address := rom_loader.io.rom_address
val CPU_clkdiv = RegInit(UInt(2.W),0.U)
val CPU_tick = Wire(Bool())
val CPU_next = Wire(UInt(2.W))
CPU_next := Mux(CPU_clkdiv === 3.U, 0.U, CPU_clkdiv + 1.U)
CPU_tick := CPU_clkdiv === 0.U
CPU_clkdiv := CPU_next
withClock(CPU_tick.asClock) {
val cpu = Module(new CPU)
cpu.io.interrupt_flag := Cat(uart.io.signal_interrupt, timer.io.signal_interrupt)
cpu.io.csr_regs_debug_read_address := 0.U
cpu.io.regs_debug_read_address := 0.U
cpu.io.instruction_valid := rom_loader.io.load_finished
mem.io.instruction_address := cpu.io.instruction_address
cpu.io.instruction := mem.io.instruction
when(!rom_loader.io.load_finished) {
rom_loader.io.bundle <> mem.io.bundle
cpu.io.memory_bundle.read_data := 0.U
}.otherwise {
rom_loader.io.bundle.read_data := 0.U
when(cpu.io.deviceSelect === 4.U) {
cpu.io.memory_bundle <> timer.io.bundle
}.elsewhen(cpu.io.deviceSelect === 2.U) {
cpu.io.memory_bundle <> uart.io.bundle
}.elsewhen(cpu.io.deviceSelect === 1.U) {
cpu.io.memory_bundle <> display.io.bundle
}.otherwise {
cpu.io.memory_bundle <> mem.io.bundle
}
}
}
io.led := 15.U(4.W)
display.io.x := hdmi_display.io.x
display.io.y := hdmi_display.io.y
display.io.video_on := hdmi_display.io.video_on
hdmi_display.io.rgb := display.io.rgb
io.hdmi_hpdn := 1.U
io.hdmi_data_n := hdmi_display.io.TMDSdata_n
io.hdmi_data_p := hdmi_display.io.TMDSdata_p
io.hdmi_clk_n := hdmi_display.io.TMDSclk_n
io.hdmi_clk_p := hdmi_display.io.TMDSclk_p
}
object VerilogGenerator extends App {
(new ChiselStage).execute(Array("-X", "verilog", "-td", "verilog/pynq"), Seq(ChiselGeneratorAnnotation(() => new Top)))
}

View File

@@ -0,0 +1,45 @@
// Copyright 2022 Canbin Huang
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package board.verilator
import chisel3._
import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage}
import peripheral._
import riscv.{CPUBundle, Parameters}
import riscv.core.CPU
class Top extends Module {
val io = IO(new CPUBundle)
val cpu = Module(new CPU)
io.deviceSelect := 0.U
cpu.io.regs_debug_read_address := io.regs_debug_read_address
cpu.io.csr_regs_debug_read_address := io.csr_regs_debug_read_address
io.csr_regs_debug_read_data := cpu.io.csr_regs_debug_read_data
io.regs_debug_read_data := cpu.io.regs_debug_read_data
io.memory_bundle <> cpu.io.memory_bundle
io.instruction_address := cpu.io.instruction_address
cpu.io.instruction := io.instruction
cpu.io.interrupt_flag := io.interrupt_flag
cpu.io.instruction_valid := io.instruction_valid
}
object VerilogGenerator extends App {
(new ChiselStage).execute(Array("-X", "verilog", "-td", "verilog/verilator"), Seq(ChiselGeneratorAnnotation(() =>
new Top())))
}

View File

@@ -0,0 +1,84 @@
// Copyright 2022 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package peripheral
import chisel3.util.{MuxLookup, log2Up}
import chisel3.{Bool, Bundle, Module, Mux, Output, UInt, Wire, _}
import peripheral.ScreenInfo.{DisplayHorizontal, DisplayVertical}
import riscv.Parameters
object GlyphInfo {
val glyphWidth = 8
val glyphHeight = 16
// ASCII printable characters start from here
val spaceIndex = 1
}
object ScreenInfo {
val DisplayHorizontal = 640
val DisplayVertical = 480
}
object CharacterBufferInfo {
val CharCols = DisplayHorizontal / GlyphInfo.glyphWidth
val CharRows = DisplayVertical / GlyphInfo.glyphHeight
val Chars = CharCols * CharRows
}
class CharacterDisplay extends Module {
val io = IO(new Bundle() {
val bundle = new RAMBundle()
val x = Input(UInt(16.W))
val y = Input(UInt(16.W))
val video_on = Input(Bool())
val rgb = Output(UInt(24.W))
})
val mem = Module(new BlockRAM(CharacterBufferInfo.Chars / Parameters.WordSize))
mem.io.write_enable := io.bundle.write_enable
mem.io.write_data := io.bundle.write_data
mem.io.write_address := io.bundle.address
mem.io.write_strobe := io.bundle.write_strobe
mem.io.read_address := io.bundle.address
io.bundle.read_data := mem.io.read_data
val font_rom = Module(new FontROM)
val row = (io.y >> log2Up(GlyphInfo.glyphHeight)).asUInt
val col = (io.x >> log2Up(GlyphInfo.glyphWidth)).asUInt
val char_index = (row * CharacterBufferInfo.CharCols.U) + col
val offset = char_index(1, 0)
val ch = Wire(UInt(8.W))
mem.io.debug_read_address := char_index
ch := MuxLookup(
offset,
0.U,
IndexedSeq(
0.U -> mem.io.debug_read_data(7, 0).asUInt,
1.U -> mem.io.debug_read_data(15, 8).asUInt,
2.U -> mem.io.debug_read_data(23, 16).asUInt,
3.U -> mem.io.debug_read_data(31, 24).asUInt
)
)
font_rom.io.glyph_index := Mux(ch >= 32.U, ch - 31.U, 0.U)
font_rom.io.glyph_y := io.y(log2Up(GlyphInfo.glyphHeight) - 1, 0)
// White if pixel_on and glyph pixel on
val glyph_x = io.x(log2Up(GlyphInfo.glyphWidth) - 1, 0)
io.rgb := Mux(io.video_on && font_rom.io.glyph_pixel_byte(glyph_x), 0xFFFFFF.U, 0.U)
}

View File

@@ -0,0 +1,29 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package peripheral
import chisel3._
import riscv.Parameters
// A dummy master that never initiates reads or writes
class Dummy extends Module {
val io = IO(new Bundle {
val bundle = Flipped(new RAMBundle)
})
io.bundle.write_strobe := VecInit(Seq.fill(Parameters.WordSize)(false.B))
io.bundle.write_data := 0.U
io.bundle.write_enable := false.B
io.bundle.address := 0.U
}

View File

@@ -0,0 +1,64 @@
package peripheral
import chisel3.experimental.{ChiselAnnotation, annotate}
import chisel3.util.experimental.loadMemoryFromFileInline
import chisel3.{Bundle, Input, Module, Output, SyncReadMem, UInt, _}
import firrtl.annotations.MemorySynthInit
import java.io.FileWriter
import java.nio.file.Paths
import javax.imageio.ImageIO
class FontROM(fontBitmapFilename: String = "vga_font_8x16.bmp") extends Module {
val glyphWidth = GlyphInfo.glyphWidth
val glyphHeight = GlyphInfo.glyphHeight
val io = IO(new Bundle {
val glyph_index = Input(UInt(7.W))
val glyph_y = Input(UInt(4.W))
val glyph_pixel_byte = Output(UInt(8.W))
})
annotate(new ChiselAnnotation {
override def toFirrtl =
MemorySynthInit
})
val (hexTxtPath, glyphCount) = readFontBitmap()
val mem = SyncReadMem(glyphCount, UInt(8.W))
loadMemoryFromFileInline(mem, hexTxtPath.toString.replaceAll("\\\\", "/"))
io.glyph_pixel_byte := mem.read(io.glyph_index * GlyphInfo.glyphHeight.U + io.glyph_y, true.B)
def readFontBitmap() = {
val inputStream = getClass.getClassLoader.getResourceAsStream(fontBitmapFilename)
val image = ImageIO.read(inputStream)
val glyphColumns = image.getWidth() / glyphWidth
val glyphRows = image.getHeight / glyphHeight
val glyphCount = glyphColumns * glyphRows
val glyphs = new Array[UInt](glyphCount * GlyphInfo.glyphHeight)
for (row <- 0 until glyphRows) {
for (col <- 0 until glyphColumns) {
for (i <- 0 until glyphHeight) {
var lineInt = 0
for (j <- 0 until glyphWidth) {
if (image.getRGB(col * glyphWidth + j, row * glyphHeight + i) != 0xFFFFFFFF) {
lineInt |= (1 << j)
}
}
glyphs((row * glyphColumns + col) * GlyphInfo.glyphHeight + i) = lineInt.U(8.W)
}
}
}
val currentDir = System.getProperty("user.dir")
val hexTxtPath = Paths.get(currentDir, "verilog", f"${fontBitmapFilename}.txt")
val writer = new FileWriter(hexTxtPath.toString)
for (i <- glyphs.indices) {
writer.write(f"@$i%x\n${glyphs(i).litValue}%02x\n")
}
writer.close()
(hexTxtPath, glyphs.length)
}
}

View File

@@ -0,0 +1,394 @@
// Copyright 2022 hrpccs
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package peripheral
import chisel3._
import chisel3.util._
class HDMISync extends Module {
val io = IO(new Bundle {
val hsync = Output(Bool())
val vsync = Output(Bool())
val video_on = Output(Bool())
val p_tick = Output(Bool())
val f_tick = Output(Bool())
val x = Output(UInt(10.W))
val y = Output(UInt(10.W))
val x_next = Output(UInt(10.W))
val y_next = Output(UInt(10.W))
})
val DisplayHorizontal = ScreenInfo.DisplayHorizontal
val DisplayVertical = ScreenInfo.DisplayVertical
val BorderLeft = 48
val BorderRight = 16
val BorderTop = 10
val BorderBottom = 33
val RetraceHorizontal = 96
val RetraceVertical = 2
val MaxHorizontal = DisplayHorizontal + BorderLeft + BorderRight + RetraceHorizontal - 1
val MaxVertical = DisplayVertical + BorderTop + BorderBottom + RetraceVertical - 1
val RetraceHorizontalStart = DisplayHorizontal + BorderRight
val RetraceHorizontalEnd = RetraceHorizontalStart + RetraceHorizontal - 1
val RetraceVerticalStart = DisplayVertical + BorderBottom
val RetraceVerticalEnd = RetraceVerticalStart + RetraceVertical - 1
val pixel = RegInit(UInt(3.W), 0.U)
val pixel_next = Wire(UInt(3.W))
val pixel_tick = Wire(Bool())
val v_count_reg = RegInit(UInt(10.W), 0.U)
val h_count_reg = RegInit(UInt(10.W), 0.U)
val v_count_next = Wire(UInt(10.W))
val h_count_next = Wire(UInt(10.W))
val vsync_reg = RegInit(Bool(), false.B)
val hsync_reg = RegInit(Bool(), false.B)
val vsync_next = Wire(Bool())
val hsync_next = Wire(Bool())
pixel_next := Mux(pixel === 4.U, 0.U, pixel + 1.U)
pixel_tick := pixel === 0.U
h_count_next := Mux(
pixel_tick,
Mux(h_count_reg === MaxHorizontal.U, 0.U, h_count_reg + 1.U),
h_count_reg
)
v_count_next := Mux(
pixel_tick && h_count_reg === MaxHorizontal.U,
Mux(v_count_reg === MaxVertical.U, 0.U, v_count_reg + 1.U),
v_count_reg
)
hsync_next := h_count_reg >= RetraceHorizontalStart.U && h_count_reg <= RetraceHorizontalEnd.U
vsync_next := v_count_reg >= RetraceVerticalStart.U && v_count_reg <= RetraceVerticalEnd.U
pixel := pixel_next
hsync_reg := hsync_next
vsync_reg := vsync_next
v_count_reg := v_count_next
h_count_reg := h_count_next
io.video_on := h_count_reg < DisplayHorizontal.U && v_count_reg < DisplayVertical.U
io.hsync := hsync_reg
io.vsync := vsync_reg
io.x := h_count_reg
io.y := v_count_reg
io.x_next := h_count_next
io.y_next := v_count_next
io.p_tick := pixel_tick
io.f_tick := io.x === 0.U && io.y === 0.U
}
class TMDS_encoder extends Module {
val io = IO(new Bundle() {
val video_data = Input(UInt(8.W)) //r,g,b,8bit
val control_data = Input(UInt(2.W))
val video_on = Input(Bool())
val TMDS = Output(UInt(10.W))
})
val Nb1s = PopCount(io.video_data)
val xored = xorfct(io.video_data)
val xnored = xnorfct(io.video_data)
val XNOR = (Nb1s > 4.U(4.W)) || (Nb1s === 4.U(4.W) && io.video_data(0) === 0.U)
val q_m = RegInit(0.U(9.W))
val diffSize = 4
val diff = RegInit(0.S(diffSize.W))
q_m := Mux(
XNOR,
xnored,
xored
)
val disparitySize = 4
val disparityReg = RegInit(0.S(disparitySize.W))
diff := PopCount(q_m).asSInt - 4.S
val doutReg = RegInit("b1010101011".U(10.W))
def xorfct(value: UInt): UInt = {
val vin = VecInit(value.asBools)
val res = VecInit(511.U.asBools)
res(0) := vin(0)
for (i <- 1 to 7) {
res(i) := res(i - 1) ^ vin(i)
}
res(8) := 1.U
res.asUInt
}
def xnorfct(value: UInt): UInt = {
val vin = VecInit(value.asBools)
val res = VecInit(511.U.asBools)
res(0) := vin(0)
for (i <- 1 to 7) {
res(i) := !(res(i - 1) ^ vin(i))
}
res(8) := 0.U
res.asUInt
}
when(io.video_on === false.B) {
disparityReg := 0.S
doutReg := "b1010101011".U(10.W)
switch(io.control_data) {
is("b00".U(2.W)) {
doutReg := "b1101010100".U(10.W)
}
is("b01".U(2.W)) {
doutReg := "b0010101011".U(10.W)
}
is("b10".U(2.W)) {
doutReg := "b0101010100".U(10.W)
}
}
}.otherwise {
when(disparityReg === 0.S || diff === 0.S) {
when(q_m(8) === false.B) {
doutReg := "b10".U(2.W) ## ~q_m(7, 0)
disparityReg := disparityReg - diff
}.otherwise {
doutReg := "b01".U(2.W) ## q_m(7, 0)
disparityReg := disparityReg + diff
}
}.elsewhen((!diff(diffSize - 1) && !disparityReg(disparitySize - 1))
|| (diff(diffSize - 1) && disparityReg(disparitySize - 1))) {
doutReg := 1.U(1.W) ## q_m(8) ## ~q_m(7, 0)
when(q_m(8)) {
disparityReg := disparityReg + 1.S - diff
}.otherwise {
disparityReg := disparityReg - diff
}
}.otherwise {
doutReg := 0.U(1.W) ## q_m
when(q_m(8)) {
disparityReg := disparityReg + diff
}.otherwise {
disparityReg := disparityReg - 1.S + diff
}
}
}
io.TMDS := doutReg
}
class HDMIDisplay extends Module {
val io = IO(new Bundle() {
val rgb = Input(UInt(24.W))
val x = Output(UInt(16.W))
val y = Output(UInt(16.W))
val x_next = Output(UInt(16.W))
val y_next = Output(UInt(16.W))
val video_on = Output(Bool())
val TMDSclk_p = Output(Bool())
val TMDSdata_p = Output(UInt(3.W))
val TMDSclk_n = Output(Bool())
val TMDSdata_n = Output(UInt(3.W))
})
val rgb = io.rgb
val pixel_clk = Wire(Bool())
val hsync = Wire(Bool())
val vsync = Wire(Bool())
val sync = Module(new HDMISync)
io.x := sync.io.x
io.y := sync.io.y
io.x_next := sync.io.x_next
io.y_next := sync.io.y_next
io.video_on := sync.io.video_on
hsync := sync.io.hsync
vsync := sync.io.vsync
pixel_clk := sync.io.p_tick
// TMDS_PLLVR is a vivado IP core, check it in /verilog/pynq/TMDS_PLLVR.v
val serial_clk = Wire(Clock())
val pll_lock = Wire(Bool())
val tmdspll = Module(new TMDS_PLLVR)
val rst = Wire(Reset())
tmdspll.io.clkin := pixel_clk.asClock
serial_clk := tmdspll.io.clkout
pll_lock := tmdspll.io.lock
tmdspll.io.reset := reset
rst := ~pll_lock
val tmds = Wire(UInt(3.W))
val tmds_clk = Wire(Bool())
withClockAndReset(pixel_clk.asClock, rst) {
val tmds_channel1 = Wire(UInt(10.W))
val tmds_channel2 = Wire(UInt(10.W))
val tmds_channel0 = Wire(UInt(10.W))
val tmds_green = Module(new TMDS_encoder)
val tmds_red = Module(new TMDS_encoder)
val tmds_blue = Module(new TMDS_encoder)
tmds_red.io.video_on := sync.io.video_on
tmds_blue.io.video_on := sync.io.video_on
tmds_green.io.video_on := sync.io.video_on
tmds_blue.io.control_data := sync.io.vsync ## sync.io.hsync
tmds_green.io.control_data := 0.U
tmds_red.io.control_data := 0.U
tmds_red.io.video_data := rgb(23, 16)
tmds_blue.io.video_data := rgb(7, 0)
tmds_green.io.video_data := rgb(15, 8)
tmds_channel0 := tmds_blue.io.TMDS
tmds_channel1 := tmds_green.io.TMDS
tmds_channel2 := tmds_red.io.TMDS
val serdesBlue = Module(new Oser10Module())
serdesBlue.io.data := tmds_channel0
serdesBlue.io.fclk := serial_clk
val serdesGreen = Module(new Oser10Module())
serdesGreen.io.data := tmds_channel1
serdesGreen.io.fclk := serial_clk
val serdesRed = Module(new Oser10Module())
serdesRed.io.data := tmds_channel2
serdesRed.io.fclk := serial_clk
tmds := serdesRed.io.q ## serdesGreen.io.q ## serdesBlue.io.q
//serdesCLk : 25Mhz ,Why not directly use p_tick?
//cause Duty Ratio of p_tick is 10% , while which of serdesCLk is 50%
val serdesClk = Module(new Oser10Module())
serdesClk.io.data := "b1111100000".U(10.W)
serdesClk.io.fclk := serial_clk
tmds_clk := serdesClk.io.q
val buffDiffBlue = Module(new OBUFDS)
buffDiffBlue.io.I := tmds(0)
val buffDiffGreen = Module(new OBUFDS)
buffDiffGreen.io.I := tmds(1)
val buffDiffRed = Module(new OBUFDS)
buffDiffRed.io.I := tmds(2)
val buffDiffClk = Module(new OBUFDS)
buffDiffClk.io.I := tmds_clk
io.TMDSclk_p := buffDiffClk.io.O
io.TMDSclk_n := buffDiffClk.io.OB
io.TMDSdata_p := buffDiffRed.io.O ## buffDiffGreen.io.O ## buffDiffBlue.io.O
io.TMDSdata_n := buffDiffRed.io.OB ## buffDiffGreen.io.OB ## buffDiffBlue.io.OB
}
}
//----------------------------------------
//PLL frequency multiplier using BlackBox
class TMDS_PLLVR extends BlackBox {
val io = IO(new Bundle {
val clkin = Input(Clock())
val reset = Input(Reset())
val clkout = Output(Clock())
val clkoutd = Output(Clock())
val lock = Output(Bool())
})
}
/* OSER10 : serializer 10:1*/
class OSER10 extends Module {
val io = IO(new Bundle {
val Q = Output(Bool()) // OSER10 data output signal
val D0 = Input(Bool())
val D1 = Input(Bool())
val D2 = Input(Bool())
val D3 = Input(Bool())
val D4 = Input(Bool())
val D5 = Input(Bool())
val D6 = Input(Bool())
val D7 = Input(Bool())
val D8 = Input(Bool())
val D9 = Input(Bool()) // OSER10 data input signal
val PCLK = Input(Clock()) // Primary clock input signal
val FCLK = Input(Clock()) // High speed clock input signal
val RESET = Input(Reset()) // Asynchronous reset input signal,
//active-high.
})
withClockAndReset(io.FCLK, io.RESET) {
val count = RegInit(0.U(4.W))
val countnext = Wire(UInt(4.W))
io.Q := MuxLookup(
count,
0.U,
IndexedSeq(
0.U -> io.D0.asBool,
1.U -> io.D1.asBool,
2.U -> io.D2.asBool,
3.U -> io.D3.asBool,
4.U -> io.D4.asBool,
5.U -> io.D5.asBool,
6.U -> io.D6.asBool,
7.U -> io.D7.asBool,
8.U -> io.D8.asBool,
9.U -> io.D9.asBool
)
)
countnext := Mux(
count === 9.U, 0.U, count + 1.U
)
count := countnext
}
}
class Oser10Module extends Module {
val io = IO(new Bundle {
val q = Output(Bool())
val data = Input(UInt(10.W))
val fclk = Input(Clock()) // Fast clock
})
val osr10 = Module(new OSER10())
io.q := osr10.io.Q
osr10.io.D0 := io.data(0)
osr10.io.D1 := io.data(1)
osr10.io.D2 := io.data(2)
osr10.io.D3 := io.data(3)
osr10.io.D4 := io.data(4)
osr10.io.D5 := io.data(5)
osr10.io.D6 := io.data(6)
osr10.io.D7 := io.data(7)
osr10.io.D8 := io.data(8)
osr10.io.D9 := io.data(9)
osr10.io.PCLK := clock
osr10.io.FCLK := io.fclk
osr10.io.RESET := reset
}
/* lvds output */
class OBUFDS extends BlackBox {
val io = IO(new Bundle {
val O = Output(Bool())
val OB = Output(Bool())
val I = Input(Bool())
})
}
//-----------------------------------------
//-----------------------------------------

View File

@@ -0,0 +1,68 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package peripheral
import chisel3._
import chisel3.experimental.{ChiselAnnotation, annotate}
import chisel3.util.experimental.loadMemoryFromFileInline
import firrtl.annotations.MemorySynthInit
import riscv.Parameters
import java.io.FileWriter
import java.nio.file.{Files, Paths}
import java.nio.{ByteBuffer, ByteOrder}
class InstructionROM(instructionFilename: String) extends Module {
val io = IO(new Bundle {
val address = Input(UInt(Parameters.AddrWidth))
val data = Output(UInt(Parameters.InstructionWidth))
})
val (instructionsInitFile, capacity) = readAsmBinary(instructionFilename)
val mem = Mem(capacity, UInt(Parameters.InstructionWidth))
annotate(new ChiselAnnotation {
override def toFirrtl =
MemorySynthInit
})
loadMemoryFromFileInline(mem, instructionsInitFile.toString.replaceAll("\\\\", "/"))
io.data := mem.read(io.address)
def readAsmBinary(filename: String) = {
val inputStream = if (Files.exists(Paths.get(filename))) {
Files.newInputStream(Paths.get(filename))
} else {
getClass.getClassLoader.getResourceAsStream(filename)
}
var instructions = new Array[BigInt](0)
val arr = new Array[Byte](4)
while (inputStream.read(arr) == 4) {
val instBuf = ByteBuffer.wrap(arr)
instBuf.order(ByteOrder.LITTLE_ENDIAN)
val inst = BigInt(instBuf.getInt() & 0xFFFFFFFFL)
instructions = instructions :+ inst
}
instructions = instructions :+ BigInt(0x00000013L)
instructions = instructions :+ BigInt(0x00000013L)
instructions = instructions :+ BigInt(0x00000013L)
val currentDir = System.getProperty("user.dir")
val exeTxtPath = Paths.get(currentDir, "verilog", f"${instructionFilename}.txt")
val writer = new FileWriter(exeTxtPath.toString)
for (i <- instructions.indices) {
writer.write(f"@$i%x\n${instructions(i)}%08x\n")
}
writer.close()
(exeTxtPath, instructions.length)
}
}

View File

@@ -0,0 +1,77 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package peripheral
import chisel3._
import chisel3.util._
import riscv.Parameters
class RAMBundle extends Bundle {
val address = Input(UInt(Parameters.AddrWidth))
val write_data = Input(UInt(Parameters.DataWidth))
val write_enable = Input(Bool())
val write_strobe = Input(Vec(Parameters.WordSize, Bool()))
val read_data = Output(UInt(Parameters.DataWidth))
}
// The purpose of this module is to help the synthesis tool recognize
// our memory as a Block RAM template
class BlockRAM(capacity: Int) extends Module {
val io = IO(new Bundle {
val read_address = Input(UInt(Parameters.AddrWidth))
val write_address = Input(UInt(Parameters.AddrWidth))
val write_data = Input(UInt(Parameters.DataWidth))
val write_enable = Input(Bool())
val write_strobe = Input(Vec(Parameters.WordSize, Bool()))
val debug_read_address = Input(UInt(Parameters.AddrWidth))
val read_data = Output(UInt(Parameters.DataWidth))
val debug_read_data = Output(UInt(Parameters.DataWidth))
})
val mem = SyncReadMem(capacity, Vec(Parameters.WordSize, UInt(Parameters.ByteWidth)))
when(io.write_enable) {
val write_data_vec = Wire(Vec(Parameters.WordSize, UInt(Parameters.ByteWidth)))
for (i <- 0 until Parameters.WordSize) {
write_data_vec(i) := io.write_data((i + 1) * Parameters.ByteBits - 1, i * Parameters.ByteBits)
}
mem.write((io.write_address >> 2.U).asUInt, write_data_vec, io.write_strobe)
}
io.read_data := mem.read((io.read_address >> 2.U).asUInt, true.B).asUInt
io.debug_read_data := mem.read((io.debug_read_address >> 2.U).asUInt, true.B).asUInt
}
class Memory(capacity: Int) extends Module {
val io = IO(new Bundle {
val bundle = new RAMBundle
val instruction = Output(UInt(Parameters.DataWidth))
val instruction_address = Input(UInt(Parameters.AddrWidth))
val debug_read_address = Input(UInt(Parameters.AddrWidth))
val debug_read_data = Output(UInt(Parameters.DataWidth))
})
val mem = SyncReadMem(capacity, Vec(Parameters.WordSize, UInt(Parameters.ByteWidth)))
when(io.bundle.write_enable) {
val write_data_vec = Wire(Vec(Parameters.WordSize, UInt(Parameters.ByteWidth)))
for (i <- 0 until Parameters.WordSize) {
write_data_vec(i) := io.bundle.write_data((i + 1) * Parameters.ByteBits - 1, i * Parameters.ByteBits)
}
mem.write((io.bundle.address >> 2.U).asUInt, write_data_vec, io.bundle.write_strobe)
}
io.bundle.read_data := mem.read((io.bundle.address >> 2.U).asUInt, true.B).asUInt
io.debug_read_data := mem.read((io.debug_read_address >> 2.U).asUInt, true.B).asUInt
io.instruction := mem.read((io.instruction_address >> 2.U).asUInt, true.B).asUInt
}

View File

@@ -0,0 +1,50 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package peripheral
import chisel3._
import riscv.Parameters
class ROMLoader(capacity: Int) extends Module {
val io = IO(new Bundle {
val bundle = Flipped(new RAMBundle)
val rom_address = Output(UInt(Parameters.AddrWidth))
val rom_data = Input(UInt(Parameters.InstructionWidth))
val load_address = Input(UInt(Parameters.AddrWidth))
val load_finished = Output(Bool())
})
val address = RegInit(0.U(32.W))
val valid = RegInit(false.B)
io.bundle.write_strobe := VecInit(Seq.fill(Parameters.WordSize)(false.B))
io.bundle.address := 0.U
io.bundle.write_data := 0.U
io.bundle.write_enable := false.B
when(address <= (capacity - 1).U) {
io.bundle.write_enable := true.B
io.bundle.write_data := io.rom_data
io.bundle.address := (address << 2.U).asUInt + io.load_address
io.bundle.write_strobe := VecInit(Seq.fill(Parameters.WordSize)(true.B))
address := address + 1.U
when(address === (capacity - 1).U) {
valid := true.B
}
}
io.load_finished := valid
io.rom_address := address
}

View File

@@ -0,0 +1,38 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package peripheral
import chisel3._
import chisel3.util._
import riscv.Parameters
class Timer extends Module {
val io = IO(new Bundle {
val bundle = new RAMBundle
val signal_interrupt = Output(Bool())
val debug_limit = Output(UInt(Parameters.DataWidth))
val debug_enabled = Output(Bool())
})
val count = RegInit(0.U(32.W))
val limit = RegInit(100000000.U(32.W))
io.debug_limit := limit
val enabled = RegInit(true.B)
io.debug_enabled := enabled
//lab2(CLINTCSR)
//finish the read-write for count,limit,enabled. And produce appropriate signal_interrupt
}

View File

@@ -0,0 +1,204 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package peripheral
import chisel3._
import chisel3.util._
class UartIO extends DecoupledIO(UInt(8.W)) {
}
/**
* Transmit part of the UART.
* A minimal version without any additional buffering.
* Use a ready/valid handshaking.
*/
class Tx(frequency: Int, baudRate: Int) extends Module {
val io = IO(new Bundle {
val txd = Output(UInt(1.W))
val channel = Flipped(new UartIO())
})
val BIT_CNT = ((frequency + baudRate / 2) / baudRate - 1).U
val shiftReg = RegInit(0x7ff.U)
val cntReg = RegInit(0.U(20.W))
val bitsReg = RegInit(0.U(4.W))
io.channel.ready := (cntReg === 0.U) && (bitsReg === 0.U)
io.txd := shiftReg(0)
when(cntReg === 0.U) {
cntReg := BIT_CNT
when(bitsReg =/= 0.U) {
val shift = shiftReg >> 1
shiftReg := Cat(1.U, shift(9, 0))
bitsReg := bitsReg - 1.U
}.otherwise {
when(io.channel.valid) {
shiftReg := Cat(Cat(3.U, io.channel.bits), 0.U) // two stop bits, data, one start bit
bitsReg := 11.U
}.otherwise {
shiftReg := 0x7ff.U
}
}
}.otherwise {
cntReg := cntReg - 1.U
}
}
/**
* Receive part of the UART.
* A minimal version without any additional buffering.
* Use a ready/valid handshaking.
*
* The following code is inspired by Tommy's receive code at:
* https://github.com/tommythorn/yarvi
*/
class Rx(frequency: Int, baudRate: Int) extends Module {
val io = IO(new Bundle {
val rxd = Input(UInt(1.W))
val channel = new UartIO()
})
val BIT_CNT = ((frequency + baudRate / 2) / baudRate - 1).U
val START_CNT = ((3 * frequency / 2 + baudRate / 2) / baudRate - 1).U
// Sync in the asynchronous RX data, reset to 1 to not start reading after a reset
val rxReg = RegNext(RegNext(io.rxd, 1.U), 1.U)
val shiftReg = RegInit(0.U(8.W))
val cntReg = RegInit(0.U(20.W))
val bitsReg = RegInit(0.U(4.W))
val valReg = RegInit(false.B)
when(cntReg =/= 0.U) {
cntReg := cntReg - 1.U
}.elsewhen(bitsReg =/= 0.U) {
cntReg := BIT_CNT
shiftReg := Cat(rxReg, shiftReg >> 1)
bitsReg := bitsReg - 1.U
// the last shifted in
when(bitsReg === 1.U) {
valReg := true.B
}
}.elsewhen(rxReg === 0.U) { // wait 1.5 bits after falling edge of start
cntReg := START_CNT
bitsReg := 8.U
}
when(valReg && io.channel.ready) {
valReg := false.B
}
io.channel.bits := shiftReg
io.channel.valid := valReg
}
/**
* A single byte buffer with a ready/valid interface
*/
class Buffer extends Module {
val io = IO(new Bundle {
val in = Flipped(new UartIO())
val out = new UartIO()
})
val empty :: full :: Nil = Enum(2)
val stateReg = RegInit(empty)
val dataReg = RegInit(0.U(8.W))
io.in.ready := stateReg === empty
io.out.valid := stateReg === full
when(stateReg === empty) {
when(io.in.valid) {
dataReg := io.in.bits
stateReg := full
}
}.otherwise { // full
when(io.out.ready) {
stateReg := empty
}
}
io.out.bits := dataReg
}
/**
* A transmitter with a single buffer.
*/
class BufferedTx(frequency: Int, baudRate: Int) extends Module {
val io = IO(new Bundle {
val txd = Output(UInt(1.W))
val channel = Flipped(new UartIO())
})
val tx = Module(new Tx(frequency, baudRate))
val buf = Module(new Buffer)
buf.io.in <> io.channel
tx.io.channel <> buf.io.out
io.txd <> tx.io.txd
}
class Uart(frequency: Int, baudRate: Int) extends Module {
val io = IO(new Bundle {
val bundle = new RAMBundle
val rxd = Input(UInt(1.W))
val txd = Output(UInt(1.W))
val signal_interrupt = Output(Bool())
})
val interrupt = RegInit(false.B)
val rxData = RegInit(0.U)
val tx = Module(new BufferedTx(frequency, baudRate))
val rx = Module(new Rx(frequency, baudRate))
io.bundle.read_data := 0.U
when(io.bundle.address === 0x4.U) {
io.bundle.read_data := baudRate.U
}.elsewhen(io.bundle.address === 0xC.U) {
io.bundle.read_data := rxData
interrupt := false.B
}
tx.io.channel.valid := false.B
tx.io.channel.bits := 0.U
when(io.bundle.write_enable) {
when(io.bundle.address === 0x8.U) {
interrupt := io.bundle.write_data =/= 0.U
}.elsewhen(io.bundle.address === 0x10.U) {
tx.io.channel.valid := true.B
tx.io.channel.bits := io.bundle.write_data
}
}
io.txd := tx.io.txd
rx.io.rxd := io.rxd
io.signal_interrupt := interrupt
rx.io.channel.ready := false.B
when(rx.io.channel.valid) {
rx.io.channel.ready := true.B
rxData := rx.io.channel.bits
interrupt := true.B
}
}

View File

@@ -0,0 +1,116 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package peripheral
import chisel3._
class VGASync extends Module {
val io = IO(new Bundle {
val hsync = Output(Bool())
val vsync = Output(Bool())
val video_on = Output(Bool())
val p_tick = Output(Bool())
val f_tick = Output(Bool())
val x = Output(UInt(10.W))
val y = Output(UInt(10.W))
})
val DisplayHorizontal = ScreenInfo.DisplayHorizontal
val DisplayVertical = ScreenInfo.DisplayVertical
val BorderLeft = 48
val BorderRight = 16
val BorderTop = 10
val BorderBottom = 33
val RetraceHorizontal = 96
val RetraceVertical = 2
val MaxHorizontal = DisplayHorizontal + BorderLeft + BorderRight + RetraceHorizontal - 1
val MaxVertical = DisplayVertical + BorderTop + BorderBottom + RetraceVertical - 1
val RetraceHorizontalStart = DisplayHorizontal + BorderRight
val RetraceHorizontalEnd = RetraceHorizontalStart + RetraceHorizontal - 1
val RetraceVerticalStart = DisplayVertical + BorderBottom
val RetraceVerticalEnd = RetraceVerticalStart + RetraceVertical - 1
val pixel = RegInit(UInt(2.W), 0.U)
val pixel_next = Wire(UInt(2.W))
val pixel_tick = Wire(Bool())
val v_count_reg = RegInit(UInt(10.W), 0.U)
val h_count_reg = RegInit(UInt(10.W), 0.U)
val v_count_next = Wire(UInt(10.W))
val h_count_next = Wire(UInt(10.W))
val vsync_reg = RegInit(Bool(), false.B)
val hsync_reg = RegInit(Bool(), false.B)
val vsync_next = Wire(Bool())
val hsync_next = Wire(Bool())
pixel_next := pixel + 1.U
pixel_tick := pixel === 0.U
h_count_next := Mux(
pixel_tick,
Mux(h_count_reg === MaxHorizontal.U, 0.U, h_count_reg + 1.U),
h_count_reg
)
v_count_next := Mux(
pixel_tick && h_count_reg === MaxHorizontal.U,
Mux(v_count_reg === MaxVertical.U, 0.U, v_count_reg + 1.U),
v_count_reg
)
hsync_next := h_count_reg >= RetraceHorizontalStart.U && h_count_reg <= RetraceHorizontalEnd.U
vsync_next := v_count_reg >= RetraceVerticalStart.U && v_count_reg <= RetraceVerticalEnd.U
pixel := pixel_next
hsync_reg := hsync_next
vsync_reg := vsync_next
v_count_reg := v_count_next
h_count_reg := h_count_next
io.video_on := h_count_reg < DisplayHorizontal.U && v_count_reg < DisplayVertical.U
io.hsync := hsync_reg
io.vsync := vsync_reg
io.x := h_count_reg
io.y := v_count_reg
io.p_tick := pixel_tick
io.f_tick := io.x === 0.U && io.y === 0.U
}
class VGADisplay extends Module {
val io = IO(new Bundle() {
val x = Output(UInt(16.W))
val y = Output(UInt(16.W))
val video_on = Output(Bool())
val hsync = Output(Bool())
val vsync = Output(Bool())
})
val sync = Module(new VGASync)
io.hsync := sync.io.hsync
io.vsync := sync.io.vsync
io.x := sync.io.x
io.y := sync.io.y
io.video_on := sync.io.y
}

View File

@@ -0,0 +1,31 @@
// Copyright 2022 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv
import chisel3._
import peripheral.RAMBundle
class CPUBundle extends Bundle {
val instruction_address = Output(UInt(Parameters.AddrWidth))
val instruction = Input(UInt(Parameters.DataWidth))
val instruction_valid = Input(Bool())
val interrupt_flag = Input(UInt(Parameters.InterruptFlagWidth))
val memory_bundle = Flipped(new RAMBundle)
val deviceSelect = Output(UInt(Parameters.SlaveDeviceCountBits.W))
val regs_debug_read_address = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val regs_debug_read_data = Output(UInt(Parameters.DataWidth))
val csr_regs_debug_read_address = Input(UInt(Parameters.CSRRegisterAddrWidth))
val csr_regs_debug_read_data = Output(UInt(Parameters.DataWidth))
}

View File

@@ -0,0 +1,58 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv
import chisel3._
import chisel3.util._
object ImplementationType {
val ThreeStage = 0
val FiveStage = 1
}
object Parameters {
val AddrBits = 32
val AddrWidth = AddrBits.W
val InstructionBits = 32
val InstructionWidth = InstructionBits.W
val DataBits = 32
val DataWidth = DataBits.W
val ByteBits = 8
val ByteWidth = ByteBits.W
val WordSize = Math.ceil(DataBits / ByteBits).toInt
val PhysicalRegisters = 32
val PhysicalRegisterAddrBits = log2Up(PhysicalRegisters)
val PhysicalRegisterAddrWidth = PhysicalRegisterAddrBits.W
val CSRRegisterAddrBits = 12
val CSRRegisterAddrWidth = CSRRegisterAddrBits.W
val InterruptFlagBits = 32
val InterruptFlagWidth = InterruptFlagBits.W
val HoldStateBits = 3
val StallStateWidth = HoldStateBits.W
val MemorySizeInBytes = 32768
val MemorySizeInWords = MemorySizeInBytes / 4
val EntryAddress = 0x1000.U(Parameters.AddrWidth)
val MasterDeviceCount = 1
val SlaveDeviceCount = 8
val SlaveDeviceCountBits = log2Up(Parameters.SlaveDeviceCount)
}

View File

@@ -0,0 +1,70 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core
import chisel3._
import chisel3.experimental.ChiselEnum
import chisel3.util._
import riscv.Parameters
object ALUFunctions extends ChiselEnum {
val zero, add, sub, sll, slt, xor, or, and, srl, sra, sltu = Value
}
class ALU extends Module {
val io = IO(new Bundle {
val func = Input(ALUFunctions())
val op1 = Input(UInt(Parameters.DataWidth))
val op2 = Input(UInt(Parameters.DataWidth))
val result = Output(UInt(Parameters.DataWidth))
})
io.result := 0.U
switch(io.func) {
is(ALUFunctions.add) {
io.result := io.op1 + io.op2
}
is(ALUFunctions.sub) {
io.result := io.op1 - io.op2
}
is(ALUFunctions.sll) {
io.result := io.op1 << io.op2(4, 0)
}
is(ALUFunctions.slt) {
io.result := io.op1.asSInt < io.op2.asSInt
}
is(ALUFunctions.xor) {
io.result := io.op1 ^ io.op2
}
is(ALUFunctions.or) {
io.result := io.op1 | io.op2
}
is(ALUFunctions.and) {
io.result := io.op1 & io.op2
}
is(ALUFunctions.srl) {
io.result := io.op1 >> io.op2(4, 0)
}
is(ALUFunctions.sra) {
io.result := (io.op1.asSInt >> io.op2(4, 0)).asUInt
}
is(ALUFunctions.sltu) {
io.result := io.op1 < io.op2
}
}
}

View File

@@ -0,0 +1,86 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core
import chisel3._
import chisel3.util._
class ALUControl extends Module {
val io = IO(new Bundle {
val opcode = Input(UInt(7.W))
val funct3 = Input(UInt(3.W))
val funct7 = Input(UInt(7.W))
val alu_funct = Output(ALUFunctions())
})
io.alu_funct := ALUFunctions.zero
switch(io.opcode) {
is(InstructionTypes.I) {
io.alu_funct := MuxLookup(
io.funct3,
ALUFunctions.zero,
IndexedSeq(
InstructionsTypeI.addi -> ALUFunctions.add,
InstructionsTypeI.slli -> ALUFunctions.sll,
InstructionsTypeI.slti -> ALUFunctions.slt,
InstructionsTypeI.sltiu -> ALUFunctions.sltu,
InstructionsTypeI.xori -> ALUFunctions.xor,
InstructionsTypeI.ori -> ALUFunctions.or,
InstructionsTypeI.andi -> ALUFunctions.and,
InstructionsTypeI.sri -> Mux(io.funct7(5), ALUFunctions.sra, ALUFunctions.srl)
),
)
}
is(InstructionTypes.RM) {
io.alu_funct := MuxLookup(
io.funct3,
ALUFunctions.zero,
IndexedSeq(
InstructionsTypeR.add_sub -> Mux(io.funct7(5), ALUFunctions.sub, ALUFunctions.add),
InstructionsTypeR.sll -> ALUFunctions.sll,
InstructionsTypeR.slt -> ALUFunctions.slt,
InstructionsTypeR.sltu -> ALUFunctions.sltu,
InstructionsTypeR.xor -> ALUFunctions.xor,
InstructionsTypeR.or -> ALUFunctions.or,
InstructionsTypeR.and -> ALUFunctions.and,
InstructionsTypeR.sr -> Mux(io.funct7(5), ALUFunctions.sra, ALUFunctions.srl)
),
)
}
is(InstructionTypes.B) {
io.alu_funct := ALUFunctions.add
}
is(InstructionTypes.L) {
io.alu_funct := ALUFunctions.add
}
is(InstructionTypes.S) {
io.alu_funct := ALUFunctions.add
}
is(Instructions.jal) {
io.alu_funct := ALUFunctions.add
}
is(Instructions.jalr) {
io.alu_funct := ALUFunctions.add
}
is(Instructions.lui) {
io.alu_funct := ALUFunctions.add
}
is(Instructions.auipc) {
io.alu_funct := ALUFunctions.add
}
}
}

View File

@@ -0,0 +1,107 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core
import chisel3._
import chisel3.util.MuxLookup
import riscv.Parameters
object InterruptStatus {
val None = 0x0.U(8.W)
val Timer0 = 0x1.U(8.W)
val Ret = 0xFF.U(8.W)
}
object InterruptEntry {
val Timer0 = 0x4.U(8.W)
}
object InterruptState {
val Idle = 0x0.U
val SyncAssert = 0x1.U
val AsyncAssert = 0x2.U
val MRET = 0x3.U
}
object CSRState {
val Idle = 0x0.U
val Traping = 0x1.U
val Mret = 0x2.U
}
class CSRDirectAccessBundle extends Bundle {
val mstatus = Input(UInt(Parameters.DataWidth))
val mepc = Input(UInt(Parameters.DataWidth))
val mcause = Input(UInt(Parameters.DataWidth))
val mtvec = Input(UInt(Parameters.DataWidth))
val mstatus_write_data= Output(UInt(Parameters.DataWidth))
val mepc_write_data= Output(UInt(Parameters.DataWidth))
val mcause_write_data= Output(UInt(Parameters.DataWidth))
val direct_write_enable = Output(Bool())
}
// Core Local Interrupt Controller
class CLINT extends Module {
val io = IO(new Bundle {
// Interrupt signals from peripherals
val interrupt_flag = Input(UInt(Parameters.InterruptFlagWidth))
val instruction = Input(UInt(Parameters.InstructionWidth))
val instruction_address = Input(UInt(Parameters.AddrWidth))
val jump_flag = Input(Bool())
val jump_address = Input(UInt(Parameters.AddrWidth))
val interrupt_handler_address = Output(UInt(Parameters.AddrWidth))
val interrupt_assert = Output(Bool())
val csr_bundle = new CSRDirectAccessBundle
})
val interrupt_enable = io.csr_bundle.mstatus(3)
val instruction_address = Mux(
io.jump_flag,
io.jump_address,
io.instruction_address + 4.U,
)
//lab2(CLINTCSR)
/*
val interrupt_enable =
when(io.interrupt_flag =/= InterruptStatus.None && interrupt_enable) {
io.csr_bundle.mstatus_write_data :=
io.csr_bundle.mepc_write_data :=
io.csr_bundle.mcause_write_data :=
io.csr_bundle.direct_write_enable :=
io.interrupt_assert :=
io.interrupt_handler_address :=
}.elsewhen(io.instruction === InstructionsRet.mret) {
io.csr_bundle.mstatus_write_data :=
io.csr_bundle.mepc_write_data :=
io.csr_bundle.mcause_write_data :=
io.csr_bundle.direct_write_enable :=
io.interrupt_assert :=
io.interrupt_handler_address :=
}.otherwise {
io.csr_bundle.mstatus_write_data :=
io.csr_bundle.mepc_write_data :=
io.csr_bundle.mcause_write_data :=
io.csr_bundle.direct_write_enable :=
io.interrupt_assert :=
io.interrupt_handler_address :=
}
*/
}

View File

@@ -0,0 +1,96 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core
import chisel3._
import chisel3.util.Cat
import riscv.{CPUBundle, Parameters}
class CPU extends Module {
val io = IO(new CPUBundle)
val regs = Module(new RegisterFile)
val inst_fetch = Module(new InstructionFetch)
val id = Module(new InstructionDecode)
val ex = Module(new Execute)
val mem = Module(new MemoryAccess)
val wb = Module(new WriteBack)
val csr_regs = Module(new CSR)
val clint = Module(new CLINT)
io.regs_debug_read_data := regs.io.debug_read_data
io.csr_regs_debug_read_data := csr_regs.io.debug_reg_read_data
regs.io.debug_read_address := io.regs_debug_read_address
csr_regs.io.debug_reg_read_address := io.csr_regs_debug_read_address
io.deviceSelect := mem.io.memory_bundle.address(Parameters.AddrBits - 1, Parameters.AddrBits - Parameters.SlaveDeviceCountBits)
inst_fetch.io.jump_address_id := ex.io.if_jump_address
inst_fetch.io.jump_flag_id := ex.io.if_jump_flag
inst_fetch.io.interrupt_assert := clint.io.interrupt_assert
inst_fetch.io.interrupt_handler_address := clint.io.interrupt_handler_address
inst_fetch.io.instruction_valid := io.instruction_valid
inst_fetch.io.instruction_read_data := io.instruction
io.instruction_address := inst_fetch.io.instruction_address
regs.io.write_enable := id.io.reg_write_enable
regs.io.write_address := id.io.reg_write_address
regs.io.write_data := wb.io.regs_write_data
regs.io.read_address1 := id.io.regs_reg1_read_address
regs.io.read_address2 := id.io.regs_reg2_read_address
id.io.instruction := inst_fetch.io.instruction
csr_regs.io.clint_access_bundle <> clint.io.csr_bundle
csr_regs.io.reg_read_address_id := id.io.csr_reg_address
csr_regs.io.reg_write_data_ex := ex.io.csr_reg_write_data
csr_regs.io.reg_write_address_id := id.io.csr_reg_address
csr_regs.io.reg_write_enable_id := id.io.csr_reg_write_enable
ex.io.instruction := inst_fetch.io.instruction
ex.io.instruction_address := inst_fetch.io.instruction_address
ex.io.reg1_data := regs.io.read_data1
ex.io.reg2_data := regs.io.read_data2
ex.io.immediate := id.io.ex_immediate
ex.io.aluop1_source := id.io.ex_aluop1_source
ex.io.aluop2_source := id.io.ex_aluop2_source
ex.io.csr_reg_read_data := csr_regs.io.reg_read_data
mem.io.alu_result := ex.io.mem_alu_result
mem.io.reg2_data := regs.io.read_data2
mem.io.memory_read_enable := id.io.memory_read_enable
mem.io.memory_write_enable := id.io.memory_write_enable
mem.io.funct3 := inst_fetch.io.instruction(14, 12)
io.memory_bundle.address := Cat(0.U(Parameters.SlaveDeviceCountBits.W),mem.io.memory_bundle.address(Parameters.AddrBits - 1 - Parameters.SlaveDeviceCountBits, 0))
io.memory_bundle.write_enable := mem.io.memory_bundle.write_enable
io.memory_bundle.write_data := mem.io.memory_bundle.write_data
io.memory_bundle.write_strobe := mem.io.memory_bundle.write_strobe
mem.io.memory_bundle.read_data := io.memory_bundle.read_data
wb.io.instruction_address := inst_fetch.io.instruction_address
wb.io.alu_result := ex.io.mem_alu_result
wb.io.memory_read_data := mem.io.wb_memory_read_data
wb.io.regs_write_source := id.io.wb_reg_write_source
wb.io.csr_read_data := csr_regs.io.reg_read_data
clint.io.instruction := inst_fetch.io.instruction
clint.io.instruction_address := inst_fetch.io.instruction_address
clint.io.interrupt_flag := io.interrupt_flag
clint.io.jump_flag := ex.io.if_jump_flag
clint.io.jump_address := ex.io.if_jump_address
}

View File

@@ -0,0 +1,107 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core
import chisel3._
import chisel3.util._
import riscv.Parameters
object CSRRegister {
// Refer to Spec. Vol.II Page 8-10
val MSTATUS = 0x300.U(Parameters.CSRRegisterAddrWidth)
val MIE = 0x304.U(Parameters.CSRRegisterAddrWidth)
val MTVEC = 0x305.U(Parameters.CSRRegisterAddrWidth)
val MSCRATCH = 0x340.U(Parameters.CSRRegisterAddrWidth)
val MEPC = 0x341.U(Parameters.CSRRegisterAddrWidth)
val MCAUSE = 0x342.U(Parameters.CSRRegisterAddrWidth)
val CycleL = 0xc00.U(Parameters.CSRRegisterAddrWidth)
val CycleH = 0xc80.U(Parameters.CSRRegisterAddrWidth)
}
class CSR extends Module {
val io = IO(new Bundle {
val reg_read_address_id = Input(UInt(Parameters.CSRRegisterAddrWidth))
val reg_write_enable_id= Input(Bool())
val reg_write_address_id = Input(UInt(Parameters.CSRRegisterAddrWidth))
val reg_write_data_ex= Input(UInt(Parameters.DataWidth))
val debug_reg_read_address = Input(UInt(Parameters.CSRRegisterAddrWidth))
val debug_reg_read_data = Output(UInt(Parameters.DataWidth))
val reg_read_data = Output(UInt(Parameters.DataWidth))
val clint_access_bundle = Flipped(new CSRDirectAccessBundle)
})
val mstatus = RegInit(UInt(Parameters.DataWidth), 0.U)
val mie = RegInit(UInt(Parameters.DataWidth), 0.U)
val mtvec = RegInit(UInt(Parameters.DataWidth), 0.U)
val mscratch = RegInit(UInt(Parameters.DataWidth), 0.U)
val mepc = RegInit(UInt(Parameters.DataWidth), 0.U)
val mcause = RegInit(UInt(Parameters.DataWidth), 0.U)
val cycles = RegInit(UInt(64.W), 0.U)
val regLUT =
IndexedSeq(
CSRRegister.MSTATUS -> mstatus,
CSRRegister.MIE -> mie,
CSRRegister.MTVEC -> mtvec,
CSRRegister.MSCRATCH -> mscratch,
CSRRegister.MEPC -> mepc,
CSRRegister.MCAUSE -> mcause,
CSRRegister.CycleL -> cycles(31, 0),
CSRRegister.CycleH -> cycles(63, 32),
)
cycles := cycles + 1.U
// If the pipeline and the CLINT are going to read and write the CSR at the same time, let the pipeline write first.
// This is implemented in a single cycle by passing reg_write_data_ex to clint and writing the data from the CLINT to the CSR.
io.reg_read_data := MuxLookup(io.reg_read_address_id, 0.U, regLUT)
io.debug_reg_read_data := MuxLookup(io.debug_reg_read_address, 0.U,regLUT)
//lab2(CLINTCSR)
//what data should be passed from csr to clint (Note: what should clint see is the next state of the CPU)
/*
io.clint_access_bundle.mstatus :=
io.clint_access_bundle.mtvec :=
io.clint_access_bundle.mcause :=
io.clint_access_bundle.mepc :=
*/
when(io.clint_access_bundle.direct_write_enable) {
mstatus := io.clint_access_bundle.mstatus_write_data
mepc := io.clint_access_bundle.mepc_write_data
mcause := io.clint_access_bundle.mcause_write_data
}.elsewhen(io.reg_write_enable_id) {
when(io.reg_write_address_id === CSRRegister.MSTATUS) {
mstatus := io.reg_write_data_ex
}.elsewhen(io.reg_write_address_id === CSRRegister.MEPC) {
mepc := io.reg_write_data_ex
}.elsewhen(io.reg_write_address_id === CSRRegister.MCAUSE) {
mcause := io.reg_write_data_ex
}
}
when(io.reg_write_enable_id) {
when(io.reg_write_address_id === CSRRegister.MIE) {
mie := io.reg_write_data_ex
}.elsewhen(io.reg_write_address_id === CSRRegister.MTVEC){
mtvec := io.reg_write_data_ex
}.elsewhen(io.reg_write_address_id === CSRRegister.MSCRATCH) {
mscratch := io.reg_write_data_ex
}
}
}

View File

@@ -0,0 +1,79 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core
import chisel3._
import chisel3.util.{Cat, MuxLookup}
import riscv.Parameters
class Execute extends Module {
val io = IO(new Bundle {
val instruction = Input(UInt(Parameters.InstructionWidth))
val instruction_address = Input(UInt(Parameters.AddrWidth))
val reg1_data = Input(UInt(Parameters.DataWidth))
val reg2_data = Input(UInt(Parameters.DataWidth))
val immediate = Input(UInt(Parameters.DataWidth))
val aluop1_source = Input(UInt(1.W))
val aluop2_source = Input(UInt(1.W))
val csr_reg_read_data = Input(UInt(Parameters.DataWidth))
val mem_alu_result = Output(UInt(Parameters.DataWidth))
val csr_reg_write_data = Output(UInt(Parameters.DataWidth))
val if_jump_flag = Output(Bool())
val if_jump_address = Output(UInt(Parameters.DataWidth))
})
val opcode = io.instruction(6, 0)
val funct3 = io.instruction(14, 12)
val funct7 = io.instruction(31, 25)
val alu = Module(new ALU)
val alu_ctrl = Module(new ALUControl)
alu_ctrl.io.opcode := opcode
alu_ctrl.io.funct3 := funct3
alu_ctrl.io.funct7 := funct7
alu.io.func := alu_ctrl.io.alu_funct
alu.io.op1 := Mux(
io.aluop1_source === ALUOp1Source.InstructionAddress,
io.instruction_address,
io.reg1_data,
)
alu.io.op2 := Mux(
io.aluop2_source === ALUOp2Source.Immediate,
io.immediate,
io.reg2_data,
)
io.if_jump_flag := opcode === Instructions.jal ||
(opcode === Instructions.jalr) ||
(opcode === InstructionTypes.B) && MuxLookup(
funct3,
false.B,
IndexedSeq(
InstructionsTypeB.beq -> (io.reg1_data === io.reg2_data),
InstructionsTypeB.bne -> (io.reg1_data =/= io.reg2_data),
InstructionsTypeB.blt -> (io.reg1_data.asSInt < io.reg2_data.asSInt),
InstructionsTypeB.bge -> (io.reg1_data.asSInt >= io.reg2_data.asSInt),
InstructionsTypeB.bltu -> (io.reg1_data.asUInt < io.reg2_data.asUInt),
InstructionsTypeB.bgeu -> (io.reg1_data.asUInt >= io.reg2_data.asUInt)
)
)
io.if_jump_address := io.immediate + Mux(opcode === Instructions.jalr, io.reg1_data, io.instruction_address)
io.mem_alu_result := alu.io.result
// lab2(CLINTCSR)
/*
io.csr_reg_write_data :=
*/
}

View File

@@ -0,0 +1,208 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core
import chisel3._
import chisel3.util._
import riscv.Parameters
object InstructionTypes {
val L = "b0000011".U
val I = "b0010011".U
val S = "b0100011".U
val RM = "b0110011".U
val B = "b1100011".U
}
object Instructions {
val lui = "b0110111".U
val nop = "b0000001".U
val jal = "b1101111".U
val jalr = "b1100111".U
val auipc = "b0010111".U
val csr = "b1110011".U
val fence = "b0001111".U
}
object InstructionsTypeL {
val lb = "b000".U
val lh = "b001".U
val lw = "b010".U
val lbu = "b100".U
val lhu = "b101".U
}
object InstructionsTypeI {
val addi = 0.U
val slli = 1.U
val slti = 2.U
val sltiu = 3.U
val xori = 4.U
val sri = 5.U
val ori = 6.U
val andi = 7.U
}
object InstructionsTypeS {
val sb = "b000".U
val sh = "b001".U
val sw = "b010".U
}
object InstructionsTypeR {
val add_sub = 0.U
val sll = 1.U
val slt = 2.U
val sltu = 3.U
val xor = 4.U
val sr = 5.U
val or = 6.U
val and = 7.U
}
object InstructionsTypeM {
val mul = 0.U
val mulh = 1.U
val mulhsu = 2.U
val mulhum = 3.U
val div = 4.U
val divu = 5.U
val rem = 6.U
val remu = 7.U
}
object InstructionsTypeB {
val beq = "b000".U
val bne = "b001".U
val blt = "b100".U
val bge = "b101".U
val bltu = "b110".U
val bgeu = "b111".U
}
object InstructionsTypeCSR {
val csrrw = "b001".U
val csrrs = "b010".U
val csrrc = "b011".U
val csrrwi = "b101".U
val csrrsi = "b110".U
val csrrci = "b111".U
}
object InstructionsNop {
val nop = 0x00000013L.U(Parameters.DataWidth)
}
object InstructionsRet {
val mret = 0x30200073L.U(Parameters.DataWidth)
val ret = 0x00008067L.U(Parameters.DataWidth)
}
object InstructionsEnv {
val ecall = 0x00000073L.U(Parameters.DataWidth)
val ebreak = 0x00100073L.U(Parameters.DataWidth)
}
object ALUOp1Source {
val Register = 0.U(1.W)
val InstructionAddress = 1.U(1.W)
}
object ALUOp2Source {
val Register = 0.U(1.W)
val Immediate = 1.U(1.W)
}
object RegWriteSource {
val ALUResult = 0.U(2.W)
val Memory = 1.U(2.W)
val CSR = 2.U(2.W)
val NextInstructionAddress = 3.U(2.W)
}
class InstructionDecode extends Module {
val io = IO(new Bundle {
val instruction = Input(UInt(Parameters.InstructionWidth))
val regs_reg1_read_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
val regs_reg2_read_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
val ex_immediate = Output(UInt(Parameters.DataWidth))
val ex_aluop1_source = Output(UInt(1.W))
val ex_aluop2_source = Output(UInt(1.W))
val memory_read_enable = Output(Bool())
val memory_write_enable = Output(Bool())
val wb_reg_write_source = Output(UInt(2.W))
val reg_write_enable = Output(Bool())
val reg_write_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
val csr_reg_write_enable = Output(Bool())
val csr_reg_address = Output(UInt(Parameters.DataWidth))
})
val opcode = io.instruction(6, 0)
val funct3 = io.instruction(14, 12)
val funct7 = io.instruction(31, 25)
val rd = io.instruction(11, 7)
val rs1 = io.instruction(19, 15)
val rs2 = io.instruction(24, 20)
io.regs_reg1_read_address := Mux(opcode === Instructions.lui, 0.U(Parameters.PhysicalRegisterAddrWidth), rs1)
io.regs_reg2_read_address := rs2
val immediate = MuxLookup(
opcode,
Cat(Fill(20, io.instruction(31)), io.instruction(31, 20)),
IndexedSeq(
InstructionTypes.I -> Cat(Fill(21, io.instruction(31)), io.instruction(30, 20)),
InstructionTypes.L -> Cat(Fill(21, io.instruction(31)), io.instruction(30, 20)),
Instructions.jalr -> Cat(Fill(21, io.instruction(31)), io.instruction(30, 20)),
InstructionTypes.S -> Cat(Fill(21, io.instruction(31)), io.instruction(30, 25), io.instruction(11, 7)),
InstructionTypes.B -> Cat(Fill(20, io.instruction(31)), io.instruction(7), io.instruction(30, 25), io.instruction(11, 8), 0.U(1.W)),
Instructions.lui -> Cat(io.instruction(31, 12), 0.U(12.W)),
Instructions.auipc -> Cat(io.instruction(31, 12), 0.U(12.W)),
Instructions.jal -> Cat(Fill(12, io.instruction(31)), io.instruction(19, 12), io.instruction(20), io.instruction(30, 21), 0.U(1.W))
)
)
io.ex_immediate := immediate
io.ex_aluop1_source := Mux(
opcode === Instructions.auipc || opcode === InstructionTypes.B || opcode === Instructions.jal,
ALUOp1Source.InstructionAddress,
ALUOp1Source.Register
)
io.ex_aluop2_source := Mux(
opcode === InstructionTypes.RM,
ALUOp2Source.Register,
ALUOp2Source.Immediate
)
io.memory_read_enable := opcode === InstructionTypes.L
io.memory_write_enable := opcode === InstructionTypes.S
io.wb_reg_write_source := MuxLookup(
opcode,
RegWriteSource.ALUResult,
IndexedSeq(
InstructionTypes.L -> RegWriteSource.Memory,
Instructions.jal -> RegWriteSource.NextInstructionAddress,
Instructions.jalr -> RegWriteSource.NextInstructionAddress,
Instructions.csr -> RegWriteSource.CSR
)
)
io.reg_write_enable := (opcode === InstructionTypes.RM) || (opcode === InstructionTypes.I) ||
(opcode === InstructionTypes.L) || (opcode === Instructions.auipc) || (opcode === Instructions.lui) ||
(opcode === Instructions.jal) || (opcode === Instructions.jalr) || (opcode === Instructions.csr)
io.reg_write_address := io.instruction(11, 7)
io.csr_reg_address := io.instruction(31,20)
io.csr_reg_write_enable := (opcode === Instructions.csr) && (
funct3 === InstructionsTypeCSR.csrrw || funct3 === InstructionsTypeCSR.csrrwi ||
funct3 === InstructionsTypeCSR.csrrs || funct3 === InstructionsTypeCSR.csrrsi ||
funct3 === InstructionsTypeCSR.csrrc || funct3 === InstructionsTypeCSR.csrrci
)
}

View File

@@ -0,0 +1,53 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core
import chisel3._
import riscv.Parameters
object ProgramCounter {
val EntryAddress = Parameters.EntryAddress
}
class InstructionFetch extends Module {
val io = IO(new Bundle {
val jump_flag_id = Input(Bool())
val jump_address_id = Input(UInt(Parameters.AddrWidth))
val instruction_read_data = Input(UInt(Parameters.DataWidth))
val interrupt_assert = Input(Bool())
val interrupt_handler_address = Input(UInt(Parameters.AddrWidth))
val instruction_valid = Input(Bool())
val instruction_address = Output(UInt(Parameters.AddrWidth))
val instruction = Output(UInt(Parameters.InstructionWidth))
})
val pc = RegInit(ProgramCounter.EntryAddress)
when(io.instruction_valid) {
when(io.interrupt_assert){
pc := io.interrupt_handler_address
}.elsewhen(io.jump_flag_id){
pc := io.jump_address_id
}.otherwise {
pc := pc + 4.U
}
io.instruction := io.instruction_read_data
}.otherwise{
pc := pc
io.instruction := 0x00000013.U
}
io.instruction_address := pc
}

View File

@@ -0,0 +1,105 @@
// Copyright 2022 Canbin Huang
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core
import chisel3._
import chisel3.util._
import peripheral.RAMBundle
import riscv.Parameters
class MemoryAccess extends Module {
val io = IO(new Bundle() {
val alu_result = Input(UInt(Parameters.DataWidth))
val reg2_data = Input(UInt(Parameters.DataWidth))
val memory_read_enable = Input(Bool())
val memory_write_enable = Input(Bool())
val funct3 = Input(UInt(3.W))
val wb_memory_read_data = Output(UInt(Parameters.DataWidth))
val memory_bundle = Flipped(new RAMBundle)
})
val mem_address_index = io.alu_result(log2Up(Parameters.WordSize) - 1, 0).asUInt
io.memory_bundle.write_enable := false.B
io.memory_bundle.write_data := 0.U
io.memory_bundle.address := io.alu_result
io.memory_bundle.write_strobe := VecInit(Seq.fill(Parameters.WordSize)(false.B))
io.wb_memory_read_data := 0.U
when(io.memory_read_enable) {
val data = io.memory_bundle.read_data
io.wb_memory_read_data := MuxLookup(
io.funct3,
0.U,
IndexedSeq(
InstructionsTypeL.lb -> MuxLookup(
mem_address_index,
Cat(Fill(24, data(31)), data(31, 24)),
IndexedSeq(
0.U -> Cat(Fill(24, data(7)), data(7, 0)),
1.U -> Cat(Fill(24, data(15)), data(15, 8)),
2.U -> Cat(Fill(24, data(23)), data(23, 16))
)
),
InstructionsTypeL.lbu -> MuxLookup(
mem_address_index,
Cat(Fill(24, 0.U), data(31, 24)),
IndexedSeq(
0.U -> Cat(Fill(24, 0.U), data(7, 0)),
1.U -> Cat(Fill(24, 0.U), data(15, 8)),
2.U -> Cat(Fill(24, 0.U), data(23, 16))
)
),
InstructionsTypeL.lh -> Mux(
mem_address_index === 0.U,
Cat(Fill(16, data(15)), data(15, 0)),
Cat(Fill(16, data(31)), data(31, 16))
),
InstructionsTypeL.lhu -> Mux(
mem_address_index === 0.U,
Cat(Fill(16, 0.U), data(15, 0)),
Cat(Fill(16, 0.U), data(31, 16))
),
InstructionsTypeL.lw -> data
)
)
}.elsewhen(io.memory_write_enable) {
io.memory_bundle.write_data := io.reg2_data
io.memory_bundle.write_enable := true.B
io.memory_bundle.write_strobe := VecInit(Seq.fill(Parameters.WordSize)(false.B))
when(io.funct3 === InstructionsTypeS.sb) {
io.memory_bundle.write_strobe(mem_address_index) := true.B
io.memory_bundle.write_data := io.reg2_data(Parameters.ByteBits, 0) << (mem_address_index << log2Up(Parameters.ByteBits).U)
}.elsewhen(io.funct3 === InstructionsTypeS.sh) {
when(mem_address_index === 0.U) {
for (i <- 0 until Parameters.WordSize / 2) {
io.memory_bundle.write_strobe(i) := true.B
}
io.memory_bundle.write_data := io.reg2_data(Parameters.WordSize / 2 * Parameters.ByteBits, 0)
}.otherwise {
for (i <- Parameters.WordSize / 2 until Parameters.WordSize) {
io.memory_bundle.write_strobe(i) := true.B
}
io.memory_bundle.write_data := io.reg2_data(Parameters.WordSize / 2 * Parameters.ByteBits, 0) << (Parameters
.WordSize / 2 * Parameters.ByteBits)
}
}.elsewhen(io.funct3 === InstructionsTypeS.sw) {
for (i <- 0 until Parameters.WordSize) {
io.memory_bundle.write_strobe(i) := true.B
}
}
}
}

View File

@@ -0,0 +1,95 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core
import chisel3._
import chisel3.util._
import riscv.Parameters
object Registers extends Enumeration {
type Register = Value
val zero,
ra, sp, gp, tp,
t0, t1, t2, fp,
s1,
a0, a1, a2, a3, a4, a5, a6, a7,
s2, s3, s4, s5, s6, s7, s8, s9, s10, s11,
t3, t4, t5, t6 = Value
}
class RegisterFile extends Module {
val io = IO(new Bundle {
val write_enable = Input(Bool())
val write_address = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val write_data = Input(UInt(Parameters.DataWidth))
val read_address1 = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val read_address2 = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val read_data1 = Output(UInt(Parameters.DataWidth))
val read_data2 = Output(UInt(Parameters.DataWidth))
val debug_read_address = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val debug_read_data = Output(UInt(Parameters.DataWidth))
})
val registers = RegInit(VecInit(Seq.fill(Parameters.PhysicalRegisters)(0.U(Parameters.DataWidth))))
when(!reset.asBool) {
when(io.write_enable && io.write_address =/= 0.U) {
registers(io.write_address) := io.write_data
}
}
io.read_data1 := Mux(
io.read_address1 === 0.U,
0.U,
registers(io.read_address1)
)
io.read_data2 := Mux(
io.read_address2 === 0.U,
0.U,
registers(io.read_address2)
)
io.debug_read_data := Mux(
io.debug_read_address === 0.U,
0.U,
registers(io.debug_read_address)
)
// io.read_data1 := MuxCase(
// registers(io.read_address1),
// IndexedSeq(
// (io.read_address1 === 0.U) -> 0.U,
// (io.read_address1 === io.write_address && io.write_enable) -> io.write_data
// )
// )
//
// io.read_data2 := MuxCase(
// registers(io.read_address2),
// IndexedSeq(
// (io.read_address2 === 0.U) -> 0.U,
// (io.read_address2 === io.write_address && io.write_enable) -> io.write_data
// )
// )
//
// io.debug_read_data := MuxCase(
// registers(io.debug_read_address),
// IndexedSeq(
// (io.debug_read_address === 0.U) -> 0.U,
// (io.debug_read_address === io.write_address && io.write_enable) -> io.write_data
// )
// )
}

View File

@@ -0,0 +1,39 @@
// Copyright 2022 Canbin Huang
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core
import chisel3._
import chisel3.util._
import riscv.Parameters
class WriteBack extends Module {
val io = IO(new Bundle() {
val instruction_address = Input(UInt(Parameters.AddrWidth))
val alu_result = Input(UInt(Parameters.DataWidth))
val memory_read_data = Input(UInt(Parameters.DataWidth))
val regs_write_source = Input(UInt(2.W))
val csr_read_data = Input(UInt(Parameters.DataWidth))
val regs_write_data = Output(UInt(Parameters.DataWidth))
})
io.regs_write_data := MuxLookup(
io.regs_write_source,
io.alu_result,
IndexedSeq(
RegWriteSource.Memory -> io.memory_read_data,
RegWriteSource.CSR -> io.csr_read_data,
RegWriteSource.NextInstructionAddress -> (io.instruction_address + 4.U),
)
)
}

View File

@@ -0,0 +1,52 @@
// Copyright 2022 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv
import chiseltest.{VerilatorBackendAnnotation, WriteVcdAnnotation}
import firrtl.AnnotationSeq
import java.nio.file.{Files, Paths}
object VerilatorEnabler {
val annos: AnnotationSeq = if (sys.env.contains("Path")) {
if (sys.env.getOrElse("Path", "").split(";").exists(path => {
Files.exists(Paths.get(path, "verilator"))
})) {
Seq(VerilatorBackendAnnotation)
} else {
Seq()
}
} else {
if (sys.env.getOrElse("PATH", "").split(":").exists(path => {
Files.exists(Paths.get(path, "verilator"))
})) {
Seq(VerilatorBackendAnnotation)
} else {
Seq()
}
}
}
object WriteVcdEnabler {
val annos: AnnotationSeq = if (sys.env.contains("WRITE_VCD")) {
Seq(WriteVcdAnnotation)
} else {
Seq()
}
}
object TestAnnotations {
val annos = VerilatorEnabler.annos ++ WriteVcdEnabler.annos
}

View File

@@ -0,0 +1,142 @@
// Copyright 2022 hrpccs
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.singlecycle
import chisel3._
import chiseltest._
import org.scalatest.flatspec.AnyFlatSpec
import riscv.{Parameters, TestAnnotations}
import riscv.core.{ALUOp1Source, ALUOp2Source, CLINT, CSR, CSRRegister, InstructionDecode, InstructionsNop, InstructionsRet}
class CLINTCSRTestTopModule extends Module {
val io = IO( new Bundle{
val csr_regs_debug_read_address = Input(UInt(Parameters.CSRRegisterAddrWidth))
val csr_regs_write_address = Input(UInt(Parameters.CSRRegisterAddrWidth))
val csr_regs_write_data = Input(UInt(Parameters.DataWidth))
val csr_regs_write_enable = Input(Bool())
val interrupt_flag = Input(UInt(Parameters.InterruptFlagWidth))
val instruction = Input(UInt(Parameters.DataWidth))
val instruction_address = Input(UInt(Parameters.AddrWidth))
val jump_flag = Input(Bool())
val jump_address = Input(UInt(Parameters.AddrWidth))
val interrupt_assert = Output(Bool())
val interrupt_handler_address = Output(UInt(Parameters.DataWidth))
val csr_regs_read_data = Output(UInt(Parameters.DataWidth))
val csr_regs_debug_read_data = Output(UInt(Parameters.DataWidth))
})
val csr_regs = Module(new CSR)
val clint = Module(new CLINT)
clint.io.instruction := io.instruction
clint.io.instruction_address := io.instruction_address
clint.io.interrupt_flag := io.interrupt_flag
clint.io.jump_flag := io.jump_flag
clint.io.jump_address := io.jump_address
io.interrupt_handler_address := clint.io.interrupt_handler_address
io.interrupt_assert := clint.io.interrupt_assert
io.csr_regs_read_data := csr_regs.io.reg_read_data
csr_regs.io.reg_write_address_id := io.csr_regs_write_address
csr_regs.io.debug_reg_read_address := io.csr_regs_debug_read_address
csr_regs.io.reg_write_data_ex := io.csr_regs_write_data
csr_regs.io.reg_write_enable_id := io.csr_regs_write_enable
csr_regs.io.reg_read_address_id := io.csr_regs_write_address
io.csr_regs_debug_read_data := csr_regs.io.debug_reg_read_data
csr_regs.io.clint_access_bundle <> clint.io.csr_bundle
}
class CLINTCSRTest extends AnyFlatSpec with ChiselScalatestTester{
behavior of "CLINTCSRTest of Single Cycle CPU"
it should "process " in {
test(new CLINTCSRTestTopModule).withAnnotations(TestAnnotations.annos) { c =>
//
c.io.jump_flag.poke(false.B)
c.io.csr_regs_write_enable.poke(false.B)
c.io.interrupt_flag.poke(0.U)
c.clock.step()
c.io.csr_regs_write_enable.poke(true.B)
c.io.csr_regs_write_address.poke(CSRRegister.MTVEC)
c.io.csr_regs_write_data.poke(0x1144L.U)
c.clock.step()
c.io.csr_regs_write_address.poke(CSRRegister.MSTATUS)
c.io.csr_regs_write_data.poke(0x1888L.U)
c.clock.step()
c.io.csr_regs_write_enable.poke(false.B)
//handle interrupt when not jumping
c.io.jump_flag.poke(false.B)
c.io.instruction_address.poke(0x1900L.U)
c.io.instruction.poke(InstructionsNop.nop)
c.io.interrupt_flag.poke(1.U)
c.io.interrupt_assert.expect(true.B)
c.io.interrupt_handler_address.expect(0x1144L.U)
c.clock.step()
c.io.interrupt_flag.poke(0.U)
c.io.csr_regs_debug_read_address.poke(CSRRegister.MEPC)
c.io.csr_regs_debug_read_data.expect(0x1904L.U)
c.io.csr_regs_debug_read_address.poke(CSRRegister.MCAUSE)
c.io.csr_regs_debug_read_data.expect(0x80000007L.U)
c.io.csr_regs_debug_read_address.poke(CSRRegister.MSTATUS)
c.io.csr_regs_debug_read_data.expect(0x1880L.U)
c.clock.step(25)
//mret from interrupt handler
c.io.instruction.poke(InstructionsRet.mret)
c.io.interrupt_assert.expect(true.B)
c.io.interrupt_handler_address.expect(0x1904L.U)
c.clock.step()
c.io.csr_regs_debug_read_address.poke(CSRRegister.MSTATUS)
c.io.csr_regs_debug_read_data.expect(0x1888L.U)
//handle interrupt when jumping
c.io.jump_flag.poke(true.B)
c.io.jump_address.poke(0x1990L.U)
c.io.interrupt_flag.poke(2.U)
c.io.interrupt_assert.expect(true.B)
c.io.interrupt_handler_address.expect(0x1144L.U)
c.clock.step()
c.io.interrupt_flag.poke(0.U)
c.io.csr_regs_debug_read_address.poke(CSRRegister.MEPC)
c.io.csr_regs_debug_read_data.expect(0x1990L.U)
c.io.csr_regs_debug_read_address.poke(CSRRegister.MCAUSE)
c.io.csr_regs_debug_read_data.expect(0x8000000BL.U)
c.io.csr_regs_debug_read_address.poke(CSRRegister.MSTATUS)
c.io.csr_regs_debug_read_data.expect(0x1880L.U)
c.clock.step(25)
//mret from interrupt handler
c.io.instruction.poke(InstructionsRet.mret)
c.io.interrupt_assert.expect(true.B)
c.io.interrupt_handler_address.expect(0x1990L.U)
c.clock.step()
c.io.csr_regs_debug_read_address.poke(CSRRegister.MSTATUS)
c.io.csr_regs_debug_read_data.expect(0x1888L.U)
c.io.instruction.poke(InstructionsNop.nop)
//don't handle interrupt under certain situation
c.io.csr_regs_write_enable.poke(true.B)
c.io.csr_regs_write_address.poke(CSRRegister.MSTATUS)
c.io.csr_regs_write_data.poke(0x1880L.U)
c.io.interrupt_flag.poke(1.U)
c.io.interrupt_assert.expect(false.B)
}
}
}

View File

@@ -0,0 +1,162 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.singlecycle
import board.basys3.BootStates
import chisel3._
import chiseltest._
import org.scalatest.flatspec.AnyFlatSpec
import peripheral.{InstructionROM, Memory, ROMLoader}
import riscv.core.{CPU, CSRRegister, ProgramCounter}
import riscv.{Parameters, TestAnnotations}
import java.nio.{ByteBuffer, ByteOrder}
class TestTopModule(exeFilename: String) extends Module {
val io = IO(new Bundle {
val mem_debug_read_address = Input(UInt(Parameters.AddrWidth))
val regs_debug_read_address = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val csr_regs_debug_read_address = Input(UInt(Parameters.CSRRegisterAddrWidth))
val interrupt_flag = Input(UInt(Parameters.InterruptFlagWidth))
val regs_debug_read_data = Output(UInt(Parameters.DataWidth))
val mem_debug_read_data = Output(UInt(Parameters.DataWidth))
val csr_regs_debug_read_data = Output(UInt(Parameters.DataWidth))
val pc_debug_read = Output(UInt(Parameters.AddrWidth));
})
val mem = Module(new Memory(8192))
val instruction_rom = Module(new InstructionROM(exeFilename))
val rom_loader = Module(new ROMLoader(instruction_rom.capacity))
rom_loader.io.rom_data := instruction_rom.io.data
rom_loader.io.load_address := Parameters.EntryAddress
instruction_rom.io.address := rom_loader.io.rom_address
val CPU_clkdiv = RegInit(UInt(2.W), 0.U)
val CPU_tick = Wire(Bool())
val CPU_next = Wire(UInt(2.W))
CPU_next := Mux(CPU_clkdiv === 3.U, 0.U, CPU_clkdiv + 1.U)
CPU_tick := CPU_clkdiv === 0.U
CPU_clkdiv := CPU_next
withClock(CPU_tick.asClock) {
val cpu = Module(new CPU)
cpu.io.instruction_valid := rom_loader.io.load_finished
mem.io.instruction_address := cpu.io.instruction_address
cpu.io.instruction := mem.io.instruction
cpu.io.interrupt_flag := io.interrupt_flag
when(!rom_loader.io.load_finished) {
rom_loader.io.bundle <> mem.io.bundle
cpu.io.memory_bundle.read_data := 0.U
}.otherwise {
rom_loader.io.bundle.read_data := 0.U
cpu.io.memory_bundle <> mem.io.bundle
}
cpu.io.regs_debug_read_address := io.regs_debug_read_address
cpu.io.csr_regs_debug_read_address := io.csr_regs_debug_read_address
io.regs_debug_read_data := cpu.io.regs_debug_read_data
io.csr_regs_debug_read_data := cpu.io.csr_regs_debug_read_data
io.pc_debug_read := cpu.io.instruction_address
}
mem.io.debug_read_address := io.mem_debug_read_address
io.mem_debug_read_data := mem.io.debug_read_data
}
class FibonacciTest extends AnyFlatSpec with ChiselScalatestTester {
behavior of "Single Cycle CPU with CSR and CLINT"
it should "calculate recursively fibonacci(10)" in {
test(new TestTopModule("fibonacci.asmbin")).withAnnotations(TestAnnotations.annos) { c =>
for (i <- 1 to 50) {
c.clock.step(1000)
c.io.mem_debug_read_address.poke((i * 4).U) // Avoid timeout
}
c.io.mem_debug_read_address.poke(4.U)
c.clock.step()
c.io.mem_debug_read_data.expect(55.U)
}
}
}
class QuicksortTest extends AnyFlatSpec with ChiselScalatestTester {
behavior of "Single Cycle CPU with CSR and CLINT"
it should "quicksort 10 numbers" in {
test(new TestTopModule("quicksort.asmbin")).withAnnotations(TestAnnotations.annos) { c =>
for (i <- 1 to 50) {
c.clock.step(1000)
c.io.mem_debug_read_address.poke((i * 4).U) // Avoid timeout
}
for (i <- 1 to 10) {
c.io.mem_debug_read_address.poke((4 * i).U)
c.clock.step()
c.io.mem_debug_read_data.expect((i - 1).U)
}
}
}
}
class ByteAccessTest extends AnyFlatSpec with ChiselScalatestTester {
behavior of "Single Cycle CPU with CSR and CLINT"
it should "store and load single byte" in {
test(new TestTopModule("sb.asmbin")).withAnnotations(TestAnnotations.annos) { c =>
for (i <- 1 to 500) {
c.clock.step()
c.io.mem_debug_read_address.poke((i * 4).U) // Avoid timeout
}
c.io.regs_debug_read_address.poke(5.U)
c.io.regs_debug_read_data.expect(0xDEADBEEFL.U)
c.io.regs_debug_read_address.poke(6.U)
c.io.regs_debug_read_data.expect(0xEF.U)
c.io.regs_debug_read_address.poke(1.U)
c.io.regs_debug_read_data.expect(0x15EF.U)
}
}
}
class SimpleTrapTest extends AnyFlatSpec with ChiselScalatestTester {
behavior of "Single Cycle CPU with CSR and CLINT"
it should "jump to trap handler and then return" in {
test(new TestTopModule("simpletest.asmbin")).withAnnotations(TestAnnotations.annos) { c =>
for (i <- 1 to 1000) {
c.clock.step()
c.io.mem_debug_read_address.poke((i * 4).U) // Avoid timeout
}
c.io.mem_debug_read_address.poke(4.U)
c.clock.step()
c.io.mem_debug_read_data.expect(0xDEADBEEFL.U)
c.io.interrupt_flag.poke(0x1.U)
c.clock.step(5)
c.io.interrupt_flag.poke(0.U)
for (i <- 1 to 1000) {
c.clock.step()
c.io.mem_debug_read_address.poke((i * 4).U) // Avoid timeout
}
c.io.csr_regs_debug_read_address.poke(CSRRegister.MSTATUS)
c.io.csr_regs_debug_read_data.expect(0x1888.U)
c.io.csr_regs_debug_read_address.poke(CSRRegister.MCAUSE)
c.io.csr_regs_debug_read_data.expect(0x80000007L.U)
c.io.mem_debug_read_address.poke(0x4.U)
c.clock.step()
c.io.mem_debug_read_data.expect(0x2022L.U)
}
}
}

View File

@@ -0,0 +1,49 @@
// Copyright 2022 hrpccs
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.singlecycle
import chisel3._
import chiseltest._
import org.scalatest.flatspec.AnyFlatSpec
import riscv.TestAnnotations
import riscv.core.Execute
class ExecuteTest extends AnyFlatSpec with ChiselScalatestTester{
behavior of "CLINTCSRTest of Single Cycle CPU"
it should "produce correct data for csr write" in {
test(new Execute).withAnnotations(TestAnnotations.annos) { c =>
c.io.instruction.poke(0x30047073L.U) // csrc mstatus,3
c.io.csr_reg_read_data.poke(0x1888L.U)
c.io.reg1_data.poke(0x1880L.U)
c.io.csr_reg_write_data.expect(0x1880.U)
c.clock.step()
c.io.instruction.poke(0x30046073L.U) //csrs mastatus,3
c.io.csr_reg_read_data.poke(0x1880L.U)
c.io.reg1_data.poke(0x1880L.U)
c.io.csr_reg_write_data.expect(0x1888.U)
c.clock.step()
c.io.instruction.poke(0x30051073L.U) //csrw mstatus, a0
c.io.csr_reg_read_data.poke(0.U)
c.io.reg1_data.poke(0x1888L.U)
c.io.csr_reg_write_data.expect(0x1888.U)
c.clock.step()
c.io.instruction.poke(0x30002573L.U) //csrr a0, mstatus
c.io.csr_reg_read_data.poke(0x1888.U)
c.io.reg1_data.poke(0x0L.U)
c.io.csr_reg_write_data.expect(0x1888.U)
c.clock.step()
}
}
}

View File

@@ -0,0 +1,61 @@
// Copyright 2022 hrpccs
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.singlecycle
import chisel3._
import chiseltest._
import org.scalatest.flatspec.AnyFlatSpec
import riscv.{Parameters, TestAnnotations}
import peripheral.{RAMBundle, Timer}
class TimerTest extends AnyFlatSpec with ChiselScalatestTester {
class TestTimer extends Module {
val io = IO(new Bundle {
val debug_limit = Output(UInt(Parameters.DataWidth))
val debug_enabled = Output(Bool())
val bundle = new RAMBundle
val write_strobe = Input(UInt(4.W))
})
val timer = Module(new Timer)
io.debug_limit := timer.io.debug_limit
io.debug_enabled := timer.io.debug_enabled
timer.io.bundle <> io.bundle
timer.io.bundle.write_strobe := VecInit(io.write_strobe.asBools)
}
behavior of "Timer"
it should "read and write the limit" in {
test(new TestTimer).withAnnotations(TestAnnotations.annos) {c =>
c.io.write_strobe.poke(0xF.U)
c.io.bundle.write_enable.poke(true.B)
c.io.bundle.address.poke(0x4.U)
c.io.bundle.write_data.poke(0x990315.U)
c.clock.step()
c.io.bundle.write_enable.poke(false.B)
c.clock.step()
c.io.debug_limit.expect(0x990315.U)
c.io.bundle.write_enable.poke(true.B)
c.io.bundle.address.poke(0x8.U)
c.io.bundle.write_data.poke(0.U)
c.clock.step()
c.io.bundle.write_enable.poke(false.B)
c.io.debug_enabled.expect(false.B)
}
}
}

View File

@@ -0,0 +1,35 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2021/12/17 16:31:05
// Design Name:
// Module Name: test
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module test();
reg clock;
reg reset;
initial begin
clock = 0;
forever #1 clock = ~clock;
end
initial begin
reset = 1;
#2 reset = 0;
end
Top top(clock, reset);
endmodule

View File

@@ -0,0 +1,221 @@
// file: TMDS_PLLVR.v
//
// (c) Copyright 2008 - 2013 Xilinx, Inc. All rights reserved.
//
// This file contains confidential and proprietary information
// of Xilinx, Inc. and is protected under U.S. and
// international copyright and other intellectual property
// laws.
//
// DISCLAIMER
// This disclaimer is not a license and does not grant any
// rights to the materials distributed herewith. Except as
// otherwise provided in a valid license issued to you by
// Xilinx, and to the maximum extent permitted by applicable
// law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
// WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
// AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
// BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
// INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
// (2) Xilinx shall not be liable (whether in contract or tort,
// including negligence, or under any other theory of
// liability) for any loss or damage of any kind or nature
// related to, arising under or in connection with these
// materials, including for any direct, or any indirect,
// special, incidental, or consequential loss or damage
// (including loss of data, profits, goodwill, or any type of
// loss or damage suffered as a result of any action brought
// by a third party) even if such damage or loss was
// reasonably foreseeable or Xilinx had been advised of the
// possibility of the same.
//
// CRITICAL APPLICATIONS
// Xilinx products are not designed or intended to be fail-
// safe, or for use in any application requiring fail-safe
// performance, such as life-support or safety devices or
// systems, Class III medical devices, nuclear facilities,
// applications related to the deployment of airbags, or any
// other applications that could lead to death, personal
// injury, or severe property or environmental damage
// (individually and collectively, "Critical
// Applications"). Customer assumes the sole risk and
// liability of any use of Xilinx products in Critical
// Applications, subject only to applicable laws and
// regulations governing limitations on product liability.
//
// THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
// PART OF THIS FILE AT ALL TIMES.
//
//----------------------------------------------------------------------------
// User entered comments
//----------------------------------------------------------------------------
// None
//
//----------------------------------------------------------------------------
// Output Output Phase Duty Cycle Pk-to-Pk Phase
// Clock Freq (MHz) (degrees) (%) Jitter (ps) Error (ps)
//----------------------------------------------------------------------------
// __clkout__250.00000______0.000______50.0______200.536____237.727
// _clkoutd__100.00000______0.000______50.0______226.965____237.727
//
//----------------------------------------------------------------------------
// Input Clock Freq (MHz) Input Jitter (UI)
//----------------------------------------------------------------------------
// __primary__________25.000____________0.010
`timescale 1ps/1ps
(* CORE_GENERATION_INFO = "TMDS_PLLVR,clk_wiz_v6_0_5_0_0,{component_name=TMDS_PLLVR,use_phase_alignment=true,use_min_o_jitter=false,use_max_i_jitter=false,use_dyn_phase_shift=false,use_inclk_switchover=false,use_dyn_reconfig=false,enable_axi=0,feedback_source=FDBK_AUTO,PRIMITIVE=PLL,num_out_clk=2,clkin1_period=40.000,clkin2_period=10.0,use_power_down=false,use_reset=true,use_locked=true,use_inclk_stopped=false,feedback_type=SINGLE,CLOCK_MGR_TYPE=NA,manual_override=true}" *)
module TMDS_PLLVR
(
// Clock out ports
output clkout,
output clkoutd,
// Status and control signals
input reset,
output lock,
// Clock in ports
input clkin
);
TMDS_PLLVR_clk_wiz inst
(
// Clock out ports
.clkout(clkout),
.clkoutd(clkoutd),
// Status and control signals
.reset(reset),
.lock(lock),
// Clock in ports
.clk_in1(clkin)
);
endmodule
module TMDS_PLLVR_clk_wiz
(// Clock in ports
// Clock out ports
output clkout,
output clkoutd,
// Status and control signals
input reset,
output lock,
input clk_in1
);
// Input buffering
//------------------------------------
wire clk_in1_TMDS_PLLVR;
wire clk_in2_TMDS_PLLVR;
IBUF clkin1_ibufg
(.O (clk_in1_TMDS_PLLVR),
.I (clk_in1));
// Clocking PRIMITIVE
//------------------------------------
// Instantiation of the MMCM PRIMITIVE
// * Unused inputs are tied off
// * Unused outputs are labeled unused
wire clkout_TMDS_PLLVR;
wire clkoutd_TMDS_PLLVR;
wire clk_out3_TMDS_PLLVR;
wire clk_out4_TMDS_PLLVR;
wire clk_out5_TMDS_PLLVR;
wire clk_out6_TMDS_PLLVR;
wire clk_out7_TMDS_PLLVR;
wire [15:0] do_unused;
wire drdy_unused;
wire psdone_unused;
wire lock_int;
wire clkfbout_TMDS_PLLVR;
wire clkfbout_buf_TMDS_PLLVR;
wire clkfboutb_unused;
wire clkout2_unused;
wire clkout3_unused;
wire clkout4_unused;
wire clkout5_unused;
wire clkout6_unused;
wire clkfbstopped_unused;
wire clkinstopped_unused;
wire reset_high;
PLLE2_ADV
#(.BANDWIDTH ("OPTIMIZED"),
.COMPENSATION ("ZHOLD"),
.STARTUP_WAIT ("FALSE"),
.DIVCLK_DIVIDE (1),
.CLKFBOUT_MULT (40),
.CLKFBOUT_PHASE (0.000),
.CLKOUT0_DIVIDE (4),
.CLKOUT0_PHASE (0.000),
.CLKOUT0_DUTY_CYCLE (0.500),
.CLKOUT1_DIVIDE (10),
.CLKOUT1_PHASE (0.000),
.CLKOUT1_DUTY_CYCLE (0.500),
.CLKIN1_PERIOD (40.000))
plle2_adv_inst
// Output clocks
(
.CLKFBOUT (clkfbout_TMDS_PLLVR),
.CLKOUT0 (clkout_TMDS_PLLVR),
.CLKOUT1 (clkoutd_TMDS_PLLVR),
.CLKOUT2 (clkout2_unused),
.CLKOUT3 (clkout3_unused),
.CLKOUT4 (clkout4_unused),
.CLKOUT5 (clkout5_unused),
// Input clock control
.CLKFBIN (clkfbout_buf_TMDS_PLLVR),
.CLKIN1 (clk_in1_TMDS_PLLVR),
.CLKIN2 (1'b0),
// Tied to always select the primary input clock
.CLKINSEL (1'b1),
// Ports for dynamic reconfiguration
.DADDR (7'h0),
.DCLK (1'b0),
.DEN (1'b0),
.DI (16'h0),
.DO (do_unused),
.DRDY (drdy_unused),
.DWE (1'b0),
// Other control and status signals
.LOCKED (lock_int),
.PWRDWN (1'b0),
.RST (reset_high));
assign reset_high = reset;
assign lock = lock_int;
// Clock Monitor clock assigning
//--------------------------------------
// Output buffering
//-----------------------------------
BUFG clkf_buf
(.O (clkfbout_buf_TMDS_PLLVR),
.I (clkfbout_TMDS_PLLVR));
BUFG clkout1_buf
(.O (clkout),
.I (clkout_TMDS_PLLVR));
BUFG clkout2_buf
(.O (clkoutd),
.I (clkoutd_TMDS_PLLVR));
endmodule

35
lab2/verilog/pynq/test.v Normal file
View File

@@ -0,0 +1,35 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2021/12/17 16:31:05
// Design Name:
// Module Name: test
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module test();
reg clock;
reg reset;
initial begin
clock = 0;
forever #100 clock = ~clock;
end
initial begin
reset = 1;
#200 reset = 0;
end
Top top(clock, reset);
endmodule

View File

@@ -0,0 +1,246 @@
#include <verilated.h>
#include <verilated_vcd_c.h>
#include <algorithm>
#include <fstream>
#include <iostream>
#include <string>
#include <memory>
#include <vector>
#include "VTop.h" // From Verilating "top.v"
class Memory {
std::vector<uint32_t> memory;
public:
Memory(size_t size) : memory(size, 0) {}
uint32_t read(size_t address) {
address = address / 4;
if (address >= memory.size()) {
// printf("invalid read address 0x%08x\n", address * 4);
return 0;
}
return memory[address];
}
uint32_t readInst(size_t address) {
address = address / 4;
if (address >= memory.size()) {
// printf("invalid read Inst address 0x%08x\n", address * 4);
return 0;
}
return memory[address];
}
void write(size_t address, uint32_t value, bool write_strobe[4]) {
address = address / 4;
uint32_t write_mask = 0;
if (write_strobe[0]) write_mask |= 0x000000FF;
if (write_strobe[1]) write_mask |= 0x0000FF00;
if (write_strobe[2]) write_mask |= 0x00FF0000;
if (write_strobe[3]) write_mask |= 0xFF000000;
if (address >= memory.size()) {
// printf("invalid write address 0x%08x\n", address * 4);
return;
}
memory[address] = (memory[address] & ~write_mask) | (value & write_mask);
}
void load_binary(std::string const& filename, size_t load_address = 0x1000) {
std::ifstream file(filename, std::ios::binary);
if (!file) {
throw std::runtime_error("Could not open file " + filename);
}
file.seekg(0, std::ios::end);
size_t size = file.tellg();
if (load_address + size > memory.size() * 4) {
throw std::runtime_error("File " + filename + " is too large (File is " +
std::to_string(size) + " bytes. Memory is " +
std::to_string(memory.size() * 4 - load_address) + " bytes.)");
}
file.seekg(0, std::ios::beg);
for (int i = 0; i < size / 4; ++i) {
file.read(reinterpret_cast<char*>(&memory[i + load_address / 4]),
sizeof(uint32_t));
}
}
};
class VCDTracer {
VerilatedVcdC* tfp = nullptr;
public:
void enable(std::string const& filename, VTop& top) {
Verilated::traceEverOn(true);
tfp = new VerilatedVcdC;
top.trace(tfp, 99);
tfp->open(filename.c_str());
tfp->set_time_resolution("1ps");
tfp->set_time_unit("1ns");
if (!tfp->isOpen()) {
throw std::runtime_error("Failed to open VCD dump file " + filename);
}
}
void dump(vluint64_t time) {
if (tfp) {
tfp->dump(time);
}
}
~VCDTracer() {
if (tfp) {
tfp->close();
delete tfp;
}
}
};
uint32_t parse_number(std::string const& str) {
if (str.size() > 2) {
auto&& prefix = str.substr(0, 2);
if (prefix == "0x" || prefix == "0X") {
return std::stoul(str.substr(2), nullptr, 16);
}
}
return std::stoul(str);
}
class Simulator {
vluint64_t main_time = 0;
vluint64_t max_sim_time = 10000;
uint32_t halt_address = 0;
size_t memory_words = 1024 * 1024; // 4MB
bool dump_vcd = false;
std::unique_ptr<VTop> top;
std::unique_ptr<VCDTracer> vcd_tracer;
std::unique_ptr<Memory> memory;
bool dump_signature = false;
unsigned long signature_begin, signature_end;
std::string signature_filename;
std::string instruction_filename;
public:
void parse_args(std::vector<std::string> const& args) {
if (auto it = std::find(args.begin(), args.end(), "-halt");
it != args.end()) {
halt_address = parse_number(*(it + 1));
}
if (auto it = std::find(args.begin(), args.end(), "-memory");
it != args.end()) {
memory_words = std::stoul(*(it + 1));
}
if (auto it = std::find(args.begin(), args.end(), "-time");
it != args.end()) {
max_sim_time = std::stoul(*(it + 1));
}
if (auto it = std::find(args.begin(), args.end(), "-vcd");
it != args.end()) {
vcd_tracer->enable(*(it + 1), *top);
}
if (auto it = std::find(args.begin(), args.end(), "-signature");
it != args.end()) {
dump_signature = true;
signature_begin = parse_number(*(it + 1));
signature_end = parse_number(*(it + 2));
signature_filename = *(it + 3);
}
if (auto it = std::find(args.begin(), args.end(), "-instruction");
it != args.end()) {
instruction_filename = *(it + 1);
}
}
Simulator(std::vector<std::string> const& args)
: top(std::make_unique<VTop>()),
vcd_tracer(std::make_unique<VCDTracer>()) {
parse_args(args);
memory = std::make_unique<Memory>(memory_words);
if (!instruction_filename.empty()) {
memory->load_binary(instruction_filename);
}
}
void run() {
top->reset = 1;
top->clock = 0;
top->io_instruction_valid = 1;
top->eval();
vcd_tracer->dump(main_time);
uint32_t data_memory_read_word = 0;
uint32_t inst_memory_read_word = 0;
uint32_t timer_interrupt = 0;
uint32_t counter = 0;
uint32_t clocktime = 1;
bool memory_write_strobe[4] = {false};
while (main_time < max_sim_time && !Verilated::gotFinish()) {
++main_time;
++counter;
if(counter > clocktime){
top->clock = !top->clock;
counter = 0;
}
if (main_time > 2) {
top->reset = 0;
}
// top->io_mem_slave_read_data = memory_read_word;
top->io_memory_bundle_read_data = data_memory_read_word;
top->io_instruction = inst_memory_read_word;
top->clock = !top->clock;
top->eval();
top->io_interrupt_flag = 0;
data_memory_read_word = memory->read(top->io_memory_bundle_address);
inst_memory_read_word = memory->readInst(top->io_instruction_address);
if (top->io_memory_bundle_write_enable) {
memory_write_strobe[0] = top->io_memory_bundle_write_strobe_0;
memory_write_strobe[1] = top->io_memory_bundle_write_strobe_1;
memory_write_strobe[2] = top->io_memory_bundle_write_strobe_2;
memory_write_strobe[3] = top->io_memory_bundle_write_strobe_3;
memory->write(top->io_memory_bundle_address, top->io_memory_bundle_write_data,
memory_write_strobe);
}
vcd_tracer->dump(main_time);
if (halt_address) {
if (memory->read(halt_address) == 0xBABECAFE) {
break;
}
}
}
if (dump_signature) {
char data[9] = {0};
std::ofstream signature_file(signature_filename);
for (size_t addr = signature_begin; addr < signature_end; addr += 4) {
snprintf(data, 9, "%08x", memory->read(addr));
signature_file << data << std::endl;
}
}
}
~Simulator() {
if (top) {
top->final();
}
}
};
int main(int argc, char** argv) {
Verilated::commandArgs(argc, argv);
std::vector<std::string> args(argv, argv + argc);
Simulator simulator(args);
simulator.run();
return 0;
}

View File

@@ -0,0 +1,307 @@
# Copyright 2021 Howard Lau
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
## Clock signal
set_property PACKAGE_PIN W5 [get_ports clock]
set_property IOSTANDARD LVCMOS33 [get_ports clock]
create_clock -add -name sys_clk_pin -period 20.00 -waveform {0 5} [get_ports clock]
## Switches
set_property PACKAGE_PIN V17 [get_ports {io_switch[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_switch[0]}]
set_property PACKAGE_PIN V16 [get_ports {io_switch[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_switch[1]}]
set_property PACKAGE_PIN W16 [get_ports {io_switch[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_switch[2]}]
set_property PACKAGE_PIN W17 [get_ports {io_switch[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_switch[3]}]
set_property PACKAGE_PIN W15 [get_ports {io_switch[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_switch[4]}]
set_property PACKAGE_PIN V15 [get_ports {io_switch[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_switch[5]}]
set_property PACKAGE_PIN W14 [get_ports {io_switch[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_switch[6]}]
set_property PACKAGE_PIN W13 [get_ports {io_switch[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_switch[7]}]
set_property PACKAGE_PIN V2 [get_ports {io_switch[8]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_switch[8]}]
set_property PACKAGE_PIN T3 [get_ports {io_switch[9]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_switch[9]}]
set_property PACKAGE_PIN T2 [get_ports {io_switch[10]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_switch[10]}]
set_property PACKAGE_PIN R3 [get_ports {io_switch[11]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_switch[11]}]
set_property PACKAGE_PIN W2 [get_ports {io_switch[12]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_switch[12]}]
set_property PACKAGE_PIN U1 [get_ports {io_switch[13]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_switch[13]}]
set_property PACKAGE_PIN T1 [get_ports {io_switch[14]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_switch[14]}]
set_property PACKAGE_PIN R2 [get_ports {io_switch[15]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_switch[15]}]
## LEDs
set_property PACKAGE_PIN U16 [get_ports {io_led[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_led[0]}]
set_property PACKAGE_PIN E19 [get_ports {io_led[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_led[1]}]
set_property PACKAGE_PIN U19 [get_ports {io_led[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_led[2]}]
set_property PACKAGE_PIN V19 [get_ports {io_led[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_led[3]}]
set_property PACKAGE_PIN W18 [get_ports {io_led[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_led[4]}]
set_property PACKAGE_PIN U15 [get_ports {io_led[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_led[5]}]
set_property PACKAGE_PIN U14 [get_ports {io_led[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_led[6]}]
set_property PACKAGE_PIN V14 [get_ports {io_led[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_led[7]}]
set_property PACKAGE_PIN V13 [get_ports {io_led[8]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_led[8]}]
set_property PACKAGE_PIN V3 [get_ports {io_led[9]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_led[9]}]
set_property PACKAGE_PIN W3 [get_ports {io_led[10]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_led[10]}]
set_property PACKAGE_PIN U3 [get_ports {io_led[11]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_led[11]}]
set_property PACKAGE_PIN P3 [get_ports {io_led[12]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_led[12]}]
set_property PACKAGE_PIN N3 [get_ports {io_led[13]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_led[13]}]
set_property PACKAGE_PIN P1 [get_ports {io_led[14]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_led[14]}]
set_property PACKAGE_PIN L1 [get_ports {io_led[15]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_led[15]}]
##7 segment display
set_property PACKAGE_PIN U7 [get_ports io_segs[0]]
set_property IOSTANDARD LVCMOS33 [get_ports io_segs[0]]
set_property PACKAGE_PIN V5 [get_ports io_segs[1]]
set_property IOSTANDARD LVCMOS33 [get_ports io_segs[1]]
set_property PACKAGE_PIN U5 [get_ports io_segs[2]]
set_property IOSTANDARD LVCMOS33 [get_ports io_segs[2]]
set_property PACKAGE_PIN V8 [get_ports io_segs[3]]
set_property IOSTANDARD LVCMOS33 [get_ports io_segs[3]]
set_property PACKAGE_PIN U8 [get_ports io_segs[4]]
set_property IOSTANDARD LVCMOS33 [get_ports io_segs[4]]
set_property PACKAGE_PIN W6 [get_ports io_segs[5]]
set_property IOSTANDARD LVCMOS33 [get_ports io_segs[5]]
set_property PACKAGE_PIN W7 [get_ports io_segs[6]]
set_property IOSTANDARD LVCMOS33 [get_ports io_segs[6]]
set_property PACKAGE_PIN V7 [get_ports io_segs[7]]
set_property IOSTANDARD LVCMOS33 [get_ports io_segs[7]]
set_property PACKAGE_PIN U2 [get_ports {io_digit_mask[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_digit_mask[0]}]
set_property PACKAGE_PIN U4 [get_ports {io_digit_mask[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_digit_mask[1]}]
set_property PACKAGE_PIN V4 [get_ports {io_digit_mask[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_digit_mask[2]}]
set_property PACKAGE_PIN W4 [get_ports {io_digit_mask[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_digit_mask[3]}]
##Buttons
set_property PACKAGE_PIN U18 [get_ports reset]
set_property IOSTANDARD LVCMOS33 [get_ports reset]
#set_property PACKAGE_PIN T18 [get_ports io_freqIncrease]
#set_property IOSTANDARD LVCMOS33 [get_ports io_freqIncrease]
#set_property PACKAGE_PIN W19 [get_ports io_widthIncrease]
#set_property IOSTANDARD LVCMOS33 [get_ports io_widthIncrease]
#set_property PACKAGE_PIN T17 [get_ports io_widthDecrease]
#set_property IOSTANDARD LVCMOS33 [get_ports io_widthDecrease]
#set_property PACKAGE_PIN U17 [get_ports io_freqDecrease]
#set_property IOSTANDARD LVCMOS33 [get_ports io_freqDecrease]
##Pmod Header JA
##Sch name = JA1
#set_property PACKAGE_PIN J1 [get_ports {JA[0]}]
#set_property IOSTANDARD LVCMOS33 [get_ports {JA[0]}]
##Sch name = JA2
#set_property PACKAGE_PIN L2 [get_ports {JA[1]}]
#set_property IOSTANDARD LVCMOS33 [get_ports {JA[1]}]
##Sch name = JA3
#set_property PACKAGE_PIN J2 [get_ports {JA[2]}]
#set_property IOSTANDARD LVCMOS33 [get_ports {JA[2]}]
##Sch name = JA4
#set_property PACKAGE_PIN G2 [get_ports {JA[3]}]
#set_property IOSTANDARD LVCMOS33 [get_ports {JA[3]}]
##Sch name = JA7
#set_property PACKAGE_PIN H1 [get_ports {JA[4]}]
#set_property IOSTANDARD LVCMOS33 [get_ports {JA[4]}]
##Sch name = JA8
#set_property PACKAGE_PIN K2 [get_ports {JA[5]}]
#set_property IOSTANDARD LVCMOS33 [get_ports {JA[5]}]
##Sch name = JA9
#set_property PACKAGE_PIN H2 [get_ports {JA[6]}]
#set_property IOSTANDARD LVCMOS33 [get_ports {JA[6]}]
##Sch name = JA10
#set_property PACKAGE_PIN G3 [get_ports {JA[7]}]
#set_property IOSTANDARD LVCMOS33 [get_ports {JA[7]}]
##Pmod Header JB
##Sch name = JB1
#set_property PACKAGE_PIN A14 [get_ports {JB[0]}]
#set_property IOSTANDARD LVCMOS33 [get_ports {JB[0]}]
##Sch name = JB2
#set_property PACKAGE_PIN A16 [get_ports {JB[1]}]
#set_property IOSTANDARD LVCMOS33 [get_ports {JB[1]}]
##Sch name = JB3
#set_property PACKAGE_PIN B15 [get_ports {JB[2]}]
#set_property IOSTANDARD LVCMOS33 [get_ports {JB[2]}]
##Sch name = JB4
#set_property PACKAGE_PIN B16 [get_ports {JB[3]}]
#set_property IOSTANDARD LVCMOS33 [get_ports {JB[3]}]
##Sch name = JB7
#set_property PACKAGE_PIN A15 [get_ports {JB[4]}]
#set_property IOSTANDARD LVCMOS33 [get_ports {JB[4]}]
##Sch name = JB8
#set_property PACKAGE_PIN A17 [get_ports {JB[5]}]
#set_property IOSTANDARD LVCMOS33 [get_ports {JB[5]}]
##Sch name = JB9
#set_property PACKAGE_PIN C15 [get_ports {JB[6]}]
#set_property IOSTANDARD LVCMOS33 [get_ports {JB[6]}]
##Sch name = JB10
#set_property PACKAGE_PIN C16 [get_ports {JB[7]}]
#set_property IOSTANDARD LVCMOS33 [get_ports {JB[7]}]
##Pmod Header JC
##Sch name = JC1
#set_property PACKAGE_PIN K17 [get_ports {JC[0]}]
#set_property IOSTANDARD LVCMOS33 [get_ports {JC[0]}]
##Sch name = JC2
#set_property PACKAGE_PIN M18 [get_ports {JC[1]}]
#set_property IOSTANDARD LVCMOS33 [get_ports {JC[1]}]
##Sch name = JC3
#set_property PACKAGE_PIN N17 [get_ports {JC[2]}]
#set_property IOSTANDARD LVCMOS33 [get_ports {JC[2]}]
##Sch name = JC4
#set_property PACKAGE_PIN P18 [get_ports {JC[3]}]
#set_property IOSTANDARD LVCMOS33 [get_ports {JC[3]}]
##Sch name = JC7
#set_property PACKAGE_PIN L17 [get_ports {JC[4]}]
#set_property IOSTANDARD LVCMOS33 [get_ports {JC[4]}]
##Sch name = JC8
#set_property PACKAGE_PIN M19 [get_ports {JC[5]}]
#set_property IOSTANDARD LVCMOS33 [get_ports {JC[5]}]
##Sch name = JC9
#set_property PACKAGE_PIN P17 [get_ports {JC[6]}]
#set_property IOSTANDARD LVCMOS33 [get_ports {JC[6]}]
##Sch name = JC10
#set_property PACKAGE_PIN R18 [get_ports {JC[7]}]
#set_property IOSTANDARD LVCMOS33 [get_ports {JC[7]}]
##Pmod Header JXADC
##Sch name = XA1_P
#set_property PACKAGE_PIN J3 [get_ports {JXADC[0]}]
#set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[0]}]
##Sch name = XA2_P
#set_property PACKAGE_PIN L3 [get_ports {JXADC[1]}]
#set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[1]}]
##Sch name = XA3_P
#set_property PACKAGE_PIN M2 [get_ports {JXADC[2]}]
#set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[2]}]
##Sch name = XA4_P
#set_property PACKAGE_PIN N2 [get_ports {JXADC[3]}]
#set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[3]}]
##Sch name = XA1_N
#set_property PACKAGE_PIN K3 [get_ports {JXADC[4]}]
#set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[4]}]
##Sch name = XA2_N
#set_property PACKAGE_PIN M3 [get_ports {JXADC[5]}]
#set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[5]}]
##Sch name = XA3_N
#set_property PACKAGE_PIN M1 [get_ports {JXADC[6]}]
#set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[6]}]
##Sch name = XA4_N
#set_property PACKAGE_PIN N1 [get_ports {JXADC[7]}]
#set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[7]}]
##VGA Connector
set_property PACKAGE_PIN G19 [get_ports {io_rgb[8]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_rgb[8]}]
set_property PACKAGE_PIN H19 [get_ports {io_rgb[9]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_rgb[9]}]
set_property PACKAGE_PIN J19 [get_ports {io_rgb[10]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_rgb[10]}]
set_property PACKAGE_PIN N19 [get_ports {io_rgb[11]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_rgb[11]}]
set_property PACKAGE_PIN N18 [get_ports {io_rgb[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_rgb[0]}]
set_property PACKAGE_PIN L18 [get_ports {io_rgb[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_rgb[1]}]
set_property PACKAGE_PIN K18 [get_ports {io_rgb[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_rgb[2]}]
set_property PACKAGE_PIN J18 [get_ports {io_rgb[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_rgb[3]}]
set_property PACKAGE_PIN J17 [get_ports {io_rgb[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_rgb[4]}]
set_property PACKAGE_PIN H17 [get_ports {io_rgb[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_rgb[5]}]
set_property PACKAGE_PIN G17 [get_ports {io_rgb[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_rgb[6]}]
set_property PACKAGE_PIN D17 [get_ports {io_rgb[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {io_rgb[7]}]
set_property PACKAGE_PIN P19 [get_ports io_hsync]
set_property IOSTANDARD LVCMOS33 [get_ports io_hsync]
set_property PACKAGE_PIN R19 [get_ports io_vsync]
set_property IOSTANDARD LVCMOS33 [get_ports io_vsync]
##USB-RS232 Interface
set_property PACKAGE_PIN B18 [get_ports io_rx]
set_property IOSTANDARD LVCMOS33 [get_ports io_rx]
set_property PACKAGE_PIN A18 [get_ports io_tx]
set_property IOSTANDARD LVCMOS33 [get_ports io_tx]
##USB HID (PS/2)
#set_property PACKAGE_PIN C17 [get_ports PS2Clk]
#set_property IOSTANDARD LVCMOS33 [get_ports PS2Clk]
#set_property PULLUP true [get_ports PS2Clk]
#set_property PACKAGE_PIN B17 [get_ports PS2Data]
#set_property IOSTANDARD LVCMOS33 [get_ports PS2Data]
#set_property PULLUP true [get_ports PS2Data]
##Quad SPI Flash
##Note that CCLK_0 cannot be placed in 7 series devices. You can access it using the
##STARTUPE2 primitive.
#set_property PACKAGE_PIN D18 [get_ports {QspiDB[0]}]
#set_property IOSTANDARD LVCMOS33 [get_ports {QspiDB[0]}]
#set_property PACKAGE_PIN D19 [get_ports {QspiDB[1]}]
#set_property IOSTANDARD LVCMOS33 [get_ports {QspiDB[1]}]
#set_property PACKAGE_PIN G18 [get_ports {QspiDB[2]}]
#set_property IOSTANDARD LVCMOS33 [get_ports {QspiDB[2]}]
#set_property PACKAGE_PIN F18 [get_ports {QspiDB[3]}]
#set_property IOSTANDARD LVCMOS33 [get_ports {QspiDB[3]}]
#set_property PACKAGE_PIN K19 [get_ports QspiCSn]
#set_property IOSTANDARD LVCMOS33 [get_ports QspiCSn]
## Configuration options, can be used for all designs
set_property CONFIG_VOLTAGE 3.3 [current_design]
set_property CFGBVS VCCO [current_design]

View File

@@ -0,0 +1,17 @@
# Copyright 2021 Howard Lau
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Only tested on Vivado 2020.1 on Windows 10
source generate_bitstream.tcl
source program_device.tcl

View File

@@ -0,0 +1,55 @@
# Copyright 2021 Howard Lau
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
source open_project.tcl
while 1 {
if { [catch {launch_runs synth_1 -jobs 4 } ] } {
regexp {ERROR: \[Common (\d+-\d+)]} $errorInfo -> code
if { [string equal $code "12-978"] } {
puts "Already generated and up-to-date"
break
} elseif { [string equal $code "17-69"] } {
puts "Out of date, reset runs"
reset_runs synth_1
continue
} else {
puts "UNKNOWN ERROR!!! $errorInfo"
exit
}
}
break
}
wait_on_run synth_1
while 1 {
if { [catch {launch_runs impl_1 -jobs 4 -to_step write_bitstream } ] } {
regexp {ERROR: \[Vivado (\d+-\d+)]} $errorInfo -> code
if { [string equal $code "12-978"] } {
puts "Already generated and up-to-date"
break
} elseif { [string equal $code "12-1088"] } {
puts "Out of date, reset runs"
reset_runs impl_1
continue
} else {
puts "UNKNOWN ERROR!!! $errorInfo"
exit
}
}
break
}
wait_on_run impl_1

View File

@@ -0,0 +1,39 @@
# Copyright 2021 Howard Lau
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Only tested on Vivado 2020.1 on Windows 10
# set variables
set project_dir riscv-basys3
set project_name riscv-basys3
set part xc7a35tcpg236-1
set sources {../../verilog/basys3/Top.v}
set test_sources {../../verilog/basys3/test.v}
# open the project. will create one if it doesn't exist
if {[file exist $project_dir]} {
# check that it's a directory
if {! [file isdirectory $project_dir]} {
puts "$project_dir exists, but it's a file"
}
open_project $project_dir/$project_name.xpr -part $part
} else {
create_project $project_name $project_dir -part $part
}
add_files -norecurse $sources
update_compile_order -fileset sources_1
add_files -fileset constrs_1 -norecurse basys3.xdc
add_files -fileset sim_1 -norecurse $test_sources
update_compile_order -fileset sim_1

View File

@@ -0,0 +1,24 @@
# Copyright 2021 Howard Lau
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Only tested on Vivado 2020.1 on Windows 10
open_hw_manager
connect_hw_server -allow_non_jtag
open_hw_target
current_hw_device [get_hw_devices xc7a35t_0]
refresh_hw_server [current_hw_server]
open_hw_target [lindex [get_hw_targets] 0]
set_property PROGRAM.FILE {./riscv-basys3/riscv-basys3.runs/impl_1/Top.bit} [get_hw_devices xc7a35t_0]
program_hw_devices [get_hw_devices xc7a35t_0]
close_hw_target

View File

@@ -0,0 +1,4 @@
cd ..
sbt run
cd vivado
C:\Xilinx\Vivado\2020.1\bin\vivado -mode batch -source .\generate_and_program.tcl

View File

@@ -0,0 +1,24 @@
# Copyright 2021 Howard Lau
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
source open_project.tcl
launch_simulation
restart
open_vcd
log_wave -recursive [get_object /test/top/cpu/*]
log_vcd [get_object /test/top/cpu/*]
run 1000ns
close_vcd
close_sim

View File

@@ -0,0 +1,17 @@
# Copyright 2021 Howard Lau
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Only tested on Vivado 2020.1 on Windows 10
source generate_bitstream.tcl
source program_device.tcl

View File

@@ -0,0 +1,57 @@
# Copyright 2021 Howard Lau
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
source open_project.tcl
set_param general.maxThreads 16
set_param pwropt.maxFaninFanoutToNetRatio 5000
while 1 {
if { [catch {launch_runs synth_1 -jobs 16 } ] } {
regexp {ERROR: \[Common (\d+-\d+)]} $errorInfo -> code
if { [string equal $code "12-978"] } {
puts "Already generated and up-to-date"
break
} elseif { [string equal $code "17-69"] } {
puts "Out of date, reset runs"
reset_runs synth_1
continue
} else {
puts "UNKNOWN ERROR!!! $errorInfo"
exit
}
}
break
}
wait_on_run synth_1
while 1 {
if { [catch {launch_runs impl_1 -jobs 16 -to_step write_bitstream } ] } {
regexp {ERROR: \[Vivado (\d+-\d+)]} $errorInfo -> code
if { [string equal $code "12-978"] } {
puts "Already generated and up-to-date"
break
} elseif { [string equal $code "12-1088"] } {
puts "Out of date, reset runs"
reset_runs impl_1
continue
} else {
puts "UNKNOWN ERROR!!! $errorInfo"
exit
}
}
break
}
wait_on_run impl_1

View File

@@ -0,0 +1,40 @@
# Copyright 2021 Howard Lau
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Only tested on Vivado 2020.1 on Windows 10
# set variables
set project_dir riscv-pynq
set project_name riscv-pynq
set part xc7z020clg400-1
set sources {../../verilog/pynq/Top.v}
set test_sources {../../verilog/pynq/test.v}
# open the project. will create one if it doesn't exist
if {[file exist $project_dir]} {
# check that it's a directory
if {! [file isdirectory $project_dir]} {
puts "$project_dir exists, but it's a file"
}
open_project $project_dir/$project_name.xpr -part $part
} else {
create_project $project_name $project_dir -part $part
}
add_files -norecurse $sources
add_files -norecurse ../../verilog/pynq/TMDS_PLLVR.v
update_compile_order -fileset sources_1
add_files -fileset constrs_1 -norecurse pynq.xdc
add_files -fileset sim_1 -norecurse $test_sources
update_compile_order -fileset sim_1

View File

@@ -0,0 +1,22 @@
# Copyright 2021 Howard Lau
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Only tested on Vivado 2020.1 on Windows 10
open_hw_manager
connect_hw_server -allow_non_jtag
refresh_hw_server [current_hw_server]
open_hw_target [lindex [get_hw_targets] 0]
set_property PROGRAM.FILE {riscv-pynq/riscv-pynq.runs/impl_1/Top.bit} [get_hw_devices xc7z020_1]
program_hw_devices [get_hw_devices xc7z020_1]
close_hw_target

191
lab2/vivado/pynq/pynq.xdc Normal file
View File

@@ -0,0 +1,191 @@
## This file is a general .xdc for the PYNQ-Z1 board Rev. C
## To use it in a project:
## - uncomment the lines corresponding to used pins
## - rename the used ports (in each line, after get_ports) according to the top level signal names in the project
## Clock signal 125 MHz
set_property -dict {PACKAGE_PIN H16 IOSTANDARD LVCMOS33} [get_ports clock]
create_clock -period 8.000 -name sys_clk_pin -waveform {0.000 4.000} -add [get_ports clock]
##Switches
set_property -dict { PACKAGE_PIN M20 IOSTANDARD LVCMOS33 } [get_ports { io_debug_step }]; #IO_L7N_T1_AD2N_35 Sch=sw[0]
#set_property -dict { PACKAGE_PIN M19 IOSTANDARD LVCMOS33 } [get_ports { sw[1] }]; #IO_L7P_T1_AD2P_35 Sch=sw[1]
##RGB LEDs
#set_property -dict { PACKAGE_PIN L15 IOSTANDARD LVCMOS33 } [get_ports { led4_b }]; #IO_L22N_T3_AD7N_35 Sch=led4_b
#set_property -dict { PACKAGE_PIN G17 IOSTANDARD LVCMOS33 } [get_ports { led4_g }]; #IO_L16P_T2_35 Sch=led4_g
#set_property -dict { PACKAGE_PIN N15 IOSTANDARD LVCMOS33 } [get_ports { led4_r }]; #IO_L21P_T3_DQS_AD14P_35 Sch=led4_r
#set_property -dict { PACKAGE_PIN G14 IOSTANDARD LVCMOS33 } [get_ports { led5_b }]; #IO_0_35 Sch=led5_b
#set_property -dict { PACKAGE_PIN L14 IOSTANDARD LVCMOS33 } [get_ports { led5_g }]; #IO_L22P_T3_AD7P_35 Sch=led5_g
#set_property -dict { PACKAGE_PIN M15 IOSTANDARD LVCMOS33 } [get_ports { led5_r }]; #IO_L23N_T3_35 Sch=led5_r
##LEDs
set_property -dict {PACKAGE_PIN R14 IOSTANDARD LVCMOS33} [get_ports {io_led[0]}]
set_property -dict {PACKAGE_PIN P14 IOSTANDARD LVCMOS33} [get_ports {io_led[1]}]
set_property -dict {PACKAGE_PIN N16 IOSTANDARD LVCMOS33} [get_ports {io_led[2]}]
set_property -dict {PACKAGE_PIN M14 IOSTANDARD LVCMOS33} [get_ports {io_led[3]}]
##Buttons
set_property -dict {PACKAGE_PIN D19 IOSTANDARD LVCMOS33} [get_ports reset]
set_property -dict { PACKAGE_PIN D20 IOSTANDARD LVCMOS33 } [get_ports { io_debug_clk }]; #IO_L4N_T0_35 Sch=btn[1]
#set_property -dict { PACKAGE_PIN L20 IOSTANDARD LVCMOS33 } [get_ports { btn[2] }]; #IO_L9N_T1_DQS_AD3N_35 Sch=btn[2]
#set_property -dict { PACKAGE_PIN L19 IOSTANDARD LVCMOS33 } [get_ports { btn[3] }]; #IO_L9P_T1_DQS_AD3P_35 Sch=btn[3]
##Pmod Header JA
#set_property -dict { PACKAGE_PIN Y18 IOSTANDARD LVCMOS33 } [get_ports { io_rx }]; #IO_L17P_T2_34 Sch=ja_p[1]
#set_property -dict { PACKAGE_PIN Y19 IOSTANDARD LVCMOS33 } [get_ports { io_tx }]; #IO_L17N_T2_34 Sch=ja_n[1]
set_property -dict {PACKAGE_PIN Y16 IOSTANDARD LVCMOS33} [get_ports io_rx]
set_property -dict {PACKAGE_PIN Y17 IOSTANDARD LVCMOS33} [get_ports io_tx]
#set_property -dict { PACKAGE_PIN U18 IOSTANDARD LVCMOS33 } [get_ports { ja[4] }]; #IO_L12P_T1_MRCC_34 Sch=ja_p[3]
#set_property -dict { PACKAGE_PIN U19 IOSTANDARD LVCMOS33 } [get_ports { ja[5] }]; #IO_L12N_T1_MRCC_34 Sch=ja_n[3]
#set_property -dict { PACKAGE_PIN W18 IOSTANDARD LVCMOS33 } [get_ports { ja[6] }]; #IO_L22P_T3_34 Sch=ja_p[4]
#set_property -dict { PACKAGE_PIN W19 IOSTANDARD LVCMOS33 } [get_ports { ja[7] }]; #IO_L22N_T3_34 Sch=ja_n[4]
##Pmod Header JB
#set_property -dict { PACKAGE_PIN W14 IOSTANDARD LVCMOS33 } [get_ports { jb[0] }]; #IO_L8P_T1_34 Sch=jb_p[1]
#set_property -dict { PACKAGE_PIN Y14 IOSTANDARD LVCMOS33 } [get_ports { jb[1] }]; #IO_L8N_T1_34 Sch=jb_n[1]
#set_property -dict { PACKAGE_PIN T11 IOSTANDARD LVCMOS33 } [get_ports { jb[2] }]; #IO_L1P_T0_34 Sch=jb_p[2]
#set_property -dict { PACKAGE_PIN T10 IOSTANDARD LVCMOS33 } [get_ports { jb[3] }]; #IO_L1N_T0_34 Sch=jb_n[2]
#set_property -dict { PACKAGE_PIN V16 IOSTANDARD LVCMOS33 } [get_ports { jb[4] }]; #IO_L18P_T2_34 Sch=jb_p[3]
#set_property -dict { PACKAGE_PIN W16 IOSTANDARD LVCMOS33 } [get_ports { jb[5] }]; #IO_L18N_T2_34 Sch=jb_n[3]
#set_property -dict { PACKAGE_PIN V12 IOSTANDARD LVCMOS33 } [get_ports { jb[6] }]; #IO_L4P_T0_34 Sch=jb_p[4]
#set_property -dict { PACKAGE_PIN W13 IOSTANDARD LVCMOS33 } [get_ports { jb[7] }]; #IO_L4N_T0_34 Sch=jb_n[4]
##Audio Out
#set_property -dict { PACKAGE_PIN R18 IOSTANDARD LVCMOS33 } [get_ports { aud_pwm }]; #IO_L20N_T3_34 Sch=aud_pwm
#set_property -dict { PACKAGE_PIN T17 IOSTANDARD LVCMOS33 } [get_ports { aud_sd }]; #IO_L20P_T3_34 Sch=aud_sd
##Mic input
#set_property -dict { PACKAGE_PIN F17 IOSTANDARD LVCMOS33 } [get_ports { m_clk }]; #IO_L6N_T0_VREF_35 Sch=m_clk
#set_property -dict { PACKAGE_PIN G18 IOSTANDARD LVCMOS33 } [get_ports { m_data }]; #IO_L16N_T2_35 Sch=m_data
##ChipKit Single Ended Analog Inputs
##NOTE: The ck_an_p pins can be used as single ended analog inputs with voltages from 0-3.3V (Chipkit Analog pins A0-A5).
## These signals should only be connected to the XADC core. When using these pins as digital I/O, use pins ck_io[14-19].
#set_property -dict { PACKAGE_PIN D18 IOSTANDARD LVCMOS33 } [get_ports { ck_an_n[0] }]; #IO_L3N_T0_DQS_AD1N_35 Sch=ck_an_n[0]
#set_property -dict { PACKAGE_PIN E17 IOSTANDARD LVCMOS33 } [get_ports { ck_an_p[0] }]; #IO_L3P_T0_DQS_AD1P_35 Sch=ck_an_p[0]
#set_property -dict { PACKAGE_PIN E19 IOSTANDARD LVCMOS33 } [get_ports { ck_an_n[1] }]; #IO_L5N_T0_AD9N_35 Sch=ck_an_n[1]
#set_property -dict { PACKAGE_PIN E18 IOSTANDARD LVCMOS33 } [get_ports { ck_an_p[1] }]; #IO_L5P_T0_AD9P_35 Sch=ck_an_p[1]
#set_property -dict { PACKAGE_PIN J14 IOSTANDARD LVCMOS33 } [get_ports { ck_an_n[2] }]; #IO_L20N_T3_AD6N_35 Sch=ck_an_n[2]
#set_property -dict { PACKAGE_PIN K14 IOSTANDARD LVCMOS33 } [get_ports { ck_an_p[2] }]; #IO_L20P_T3_AD6P_35 Sch=ck_an_p[2]
#set_property -dict { PACKAGE_PIN J16 IOSTANDARD LVCMOS33 } [get_ports { ck_an_n[3] }]; #IO_L24N_T3_AD15N_35 Sch=ck_an_n[3]
#set_property -dict { PACKAGE_PIN K16 IOSTANDARD LVCMOS33 } [get_ports { ck_an_p[3] }]; #IO_L24P_T3_AD15P_35 Sch=ck_an_p[3]
#set_property -dict { PACKAGE_PIN H20 IOSTANDARD LVCMOS33 } [get_ports { ck_an_n[4] }]; #IO_L17N_T2_AD5N_35 Sch=ck_an_n[4]
#set_property -dict { PACKAGE_PIN J20 IOSTANDARD LVCMOS33 } [get_ports { ck_an_p[4] }]; #IO_L17P_T2_AD5P_35 Sch=ck_an_p[4]
#set_property -dict { PACKAGE_PIN G20 IOSTANDARD LVCMOS33 } [get_ports { ck_an_n[5] }]; #IO_L18N_T2_AD13N_35 Sch=ck_an_n[5]
#set_property -dict { PACKAGE_PIN G19 IOSTANDARD LVCMOS33 } [get_ports { ck_an_p[5] }]; #IO_L18P_T2_AD13P_35 Sch=ck_an_p[5]
##ChipKit Digital I/O Low
#set_property -dict { PACKAGE_PIN T14 IOSTANDARD LVCMOS33 } [get_ports { ck_io[0] }]; #IO_L5P_T0_34 Sch=ck_io[0]
#set_property -dict { PACKAGE_PIN U12 IOSTANDARD LVCMOS33 } [get_ports { ck_io[1] }]; #IO_L2N_T0_34 Sch=ck_io[1]
#set_property -dict { PACKAGE_PIN U13 IOSTANDARD LVCMOS33 } [get_ports { ck_io[2] }]; #IO_L3P_T0_DQS_PUDC_B_34 Sch=ck_io[2]
#set_property -dict { PACKAGE_PIN V13 IOSTANDARD LVCMOS33 } [get_ports { ck_io[3] }]; #IO_L3N_T0_DQS_34 Sch=ck_io[3]
#set_property -dict { PACKAGE_PIN V15 IOSTANDARD LVCMOS33 } [get_ports { ck_io[4] }]; #IO_L10P_T1_34 Sch=ck_io[4]
#set_property -dict { PACKAGE_PIN T15 IOSTANDARD LVCMOS33 } [get_ports { ck_io[5] }]; #IO_L5N_T0_34 Sch=ck_io[5]
#set_property -dict { PACKAGE_PIN R16 IOSTANDARD LVCMOS33 } [get_ports { ck_io[6] }]; #IO_L19P_T3_34 Sch=ck_io[6]
#set_property -dict { PACKAGE_PIN U17 IOSTANDARD LVCMOS33 } [get_ports { ck_io[7] }]; #IO_L9N_T1_DQS_34 Sch=ck_io[7]
#set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 } [get_ports { ck_io[8] }]; #IO_L21P_T3_DQS_34 Sch=ck_io[8]
#set_property -dict { PACKAGE_PIN V18 IOSTANDARD LVCMOS33 } [get_ports { ck_io[9] }]; #IO_L21N_T3_DQS_34 Sch=ck_io[9]
#set_property -dict { PACKAGE_PIN T16 IOSTANDARD LVCMOS33 } [get_ports { ck_io[10] }]; #IO_L9P_T1_DQS_34 Sch=ck_io[10]
#set_property -dict { PACKAGE_PIN R17 IOSTANDARD LVCMOS33 } [get_ports { ck_io[11] }]; #IO_L19N_T3_VREF_34 Sch=ck_io[11]
#set_property -dict { PACKAGE_PIN P18 IOSTANDARD LVCMOS33 } [get_ports { ck_io[12] }]; #IO_L23N_T3_34 Sch=ck_io[12]
#set_property -dict { PACKAGE_PIN N17 IOSTANDARD LVCMOS33 } [get_ports { ck_io[13] }]; #IO_L23P_T3_34 Sch=ck_io[13]
##ChipKit Digital I/O On Outer Analog Header
##NOTE: These pins should be used when using the analog header signals A0-A5 as digital I/O (Chipkit digital pins 14-19)
#set_property -dict { PACKAGE_PIN Y11 IOSTANDARD LVCMOS33 } [get_ports { ck_io[14] }]; #IO_L18N_T2_13 Sch=ck_a[0]
#set_property -dict { PACKAGE_PIN Y12 IOSTANDARD LVCMOS33 } [get_ports { ck_io[15] }]; #IO_L20P_T3_13 Sch=ck_a[1]
#set_property -dict { PACKAGE_PIN W11 IOSTANDARD LVCMOS33 } [get_ports { ck_io[16] }]; #IO_L18P_T2_13 Sch=ck_a[2]
#set_property -dict { PACKAGE_PIN V11 IOSTANDARD LVCMOS33 } [get_ports { ck_io[17] }]; #IO_L21P_T3_DQS_13 Sch=ck_a[3]
#set_property -dict { PACKAGE_PIN T5 IOSTANDARD LVCMOS33 } [get_ports { ck_io[18] }]; #IO_L19P_T3_13 Sch=ck_a[4]
#set_property -dict { PACKAGE_PIN U10 IOSTANDARD LVCMOS33 } [get_ports { ck_io[19] }]; #IO_L12N_T1_MRCC_13 Sch=ck_a[5]
##ChipKit Digital I/O On Inner Analog Header
##NOTE: These pins will need to be connected to the XADC core when used as differential analog inputs (Chipkit analog pins A6-A11)
#set_property -dict { PACKAGE_PIN B20 IOSTANDARD LVCMOS33 } [get_ports { ck_io[20] }]; #IO_L1N_T0_AD0N_35 Sch=ad_n[0]
#set_property -dict { PACKAGE_PIN C20 IOSTANDARD LVCMOS33 } [get_ports { ck_io[21] }]; #IO_L1P_T0_AD0P_35 Sch=ad_p[0]
#set_property -dict { PACKAGE_PIN F20 IOSTANDARD LVCMOS33 } [get_ports { ck_io[22] }]; #IO_L15N_T2_DQS_AD12N_35 Sch=ad_n[12]
#set_property -dict { PACKAGE_PIN F19 IOSTANDARD LVCMOS33 } [get_ports { ck_io[23] }]; #IO_L15P_T2_DQS_AD12P_35 Sch=ad_p[12]
#set_property -dict { PACKAGE_PIN A20 IOSTANDARD LVCMOS33 } [get_ports { ck_io[24] }]; #IO_L2N_T0_AD8N_35 Sch=ad_n[8]
#set_property -dict { PACKAGE_PIN B19 IOSTANDARD LVCMOS33 } [get_ports { ck_io[25] }]; #IO_L2P_T0_AD8P_35 Sch=ad_p[8]
##ChipKit Digital I/O High
#set_property -dict { PACKAGE_PIN U5 IOSTANDARD LVCMOS33 } [get_ports { ck_io[26] }]; #IO_L19N_T3_VREF_13 Sch=ck_io[26]
#set_property -dict { PACKAGE_PIN V5 IOSTANDARD LVCMOS33 } [get_ports { ck_io[27] }]; #IO_L6N_T0_VREF_13 Sch=ck_io[27]
#set_property -dict { PACKAGE_PIN V6 IOSTANDARD LVCMOS33 } [get_ports { ck_io[28] }]; #IO_L22P_T3_13 Sch=ck_io[28]
#set_property -dict { PACKAGE_PIN U7 IOSTANDARD LVCMOS33 } [get_ports { ck_io[29] }]; #IO_L11P_T1_SRCC_13 Sch=ck_io[29]
#set_property -dict { PACKAGE_PIN V7 IOSTANDARD LVCMOS33 } [get_ports { ck_io[30] }]; #IO_L11N_T1_SRCC_13 Sch=ck_io[30]
#set_property -dict { PACKAGE_PIN U8 IOSTANDARD LVCMOS33 } [get_ports { ck_io[31] }]; #IO_L17N_T2_13 Sch=ck_io[31]
#set_property -dict { PACKAGE_PIN V8 IOSTANDARD LVCMOS33 } [get_ports { ck_io[32] }]; #IO_L15P_T2_DQS_13 Sch=ck_io[32]
#set_property -dict { PACKAGE_PIN V10 IOSTANDARD LVCMOS33 } [get_ports { ck_io[33] }]; #IO_L21N_T3_DQS_13 Sch=ck_io[33]
#set_property -dict { PACKAGE_PIN W10 IOSTANDARD LVCMOS33 } [get_ports { ck_io[34] }]; #IO_L16P_T2_13 Sch=ck_io[34]
#set_property -dict { PACKAGE_PIN W6 IOSTANDARD LVCMOS33 } [get_ports { ck_io[35] }]; #IO_L22N_T3_13 Sch=ck_io[35]
#set_property -dict { PACKAGE_PIN Y6 IOSTANDARD LVCMOS33 } [get_ports { ck_io[36] }]; #IO_L13N_T2_MRCC_13 Sch=ck_io[36]
#set_property -dict { PACKAGE_PIN Y7 IOSTANDARD LVCMOS33 } [get_ports { ck_io[37] }]; #IO_L13P_T2_MRCC_13 Sch=ck_io[37]
#set_property -dict { PACKAGE_PIN W8 IOSTANDARD LVCMOS33 } [get_ports { ck_io[38] }]; #IO_L15N_T2_DQS_13 Sch=ck_io[38]
#set_property -dict { PACKAGE_PIN Y8 IOSTANDARD LVCMOS33 } [get_ports { ck_io[39] }]; #IO_L14N_T2_SRCC_13 Sch=ck_io[39]
#set_property -dict { PACKAGE_PIN W9 IOSTANDARD LVCMOS33 } [get_ports { ck_io[40] }]; #IO_L16N_T2_13 Sch=ck_io[40]
#set_property -dict { PACKAGE_PIN Y9 IOSTANDARD LVCMOS33 } [get_ports { ck_io[41] }]; #IO_L14P_T2_SRCC_13 Sch=ck_io[41]
#set_property -dict { PACKAGE_PIN Y13 IOSTANDARD LVCMOS33 } [get_ports { ck_io[42] }]; #IO_L20N_T3_13 Sch=ck_ioa
## ChipKit SPI
#set_property -dict { PACKAGE_PIN W15 IOSTANDARD LVCMOS33 } [get_ports { ck_miso }]; #IO_L10N_T1_34 Sch=ck_miso
#set_property -dict { PACKAGE_PIN T12 IOSTANDARD LVCMOS33 } [get_ports { ck_mosi }]; #IO_L2P_T0_34 Sch=ck_mosi
#set_property -dict { PACKAGE_PIN H15 IOSTANDARD LVCMOS33 } [get_ports { ck_sck }]; #IO_L19P_T3_35 Sch=ck_sck
#set_property -dict { PACKAGE_PIN F16 IOSTANDARD LVCMOS33 } [get_ports { ck_ss }]; #IO_L6P_T0_35 Sch=ck_ss
## ChipKit I2C
#set_property -dict { PACKAGE_PIN P16 IOSTANDARD LVCMOS33 } [get_ports { ck_scl }]; #IO_L24N_T3_34 Sch=ck_scl
#set_property -dict { PACKAGE_PIN P15 IOSTANDARD LVCMOS33 } [get_ports { ck_sda }]; #IO_L24P_T3_34 Sch=ck_sda
##HDMI Rx
#set_property -dict { PACKAGE_PIN H17 IOSTANDARD LVCMOS33 } [get_ports { hdmi_rx_cec }]; #IO_L13N_T2_MRCC_35 Sch=hdmi_rx_cec
#set_property -dict { PACKAGE_PIN P19 IOSTANDARD TMDS_33 } [get_ports { io_debug_hdmi_clk_n }]; #IO_L13N_T2_MRCC_34 Sch=hdmi_rx_clk_n
#set_property -dict { PACKAGE_PIN N18 IOSTANDARD TMDS_33 } [get_ports { io_debug_hdmi_clk_p }]; #IO_L13P_T2_MRCC_34 Sch=hdmi_rx_clk_p
#set_property -dict { PACKAGE_PIN W20 IOSTANDARD TMDS_33 } [get_ports { io_debug_hdmi_data_n[0] }]; #IO_L16N_T2_34 Sch=hdmi_rx_d_n[0]
#set_property -dict { PACKAGE_PIN V20 IOSTANDARD TMDS_33 } [get_ports { io_debug_hdmi_data_p[0] }]; #IO_L16P_T2_34 Sch=hdmi_rx_d_p[0]
#set_property -dict { PACKAGE_PIN U20 IOSTANDARD TMDS_33 } [get_ports { io_debug_hdmi_data_n[1] }]; #IO_L15N_T2_DQS_34 Sch=hdmi_rx_d_n[1]
#set_property -dict { PACKAGE_PIN T20 IOSTANDARD TMDS_33 } [get_ports { io_debug_hdmi_data_p[1] }]; #IO_L15P_T2_DQS_34 Sch=hdmi_rx_d_p[1]
#set_property -dict { PACKAGE_PIN P20 IOSTANDARD TMDS_33 } [get_ports { io_debug_hdmi_data_n[2] }]; #IO_L14N_T2_SRCC_34 Sch=hdmi_rx_d_n[2]
#set_property -dict { PACKAGE_PIN N20 IOSTANDARD TMDS_33 } [get_ports { io_debug_hdmi_data_p[2] }]; #IO_L14P_T2_SRCC_34 Sch=hdmi_rx_d_p[2]
#set_property -dict { PACKAGE_PIN T19 IOSTANDARD LVCMOS33 } [get_ports { io_debug_hdmi_hpdn }]; #IO_25_34 Sch=hdmi_rx_hpd
#set_property -dict { PACKAGE_PIN U14 IOSTANDARD LVCMOS33 } [get_ports { hdmi_rx_scl }]; #IO_L11P_T1_SRCC_34 Sch=hdmi_rx_scl
#set_property -dict { PACKAGE_PIN U15 IOSTANDARD LVCMOS33 } [get_ports { hdmi_rx_sda }]; #IO_L11N_T1_SRCC_34 Sch=hdmi_rx_sda
##HDMI Tx
#set_property -dict { PACKAGE_PIN G15 IOSTANDARD LVCMOS33 } [get_ports { hdmi_tx_cec }]; #IO_L19N_T3_VREF_35 Sch=hdmi_tx_cec
set_property -dict {PACKAGE_PIN L17 IOSTANDARD TMDS_33} [get_ports io_hdmi_clk_n]
set_property -dict {PACKAGE_PIN L16 IOSTANDARD TMDS_33} [get_ports io_hdmi_clk_p]
set_property -dict {PACKAGE_PIN K18 IOSTANDARD TMDS_33} [get_ports {io_hdmi_data_n[0]}]
set_property -dict {PACKAGE_PIN K17 IOSTANDARD TMDS_33} [get_ports {io_hdmi_data_p[0]}]
set_property -dict {PACKAGE_PIN J19 IOSTANDARD TMDS_33} [get_ports {io_hdmi_data_n[1]}]
set_property -dict {PACKAGE_PIN K19 IOSTANDARD TMDS_33} [get_ports {io_hdmi_data_p[1]}]
set_property -dict {PACKAGE_PIN H18 IOSTANDARD TMDS_33} [get_ports {io_hdmi_data_n[2]}]
set_property -dict {PACKAGE_PIN J18 IOSTANDARD TMDS_33} [get_ports {io_hdmi_data_p[2]}]
set_property -dict {PACKAGE_PIN R19 IOSTANDARD LVCMOS33} [get_ports io_hdmi_hpdn]
#set_property -dict { PACKAGE_PIN M17 IOSTANDARD LVCMOS33 } [get_ports { hdmi_tx_scl }]; #IO_L8P_T1_AD10P_35 Sch=hdmi_tx_scl
#set_property -dict { PACKAGE_PIN M18 IOSTANDARD LVCMOS33 } [get_ports { hdmi_tx_sda }]; #IO_L8N_T1_AD10N_35 Sch=hdmi_tx_sda
##Crypto SDA
#set_property -dict { PACKAGE_PIN J15 IOSTANDARD LVCMOS33 } [get_ports { crypto_sda }]; #IO_25_35 Sch=crypto_sda

4
lab2/vivado/pynq/run.ps1 Normal file
View File

@@ -0,0 +1,4 @@
cd ..
sbt run
cd vivado
C:\Xilinx\Vivado\2020.1\bin\vivado -mode batch -source .\generate_and_program.tcl

View File

@@ -0,0 +1,28 @@
# Copyright 2021 Howard Lau
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
source open_project.tcl
launch_simulation
restart
open_vcd
#log_wave -recursive [get_object /test/top/hdmi_display/*]
#log_vcd [get_object /test/top/hdmi_display/*]
#log_wave -recursive [get_object /test/top/*]
#log_vcd [get_object /test/top/*]
log_wave -recursive [get_object /test/top/hdmi_display/serdesBlue/osr10/*]
log_vcd [get_object /test/top/hdmi_display/serdesBlue/osr10/*]
run 1000000ns
close_vcd
close_sim