From 07c0b18e4c2ed48b41496f98637600c7126d23be Mon Sep 17 00:00:00 2001 From: Launchcore Date: Tue, 17 Jun 2025 00:35:40 +0800 Subject: [PATCH] Initial commit --- .gitignore | 216 +++++++ Hardware/.gitignore | 66 +++ Hardware/LA32R.cache/wt/webtalk_pa.xml | 60 ++ Hardware/LA32R.ip_user_files/README.txt | 1 + .../LA32R.sim/sim_1/behav/xsim/cpu_tb.tcl | 11 + .../sim_1/behav/xsim/cpu_tb_vlog.prj | 17 + Hardware/LA32R.sim/sim_1/behav/xsim/glbl.v | 71 +++ .../LA32R.sim/sim_1/behav/xsim/webtalk.jou | 12 + .../sim_1/behav/xsim/webtalk_16180.backup.jou | 12 + Hardware/LA32R.sim/sim_1/behav/xsim/xelab.pb | Bin 0 -> 2069 bytes .../cpu_tb_snapshot/Compile_Options.txt | 1 + .../cpu_tb_snapshot/TempBreakPointFile.txt | 1 + .../xsim/xsim.dir/cpu_tb_snapshot/xsim.mem | Bin 0 -> 5511 bytes .../xsim.dir/cpu_tb_snapshot/xsim_script.tcl | 1 + Hardware/LA32R.sim/sim_1/behav/xsim/xsim.jou | 13 + Hardware/LA32R.sim/sim_1/behav/xsim/xvlog.pb | Bin 0 -> 3213 bytes Hardware/LA32R.srcs/sim_1/new/cpu_tb.v | 101 ++++ Hardware/LA32R.srcs/sources_1/new/alu.v | 80 +++ .../LA32R.srcs/sources_1/new/control_unit.v | 166 ++++++ Hardware/LA32R.srcs/sources_1/new/cpu_top.v | 144 +++++ .../LA32R.srcs/sources_1/new/data_memory.v | 32 ++ .../LA32R.srcs/sources_1/new/imm_extender.v | 76 +++ .../sources_1/new/instruction_memory.v | 31 + Hardware/LA32R.srcs/sources_1/new/pc.v | 56 ++ .../LA32R.srcs/sources_1/new/register_file.v | 79 +++ Hardware/LA32R.xpr | 190 +++++++ ...型共计14条指令的单周期LA32R CPU逻辑电路图.png | Bin 0 -> 101557 bytes Reference/设计方案.md | 528 ++++++++++++++++++ Reference/课程设计指导书.md | 41 ++ Software/assembler.py | 130 +++++ Software/program.hex | 21 + program.asm | 35 ++ run.bat | 108 ++++ 33 files changed, 2300 insertions(+) create mode 100644 .gitignore create mode 100644 Hardware/.gitignore create mode 100644 Hardware/LA32R.cache/wt/webtalk_pa.xml create mode 100644 Hardware/LA32R.ip_user_files/README.txt create mode 100644 Hardware/LA32R.sim/sim_1/behav/xsim/cpu_tb.tcl create mode 100644 Hardware/LA32R.sim/sim_1/behav/xsim/cpu_tb_vlog.prj create mode 100644 Hardware/LA32R.sim/sim_1/behav/xsim/glbl.v create mode 100644 Hardware/LA32R.sim/sim_1/behav/xsim/webtalk.jou create mode 100644 Hardware/LA32R.sim/sim_1/behav/xsim/webtalk_16180.backup.jou create mode 100644 Hardware/LA32R.sim/sim_1/behav/xsim/xelab.pb create mode 100644 Hardware/LA32R.sim/sim_1/behav/xsim/xsim.dir/cpu_tb_snapshot/Compile_Options.txt create mode 100644 Hardware/LA32R.sim/sim_1/behav/xsim/xsim.dir/cpu_tb_snapshot/TempBreakPointFile.txt create mode 100644 Hardware/LA32R.sim/sim_1/behav/xsim/xsim.dir/cpu_tb_snapshot/xsim.mem create mode 100644 Hardware/LA32R.sim/sim_1/behav/xsim/xsim.dir/cpu_tb_snapshot/xsim_script.tcl create mode 100644 Hardware/LA32R.sim/sim_1/behav/xsim/xsim.jou create mode 100644 Hardware/LA32R.sim/sim_1/behav/xsim/xvlog.pb create mode 100644 Hardware/LA32R.srcs/sim_1/new/cpu_tb.v create mode 100644 Hardware/LA32R.srcs/sources_1/new/alu.v create mode 100644 Hardware/LA32R.srcs/sources_1/new/control_unit.v create mode 100644 Hardware/LA32R.srcs/sources_1/new/cpu_top.v create mode 100644 Hardware/LA32R.srcs/sources_1/new/data_memory.v create mode 100644 Hardware/LA32R.srcs/sources_1/new/imm_extender.v create mode 100644 Hardware/LA32R.srcs/sources_1/new/instruction_memory.v create mode 100644 Hardware/LA32R.srcs/sources_1/new/pc.v create mode 100644 Hardware/LA32R.srcs/sources_1/new/register_file.v create mode 100644 Hardware/LA32R.xpr create mode 100644 Reference/支持5种类型共计14条指令的单周期LA32R CPU逻辑电路图.png create mode 100644 Reference/设计方案.md create mode 100644 Reference/课程设计指导书.md create mode 100644 Software/assembler.py create mode 100644 Software/program.hex create mode 100644 program.asm create mode 100644 run.bat diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f880961 --- /dev/null +++ b/.gitignore @@ -0,0 +1,216 @@ +### Python ### +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ + +### Python Patch ### +# Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration +poetry.toml + +# ruff +.ruff_cache/ + +# LSP config files +pyrightconfig.json + +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history +.ionide + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk diff --git a/Hardware/.gitignore b/Hardware/.gitignore new file mode 100644 index 0000000..64a5d42 --- /dev/null +++ b/Hardware/.gitignore @@ -0,0 +1,66 @@ +### Vivado ### +######################################################################################################### +## This is an example .gitignore file for Vivado, please treat it as an example as +## it might not be complete. In addition, XAPP 1165 should be followed. +######### +#Exclude all +* +!*/ +!.gitignore +########################################################################### +## VIVADO +#Source files: +#Do NOT ignore VHDL, Verilog, block diagrams or EDIF files. +!*.vhd +!*.v +!*.sv +!*.bd +!*.edif +#IP files +#.xci: synthesis and implemented not possible - you need to return back to the previous version to generate output products +#.xci + .dcp: implementation possible but not re-synthesis +#*.xci(www.spiritconsortium.org) +!*.xci +#.xcix: Core container file +#.xcix: https://www.xilinx.com/support/documentation/sw_manuals/xilinx2016_2/ug896-vivado-ip.pdf (Page 41) +!*.xcix +#*.dcp(checkpoint files) +!*.dcp +!*.vds +!*.pb +#All bd comments and layout coordinates are stored within .ui +!*.ui +!*.ooc +#System Generator +!*.mdl +!*.slx +!*.bxml +#Simulation logic analyzer +!*.wcfg +!*.coe +#MIG +!*.prj +!*.mem +#Project files +#XPR + *.XML ? XPR (Files are merged into a single XPR file for 2014.1 version) +#Do NOT ignore *.xpr files +!*.xpr +#Include *.xml files for 2013.4 or earlier version +!*.xml +#Constraint files +#Do NOT ignore *.xdc files +!*.xdc +#TCL - files +!*.tcl +#Journal - files +!*.jou +#Reports +!*.rpt +!*.txt +!*.vdi +#C-files +!*.c +!*.h +!*.elf +!*.bmm +!*.xmp diff --git a/Hardware/LA32R.cache/wt/webtalk_pa.xml b/Hardware/LA32R.cache/wt/webtalk_pa.xml new file mode 100644 index 0000000..5053921 --- /dev/null +++ b/Hardware/LA32R.cache/wt/webtalk_pa.xml @@ -0,0 +1,60 @@ + + + + +
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
diff --git a/Hardware/LA32R.ip_user_files/README.txt b/Hardware/LA32R.ip_user_files/README.txt new file mode 100644 index 0000000..023052c --- /dev/null +++ b/Hardware/LA32R.ip_user_files/README.txt @@ -0,0 +1 @@ +The files in this directory structure are automatically generated and managed by Vivado. Editing these files is not recommended. diff --git a/Hardware/LA32R.sim/sim_1/behav/xsim/cpu_tb.tcl b/Hardware/LA32R.sim/sim_1/behav/xsim/cpu_tb.tcl new file mode 100644 index 0000000..1094e45 --- /dev/null +++ b/Hardware/LA32R.sim/sim_1/behav/xsim/cpu_tb.tcl @@ -0,0 +1,11 @@ +set curr_wave [current_wave_config] +if { [string length $curr_wave] == 0 } { + if { [llength [get_objects]] > 0} { + add_wave / + set_property needs_save false [current_wave_config] + } else { + send_msg_id Add_Wave-1 WARNING "No top level signals found. Simulator will start without a wave window. If you want to open a wave window go to 'File->New Waveform Configuration' or type 'create_wave_config' in the TCL console." + } +} + +run 1000ns diff --git a/Hardware/LA32R.sim/sim_1/behav/xsim/cpu_tb_vlog.prj b/Hardware/LA32R.sim/sim_1/behav/xsim/cpu_tb_vlog.prj new file mode 100644 index 0000000..ff790c7 --- /dev/null +++ b/Hardware/LA32R.sim/sim_1/behav/xsim/cpu_tb_vlog.prj @@ -0,0 +1,17 @@ +# compile verilog/system verilog design source files +verilog xil_defaultlib \ +"../../../../LA32R.srcs/sources_1/new/alu.v" \ +"../../../../LA32R.srcs/sources_1/new/control_unit.v" \ +"../../../../LA32R.srcs/sources_1/new/cpu_top.v" \ +"../../../../LA32R.srcs/sources_1/new/data_memory.v" \ +"../../../../LA32R.srcs/sources_1/new/imm_extender.v" \ +"../../../../LA32R.srcs/sources_1/new/instruction_memory.v" \ +"../../../../LA32R.srcs/sources_1/new/pc.v" \ +"../../../../LA32R.srcs/sources_1/new/register_file.v" \ +"../../../../LA32R.srcs/sim_1/new/cpu_tb.v" \ + +# compile glbl module +verilog xil_defaultlib "glbl.v" + +# Do not sort compile order +nosort diff --git a/Hardware/LA32R.sim/sim_1/behav/xsim/glbl.v b/Hardware/LA32R.sim/sim_1/behav/xsim/glbl.v new file mode 100644 index 0000000..be64233 --- /dev/null +++ b/Hardware/LA32R.sim/sim_1/behav/xsim/glbl.v @@ -0,0 +1,71 @@ +// $Header: /devl/xcs/repo/env/Databases/CAEInterfaces/verunilibs/data/glbl.v,v 1.14 2010/10/28 20:44:00 fphillip Exp $ +`ifndef GLBL +`define GLBL +`timescale 1 ps / 1 ps + +module glbl (); + + parameter ROC_WIDTH = 100000; + parameter TOC_WIDTH = 0; + +//-------- STARTUP Globals -------------- + wire GSR; + wire GTS; + wire GWE; + wire PRLD; + tri1 p_up_tmp; + tri (weak1, strong0) PLL_LOCKG = p_up_tmp; + + wire PROGB_GLBL; + wire CCLKO_GLBL; + wire FCSBO_GLBL; + wire [3:0] DO_GLBL; + wire [3:0] DI_GLBL; + + reg GSR_int; + reg GTS_int; + reg PRLD_int; + +//-------- JTAG Globals -------------- + wire JTAG_TDO_GLBL; + wire JTAG_TCK_GLBL; + wire JTAG_TDI_GLBL; + wire JTAG_TMS_GLBL; + wire JTAG_TRST_GLBL; + + reg JTAG_CAPTURE_GLBL; + reg JTAG_RESET_GLBL; + reg JTAG_SHIFT_GLBL; + reg JTAG_UPDATE_GLBL; + reg JTAG_RUNTEST_GLBL; + + reg JTAG_SEL1_GLBL = 0; + reg JTAG_SEL2_GLBL = 0 ; + reg JTAG_SEL3_GLBL = 0; + reg JTAG_SEL4_GLBL = 0; + + reg JTAG_USER_TDO1_GLBL = 1'bz; + reg JTAG_USER_TDO2_GLBL = 1'bz; + reg JTAG_USER_TDO3_GLBL = 1'bz; + reg JTAG_USER_TDO4_GLBL = 1'bz; + + assign (strong1, weak0) GSR = GSR_int; + assign (strong1, weak0) GTS = GTS_int; + assign (weak1, weak0) PRLD = PRLD_int; + + initial begin + GSR_int = 1'b1; + PRLD_int = 1'b1; + #(ROC_WIDTH) + GSR_int = 1'b0; + PRLD_int = 1'b0; + end + + initial begin + GTS_int = 1'b1; + #(TOC_WIDTH) + GTS_int = 1'b0; + end + +endmodule +`endif diff --git a/Hardware/LA32R.sim/sim_1/behav/xsim/webtalk.jou b/Hardware/LA32R.sim/sim_1/behav/xsim/webtalk.jou new file mode 100644 index 0000000..2507de1 --- /dev/null +++ b/Hardware/LA32R.sim/sim_1/behav/xsim/webtalk.jou @@ -0,0 +1,12 @@ +#----------------------------------------------------------- +# Webtalk v2018.1 (64-bit) +# SW Build 2188600 on Wed Apr 4 18:40:38 MDT 2018 +# IP Build 2185939 on Wed Apr 4 20:55:05 MDT 2018 +# Start of session at: Tue Jun 17 00:19:34 2025 +# Process ID: 36764 +# Current directory: D:/Schoolwork/ComputerComposition/LA32R/Hardware/LA32R.sim/sim_1/behav/xsim +# Command line: wbtcv.exe -mode batch -source D:/Schoolwork/ComputerComposition/LA32R/Hardware/LA32R.sim/sim_1/behav/xsim/xsim.dir/cpu_tb_snapshot/webtalk/xsim_webtalk.tcl -notrace +# Log file: D:/Schoolwork/ComputerComposition/LA32R/Hardware/LA32R.sim/sim_1/behav/xsim/webtalk.log +# Journal file: D:/Schoolwork/ComputerComposition/LA32R/Hardware/LA32R.sim/sim_1/behav/xsim\webtalk.jou +#----------------------------------------------------------- +source D:/Schoolwork/ComputerComposition/LA32R/Hardware/LA32R.sim/sim_1/behav/xsim/xsim.dir/cpu_tb_snapshot/webtalk/xsim_webtalk.tcl -notrace diff --git a/Hardware/LA32R.sim/sim_1/behav/xsim/webtalk_16180.backup.jou b/Hardware/LA32R.sim/sim_1/behav/xsim/webtalk_16180.backup.jou new file mode 100644 index 0000000..885483f --- /dev/null +++ b/Hardware/LA32R.sim/sim_1/behav/xsim/webtalk_16180.backup.jou @@ -0,0 +1,12 @@ +#----------------------------------------------------------- +# Webtalk v2018.1 (64-bit) +# SW Build 2188600 on Wed Apr 4 18:40:38 MDT 2018 +# IP Build 2185939 on Wed Apr 4 20:55:05 MDT 2018 +# Start of session at: Tue Jun 17 00:19:31 2025 +# Process ID: 16180 +# Current directory: D:/Schoolwork/ComputerComposition/LA32R/Hardware/LA32R.sim/sim_1/behav/xsim +# Command line: wbtcv.exe -mode batch -source D:/Schoolwork/ComputerComposition/LA32R/Hardware/LA32R.sim/sim_1/behav/xsim/xsim.dir/cpu_tb_snapshot/webtalk/xsim_webtalk.tcl -notrace +# Log file: D:/Schoolwork/ComputerComposition/LA32R/Hardware/LA32R.sim/sim_1/behav/xsim/webtalk.log +# Journal file: D:/Schoolwork/ComputerComposition/LA32R/Hardware/LA32R.sim/sim_1/behav/xsim\webtalk.jou +#----------------------------------------------------------- +source D:/Schoolwork/ComputerComposition/LA32R/Hardware/LA32R.sim/sim_1/behav/xsim/xsim.dir/cpu_tb_snapshot/webtalk/xsim_webtalk.tcl -notrace diff --git a/Hardware/LA32R.sim/sim_1/behav/xsim/xelab.pb b/Hardware/LA32R.sim/sim_1/behav/xsim/xelab.pb new file mode 100644 index 0000000000000000000000000000000000000000..48159e5d4f7c8a82c93c900118c93185e4227d08 GIT binary patch literal 2069 zcmchY%Wl&^6o#9oYQ+(Ph)S(gT4@B7qSE-Di@SnGELfC9TM%LsP3%cBFrIP8<2HE* z7Q6y4#q(gtX_&f=FdKG09_#t4j&{mN*Pu{IxnE{iC*DQ zp!3DMjgSm+%GB}AgR=wcj%9ZZ+qrqQIQz2UxlPyabjB<3+GOoVZKbgamr$SKbkYU9 z>4|tM>1eEw?RVQv+xPt=L1!c(@`{AUUAhka zRfC6TDd&`rj&Iz$uB+$pvj*R5y<@W=nT2z+ux1V@H&cEsaU7G-yr#VE8N!?ph6e_j z5Y%jjWRQ-Kn#MH1EQ=G4<76xp3gWb{2K_}mp{zf@L`DZjag3Twj8HBoBv!=8qq~lZ z`}90tx5mIY%?d)BYAgv3Glz&KNN@vvO!6QrZ^G~uLB;vJ(pFpdz6GmxcNx!bc{=X| zcFz@-D%VaFRy0`TO$DFzk?T2{`aJ7aS6Au5UQa|ZBZ`E}WSp+vj)jctw{@9QIQWxH z(WF@tD8ve*ArsdKbIhg*EnK^veNSGuy7L3P((?MNqSNv3D7t=2Pcel33mTEUQw2*^ zp59PMG#|4(%*r(%K-cp$IcFQ{cAPA$i`TYv4u;J<^L$Q5C=y}HNG3ZQYpbQJzJw>G z9*hH62Ju_24!NufX~VM;gz`kmG{`TYACXANX;tXAs!$7dOVB`YB?arJoT~qTqfyi+ z6GeDPWK|ri>duC}k~>L8G*LwMhm?`3yg^mo0c@6dn59)IU#n6~cv_<5!~2gNGOS8_ z4cjH!Z2yY5sxMNNbO>Abkp@*kW7s=MDO38QSo}lg>%!@D^}&7)k4rzBWmE0?w^sTi PfOkC1HdG*F*r@#m`=4w* literal 0 HcmV?d00001 diff --git a/Hardware/LA32R.sim/sim_1/behav/xsim/xsim.dir/cpu_tb_snapshot/Compile_Options.txt b/Hardware/LA32R.sim/sim_1/behav/xsim/xsim.dir/cpu_tb_snapshot/Compile_Options.txt new file mode 100644 index 0000000..b46ddf1 --- /dev/null +++ b/Hardware/LA32R.sim/sim_1/behav/xsim/xsim.dir/cpu_tb_snapshot/Compile_Options.txt @@ -0,0 +1 @@ +--debug "typical" --snapshot "cpu_tb_snapshot" "xil_defaultlib.cpu_tb" -log "elaborate.log" diff --git a/Hardware/LA32R.sim/sim_1/behav/xsim/xsim.dir/cpu_tb_snapshot/TempBreakPointFile.txt b/Hardware/LA32R.sim/sim_1/behav/xsim/xsim.dir/cpu_tb_snapshot/TempBreakPointFile.txt new file mode 100644 index 0000000..fdbc612 --- /dev/null +++ b/Hardware/LA32R.sim/sim_1/behav/xsim/xsim.dir/cpu_tb_snapshot/TempBreakPointFile.txt @@ -0,0 +1 @@ +Breakpoint File Version 1.0 diff --git a/Hardware/LA32R.sim/sim_1/behav/xsim/xsim.dir/cpu_tb_snapshot/xsim.mem b/Hardware/LA32R.sim/sim_1/behav/xsim/xsim.dir/cpu_tb_snapshot/xsim.mem new file mode 100644 index 0000000000000000000000000000000000000000..769a9b4c8174be268418ca861383c17c4aa9667d GIT binary patch literal 5511 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 QT?2Td@~F$G#=KSg3$6hGZ2$lO literal 0 HcmV?d00001 diff --git a/Hardware/LA32R.srcs/sim_1/new/cpu_tb.v b/Hardware/LA32R.srcs/sim_1/new/cpu_tb.v new file mode 100644 index 0000000..ad859da --- /dev/null +++ b/Hardware/LA32R.srcs/sim_1/new/cpu_tb.v @@ -0,0 +1,101 @@ +`timescale 1ns / 1ps + +/******************************************************************************* +** Company: Nantong University +** Engineer: あやせももこ +** +** Create Date: 2025-06-16 +** Design Name: LA32R Single Cycle CPU Testbench +** Module Name: cpu_tb +** Project Name: Computer Architecture Course Design +** Target Devices: Any +** Tool Versions: Vivado 2018.1 +** Description: +** A self-checking testbench for the LA32R single-cycle CPU. +** - Generates clock and reset signals. +** - Instantiates the cpu_top module. +** - The instruction_memory module (instantiated within cpu_top) will load +** the machine code from "program.hex". +** - Monitors and displays the state of the PC and register file. +** +** Revision: +** Revision 0.01 - File Created +** Additional Comments: +** - Place this file and "program.hex" in the simulation directory. +** +*******************************************************************************/ + +`timescale 1ns / 1ps + +module cpu_tb; + + // --- 信号声明 (Signal Declarations) --- + reg clk; + reg rst; + + // --- 实例化待测设计 (Instantiate the Design Under Test) --- + cpu_top uut ( + .clk(clk), + .rst(rst) + ); + + // --- 时钟生成器 (Clock Generator) --- + localparam CLK_PERIOD = 10; // 时钟周期为10ns (Clock period is 10ns) + initial begin + clk = 0; + forever #(CLK_PERIOD / 2) clk = ~clk; + end + + // --- 仿真控制 (Simulation Control) --- + initial begin + // 1. 复位CPU (Reset the CPU) + rst = 1; + #(CLK_PERIOD * 2); // 保持复位2个周期 (Hold reset for 2 cycles) + rst = 0; + $display("------------------------------------------------------------"); + $display(" CPU Simulation Started. Reset is released. "); + $display("------------------------------------------------------------"); + + // 2. 运行一段时间后停止仿真 + // Stop the simulation after a certain amount of time. + // The test program has an infinite loop at the end, + // so we need to manually stop the simulation. + #500; // 运行500ns (Run for 500ns) + + // 3. 打印最终的寄存器状态 + // Print the final state of the registers + $display("\n------------------------------------------------------------"); + $display(" Simulation Finished. Final Register State: "); + $display("------------------------------------------------------------"); + // 使用$display来显示寄存器的值。注意路径需要正确。 + // Use $display to show register values. Note the path must be correct. + for (integer i = 0; i < 32; i = i + 1) begin + // 检查寄存器值是否非零,以简化输出 + // Check if register value is non-zero to simplify output + if (uut.u_reg_file.registers[i] != 32'h00000000) begin + $display("Register R%0d: 0x%08h", i, uut.u_reg_file.registers[i]); + end + end + $display("※Please note that registers with value zero are hidden.※"); + $display("------------------------------------------------------------"); + + $finish; // 结束仿真 (End simulation) + end + + // --- 监控和显示 (Monitoring and Display) --- + // 在每个时钟周期的下降沿打印信息,确保所有信号稳定 + // Display info at the falling edge of the clock to ensure all signals are stable. + always @(negedge clk) begin + if (!rst) begin + $display("Time: %0t ns | PC: 0x%08h | Instruction: 0x%08h | R4=0x%h R5=0x%h R6=0x%h", + $time, + uut.pc_out, + uut.instr, + uut.u_reg_file.registers[4], + uut.u_reg_file.registers[5], + uut.u_reg_file.registers[6] + ); + end + end + +endmodule diff --git a/Hardware/LA32R.srcs/sources_1/new/alu.v b/Hardware/LA32R.srcs/sources_1/new/alu.v new file mode 100644 index 0000000..6b8c561 --- /dev/null +++ b/Hardware/LA32R.srcs/sources_1/new/alu.v @@ -0,0 +1,80 @@ +`timescale 1ns / 1ps + +/******************************************************************************* +** Company: Nantong University +** Engineer: あやせももこ +** +** Create Date: 2025-06-16 +** Design Name: LA32R Single Cycle CPU +** Module Name: alu +** Project Name: Computer Architecture Course Design +** Target Devices: Any FPGA +** Tool Versions: Vivado 2018.1 +** Description: +** This module implements the Arithmetic Logic Unit (ALU) for the LA32R CPU. +** +** [FIXED] The implementation of SLT now uses the $signed() system function +** to correctly handle comparisons that could cause overflow, such as +** comparing a positive and a negative number. +** +** Revision: +** Revision 0.02 - Corrected SLT implementation using $signed(). +** Revision 0.01 - File Created +** +*******************************************************************************/ + +module alu ( + input wire [31:0] a, // 操作数 A (Operand A) + input wire [31:0] b, // 操作数 B (Operand B) + input wire [3:0] alu_op, // ALU 操作控制码 (ALU Operation Control Code) + output reg [31:0] result, // 运算结果 (Result) + output wire zero, // 零标志位 (Zero Flag) + output wire lt // 小于标志位 (Less Than Flag for BLT) +); + + // 定义ALU操作码的参数,增强可读性 + // Define parameters for ALU operations to enhance readability + localparam ALU_ADD = 4'b0000; + localparam ALU_SUB = 4'b0001; + localparam ALU_AND = 4'b0010; + localparam ALU_OR = 4'b0011; + localparam ALU_NOR = 4'b0100; + localparam ALU_SLT = 4'b0101; + localparam ALU_SLTU = 4'b0110; + + // 减法结果的临时线网 + // Temporary wire for subtraction result + wire [31:0] sub_result = a - b; + + // [FIX] 使用$signed()进行稳健的有符号比较 + // [FIX] Use $signed() for robust signed comparison + wire slt_res = ($signed(a) < $signed(b)); + + // 无符号比较 + // Unsigned comparison + wire sltu_res = (a < b); + + // 主组合逻辑: 根据alu_op计算结果 + // Main combinational logic: calculate result based on alu_op + always @(*) begin + case (alu_op) + ALU_ADD: result = a + b; // 加法 (Addition) + ALU_SUB: result = sub_result; // 减法 (Subtraction) + ALU_AND: result = a & b; // 与 (AND) + ALU_OR: result = a | b; // 或 (OR) + ALU_NOR: result = ~(a | b); // 或非 (NOR) + ALU_SLT: result = {31'b0, slt_res}; // 有符号小于比较 (Set on Less Than, Signed) + ALU_SLTU: result = {31'b0, sltu_res}; // 无符号小于比较 (Set on Less Than, Unsigned) + default: result = 32'hxxxxxxxx; // 默认情况,输出不定态 (Default case, output undefined) + endcase + end + + // 零标志位输出: 当减法结果为0时置1,用于BEQ指令 + // Zero flag output: set to 1 when the subtraction result is zero, for BEQ instruction + assign zero = (sub_result == 32'h00000000); + + // 小于标志位输出: 用于BLT指令 + // Less Than flag output: for BLT instruction + assign lt = slt_res; + +endmodule \ No newline at end of file diff --git a/Hardware/LA32R.srcs/sources_1/new/control_unit.v b/Hardware/LA32R.srcs/sources_1/new/control_unit.v new file mode 100644 index 0000000..bcb295b --- /dev/null +++ b/Hardware/LA32R.srcs/sources_1/new/control_unit.v @@ -0,0 +1,166 @@ +`timescale 1ns / 1ps + +/******************************************************************************* +** Company: Nantong University +** Engineer: あやせももこ +** +** Create Date: 2025-06-16 +** Design Name: LA32R Single Cycle CPU +** Module Name: control_unit +** Project Name: Computer Architecture Course Design +** Target Devices: Any FPGA +** Tool Versions: Vivado 2018.1 +** Description: +** This is the main control unit for the single-cycle LA32R CPU. It decodes +** the instruction's opcode and function fields to generate all necessary +** control signals for the datapath. +** +** [FIXED] Restructured the case statement to correctly handle instructions +** that share the same opcode, such as LD.W and ST.W. +** +** Revision: +** Revision 0.02 - Corrected case statement logic for shared opcodes. +** Revision 0.01 - File Created +** +*******************************************************************************/ + +module control_unit ( + input wire [31:0] instr, // 指令输入 (Instruction Input) + input wire zero_flag, // 来自ALU的零标志位 (Zero flag from ALU) + input wire lt_flag, // 来自ALU的小于标志位 (Less-than flag from ALU) + + output reg reg_write_en, // 寄存器写使能 (Register Write Enable) + output reg mem_to_reg, // 选择写回寄存器的数据源 (Selects data source for register write-back) + output reg mem_write_en, // 存储器写使能 (Memory Write Enable) + output reg alu_src, // 选择ALU的第二操作数源 (Selects ALU's second operand source) + output reg src_reg, // 选择寄存器堆的第二读地址源 (Selects Register File's second read address source) + output reg [2:0] ext_op, // 立即数扩展控制 (Immediate extender control) + output reg [3:0] alu_op, // ALU操作控制 (ALU operation control) + output wire pcsource // PC下一个地址来源选择 (PC next address source selection) +); + + // 提取指令中的关键字段 + // Extract key fields from the instruction + wire [5:0] opcode = instr[31:26]; + wire [1:0] func2 = instr[21:20]; // for 3R-type per ISA document + wire [4:0] func5 = instr[19:15]; // for 3R-type per ISA document + wire [3:0] func4 = instr[25:22]; // for 2RI12-type + + // 定义指令操作码 (Opcode Definitions) + localparam OP_GROUP_00 = 6'b000000; // Contains 3R instructions + localparam OP_ADDI_W = 6'b000010; + localparam OP_LUI12I = 6'b000101; + localparam OP_GROUP_0A = 6'b001010; // Contains LD.W, ST.W + localparam OP_B = 6'b010100; + localparam OP_BEQ = 6'b010110; + localparam OP_BLT = 6'b011000; + + // 定义ALU操作码 (ALU Operation Definitions) + localparam ALU_ADD = 4'b0000; + localparam ALU_SUB = 4'b0001; + localparam ALU_AND = 4'b0010; + localparam ALU_OR = 4'b0011; + localparam ALU_NOR = 4'b0100; + localparam ALU_SLT = 4'b0101; + localparam ALU_SLTU = 4'b0110; + + // 定义立即数扩展类型 (Immediate Extension Type Definitions) + localparam EXT_SI12 = 3'b001; + localparam EXT_SI16 = 3'b010; + localparam EXT_UI20 = 3'b011; + localparam EXT_SI26 = 3'b100; + + // 主译码逻辑 (Main Decoding Logic) + always @(*) begin + // --- 控制信号默认值,防止生成锁存器 --- + // Default values for control signals to prevent latches + reg_write_en = 1'b0; + mem_to_reg = 1'b0; + mem_write_en = 1'b0; + alu_src = 1'b0; + src_reg = 1'b0; + ext_op = 3'bxxx; + alu_op = 4'bxxxx; + + case (opcode) + OP_GROUP_00: begin + // Differentiate based on func2 field + if (func2 == 2'b01) begin // This is a 3R-type arithmetic/logic instruction + reg_write_en = 1'b1; + alu_src = 1'b0; // B operand comes from register + src_reg = 1'b0; // Second read address comes from rk field + // Further decode based on func5 + case(func5) + 5'b00000: alu_op = ALU_ADD; + 5'b00010: alu_op = ALU_SUB; + 5'b00100: alu_op = ALU_SLT; + 5'b00101: alu_op = ALU_SLTU; + 5'b01000: alu_op = ALU_NOR; + 5'b01001: alu_op = ALU_AND; + 5'b01010: alu_op = ALU_OR; + default: alu_op = 4'bxxxx; + endcase + end + end + OP_ADDI_W: begin + // ADDI.W has its own opcode + reg_write_en = 1'b1; + alu_src = 1'b1; // B operand comes from immediate + ext_op = EXT_SI12; + alu_op = ALU_ADD; + end + OP_LUI12I: begin + reg_write_en = 1'b1; + alu_src = 1'b1; + mem_to_reg = 1'b0; // ALU result writes back + ext_op = EXT_UI20; + alu_op = ALU_ADD; // ALU adds immediate to zero + end + OP_GROUP_0A: begin + // Differentiate LD.W and ST.W based on func4 + if (func4 == 4'b0010) begin // LD.W + reg_write_en = 1'b1; + mem_to_reg = 1'b1; // Data from memory writes back + alu_src = 1'b1; + ext_op = EXT_SI12; + alu_op = ALU_ADD; // Calculate address + end + else if (func4 == 4'b0110) begin // ST.W + mem_write_en = 1'b1; + alu_src = 1'b1; + src_reg = 1'b1; // Second read address comes from rd field + ext_op = EXT_SI12; + alu_op = ALU_ADD; // Calculate address + end + end + OP_B: begin + // Unconditional branch + ext_op = EXT_SI26; + end + OP_BEQ: begin + alu_src = 1'b0; + src_reg = 1'b1; // Second read address comes from rd field + ext_op = EXT_SI16; + alu_op = ALU_SUB; // Compare + end + OP_BLT: begin + alu_src = 1'b0; + src_reg = 1'b1; // Second read address comes from rd field + ext_op = EXT_SI16; + alu_op = ALU_SUB; // Compare + end + default: begin + // All signals keep their default values + end + endcase + end + + // PC下一个地址来源的逻辑 + // Logic for PC's next address source + wire beq_cond = (opcode == OP_BEQ) && zero_flag; + wire blt_cond = (opcode == OP_BLT) && lt_flag; + wire b_cond = (opcode == OP_B); + + assign pcsource = beq_cond || blt_cond || b_cond; + +endmodule diff --git a/Hardware/LA32R.srcs/sources_1/new/cpu_top.v b/Hardware/LA32R.srcs/sources_1/new/cpu_top.v new file mode 100644 index 0000000..ecc238d --- /dev/null +++ b/Hardware/LA32R.srcs/sources_1/new/cpu_top.v @@ -0,0 +1,144 @@ +`timescale 1ns / 1ps + +/******************************************************************************* +** Company: Nantong University +** Engineer: あやせももこ +** +** Create Date: 2025-06-16 +** Design Name: LA32R Single Cycle CPU +** Module Name: cpu_top +** Project Name: Computer Architecture Course Design +** Target Devices: Any FPGA +** Tool Versions: Vivado 2018.1 +** Description: +** This is the top-level module of the single-cycle LA32R CPU. It instantiates +** and connects all sub-modules including PC, memories, register file, ALU, +** immediate extender, and the control unit. The connections follow the +** datapath diagram provided in the course design guide. +** +** Revision: +** Revision 0.01 - File Created +** Additional Comments: +** - This file integrates the entire design. +** +*******************************************************************************/ + +`timescale 1ns / 1ps + +module cpu_top ( + input wire clk, + input wire rst +); + + // --- 内部连线声明 (Internal Wire Declarations) --- + wire [31:0] pc_out; + wire [31:0] instr; + wire [31:0] imm_ext; + wire [31:0] read_data1; + wire [31:0] read_data2; + wire [31:0] alu_result; + wire [31:0] mem_read_data; + wire [31:0] write_back_data; + wire [31:0] alu_b_operand; + + wire [4:0] reg_write_addr; + wire [4:0] reg_read_addr1; + wire [4:0] reg_read_addr2; + wire [4:0] reg_read_addr2_final; + + // 控制信号 + // Control Signals + wire reg_write_en; + wire mem_to_reg; + wire mem_write_en; + wire alu_src; + wire src_reg; + wire pcsource; + wire zero_flag; + wire lt_flag; + wire [2:0] ext_op; + wire [3:0] alu_op; + + + // --- 模块实例化 (Module Instantiation) --- + + // PC (程序计数器) + pc u_pc ( + .clk (clk), + .rst (rst), + .pcsource (pcsource), + .imm_ext (imm_ext), + .pc_out (pc_out) + ); + + // Instruction Memory (指令存储器) + instruction_memory u_inst_mem ( + .addr (pc_out), + .instr (instr) + ); + + // Control Unit (控制单元) + control_unit u_ctrl_unit ( + .instr (instr), + .zero_flag (zero_flag), + .lt_flag (lt_flag), + .reg_write_en (reg_write_en), + .mem_to_reg (mem_to_reg), + .mem_write_en (mem_write_en), + .alu_src (alu_src), + .src_reg (src_reg), + .ext_op (ext_op), + .alu_op (alu_op), + .pcsource (pcsource) + ); + + // Immediate Extender (立即数扩展单元) + imm_extender u_imm_ext ( + .instr (instr), + .ext_op (ext_op), + .imm_ext (imm_ext) + ); + + // MUX for Register File's second read address (src_reg_mux) + assign reg_read_addr2_final = src_reg ? instr[4:0] : instr[14:10]; + + // Register File (寄存器堆) + register_file u_reg_file ( + .clk (clk), + .rst (rst), + .reg_write_en (reg_write_en), + .read_addr1 (instr[9:5]), + .read_addr2 (reg_read_addr2_final), + .write_addr (instr[4:0]), + .write_data (write_back_data), + .read_data1 (read_data1), + .read_data2 (read_data2) + ); + + // MUX for ALU's second operand (alu_src_mux) + assign alu_b_operand = alu_src ? imm_ext : read_data2; + + // ALU (算术逻辑单元) + alu u_alu ( + .a (read_data1), + .b (alu_b_operand), + .alu_op (alu_op), + .result (alu_result), + .zero (zero_flag), + .lt (lt_flag) + ); + + // Data Memory (数据存储器) + data_memory u_data_mem ( + .clk (clk), + .mem_write_en (mem_write_en), + .addr (alu_result), + .write_data (read_data2), // ST.W指令的数据来自第二个读端口(rd) + .read_data (mem_read_data) + ); + + // MUX for write-back data (mem_to_reg_mux) + assign write_back_data = mem_to_reg ? mem_read_data : alu_result; + + +endmodule diff --git a/Hardware/LA32R.srcs/sources_1/new/data_memory.v b/Hardware/LA32R.srcs/sources_1/new/data_memory.v new file mode 100644 index 0000000..0ae5cbf --- /dev/null +++ b/Hardware/LA32R.srcs/sources_1/new/data_memory.v @@ -0,0 +1,32 @@ +`timescale 1ns / 1ps + +/******************************************************************************* +** Data Memory Module +*******************************************************************************/ + +module data_memory ( + input wire clk, // 时钟 (Clock) + input wire mem_write_en, // 写使能 (Write Enable) + input wire [31:0] addr, // 地址输入 (Address input) + input wire [31:0] write_data, // 待写数据 (Write data) + output wire [31:0] read_data // 读出数据 (Read data) +); + // 在FPGA中,这会综合成一个同步写的RAM + // In an FPGA, this synthesizes into a synchronous-write RAM. + + reg [31:0] mem [0:1023]; // 示例: 1KB数据空间 (Example: 1KB data space) + + // 同步写 + // Synchronous write + always @(posedge clk) begin + if (mem_write_en) begin + mem[addr[11:2]] <= write_data; + end + end + + // 异步读 + // Asynchronous read + assign read_data = mem[addr[11:2]]; + +endmodule + diff --git a/Hardware/LA32R.srcs/sources_1/new/imm_extender.v b/Hardware/LA32R.srcs/sources_1/new/imm_extender.v new file mode 100644 index 0000000..e0200e4 --- /dev/null +++ b/Hardware/LA32R.srcs/sources_1/new/imm_extender.v @@ -0,0 +1,76 @@ +`timescale 1ns / 1ps + +/******************************************************************************* +** Company: Nantong University +** Engineer: あやせももこ +** +** Create Date: 2025-06-16 +** Design Name: LA32R Single Cycle CPU +** Module Name: imm_extender +** Project Name: Computer Architecture Course Design +** Target Devices: Any FPGA +** Tool Versions: Vivado 2018.1 +** Description: +** This module handles the sign/zero extension of immediate values found in +** various instruction formats of the LA32R architecture. It generates a 32-bit +** immediate value based on the instruction and the control signal `ext_op`. +** +** Supported Extensions: +** - 12-bit signed immediate (si12) for ADDI.W, LD.W, ST.W +** - 20-bit immediate (si20) for LUI12I.W (zero-extended low) +** - 16-bit signed offset for BEQ, BLT +** - 26-bit signed offset for B +** +** Revision: +** Revision 0.01 - File Created +** Additional Comments: +** - This is a purely combinational logic module. +** +*******************************************************************************/ + +module imm_extender ( + input wire [31:0] instr, // 32位指令输入 (32-bit instruction input) + input wire [2:0] ext_op, // 扩展操作控制信号 (Extension operation control signal) + output reg [31:0] imm_ext // 32位扩展后的立即数输出 (32-bit extended immediate output) +); + + // 定义立即数扩展类型的参数 + // Define parameters for immediate extension types + localparam EXT_SI12 = 3'b001; // 12-bit signed immediate for I-type + localparam EXT_SI16 = 3'b010; // 16-bit signed offset for branches + localparam EXT_UI20 = 3'b011; // 20-bit immediate for LUI + localparam EXT_SI26 = 3'b100; // 26-bit signed offset for jump + + // 提取指令中不同格式的立即数 + // Extract immediate values from different instruction formats + wire [11:0] si12 = instr[21:10]; + wire [15:0] si16 = instr[25:10]; + wire [19:0] si20 = instr[24:5]; + wire [25:0] si26 = {instr[9:0], instr[25:10]}; // B指令的offs[25:16]在[9:0], offs[15:0]在[25:10] + + // 组合逻辑: 根据ext_op选择不同的扩展方式 + // Combinational logic: select extension method based on ext_op + always @(*) begin + case (ext_op) + EXT_SI12: + // 对si12进行符号位扩展 + // Sign-extend si12 + imm_ext = {{20{si12[11]}}, si12}; + EXT_SI16: + // 对si16进行符号位扩展并左移两位 + // Sign-extend si16 and shift left by 2 + imm_ext = {{14{si16[15]}}, si16, 2'b00}; + EXT_UI20: + // 对si20进行高位加载,低12位补0 + // Load si20 to high bits, pad low 12 bits with 0 + imm_ext = {si20, 12'b0}; + EXT_SI26: + // 对si26进行符号位扩展并左移两位 + // Sign-extend si26 and shift left by 2 + imm_ext = {{4{si26[25]}}, si26, 2'b00}; + default: + imm_ext = 32'hxxxxxxxx; // 默认情况,输出不定态 + endcase + end + +endmodule diff --git a/Hardware/LA32R.srcs/sources_1/new/instruction_memory.v b/Hardware/LA32R.srcs/sources_1/new/instruction_memory.v new file mode 100644 index 0000000..5628837 --- /dev/null +++ b/Hardware/LA32R.srcs/sources_1/new/instruction_memory.v @@ -0,0 +1,31 @@ +`timescale 1ns / 1ps + +/******************************************************************************* +** Instruction Memory Module +*******************************************************************************/ + +module instruction_memory ( + input wire [31:0] addr, // 地址输入 (Address input) + output wire [31:0] instr // 指令输出 (Instruction output) +); + // 指令存储器通常是只读的 (Instruction memory is typically read-only) + // 在FPGA中,这会综合成一个ROM + // In an FPGA, this synthesizes into a ROM. + + // 仿真时,使用reg数组和$readmemh加载程序 + // For simulation, use a reg array and $readmemh to load the program. + reg [31:0] mem [0:1023]; // 示例: 1024条指令空间 (Example: 1024 instruction space) + + initial begin + // 从文件中加载指令 + // Load instructions from a file. + // 你需要创建一个名为 "program.hex" 的文件 + // You need to create a file named "program.hex". + $readmemh("../../../../../Software/program.hex", mem); + end + + // 字节地址转换为字地址 + // Convert byte address to word address. + assign instr = mem[addr[11:2]]; + +endmodule \ No newline at end of file diff --git a/Hardware/LA32R.srcs/sources_1/new/pc.v b/Hardware/LA32R.srcs/sources_1/new/pc.v new file mode 100644 index 0000000..79b3032 --- /dev/null +++ b/Hardware/LA32R.srcs/sources_1/new/pc.v @@ -0,0 +1,56 @@ +`timescale 1ns / 1ps + +/******************************************************************************* +** Company: Nantong University +** Engineer: あやせももこ +** +** Create Date: 2025-06-16 +** Design Name: LA32R Single Cycle CPU +** Module Name: pc +** Project Name: Computer Architecture Course Design +** Target Devices: Any FPGA +** Tool Versions: Vivado 2018.1 +** Description: +** This module implements the Program Counter (PC) and its update logic. +** The PC is a 32-bit register that holds the address of the instruction +** to be fetched. It updates on every clock cycle. +** +** Update Logic: +** - If no branch/jump: PC_next = PC_current + 4 +** - If branch/jump taken: PC_next = Branch/Jump Target Address +** +** Revision: +** Revision 0.01 - File Created +** +*******************************************************************************/ + +module pc ( + input wire clk, // 时钟 (Clock) + input wire rst, // 复位 (Reset) + input wire pcsource, // PC下一个地址来源选择 (PC next address source selection) + input wire [31:0] imm_ext, // 来自立即数扩展单元的偏移量 (Offset from immediate extender) + output reg [31:0] pc_out // 当前PC值 (Current PC value) +); + + wire [31:0] pc_plus_4; + wire [31:0] pc_branch; + wire [31:0] pc_next; + + // PC寄存器 + // PC register + always @(posedge clk or posedge rst) begin + if (rst) begin + pc_out <= 32'h00000000; // 复位到0地址 + end else begin + pc_out <= pc_next; + end + end + + // PC更新逻辑 + // PC update logic + assign pc_plus_4 = pc_out + 32'd4; + assign pc_branch = pc_out + imm_ext; // 偏移量已经左移两位 + + assign pc_next = pcsource ? pc_branch : pc_plus_4; + +endmodule diff --git a/Hardware/LA32R.srcs/sources_1/new/register_file.v b/Hardware/LA32R.srcs/sources_1/new/register_file.v new file mode 100644 index 0000000..d876b9d --- /dev/null +++ b/Hardware/LA32R.srcs/sources_1/new/register_file.v @@ -0,0 +1,79 @@ +`timescale 1ns / 1ps + +/******************************************************************************* +** Company: Nantong University +** Engineer: あやせももこ +** +** Create Date: 2025-06-16 +** Design Name: LA32R Single Cycle CPU +** Module Name: register_file +** Project Name: Computer Architecture Course Design +** Target Devices: Any FPGA +** Tool Versions: Vivado 2018.1 +** Description: +** This module implements the 32x32-bit Register File for the LA32R CPU. +** It features two asynchronous read ports and one synchronous write port. +** A defensive design is implemented to ensure R0 is always zero. +** +** Features: +** - 32 general-purpose registers, each 32 bits wide. +** - Asynchronous read: Read ports reflect content immediately. +** - Synchronous write: Write operation occurs on the rising edge of the clock. +** - R0 Hardwired to Zero: Cannot be written to, and reading it always returns 0. +** +** Revision: +** Revision 0.01 - File Created +** Additional Comments: +** - Reset logic is included to initialize all registers to zero, which is good practice for simulation and synthesis. +** +*******************************************************************************/ + +module register_file ( + input wire clk, // 时钟 (Clock) + input wire rst, // 复位 (Reset) + input wire reg_write_en, // 写使能 (Write Enable) + input wire [4:0] read_addr1, // 读地址1 (Read Address 1) + input wire [4:0] read_addr2, // 读地址2 (Read Address 2) + input wire [4:0] write_addr, // 写地址 (Write Address) + input wire [31:0] write_data, // 写数据 (Write Data) + output wire [31:0] read_data1, // 读数据1 (Read Data 1) + output wire [31:0] read_data2 // 读数据2 (Read Data 2) +); + + // 声明32个32位的寄存器阵列 + // Declare an array of 32 registers, each 32 bits wide. + reg [31:0] registers[0:31]; + + integer i; + + // 同步写操作 (时钟上升沿触发) + // Synchronous write operation (triggered on the rising edge of the clock) + always @(posedge clk or posedge rst) begin + if (rst) begin + // 复位时,将所有寄存器清零 + // On reset, clear all registers to zero. + for (i = 0; i < 32; i = i + 1) begin + registers[i] <= 32'b0; + end + end else if (reg_write_en) begin + // 写使能有效时,执行写操作 + // When write enable is active, perform the write operation. + // 防御性设计:确保不写入0号寄存器 + // Defensive design: ensure register R0 is not written to. + if (write_addr != 5'd0) begin + registers[write_addr] <= write_data; + end + end + end + + // 异步读操作1 + // Asynchronous read port 1 + // 防御性设计:确保读取0号寄存器时返回0 + // Defensive design: ensure reading from R0 always returns zero. + assign read_data1 = (read_addr1 == 5'd0) ? 32'b0 : registers[read_addr1]; + + // 异步读操作2 + // Asynchronous read port 2 + assign read_data2 = (read_addr2 == 5'd0) ? 32'b0 : registers[read_addr2]; + +endmodule diff --git a/Hardware/LA32R.xpr b/Hardware/LA32R.xpr new file mode 100644 index 0000000..6e1158e --- /dev/null +++ b/Hardware/LA32R.xpr @@ -0,0 +1,190 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Reference/支持5种类型共计14条指令的单周期LA32R CPU逻辑电路图.png b/Reference/支持5种类型共计14条指令的单周期LA32R CPU逻辑电路图.png new file mode 100644 index 0000000000000000000000000000000000000000..621615215b0ff6e40712474a651545b253b2da69 GIT binary patch literal 101557 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 z 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表2 指令格式说明 + + + + + + + + + + + + +
序号 类型指令6位1位3位7位5位5位5位
31 …262524… 2221 2019…1514…109… 54… 0
11RI20LUI12I.W0001010si20rd
23RADD.W00000000000100000rkrjrd
33RSUB.W00000000000100010rkrjrd
43RSLT00000000000100100rkrjrd
53RSLTU00000000000100101rkrjrd
63RNOR00000000000101000rkrjrd
73RAND00000000000101001rkrjrd
83ROR00000000000101010rkrjrd
92RI12ADDI.W0000001010si12rjrd
102RI12LD. W0010100010si12rjrd
112RI12ST.W0010100110si12rjrd
12I26B010100offs[15:0]offs [25:16]
132RI16BEQ010110offs[15:0]rjrd
142RI16BLT011000offs [15:0]rjrd
+ +

