summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.vscode/configurationCache.log1
-rw-r--r--.vscode/dryrun.log5
-rw-r--r--.vscode/targets.log422
-rw-r--r--hdl/core.py209
4 files changed, 135 insertions, 502 deletions
diff --git a/.vscode/configurationCache.log b/.vscode/configurationCache.log
deleted file mode 100644
index 2908cc5..0000000
--- a/.vscode/configurationCache.log
+++ /dev/null
@@ -1 +0,0 @@
-{"buildTargets":["cc","clean","sim","test","test-w"],"launchTargets":[],"customConfigurationProvider":{"workspaceBrowse":{"browsePath":[],"compilerArgs":[]},"fileIndex":[]}} \ No newline at end of file
diff --git a/.vscode/dryrun.log b/.vscode/dryrun.log
deleted file mode 100644
index 9bcad8c..0000000
--- a/.vscode/dryrun.log
+++ /dev/null
@@ -1,5 +0,0 @@
-make --dry-run --always-make --keep-going --print-directory
-make: Entering directory '/home/jon/github/ASAP32'
-python3 hdl/shift_reg.py sim
-make: Leaving directory '/home/jon/github/ASAP32'
-
diff --git a/.vscode/targets.log b/.vscode/targets.log
deleted file mode 100644
index 8749a31..0000000
--- a/.vscode/targets.log
+++ /dev/null
@@ -1,422 +0,0 @@
-make all --print-data-base --no-builtin-variables --no-builtin-rules --question
-make: *** No rule to make target 'all'. Stop.
-
-# GNU Make 4.3
-# Built for x86_64-suse-linux-gnu
-# Copyright (C) 1988-2020 Free Software Foundation, Inc.
-# License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
-# This is free software: you are free to change and redistribute it.
-# There is NO WARRANTY, to the extent permitted by law.
-
-# Make data base, printed on Mon Aug 15 15:20:54 2022
-
-# Variables
-
-# environment
-JAVA_HOME = /usr/lib64/jvm/java
-# environment
-QEMU_AUDIO_DRV = pa
-# makefile (from 'Makefile', line 2)
-HDL_FOLDER = ./hdl
-# environment
-GDK_BACKEND = x11
-# environment
-LC_ALL = C
-# environment
-NO_AT_BRIDGE = 1
-# environment
-GTK_RC_FILES = /etc/gtk/gtkrc:/home/jon/.gtkrc:/home/jon/.config/gtkrc
-# environment
-WINDOWMANAGER = /usr/bin/startplasma-x11
-# environment
-VSCODE_CWD = /home/jon
-# environment
-GPG_TTY = not a tty
-# environment
-MACHTYPE = x86_64-suse-linux
-# default
-MAKE_COMMAND := make
-# automatic
-@D = $(patsubst %/,%,$(dir $@))
-# environment
-PYTHONSTARTUP = /etc/pythonstart
-# environment
-VSCODE_HANDLES_UNCAUGHT_ERRORS = true
-# default
-.VARIABLES :=
-# environment
-PWD = /home/jon/github/ASAP32
-# environment
-HOST = WarpDrive
-# automatic
-%D = $(patsubst %/,%,$(dir $%))
-# environment
-MORE = -sl
-# environment
-HOSTNAME = WarpDrive
-# environment
-MAIL = /var/spool/mail/jon
-# environment
-XNLSPATH = /usr/share/X11/nls
-# environment
-XDG_DATA_DIRS = /home/jon/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/share
-# automatic
-^D = $(patsubst %/,%,$(dir $^))
-# automatic
-%F = $(notdir $%)
-# environment
-QML_XHR_ALLOW_FILE_READ = 1
-# environment
-VSCODE_CODE_CACHE_PATH = /home/jon/.config/Code/CachedData/da76f93349a72022ca4670c1b84860304616aaa2
-# environment
-XDG_SESSION_PATH = /org/freedesktop/DisplayManager/Session0
-# environment
-PROFILEREAD = true
-# environment
-SSH_ASKPASS = /usr/libexec/ssh/ssh-askpass
-# environment
-LANG = C
-# environment
-XAUTHORITY = /run/user/1000/xauth_QWvpuc
-# environment
-MANPATHISSET = yes
-# default
-.LOADED :=
-# environment
-FROM_HEADER =
-# default
-.INCLUDE_DIRS = /usr/include /usr/local/include /usr/include
-# makefile
-MAKEFLAGS = pqrR
-# makefile
-CURDIR := /home/jon/github/ASAP32
-# environment
-APPLICATION_INSIGHTS_NO_DIAGNOSTIC_CHANNEL = true
-# environment
-LESSOPEN = lessopen.sh %s
-# automatic
-*D = $(patsubst %/,%,$(dir $*))
-# environment
-MFLAGS = -pqrR
-# environment
-SSH_AUTH_SOCK = /tmp/ssh-XXXXXXkett0U/agent.1979
-# default
-.SHELLFLAGS := -c
-# environment
-HISTSIZE = 1000
-# environment
-XDG_CONFIG_DIRS = /home/jon/.config/kdedefaults:/etc/xdg:/usr/etc/xdg
-# automatic
-+D = $(patsubst %/,%,$(dir $+))
-# environment
-XCURSOR_THEME = Qogir-dark
-# environment
-LESSKEY = /usr/etc/lesskey.bin
-# environment
-XDG_SESSION_DESKTOP = KDE
-# makefile (from 'Makefile', line 1)
-MAKEFILE_LIST := Makefile
-# automatic
-@F = $(notdir $@)
-# environment
-VSCODE_PID = 6093
-# environment
-XDG_SESSION_TYPE = x11
-# environment
-XAUTHLOCALHOSTNAME = WarpDrive
-# automatic
-?D = $(patsubst %/,%,$(dir $?))
-# environment
-INPUT_METHOD = ibus
-# environment
-SDK_HOME = /usr/lib64/jvm/java
-# environment
-SESSION_MANAGER = local/WarpDrive:@/tmp/.ICE-unix/2263,unix/WarpDrive:/tmp/.ICE-unix/2263
-# automatic
-*F = $(notdir $*)
-# environment
-MANPATH = /home/jon/.local/share/man:/usr/local/man:/usr/local/share/man:/usr/share/man:/opt/cross/share/man
-# environment
-CHROME_DESKTOP = code-url-handler.desktop
-# environment
-DBUS_SESSION_BUS_ADDRESS = unix:abstract=/tmp/dbus-WsMJbPZXWc,guid=299e3b57631cde650339f25862faa8c5
-# automatic
-<D = $(patsubst %/,%,$(dir $<))
-# environment
-JAVA_ROOT = /usr/lib64/jvm/java
-# environment
-LESS_ADVANCED_PREPROCESSOR = no
-# environment
-JAVA_BINDIR = /usr/lib64/jvm/java/bin
-# environment
-VSCODE_NLS_CONFIG = {"locale":"en-us","availableLanguages":{},"_languagePackSupport":true}
-# default
-MAKE_HOST := x86_64-suse-linux-gnu
-# environment
-WINDOW_MANAGER = /usr/bin/startplasma-x11
-# makefile
-SHELL = /bin/sh
-# default
-MAKECMDGOALS := all
-# environment
-XMODIFIERS = @im=ibus
-# environment
-PLATFORMIO_CALLER = vscode
-# environment
-SHLVL = 0
-# environment
-MAKELEVEL := 0
-# default
-MAKE = $(MAKE_COMMAND)
-# environment
-PATH = /home/jon/.local/bin:/usr/local/bin:/usr/bin:/bin:/opt/cross/bin
-# default
-MAKEFILES :=
-# automatic
-^F = $(notdir $^)
-# environment
-OSTYPE = linux
-# environment
-QSYS_ROOTDIR = /storage/large_programs/quartus/sopc_builder/bin
-# environment
-MINICOM = -c on
-# environment
-CPU = x86_64
-# environment
-LESSCLOSE = lessclose.sh %s %s
-# automatic
-?F = $(notdir $?)
-# environment
-KDE_APPLICATIONS_AS_SCOPE = 1
-# environment
-XDG_SEAT = seat0
-# environment
-XSESSION_IS_UP = yes
-# environment
-GTK_IM_MODULE = ibus
-# environment
-NO_PROXY = 127.0.0.1
-# environment
-XDG_CURRENT_DESKTOP = KDE
-# environment
-HOSTTYPE = x86_64
-# environment
-LS_COLORS = rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=01;05;37;41:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.pdf=00;32:*.ps=00;32:*.txt=00;32:*.patch=00;32:*.diff=00;32:*.log=00;32:*.tex=00;32:*.doc=00;32:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.axa=00;36:*.oga=00;36:*.spx=00;36:*.xspf=00;36:
-# automatic
-+F = $(notdir $+)
-# environment
-XDG_SEAT_PATH = /org/freedesktop/DisplayManager/Seat0
-# environment
-LESS = -M -I -R
-# environment
-DESKTOP_SESSION = /usr/share/xsessions/default
-# environment
-CONFIG_SITE = /usr/share/site/x86_64-pc-linux-gnu
-# environment
-ORIGINAL_XDG_CURRENT_DESKTOP = KDE
-# 'override' directive
-GNUMAKEFLAGS :=
-# environment
-LOGNAME = jon
-# environment
-QT_IM_SWITCHER = imsw-multi
-# environment
-AUDIODRIVER = pulseaudio
-# environment
-G_FILENAME_ENCODING = @locale,UTF-8,ISO-8859-15,CP1252
-# environment
-PLATFORMIO_PATH = /home/jon/.platformio/python3/bin:/home/jon/.local/bin:/usr/local/bin:/usr/bin:/bin:/opt/cross/bin
-# environment
-XDG_VTNR = 7
-# makefile
-.DEFAULT_GOAL := sim
-# environment
-DISPLAY = :0
-# environment
-GTK_MODULES = canberra-gtk-module:canberra-gtk-module
-# environment
-USER = jon
-# default
-MAKE_VERSION := 4.3
-# environment
-KDE_SESSION_UID = 1000
-# environment
-SSH_AGENT_PID = 2123
-# environment
-PAGER = less
-# environment
-_ = /usr/bin/make
-# environment
-XDG_RUNTIME_DIR = /run/user/1000
-# environment
-G_BROKEN_FILENAMES = 1
-# makefile (from 'Makefile', line 3)
-HDL = $(wildcard $(HDL_FOLDER)/*.py)
-# environment
-XDG_SESSION_CLASS = user
-# environment
-VSCODE_AMD_ENTRYPOINT = vs/workbench/api/node/extensionHostProcess
-# environment
-PLATFORMIO_IDE = 2.5.1
-# environment
-XKEYSYMDB = /usr/X11R6/lib/X11/XKeysymDB
-# environment
-GTK2_RC_FILES = /etc/gtk-2.0/gtkrc:/home/jon/.gtkrc-2.0:/home/jon/.config/gtkrc-2.0
-# environment
-HOME = /home/jon
-# environment
-QT_IM_MODULE = ibus
-# environment
-CSHEDIT = emacs
-# environment
-JDK_HOME = /usr/lib64/jvm/java
-# environment
-ELECTRON_RUN_AS_NODE = 1
-# environment
-VSCODE_IPC_HOOK = /run/user/1000/vscode-74f3b1db-1.70.0-main.sock
-# environment
-TERM = xterm
-# environment
-XDG_SESSION_ID = 1
-# environment
-XCURSOR_SIZE = 24
-# environment
-STARTUP = /usr/bin/startplasma-x11
-# default
-.RECIPEPREFIX :=
-# automatic
-<F = $(notdir $<)
-# default
-SUFFIXES :=
-# environment
-QT_AUTO_SCREEN_SCALE_FACTOR = 0
-# environment
-LS_OPTIONS = -N --color=tty -T 0
-# environment
-KDE_SESSION_VERSION = 5
-# default
-
-.FEATURES := target-specific order-only second-expansion else-if shortest-stem undefine oneshell nocomment grouped-target extra-prereqs archives jobserver output-sync check-symlink load
-# environment
-QT4_IM_MODULE = xim
-# environment
-KDE_FULL_SESSION = true
-# environment
-JRE_HOME = /usr/lib64/jvm/java
-# variable set hash-table stats:
-# Load=145/1024=14%, Rehash=0, Collisions=21/181=12%
-
-# Pattern-specific Variable Values
-
-# No pattern-specific variable values.
-
-# Directories
-
-# ./hdl (device 65025, inode 22952540): 7 files, no impossibilities.
-# . (device 65025, inode 21757987): 12 files, no impossibilities.
-
-# 19 files, no impossibilities in 2 directories.
-
-# Implicit Rules
-
-# No implicit rules.
-
-# Files
-
-test-w:
-# Implicit rule search has not been done.
-# Modification time never checked.
-# File has not been updated.
-# recipe to execute (from 'Makefile', line 18):
- py.test -v $(HDL)
-
-v: hdl/shift_reg.py hdl/template.py hdl/utils.py
-# Implicit rule search has not been done.
-# Modification time never checked.
-# File has not been updated.
-# recipe to execute (from 'Makefile', line 12):
- python3 $< v
-
-sim: hdl/shift_reg.py hdl/template.py hdl/utils.py
-# Implicit rule search has not been done.
-# Modification time never checked.
-# File has not been updated.
-# recipe to execute (from 'Makefile', line 6):
- python3 $< sim
-
-# Not a target:
-hdl/shift_reg.py:
-# Implicit rule search has not been done.
-# Modification time never checked.
-# File has not been updated.
-
-# Not a target:
-Makefile:
-# Implicit rule search has been done.
-# Last modified 2022-08-10 22:15:54.44768441
-# File has been updated.
-# Successfully updated.
-
-clean:
-# Implicit rule search has not been done.
-# Modification time never checked.
-# File has not been updated.
-# recipe to execute (from 'Makefile', line 21):
- $(RM) -rf $(HDL_FOLDER)/*.cc $(HDL_FOLDER)/*.v $(HDL_FOLDER)/*.vcd
-
-# Not a target:
-.DEFAULT:
-# Implicit rule search has not been done.
-# Modification time never checked.
-# File has not been updated.
-
-# Not a target:
-all:
-# Command line target.
-# Implicit rule search has been done.
-# File does not exist.
-# File has not been updated.
-
-# Not a target:
-hdl/utils.py:
-# Implicit rule search has not been done.
-# Modification time never checked.
-# File has not been updated.
-
-test:
-# Implicit rule search has not been done.
-# Modification time never checked.
-# File has not been updated.
-# recipe to execute (from 'Makefile', line 15):
- py.test --disable-pytest-warnings -v $(HDL)
-
-# Not a target:
-hdl/template.py:
-# Implicit rule search has not been done.
-# Modification time never checked.
-# File has not been updated.
-
-cc: hdl/shift_reg.py hdl/template.py hdl/utils.py
-# Implicit rule search has not been done.
-# Modification time never checked.
-# File has not been updated.
-# recipe to execute (from 'Makefile', line 9):
- python3 $< cc $(basename $< .py)
-
-# files hash-table stats:
-# Load=13/1024=1%, Rehash=0, Collisions=0/32=0%
-# VPATH Search Paths
-
-# No 'vpath' search paths.
-
-# No general ('VPATH' variable) search path.
-
-# strcache buffers: 1 (0) / strings = 32 / storage = 281 B / avg = 8 B
-# current buf: size = 8162 B / used = 281 B / count = 32 / avg = 8 B
-
-# strcache performance: lookups = 50 / hit rate = 36%
-# hash-table stats:
-# Load=32/8192=0%, Rehash=0, Collisions=0/50=0%
-# Finished Make data base on Mon Aug 15 15:20:54 2022
-
-
diff --git a/hdl/core.py b/hdl/core.py
index 17e2b33..655af68 100644
--- a/hdl/core.py
+++ b/hdl/core.py
@@ -1,6 +1,7 @@
from multiprocessing import dummy
from amaranth import *
from amaranth.sim import Simulator, Settle, Delay
+from enum import Enum, unique
from utils import cmd
@@ -78,23 +79,44 @@ from utils import cmd
# return m
+@unique
+class AluOpCodes(Enum):
+ add = 0
+ addc = 1
+ sub = 2
+ subc = 3
+ bit_and = 4
+ bit_or = 5
+ bit_xor = 6
+ bit_nor = 7
+ lleft = 8
+ lright = 9
+ aright = 10
+ set_bit = 11
+ clear_bit = 12
+ umult = 13
+ smult = 14
+ udiv = 15
+ sdiv = 16
+
class ALU(Elaboratable):
def __init__(self, sim=False):
self.in1 = Signal(32, reset_less=True)
self.in2 = Signal(32, reset_less=True)
+ self.c_in = Signal(1)
self.out = Signal(32, reset_less=True)
self.op = Signal(4, reset_less=True)
self.tmp = Signal(33, reset_less=True)
- self.signed_op = Signal(1, reset_less=True)
- self.carry = Signal(1, reset_less=True)
+ self.c_out = Signal(1, reset_less=True)
self.overflow = Signal(1, reset_less=True)
self.zero = Signal(1, reset_less=True)
- self.sign = Signal(1, reset_less=True)
+ self.neg = Signal(1, reset_less=True)
+ self.odd = Signal(1, reset_less=True)
self.sim = sim
- self.ports = [self.in1, self.in2, self.op, self.out, self.carry, self.overflow, self.zero, self.sign]
+ self.ports = [self.in1, self.in2, self.op, self.c_in, self.out, self.c_out, self.overflow, self.zero, self.neg]
def elaborate(self, platform=None):
m = Module()
@@ -105,38 +127,73 @@ class ALU(Elaboratable):
m.d.sync += dummy.eq(~dummy)
with m.Switch(self.op):
- with m.Case(0b0000):
+ with m.Case(AluOpCodes.add.value):
m.d.comb += self.tmp.eq(self.in1 + self.in2)
- with m.Case(0b0010):
- m.d.comb += self.tmp.eq(self.in1.as_signed() + self.in2.as_signed())
- m.d.comb += self.signed_op.eq(1)
- with m.Case(0b0001):
+
+ with m.Case(AluOpCodes.addc.value):
+ m.d.comb += self.tmp.eq(self.in1 + self.in2 + self.c_in)
+
+ with m.Case(AluOpCodes.sub.value):
m.d.comb += self.tmp.eq(self.in1 - self.in2)
- with m.Case(0b0011):
- m.d.comb += self.tmp.eq(self.in1.as_signed() - self.in2.as_signed())
- m.d.comb += self.signed_op.eq(1)
- with m.Case(4):
+
+ with m.Case(AluOpCodes.subc.value):
+ m.d.comb += self.tmp.eq(self.in1 + (~self.in2 + self.c_in))
+
+ with m.Case(AluOpCodes.bit_and.value):
m.d.comb += self.tmp.eq(Cat(self.in1 & self.in2, 0))
- with m.Case(5):
+
+ with m.Case(AluOpCodes.bit_or.value):
m.d.comb += self.tmp.eq(Cat(self.in1 | self.in2, 0))
- with m.Case(6):
+
+ with m.Case(AluOpCodes.bit_xor.value):
m.d.comb += self.tmp.eq(Cat(self.in1 ^ self.in2, 0))
- with m.Case(7):
- m.d.comb += self.tmp.eq(Cat(self.in1 << self.in2[0:5], 0))
- with m.Case(8):
- m.d.comb += self.tmp.eq(Cat(self.in1 >> self.in2[0:5], 0))
- with m.Case(9):
- m.d.comb += self.tmp.eq(Cat(self.in1.as_signed() >> self.in2[0:5], 0))
+
+ with m.Case(AluOpCodes.bit_nor.value):
+ m.d.comb += self.tmp.eq(Cat(~(self.in1 | self.in2), 0))
+
+ with m.Case(AluOpCodes.lleft.value):
+ m.d.comb += self.tmp.eq(Cat(self.in1, 0) << self.in2[0:5])
+
+ with m.Case(AluOpCodes.lright.value):
+ tmp2 = Signal(33)
+ m.d.comb += tmp2.eq(Cat(0, self.in1) >> self.in2[0:5])
+ m.d.comb += self.tmp.eq(Cat(tmp2[1:33], tmp2[0])) # move shifted bit to carry bit
+
+ with m.Case(AluOpCodes.aright.value):
+ tmp2 = Signal(33)
+ m.d.comb += tmp2.eq(Cat(0, self.in1).as_signed() >> self.in2[0:5])
+ m.d.comb += self.tmp.eq(Cat(tmp2[1:33], tmp2[0])) # move shifted bit to carry bit
+
+ with m.Case(AluOpCodes.set_bit.value):
+ m.d.comb += self.tmp.eq(Cat(self.in1 | (1 << self.in2[0:5]), 0))
+
+ with m.Case(AluOpCodes.clear_bit.value):
+ m.d.comb += self.tmp.eq(Cat(self.in1 & ~(1 << self.in2[0:5]), 0))
+
+ with m.Case(AluOpCodes.umult.value):
+ m.d.comb += self.tmp.eq(Cat(self.in1[0:16] * self.in2[0:16], 0))
+
+ with m.Case(AluOpCodes.smult.value):
+ m.d.comb += self.tmp.eq(Cat(self.in1[0:16].as_signed() * self.in2[0:16].as_signed(), 0))
+
+
+ # bad juju,
+ # TODO: come back and check this will work
+ # with m.Case(AluOpCodes.udiv.value):
+ # m.d.comb += self.tmp.eq(Cat(self.in1 // self.in2, 0))
+
+ # with m.Case(AluOpCodes.sdiv.value):
+ # m.d.comb += self.tmp.eq(self.in1.as_signed() // self.in2.as_signed()) # for some reason I have not confirmed, signed div can yield a 33 bit number, acording to amaranth
+
with m.Case():
- m.d.comb += self.signed_op.eq(0)
m.d.comb += self.tmp.eq(0)
- m.d.comb += self.carry.eq(self.tmp[32])
+ m.d.comb += self.c_out.eq(self.tmp[32])
m.d.comb += self.overflow.eq(self.tmp[32] ^ self.tmp[31])
- m.d.comb += self.sign.eq(self.tmp.as_signed() < 0)
- m.d.comb += self.zero.eq(self.out == 0)
-
m.d.comb += self.out.eq(self.tmp[0:32])
+ m.d.comb += self.neg.eq(self.out.as_signed() < 0)
+ m.d.comb += self.zero.eq(self.out == 0)
+ m.d.comb += self.odd.eq(self.out[0])
return m
@@ -144,111 +201,115 @@ def test_alu(filename="alu.vcd"):
dut = ALU(sim=True)
def proc1():
- def sub_proc(val1, val2):
+ def sub_proc(val1, val2, c_in=0):
yield dut.in1.eq(val1)
yield dut.in2.eq(val2)
+ yield dut.c_in.eq(c_in)
yield
yield Settle()
- # test unsigned addition
- yield dut.op.eq(0b0000)
+ # test addition
+ yield dut.op.eq(AluOpCodes.add.value)
yield from sub_proc(27, 13)
out = yield dut.out
assert 27 + 13 == (out), f'ERROR: {out} != {27 + 13}'
- # test signed addition
- yield dut.op.eq(0b0010)
- yield from sub_proc(-11, 43)
+ # test addition with carry
+ yield dut.op.eq(AluOpCodes.addc.value)
+ yield from sub_proc(11, 43, 1)
out = yield dut.out.as_signed()
- assert -11 + 43 == out, f'ERROR: {out} != {-11 + 43}'
+ assert 11 + 43 + 1 == out, f'ERROR: {out} != {11 + 43 + 1}'
- # test unsigned subtraction
- yield dut.op.eq(0b0001)
+ # test subtraction
+ yield dut.op.eq(AluOpCodes.sub.value)
yield from sub_proc(25, 13)
out = yield dut.out
assert 25 - 13 == out, f'ERROR: {out} != {25 - 13}'
- # test signed subtraction
- yield dut.op.eq(0b0011)
- yield from sub_proc(25, -13)
+ # test subtraction with carry
+ yield dut.op.eq(AluOpCodes.subc.value)
+ yield from sub_proc(25, -13, 0)
+ out = yield dut.out.as_signed()
+ assert 25 + 13 -1 +0 == out, f'ERROR: {out} != {25 + 13 -1 +0}'
+
+ # test subtraction with carry
+ yield dut.op.eq(AluOpCodes.subc.value)
+ yield from sub_proc(25, -13, 1)
out = yield dut.out.as_signed()
- assert 25 + 13 == out, f'ERROR: {out} != {25 + 13}'
+ assert 25 + 13 -1 +1 == out, f'ERROR: {out} != {25 + 13 -1 +1}'
- # test unsigned logical and
- yield dut.op.eq(4)
+ # test binary and
+ yield dut.op.eq(AluOpCodes.bit_and.value)
yield from sub_proc(0b10101011, 0b01010101)
out = yield dut.out
assert 0b00000001 == out, f'ERROR: {out} != {0b00000001}'
- # test unsigned logical or
- yield dut.op.eq(5)
+ # test binary or
+ yield dut.op.eq(AluOpCodes.bit_or.value)
yield from sub_proc(0b10101011, 0b01000101)
out = yield dut.out
assert 0b11101111 == out, f'ERROR: {out} != {0b11101111}'
- # test logical xor
- yield dut.op.eq(6)
+ # test binary nor
+ yield dut.op.eq(AluOpCodes.bit_nor.value)
+ yield from sub_proc(0b10001011, 0b01000101)
+ out = yield dut.out
+ assert 0b11111111111111111111111100110000 == out, f'ERROR: {bin(out)} != {bin(0b11111111111111111111111100110000)}'
+
+ # test binary xor
+ yield dut.op.eq(AluOpCodes.bit_xor.value)
yield from sub_proc(0b10001011, 0b01000101)
out = yield dut.out
assert 0b11001110 == out, f'ERROR: {out} != {0b11001110}'
# test logical shift left
- yield dut.op.eq(7)
- yield from sub_proc(0b10001011, 5) # shift left by 5
+ yield dut.op.eq(AluOpCodes.lleft.value)
+ yield from sub_proc(0b10001011, 25) # shift left by 5
out = yield dut.out
- assert 0b1000101100000 == out, f'ERROR: {out} != {0b1000101100000}'
+ assert 0b00010110000000000000000000000000 == out, f'ERROR: {bin(out)} != {bin(0b00010110000000000000000000000000)}'
+ out = yield dut.c_out
+ assert 1 == out, f'ERROR: {out} != {1}'
# test logical shift right
- yield dut.op.eq(8)
- yield from sub_proc(0b10001011, 5) # shift right by 5
+ yield dut.op.eq(AluOpCodes.lright.value)
+ yield from sub_proc(0b10001011, 4) # shift right by 5
out = yield dut.out
- assert 0b100 == out, f'ERROR: {out} != {0b100}'
+ assert 0b1000 == out, f'ERROR: {bin(out)} != {bin(0b1000)}'
+ out = yield dut.c_out
+ assert 1 == out, f'ERROR: {out} != {1}'
# test aligned shift right
- yield dut.op.eq(9)
+ yield dut.op.eq(AluOpCodes.aright.value)
yield from sub_proc(0x80001234, 4) # shift right by 4
out = yield dut.out
assert 0xF8000123 == out, f'ERROR: {out} != {0xF8000123}'
+ out = yield dut.c_out
+ assert 0 == out, f'ERROR: {out} != {0}'
# test unsigned overflow
- yield dut.op.eq(0b0000)
+ yield dut.op.eq(AluOpCodes.add.value)
yield from sub_proc(0xFFFFFFFF, 1) # add 1 to 0xFFFFFFFF
out = yield dut.overflow
assert out == 1, f'ERROR: {out} != {1}'
- out = yield dut.carry
- assert out == 1, f'ERROR: {out} != {1}'
-
- # test signed overflow
- yield dut.op.eq(0b0010)
- yield from sub_proc(0x7FFFFFFF, 1) # add 1 to 0x7FFFFFFF
- out = yield dut.overflow
+ out = yield dut.c_out
assert out == 1, f'ERROR: {out} != {1}'
- out = yield dut.carry
- assert out == 0, f'ERROR: {out} != {0}'
# test unsigned underflow
- yield dut.op.eq(0b0001)
+ yield dut.op.eq(AluOpCodes.add.value)
yield from sub_proc(0, -1) # subtract 1 from 0
out = yield dut.overflow
assert out == 1, f'ERROR: {out} != {1}'
- out = yield dut.carry
- assert out == 1, f'ERROR: {out} != {1}'
-
- # test signed underflow
- yield dut.op.eq(0b0010)
- yield from sub_proc(0x80000000, -1) # sub 1 from 0x80000000 (most negative number in two's complement)
- assert out == 1, f'ERROR: {out} != {1}'
- out = yield dut.carry
- assert out == 1, f'ERROR: {out} != {1}'
+ out = yield dut.c_out
+ assert out == 0, f'ERROR: {out} != {0}'
# test zero
- yield dut.op.eq(0b0000)
+ yield dut.op.eq(AluOpCodes.add.value)
yield from sub_proc(0, 0) # add 0 to 0
out = yield dut.zero
assert out == 1, f'ERROR: {out} != {1}'
# test zero
- yield dut.op.eq(0b0000)
+ yield dut.op.eq(AluOpCodes.add.value)
yield from sub_proc(0, 1) # add 0 to 0
out = yield dut.zero
assert out == 0, f'ERROR: {out} != {0}'