表3 指令功能说明
+ + + +
序号类型指令功能说明
11RI20LU12I.W rd,si20GR[rd] ⟵si20 || 12’b0①GR[rd]的高20位为si20,低12位为0
②符号||表示拼接
23RADD.W rd, rj, rkGR[rd]⟵GR[rj]+GR[rk]加法
33RSUB.W rd, rj, rkGR[rd]⟵GR[rj]-GR[rk]减法
43RSLT rd, rj, rkif (GR[rj]<GR[rk]) GR[rd]⟵1 else GR[rd]⟵0带符号数的大小比较
53RSLTU rd, rj, rkif (GR[rj]<GR[rk]) GR[rd]⟵1 else GR[rd]⟵0无符号数的大小比较
63RNOR rd, rj, rkGR[rd]⟵(GR[rj]∨GR[rk]) ̅或非
73RAND rd, rj, rkGR[rd]⟵GR[rj] ∧ GR[rk]
83ROR rd, rj, rkGR[rd]⟵GR[rj] ∨ GR[rk]
92RI12ADDI.W rd, rj, si12GR[rd]⟵GR[rj]+ SignExtend(si12)①立即数加法
②si12是12位立即数,进行符号位扩展后与GR[rj]相加
102RI12LD.W rd ,rj,si12Addr⟵GR[rj] + SignExtend (si12) ,GR[rd] ⟵M[Addr]①将内存Addr单元的值取出后存入R[rd]
②si12是12位立即数,进行符号位扩展后与GR[rj]相加后得到内存单元的地址Addr
112RI12ST.W rd, rj, si12Addr⟵GR[rj] + SignExtend (si12) , M[Addr]⟵GR[rd]①把GR[rd]的值存入内存Addr单元
②内存单元的地址Addr的计算方法与LD.W指令相同
12I26B offs26PC⟵PC+ SignExtend (offs26||2’b0)无条件跳转到目标地址
132RI16BEQ rj, rd, offs16if (GR[rj]=GR[rd])
PC⟵PC+ SignExtend (offs16||2’b0)
①符号||表示拼接
②GR[rj]=GR[rd]时,跳转到目标地址
142RI16BLT rj, rd, offs16if (signed(GR[rj])<signed(GR[rd]))
PC⟵PC+ SignExtend (offs16||2’b0)
①符号||表示拼接
②GR[rj]与GR[rd]视作带符号数
③GR[rj]<GR[rd]时,跳转到目标地址
+ +参考逻辑电路图如下。设计方案没有唯一答案,下图所示电路仅供参考。 + +![LA32R参考逻辑电路图](./支持5种类型共计14条指令的单周期LA32R%20CPU逻辑电路图.png) + +
图1 支持5种类型共计14条指令的单周期LA32R CPU逻辑电路图
+ +## 六、课程设计步骤 + +1. 对指令格式和功能进行分析,绘制不同类型指令的数据通路; +2. 分析各类型指令执行阶段控制信号,绘制控制信号取值分析表; +3. 设计总框图,进行各逻辑部件之间的互相连接,完成模型机顶层模块的设计,使得由指令系统所要求的数据通路都能实现; +4. 编写机器语言应用程序(测试程序),存入模型机指令存储器; +5. 编写模型机顶层模块的仿真激励文件; +6. 运行仿真,分析仿真结果,撰写设计报告。 diff --git a/Software/assembler.py b/Software/assembler.py new file mode 100644 index 0000000..39b8731 --- /dev/null +++ b/Software/assembler.py @@ -0,0 +1,130 @@ +# -*- coding: utf-8 -*- +import re + +""" +LA32R Simple Assembler +- Converts a simplified assembly language into 32-bit hexadecimal machine code. +- Supports all 14 instructions required by the course design. +- Handles register names like '$r4', '$r12' and immediate values. +- Outputs a 'program.hex' file suitable for Verilog's $readmemh. +""" + +# 指令编码定义 +# Instruction encoding definitions +OPCODES = { + 'add.w': '000000', 'sub.w': '000000', 'slt': '000000', 'sltu': '000000', + 'nor': '000000', 'and': '000000', 'or': '000000', + 'addi.w': '000010', 'lu12i.w': '000101', 'ld.w': '001010', 'st.w': '001010', + 'b': '010100', 'beq': '010110', 'blt': '011000' +} + +FUNC_3R = { + # 'opcode': ('func2', 'func5') + 'add.w': ('01', '00000'), 'sub.w': ('01', '00010'), 'slt': ('01', '00100'), + 'sltu': ('01', '00101'), 'nor': ('01', '01000'), 'and': ('01', '01001'), + 'or': ('01', '01010') +} + +FUNC_2RI12 = { + # 'opcode': 'func4' + 'addi.w': '1010', + 'ld.w': '0010', + 'st.w': '0110' +} + + +def to_binary(value, bits): + """Converts an integer to a two's complement binary string of specified length.""" + if value >= 0: + return format(value, 'b').zfill(bits) + else: + return format((1 << bits) + value, 'b') + + +def parse_register(reg_str): + """Parses register string '$rX' to a 5-bit binary string.""" + return to_binary(int(reg_str.strip('$r')), 5) + + +def assemble_line(line): + """Assembles a single line of assembly code into a 32-bit binary string.""" + line = line.lower().strip() + parts = re.split(r'[\s,]+', line) + op = parts[0] + + if op in FUNC_3R: # 3R-type: add.w $r3, $r1, $r2 + rd, rj, rk = parse_register(parts[1]), parse_register(parts[2]), parse_register(parts[3]) + opcode = OPCODES[op] + func2, func5 = FUNC_3R[op] + return f"{opcode}0000{func2}{func5}{rk}{rj}{rd}" + + elif op in ['addi.w', 'ld.w', 'st.w']: # 2RI12-type + rd = parse_register(parts[1]) + rj = parse_register(parts[2]) + # FIX: Use int(str, 0) to auto-detect base (e.g., '0x' for hex) + imm = to_binary(int(parts[3], 0), 12) + opcode = OPCODES[op] + func4 = FUNC_2RI12[op] + return f"{opcode}{func4}{imm}{rj}{rd}" + + elif op == 'lu12i.w': # 1RI20-type: lu12i.w $r1, 0x12345 + rd = parse_register(parts[1]) + imm = to_binary(int(parts[2], 0), 20) # Support hex (0x) and dec + opcode = OPCODES[op] + return f"{opcode}0{imm}{rd}" + + elif op in ['beq', 'blt']: # 2RI16-type: beq $r1, $r2, -4 + rj = parse_register(parts[1]) + rd = parse_register(parts[2]) + # FIX: Use int(str, 0) to auto-detect base + offset = int(parts[3], 0) >> 2 # Offset is in bytes, convert to word offset for encoding + imm = to_binary(offset, 16) + opcode = OPCODES[op] + return f"{opcode}{imm}{rj}{rd}" + + elif op == 'b': # I26-type: b -8 + # FIX: Use int(str, 0) to auto-detect base + offset = int(parts[1], 0) >> 2 # Convert to word offset + imm = to_binary(offset, 26) + offs_25_16 = imm[0:10] + offs_15_0 = imm[10:26] + opcode = OPCODES[op] + return f"{opcode}{offs_15_0}{offs_25_16}" + + else: + raise ValueError(f"Unknown instruction: {op}") + + +def main(): + """Main function to read assembly file and write hex file.""" + # 使用这个测试程序来验证CPU的功能 + # Use this test program to verify CPU functionality + assembly_code = open("../program.asm", "r").read() + + output_filename = "program.hex" + with open(output_filename, "w") as f: + print(f"Assembling code into {output_filename}...") + for line in assembly_code.split('\n'): + line = line.strip() + # 忽略注释和空行 + # Ignore comments and empty lines + if not line or line.startswith('//'): + continue + + try: + # 移除行内注释 + # Remove inline comments + line = line.split('//')[0].strip() + binary_code = assemble_line(line) + hex_code = f"{int(binary_code, 2):08x}" + f.write(hex_code + '\n') + print(f" {line:<30} -> {hex_code}") + except Exception as e: + print(f"Error assembling line: '{line}'") + print(f" > {e}") + return + print("Assembly finished successfully.") + + +if __name__ == "__main__": + main() diff --git a/Software/program.hex b/Software/program.hex new file mode 100644 index 0000000..eece3ec --- /dev/null +++ b/Software/program.hex @@ -0,0 +1,21 @@ +14246004 +0a915884 +15110005 +0abffca5 +00101486 +00111487 +00121488 +00129489 +0014948a +0015148b +00142d4c +0a819001 +29800024 +29801025 +2880002d +2880102e +580009a4 +0a80040f +600008e6 +0a800410 +53ffffff diff --git a/program.asm b/program.asm new file mode 100644 index 0000000..4996901 --- /dev/null +++ b/program.asm @@ -0,0 +1,35 @@ +// 1. 寄存器加载测试 (Register Loading Test) +lu12i.w $r4, 0x12300 // r4 = 0x12300000 +addi.w $r4, $r4, 0x456 // r4 = 0x12300456 +lu12i.w $r5, 0x88800 // r5 = 0x88800000 (negative high part) +addi.w $r5, $r5, -1 // r5 = 0x887FFFFF + +// 2. 算术/逻辑运算测试 (Arithmetic/Logic Test) +add.w $r6, $r4, $r5 // r6 = 0x12300456 + 0x887FFFFF = 0x9AB00455 +sub.w $r7, $r4, $r5 // r7 = 0x12300456 - 0x887FFFFF = 0x89B00457 +slt $r8, $r4, $r5 // r4 > r5 (signed), r8 = 0 +sltu $r9, $r4, $r5 // r4 < r5 (unsigned), r9 = 1 +and $r10, $r4, $r5 // r10 = 0x12300456 & 0x887FFFFF = 0x00300456 +or $r11, $r4, $r5 // r11 = 0x12300456 | 0x887FFFFF = 0x9A7FFFFF +nor $r12, $r10, $r11 // r12 = ~(r10 | r11) = ~0x9A7FFFFF = 0x65800000 + +// 3. 内存访问测试 (Memory Access Test) +addi.w $r1, $r0, 100 // r1 = 100 (Address base) +st.w $r4, $r1, 0 // M[100] = r4 (0x12300456) +st.w $r5, $r1, 4 // M[104] = r5 (0x887FFFFF) +ld.w $r13, $r1, 0 // r13 = M[100] +ld.w $r14, $r1, 4 // r14 = M[104] + +// 4. 分支指令测试 (Branching Test) +// BEQ: r13 == r4 is true, should jump +beq $r13, $r4, 8 // Branch to 'skip' label (PC+8) +addi.w $r15, $r0, 1 // This should NOT be executed +// 'skip:' label is here +// BLT: r7 is negative, r6 is positive, r7 < r6 is true, should jump +blt $r7, $r6, 8 // Branch to 'end' label (PC+8) +addi.w $r16, $r0, 1 // This should NOT be executed + +// 'end:' label is here +// 5. 无条件跳转: 创建一个无限循环来结束程序 +// Unconditional Jump: Create an infinite loop to end the program +b -4 // Infinite loop: jump to itself \ No newline at end of file diff --git a/run.bat b/run.bat new file mode 100644 index 0000000..fbbb91a --- /dev/null +++ b/run.bat @@ -0,0 +1,108 @@ +@echo off +:: 设置窗口标题 +TITLE LA32R CPU Simulation Automation + +:: ============================================================================ +:: LA32R 单周期 CPU 自动化仿真脚本 (适配Vivado项目结构) +:: +:: 功能: +:: 1. 定义项目文件路径。 +:: 2. 在正确的仿真目录下清理、执行所有步骤。 +:: 3. 运行 Python 汇编器生成 program.hex (已修正工作目录)。 +:: 4. 编译、链接并运行仿真 (已修正脚本提前退出的问题)。 +:: +:: 使用方法: +:: - 将此脚本放在项目的根目录下。 +:: - 确保 Vivado 的 bin 目录已添加到系统的 PATH 环境变量中。 +:: - 直接双击运行此脚本。 +:: ============================================================================ + +:: --- 步骤 0: 定义项目路径 --- +:: %~dp0 会获取脚本所在的目录,作为我们的项目根目录 +set "PROJECT_ROOT=%~dp0" +set "SOFTWARE_DIR=%PROJECT_ROOT%Software" +set "DESIGN_SRC_DIR=%PROJECT_ROOT%Hardware\LA32R.srcs\sources_1\new" +set "SIM_SRC_DIR=%PROJECT_ROOT%Hardware\LA32R.srcs\sim_1\new" +set "SIM_RUN_DIR=%PROJECT_ROOT%Hardware\LA32R.sim\sim_1\behav\xsim" + +echo Project Root: %PROJECT_ROOT% +echo Simulation Run Directory: %SIM_RUN_DIR% +echo. + +:: --- 准备工作:切换到仿真运行目录 --- +:: 创建目录(如果不存在)并进入 +if not exist "%SIM_RUN_DIR%" ( mkdir "%SIM_RUN_DIR%" ) +cd /d "%SIM_RUN_DIR%" + +:: --- 步骤 1: 清理环境 --- +echo [STEP 1] Cleaning up previous simulation files... +if exist xsim.dir ( rd /s /q xsim.dir ) +if exist *.log ( del *.log ) +if exist *.jou ( del *.jou ) +if exist verilog_files.f ( del verilog_files.f ) +if exist webtalk*.xml ( del webtalk*.xml ) +if exist webtalk*.tcl ( del webtalk*.tcl ) +echo. + +:: --- 步骤 2: 运行Python汇编器 --- +echo [STEP 2] Assembling test program... +:: [FIX] 使用 pushd/popd 临时切换目录以保证python脚本的工作目录正确 +pushd "%SOFTWARE_DIR%" +python assembler.py +popd + +:: 检查 program.hex 是否成功生成 +if not exist "%SOFTWARE_DIR%\program.hex" ( + echo [ERROR] Failed to generate program.hex. Halting script. + goto end +) +:: [FIX] 移除文件复制步骤,因为Verilog已配置为使用相对路径 +echo Assembly complete. Verilog will read program.hex from its relative path. +echo. + +:: --- 步骤 3: 创建文件列表并编译Verilog --- +echo [STEP 3] Creating file list and compiling Verilog sources... +:: 创建一个文件列表,包含所有设计和仿真源文件的绝对路径 +( + echo "%DESIGN_SRC_DIR%\data_memory.v" + echo "%DESIGN_SRC_DIR%\instruction_memory.v" + echo "%DESIGN_SRC_DIR%\alu.v" + echo "%DESIGN_SRC_DIR%\pc.v" + echo "%DESIGN_SRC_DIR%\imm_extender.v" + echo "%DESIGN_SRC_DIR%\register_file.v" + echo "%DESIGN_SRC_DIR%\control_unit.v" + echo "%DESIGN_SRC_DIR%\cpu_top.v" + echo "%SIM_SRC_DIR%\cpu_tb.v" +) > verilog_files.f + +:: [FIX] 添加 'call' 命令确保执行后控制权返回脚本 +call xvlog -sv --work xil_defaultlib -f verilog_files.f +if %errorlevel% neq 0 ( + echo [ERROR] Verilog compilation failed. Check xvlog.log for details. + goto end +) +echo Verilog compilation successful. +echo. + +:: --- 步骤 4: 链接和构建仿真快照 --- +echo [STEP 4] Elaborating the design with xelab... +:: [FIX] 添加 'call' 命令 +call xelab --debug typical --snapshot cpu_tb_snapshot xil_defaultlib.cpu_tb -log elaborate.log +if %errorlevel% neq 0 ( + echo [ERROR] Design elaboration failed. Check elaborate.log for details. + goto end +) +echo Design elaboration successful. +echo. + +:: --- 步骤 5: 运行仿真 --- +echo [STEP 5] Running simulation with xsim... +echo ======================= SIMULATION OUTPUT START ======================= +:: [FIX] 添加 'call' 命令 +call xsim cpu_tb_snapshot --runall --log ..\..\..\..\..\simulation.log +echo ======================== SIMULATION OUTPUT END ======================== +echo. + +:end +echo Script finished. Press any key to exit. +pause > nul