├── .gitignore ├── .vscode ├── c_cpp_properties.json └── settings.json ├── LICENSE ├── README.md ├── README_zh.md ├── addlic.py ├── digital_soc ├── digital │ ├── digital_soc.dig │ ├── digital_soc1.dig │ ├── digital_soc2.dig │ ├── digital_soc3.dig │ └── tt.dig ├── src │ ├── Makefile │ ├── boot.ld │ ├── boot.s │ ├── bsp │ │ ├── common │ │ │ ├── addr.h │ │ │ ├── common.c │ │ │ ├── common.h │ │ │ └── types.h │ │ ├── gpio │ │ │ ├── gpio.c │ │ │ └── gpio.h │ │ ├── iic │ │ │ ├── iic.c │ │ │ └── iic.h │ │ ├── interrupt │ │ │ ├── interrupt.c │ │ │ └── interrupt.h │ │ ├── timer │ │ │ ├── timer.c │ │ │ └── timer.h │ │ └── uart │ │ │ ├── uart.c │ │ │ └── uart.h │ ├── kernel.ld │ ├── main.c │ ├── mkhex.py │ └── start.s └── verilog │ ├── digital_soc_top.v │ ├── dynsrc │ ├── Makefile │ ├── Makefile.trace │ ├── test.c │ ├── wrapper.cpp │ ├── wrapper.dll │ └── wrapper_sync.cpp │ ├── file_list.f │ ├── iverilog.bat │ ├── vboard_plugin │ ├── Makefile │ ├── Makefile_trace.mk │ ├── plugin.cpp │ └── plugin.dll │ ├── vboard_soc_top.v │ └── vboard_top.f ├── doc ├── draw │ ├── construct.drawio │ └── construct.svg ├── image │ ├── arch.png │ ├── boot-firstaddr.png │ ├── data-bus.png │ ├── exception-int.png │ ├── execution.png │ ├── gpio.png │ ├── instruction-decoder.png │ ├── instuction-addr-selector.png │ ├── jmp-priority.png │ ├── load-kernel.png │ ├── modules.png │ ├── output.gif │ ├── pc-ir.png │ ├── peripheral.png │ ├── storage.png │ ├── uart-controller.png │ ├── uart-term.png │ ├── uart-ttl-recv1.png │ ├── uart-ttl-recv2.png │ ├── uart-ttl-send.png │ ├── uart.gif │ └── uart.png ├── netlist.md ├── netlist_zh.md └── uart_zh.md ├── fpga_soc └── TODO ├── netlist ├── digital │ ├── 32-bit-register.dig │ ├── 3bit-decoder.dig │ ├── 4-status-mechine.dig │ ├── CUPL_risc-v-computer │ │ └── CUPL.PLD │ ├── PLIC.dig │ ├── addr-compare.dig │ ├── alu.dig │ ├── base.dig │ ├── boot-rom.dig │ ├── csr-addr-spliter.dig │ ├── csr.dig │ ├── cust_ctrl.dig │ ├── gpio.dig │ ├── i2c-controller.dig │ ├── i2c-master-readdata.dig │ ├── i2c-master-senddata.dig │ ├── i2c-master-startandaddr.dig │ ├── i2c-master.dig │ ├── i2c-random.dig │ ├── i2c-slave.dig │ ├── inst-decoder-verilog.dig │ ├── instruction-decoder.dig │ ├── instuction-jump-unit.dig │ ├── int-bus.dig │ ├── int-except-unit.dig │ ├── led_waiter_ctrl.dig │ ├── mechine-op-unit.dig │ ├── memory-operation-unit.dig │ ├── memory.dig │ ├── program-counter.dig │ ├── risc-v-computer.dig │ ├── risc-v-mcu.dig │ ├── risc-v-registers.dig │ ├── test_op.dig │ ├── uart-term.dig │ ├── uart-ttl.dig │ ├── uart.dig │ └── zero-register.dig └── src │ ├── Makefile │ ├── boot.ld │ ├── boot.s │ ├── bsp │ ├── common │ │ ├── common.c │ │ ├── common.h │ │ └── types.h │ ├── gpio │ │ ├── gpio.c │ │ └── gpio.h │ ├── iic │ │ ├── iic.c │ │ └── iic.h │ ├── interrupt │ │ ├── interrupt.c │ │ └── interrupt.h │ ├── timer │ │ ├── timer.c │ │ └── timer.h │ └── uart │ │ ├── uart.c │ │ └── uart.h │ ├── examples │ ├── guess.c │ └── guess.h │ ├── kernel.ld │ ├── main.c │ ├── memory-map.txt │ ├── mkhex.py │ ├── start.s │ └── test.s └── verilog ├── breath_led.v ├── common └── fifo_async.v ├── core ├── cache.v ├── config.v ├── cpu_pipeline.v ├── cpu_top.v ├── ex_alu.v ├── ex_branch.v ├── ex_csr.v ├── ex_mem.v ├── inst_decoder.v ├── inst_fetch.v ├── mem_controller.v ├── registers.v ├── registers_csr.v └── sys_bus.v ├── instruction_decoder.v ├── led_water_ctrl.v ├── make.bat ├── peripherals ├── digital │ ├── digital_flash.v │ └── digital_ram.v ├── gpio_controller.v ├── hl_adapter.v ├── iic │ ├── iic_master.v │ ├── iic_scl.v │ ├── iic_slave.v │ └── iic_top.v ├── peripherals_bus.v ├── spi │ └── spi_master.v └── uart │ ├── uart_clk_div.v │ ├── uart_rx.v │ ├── uart_top.v │ └── uart_tx.v ├── soc ├── digital_soc.v └── vboard_soc.v └── testbench ├── cache_tb.v ├── cpu_tb.v ├── digital_soc_tb.v ├── iic_tb.v ├── instdecoder-tb.v ├── state_tb.v ├── t.v ├── tt_tb.v ├── uart_div_tb.v └── uart_top_tb.v /.gitignore: -------------------------------------------------------------------------------- 1 | # Build and Release Folders 2 | bin-debug/ 3 | bin-release/ 4 | [Oo]bj/ 5 | [Bb]in/ 6 | 7 | # Other files and folders 8 | .settings/ 9 | 10 | # Executables 11 | *.swf 12 | *.air 13 | *.ipa 14 | *.apk 15 | 16 | *.o 17 | *.bin 18 | *.bin.* 19 | *.elf 20 | *.elf.* 21 | *.hex 22 | objs/ 23 | *.vcd 24 | *.vvp 25 | *.out 26 | obj_dir/ 27 | *.exe 28 | # Project files, i.e. `.project`, `.actionScriptProperties` and `.flexProperties` 29 | # should NOT be excluded as they contain compiler settings and other important 30 | # information for Eclipse / Flash Builder. 31 | -------------------------------------------------------------------------------- /.vscode/c_cpp_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "Win64", 5 | "includePath": [ 6 | "${workspaceFolder}/**", 7 | "d:/soft/msys64/mingw64/include/**", 8 | "d:/soft/verilator/include/**", 9 | "${workspaceFolder}/digital_soc/src/bsp/**", 10 | "${workspaceFolder}/digital_soc/verilog/obj_dir/**" 11 | ], 12 | "defines": [ 13 | "_DEBUG", 14 | "UNICODE", 15 | "_UNICODE" 16 | ], 17 | "windowsSdkVersion": "10.0.18362.0", 18 | "cStandard": "c17", 19 | "cppStandard": "c++17", 20 | "intelliSenseMode": "linux-gcc-x64", 21 | "compilerPath": "D:/soft/msys64/mingw64/bin/gcc.exe" 22 | } 23 | ], 24 | "version": 4 25 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "*.ejs": "html", 4 | "*.h": "c", 5 | "*.v": "verilog", 6 | "*.s": "assembly", 7 | "typeinfo": "c", 8 | "compare": "c", 9 | "array": "cpp", 10 | "atomic": "cpp", 11 | "bit": "cpp", 12 | "*.tcc": "cpp", 13 | "bitset": "cpp", 14 | "cctype": "cpp", 15 | "cinttypes": "cpp", 16 | "clocale": "cpp", 17 | "cmath": "cpp", 18 | "concepts": "cpp", 19 | "condition_variable": "cpp", 20 | "cstdarg": "cpp", 21 | "cstddef": "cpp", 22 | "cstdint": "cpp", 23 | "cstdio": "cpp", 24 | "cstdlib": "cpp", 25 | "cstring": "cpp", 26 | "ctime": "cpp", 27 | "cwchar": "cpp", 28 | "cwctype": "cpp", 29 | "deque": "cpp", 30 | "map": "cpp", 31 | "set": "cpp", 32 | "string": "cpp", 33 | "unordered_map": "cpp", 34 | "unordered_set": "cpp", 35 | "vector": "cpp", 36 | "exception": "cpp", 37 | "algorithm": "cpp", 38 | "functional": "cpp", 39 | "iterator": "cpp", 40 | "memory": "cpp", 41 | "memory_resource": "cpp", 42 | "numeric": "cpp", 43 | "random": "cpp", 44 | "ratio": "cpp", 45 | "string_view": "cpp", 46 | "system_error": "cpp", 47 | "tuple": "cpp", 48 | "type_traits": "cpp", 49 | "utility": "cpp", 50 | "initializer_list": "cpp", 51 | "iosfwd": "cpp", 52 | "iostream": "cpp", 53 | "istream": "cpp", 54 | "limits": "cpp", 55 | "mutex": "cpp", 56 | "new": "cpp", 57 | "numbers": "cpp", 58 | "ostream": "cpp", 59 | "semaphore": "cpp", 60 | "stdexcept": "cpp", 61 | "stop_token": "cpp", 62 | "streambuf": "cpp", 63 | "thread": "cpp", 64 | "coroutine": "cpp", 65 | "list": "cpp", 66 | "fstream": "cpp", 67 | "sstream": "cpp" 68 | }, 69 | "verilog.linting.linter": "iverilog", 70 | "verilog.linting.iverilog.includePath": ["verilog","verilog/core","verilog/soc"], 71 | "verilog.linting.iverilog.arguments": "-yverilog -yverilog/peripherals/digital -yverilog/peripherals/uart -yverilog/peripherals/iic -yverilog/peripherals/spi -yverilog/common -yverilog/core -yverilog/soc -yverilog/peripherals", 72 | "verilog.linting.iverilog.runAtFileLocation": false 73 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # riscv-mcu 2 | [中文](README_zh.md) 3 | 4 | ## Directory Introduction 5 | 6 | 1. **netlist**: there are CPU designs based on the digital software, created through wiring methods, along with the corresponding boot and test codes. This part is finalized and will no longer be updated. For specific introductions, see: [riscv-digital](doc/netlist.md). 7 | 2. **verilog**: there is RISC-V CPU code developed in Verilog, which is continuously being updated. 8 | 3. **digital_soc**: there is a SoC built with CPU modules written in Verilog using the digital software, which can be run through digital simulation. 9 | 3. **fpga_soc**: there is a SoC constructed with RISC-V CPU modules based on FPGA. This has not yet started, with the goal being to run the CPU IP implemented in Verilog on an FPGA development board. 10 | 11 | #### digital_soc Introduction 12 | 13 | **1. Generating Bootloader and Test Program Hex Files** 14 | 15 | The bootloader and test program code are located in the digital_soc/src directory. To generate the hex files for the bootloader and test program, execute the following commands within that directory: 16 | 17 | ```shell 18 | make; python3 ./mkhex.py 19 | ``` 20 | 21 | **2. Verilog Simulation** 22 | For Verilog simulation, follow these steps: 23 | * Navigate to the verilog directory. 24 | * Execute the following command to build the simulation: 25 | 26 | ```shell 27 | ./make.bat digital_soc 28 | ``` 29 | * After the build is complete, run the simulation waveform viewer using: 30 | ``` shell 31 | gtkwave.exe ./digital_soc.vcd 32 | ``` 33 | This will allow you to view the simulation waveforms generated by the Verilog simulation. 34 | 35 | **3. Digital Simulation** 36 | 37 | To perform digital simulation, follow these steps: 38 | 39 | * Open the Digital software. 40 | * Load the digital_soc/digital/digital_soc.dig file. 41 | * Before running the simulation, you need to configure the riscvmcu component: 42 | * Right-click on the riscvmcu component. 43 | * In the context menu, select the Options tab. 44 | * Locate the iverilog option. 45 | * Modify the dependency path to match the corresponding path on your local machine. 46 | * Save the changes and close the configuration window. 47 | * Run the simulation. -------------------------------------------------------------------------------- /README_zh.md: -------------------------------------------------------------------------------- 1 | # riscv-mcu 2 | 3 | ## 介绍 4 | 5 | B站讲解视频(持续更新中): [讲解合集](https://space.bilibili.com/505193782/channel/collectiondetail?sid=3829887) 6 | 7 | 目录结构进行了整理: 8 | 1. netlist 目录下,存放基于digital软件,通过连线方式设计的CPU,以及对应的启动和测试代码。这部分版本定型,不再更新。具体的介绍参见:[riscv-digital](doc/netlist_zh.md)。 9 | 2. verilog 目录下, 存放基于verilog开发的riscv cpu代码,持续更新中。 10 | 3. digital_soc 目录下, 存放基于digital软件使用verilog编写的cpu模块搭建的SoC,可以通过digital模拟方式运行。 11 | 4. fpga_soc 目录下, 存放基于fpga的riscv cpu模块搭建的SoC,暂未开始,目标是在fpga开发板上运行verilog实现的cpu ip并进行外设驱动运行。 12 | 13 | ## netlist 使用说明 14 | 15 | 1. 基于digital软件的仿真模拟,参考 [riscv-digital](doc/netlist_zh.md)。 16 | 2. B站视频中cpu流水线相关的测试,如果需要运行,请git获取tag v1.0.3版本,因后续对pipeline模块进行了修改,原先的testbench无法执行,获取tag命令如下: 17 | ```shell 18 | git checkout tags/v1.0.3 19 | ``` 20 | 21 | ## digital_soc使用说明 22 | 23 | **1. 编译引导测试程序** 24 | 25 | 引导和测试程序代码在 digital_soc/src 目录下,在目录下执行: 26 | ```shell 27 | make; python3 ./mkhex.py 28 | ``` 29 | 生成的boot.hex为引导程序字节码在digital仿真中使用,test.hex在verilog仿真中使用。 30 | 31 | 32 | **2. verilog仿真** 33 | 34 | 在 verilog 目录下,执行如下命令进行综合仿真 35 | ```shell 36 | ./make.bat digital_soc 37 | ``` 38 | 然后执行如下命令查看波形 39 | ```shell 40 | gtkwave.exe ./digital_soc.vcd 41 | ``` 42 | 43 | 44 | **3. digital仿真** 45 | 46 | * 在digital软件中,打开 digital_soc/digital/digital_soc.dig文件。 47 | * 执行前,需要在 riscvmcu 组件上点击右键,然后在选项卡 中的 iverilog选项中,将依赖路径修改为本机对应的路径,然后保存关闭后运行。 48 | 49 | 50 | **4. 开发环境安装** 51 | 52 | 1. iverilog 安装: 53 | >windows下安装,[下载连接](http://bleyer.org/icarus/) 54 | linux 下安装,[参考地址](https://steveicarus.github.io/iverilog/usage/installation.html) 55 | 56 | 2. digital软件安装: [下载链接](https://github.com/hneemann/Digital) 57 | 58 | 3. riscv编译工具链安装: 59 | >地址:[riscv-gnu-toolchain](https://gitee.com/riscv-mcu/riscv-gnu-toolchain) 60 | 61 | ``` 62 | sudo apt-get install autoconf automake autotools-dev curl python3 libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev ninja-build 63 | ./configure --prefix=/opt/riscv --with-arch=rv32gc --with-abi=ilp32d 64 | make linux 65 | ``` 66 | 67 | 4. FPGA开发工具Quartus安装:[下载链接](https://www.intel.com/content/www/us/en/software-kit/825278/intel-quartus-prime-lite-edition-design-software-version-23-1-1-for-windows.html) -------------------------------------------------------------------------------- /addlic.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | def add_license_to_file(file_path, license_text, check_text): 4 | """向文件开头添加 license 信息""" 5 | with open(file_path, 'r+', encoding='utf-8') as file: 6 | content = file.read() 7 | if check_text in content: 8 | print(f"License already present in {file_path}, skipping.") 9 | return False # 跳过已经存在的文件 10 | file.seek(0) 11 | file.write(license_text + '\n' + content) 12 | print(f"Added license to {file_path}") 13 | return True 14 | 15 | def process_directory(directory, extensions, license_text, check_text): 16 | """ 17 | 遍历目录中的指定后缀文件,添加 license 信息 18 | :param directory: 要遍历的目录路径 19 | :param extensions: 指定的文件后缀,例如 ['.py', '.java'] 20 | :param license_text: 要添加的 license 信息 21 | :param check_text: 用于判断 license 是否存在的关键字 22 | """ 23 | for root, _, files in os.walk(directory): 24 | for file in files: 25 | if any(file.endswith(ext) for ext in extensions): 26 | file_path = os.path.join(root, file) 27 | add_license_to_file(file_path, license_text, check_text) 28 | 29 | if __name__ == '__main__': 30 | # 配置项 31 | directory_to_scan = './' # 项目根目录 32 | file_extensions = ['.v', '.c', '.h', '.s'] # 需要处理的文件后缀 33 | license_text = """/* 34 | Designer : Renyangang 35 | 36 | Licensed under the Apache License, Version 2.0 (the "License"); 37 | you may not use this file except in compliance with the License. 38 | You may obtain a copy of the License at 39 | 40 | http://www.apache.org/licenses/LICENSE-2.0 41 | 42 | Unless required by applicable law or agreed to in writing, software 43 | distributed under the License is distributed on an "AS IS" BASIS, 44 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 45 | See the License for the specific language governing permissions and 46 | limitations under the License. 47 | */""" 48 | check_text = "Designer : Renyangang" # 判断是否已包含的关键文本 49 | 50 | # 执行处理 51 | process_directory(directory_to_scan, file_extensions, license_text, check_text) 52 | -------------------------------------------------------------------------------- /digital_soc/src/Makefile: -------------------------------------------------------------------------------- 1 | LD := riscv32-unknown-linux-gnu-ld 2 | AS := riscv32-unknown-linux-gnu-as 3 | CC := riscv32-unknown-linux-gnu-gcc 4 | OBJCOPY := riscv32-unknown-linux-gnu-objcopy 5 | OBJDUMP := riscv32-unknown-linux-gnu-objdump 6 | 7 | OBJDIR := ./objs 8 | 9 | INCDIRS := examples \ 10 | bsp/common \ 11 | bsp/gpio \ 12 | bsp/interrupt \ 13 | bsp/uart \ 14 | bsp/iic \ 15 | bsp/timer 16 | 17 | SRCDIRS := . \ 18 | examples \ 19 | bsp/common \ 20 | bsp/gpio \ 21 | bsp/interrupt \ 22 | bsp/uart \ 23 | bsp/iic \ 24 | bsp/timer 25 | 26 | 27 | INCLUDE := $(patsubst %, -I %, $(INCDIRS)) 28 | 29 | SFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.S)) 30 | CFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.c)) 31 | 32 | SFILENDIR := $(notdir $(SFILES)) 33 | CFILENDIR := $(notdir $(CFILES)) 34 | 35 | SOBJS := $(patsubst %, $(OBJDIR)/%, $(SFILENDIR:.S=.o)) 36 | COBJS := $(patsubst %, $(OBJDIR)/%, $(CFILENDIR:.c=.o)) 37 | OBJS := $(SOBJS) $(COBJS) 38 | 39 | VPATH := $(SRCDIRS) 40 | 41 | all: boot.bin kernel.bin 42 | 43 | %.bin: $(OBJDIR)/%.elf 44 | $(OBJCOPY) -O binary -S $^ $@ 45 | 46 | $(OBJDIR)/boot.elf: $(OBJDIR)/boot.o 47 | $(LD) -T boot.ld -o $@ $^ 48 | $(OBJDUMP) -D $@ > $@.asm 49 | 50 | $(OBJDIR)/kernel.elf: $(OBJDIR)/start.o $(COBJS) 51 | $(LD) -T kernel.ld -o $@ $^ 52 | $(OBJDUMP) -D $@ > $@.asm 53 | 54 | $(OBJDIR)/%.o: %.s 55 | mkdir -p $(OBJDIR) 56 | $(AS) -march=rv32i -mabi=ilp32 $(INCLUDE) -o $@ $^ 57 | 58 | $(COBJS) : $(OBJDIR)/%.o: %.c 59 | mkdir -p $(OBJDIR) 60 | $(CC) -march=rv32i -mabi=ilp32 -Wall -nostdlib -fno-builtin-memset $(INCLUDE) -c -O2 -o $@ $< 61 | 62 | .PHONY: clean 63 | clean: 64 | rm -rf *.bin* *.o *.elf* *.hex objs -------------------------------------------------------------------------------- /digital_soc/src/boot.ld: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | /* boot rom */ 4 | FLASH (rwx) : ORIGIN = 0x00000000, LENGTH = 5120K 5 | /* gpio and so on */ 6 | PERIPHERAL(rwx): ORIGIN = 0xA0000000, LENGTH = 128K 7 | RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 128K 8 | } 9 | 10 | ENTRY(_start) 11 | 12 | SECTIONS 13 | { 14 | . = ALIGN(4); 15 | .text 0x00000000: { 16 | *(.text) 17 | _etext = .; 18 | } > FLASH 19 | } 20 | -------------------------------------------------------------------------------- /digital_soc/src/boot.s: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | .section .text 17 | .global _start 18 | _start: 19 | li t0, 0x7 20 | li t1, 0xC0000000 21 | sw t0, 0(t1) 22 | li t0, 0x7 23 | sw t0, 4(t1) 24 | li a1, 1 25 | li a2, 2 26 | li a3, 3 27 | li a4, 4 28 | li a5, 5 29 | li a6, 6 30 | li a7, 7 31 | li s0, 8 32 | li s1, 9 33 | li s2, 10 34 | li s3, 11 35 | li s4, 12 36 | li s5, 13 37 | li s6, 14 38 | li s7, 15 39 | li t2, 16 40 | li t3, 17 41 | loop: 42 | nop 43 | j loop 44 | 45 | d0: 46 | .rept 10 47 | .long 0x1 48 | .endr 49 | 50 | .end 51 | -------------------------------------------------------------------------------- /digital_soc/src/bsp/common/addr.h: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | #define GPIO_ADDR_BASE 0xC0000000 17 | #define TIMER_ADDR_BASE 0x0FFFF000 18 | #define SDRAM_ADDR_BASE 0x10000000 19 | #define INT_ADDR_BASE 0x0FFF0000 20 | #define UART1_ADDR_BASE 0xC0010000 -------------------------------------------------------------------------------- /digital_soc/src/bsp/common/common.c: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | #include "common.h" 17 | 18 | #define HEAP_BASE 0x01100000 19 | 20 | 21 | void* memset(void* s, uint8_t c, size_t n) { 22 | unsigned char* p = s; 23 | while (n--) { 24 | *p++ = (unsigned char)c; 25 | } 26 | return s; 27 | } 28 | 29 | uint8_t atoi(const char* str) { 30 | uint8_t res = 0; 31 | while (*str) { 32 | res = res * 10 + (*str++ - '0'); 33 | } 34 | return res; 35 | } 36 | 37 | char* itoa(int value, char* str) { 38 | char digits[] = "0123456789"; 39 | str[3] = '\0'; 40 | char* ptr = &str[2]; 41 | 42 | do { 43 | int digit = 0; 44 | int temp = value; 45 | while (temp >= 10) { 46 | temp -= 10; 47 | digit++; 48 | } 49 | *ptr-- = digits[temp]; 50 | 51 | value = digit; 52 | } while (value > 0); 53 | return str; 54 | } -------------------------------------------------------------------------------- /digital_soc/src/bsp/common/common.h: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | #ifndef COMMON_H 17 | #define COMMON_H 18 | 19 | #include "types.h" 20 | 21 | void* memset(void* s, uint8_t c, size_t n); 22 | 23 | uint8_t atoi(const char* str); 24 | 25 | char* itoa(int value, char* str); 26 | 27 | #endif /* COMMON_H */ -------------------------------------------------------------------------------- /digital_soc/src/bsp/common/types.h: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | #ifndef TYPES_H 17 | #define TYPES_H 18 | 19 | typedef signed char int8_t; 20 | typedef unsigned char uint8_t; 21 | typedef signed short int16_t; 22 | typedef unsigned short uint16_t; 23 | typedef signed int int32_t; 24 | typedef unsigned int uint32_t; 25 | typedef signed long long int64_t; 26 | typedef unsigned long long uint64_t; 27 | 28 | typedef uint32_t size_t; 29 | #define NULL 0 30 | 31 | #endif -------------------------------------------------------------------------------- /digital_soc/src/bsp/gpio/gpio.c: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | #include "gpio.h" 17 | 18 | void set_pin_mode(int pin, int mode) { 19 | if(mode) { 20 | *(int*)GPIO_CONFIG_ADDR = *(int*)GPIO_CONFIG_ADDR | (mode << (pin - 1)); 21 | } else { 22 | *(int*)GPIO_CONFIG_ADDR = *(int*)GPIO_CONFIG_ADDR & ~(mode << (pin - 1)); 23 | } 24 | } 25 | 26 | void set_all_pins_mode(int mode) { 27 | *(int*)GPIO_CONFIG_ADDR = mode; 28 | } 29 | 30 | void set_pin(int pin, int value) { 31 | if(value) { 32 | *(int*)GPIO_SET_ADDR = *(int*)GPIO_READ_ADDR | (1 << (pin - 1)); 33 | } else { 34 | *(int*)GPIO_SET_ADDR = *(int*)GPIO_READ_ADDR & ~(1 << (pin - 1)); 35 | } 36 | } 37 | 38 | void set_all_pins(int value) { 39 | *(int*)GPIO_SET_ADDR = value; 40 | } 41 | 42 | int get_all_pins() { 43 | return *(int*)GPIO_READ_ADDR; 44 | } 45 | 46 | int get_pin(int pin) { 47 | return *(int*)GPIO_READ_ADDR & (1 << (pin - 1)); 48 | } 49 | 50 | void clear_gpio_int() { 51 | *(int*)GPIO_INT_CLEAR_ADDR = 0; 52 | } -------------------------------------------------------------------------------- /digital_soc/src/bsp/gpio/gpio.h: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | #ifndef GPIO_H 17 | #define GPIO_H 18 | #include "addr.h" 19 | 20 | // GPIO address 21 | #define GPIO_CONFIG_ADDR GPIO_ADDR_BASE 22 | #define GPIO_SET_ADDR (GPIO_ADDR_BASE+4) 23 | #define GPIO_READ_ADDR (GPIO_ADDR_BASE+8) 24 | #define GPIO_INT_READ_ADDR (GPIO_ADDR_BASE+12) 25 | #define GPIO_INT_CLEAR_ADDR (GPIO_ADDR_BASE+16) 26 | 27 | #define GPIO_INPUT_MODE 0 28 | #define GPIO_OUTPUT_MODE 1 29 | 30 | // gpio mode set functions 31 | void set_pin_mode(int pin, int mode); 32 | void set_all_pins_mode(int mode); 33 | // gpio value set functions 34 | void set_pin(int pin, int value); 35 | void set_all_pins(int value); 36 | int get_pin(int pin); 37 | int get_all_pins(); 38 | // clear gpio interrupt 39 | void clear_gpio_int(); 40 | 41 | #endif -------------------------------------------------------------------------------- /digital_soc/src/bsp/iic/iic.c: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | #include "iic.h" 17 | #include "interrupt.h" 18 | 19 | static volatile uint32_t* iic_op = (volatile uint32_t*)IIC_OPERATION_ADDR; 20 | static volatile uint32_t* iic_res_buf = (volatile uint32_t*)IIC_READBUF_ADDR; 21 | static uint32_t iic_int_status = 0; 22 | static uint32_t iic_int_reg_status = 0; 23 | 24 | inline static void iic_int_proc() { 25 | iic_int_status = 1; 26 | } 27 | 28 | inline static void iin_int_status_clear() { 29 | iic_int_status = 0; 30 | } 31 | 32 | inline static void wait_iic_int() { 33 | // wait for interrupt or op flag complate ,this is not a good way, just for leaning 34 | while(iic_int_status == 0 && (*iic_res_buf & 0x1)); 35 | } 36 | 37 | void iic_init(void) { 38 | if(iic_int_reg_status == 0) { 39 | register_peripheral_int_handler(INT_IIC, iic_int_proc); 40 | iic_int_reg_status = 1; 41 | } 42 | iin_int_status_clear(); 43 | } 44 | 45 | void iic_write(uint8_t dev_addr, uint8_t reg_addr, uint8_t data) { 46 | iic_init(); 47 | uint32_t op = 0; 48 | op |= (dev_addr << 1); 49 | op |= (reg_addr << 8); 50 | op |= (data << 16); 51 | *iic_op = op; 52 | wait_iic_int(); 53 | } 54 | 55 | uint8_t iic_read(uint8_t dev_addr, uint8_t reg_addr) { 56 | iic_init(); 57 | uint32_t op = 0; 58 | op |= 0x1; 59 | op |= (dev_addr << 1); 60 | // reg_addr is ignored 61 | *iic_op = op; 62 | wait_iic_int(); 63 | // read data 64 | uint8_t r = (uint8_t)(((*iic_res_buf) >> 8) & 0xFF); 65 | return r; 66 | } -------------------------------------------------------------------------------- /digital_soc/src/bsp/iic/iic.h: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | #ifndef IIC_H 17 | #define IIC_H 18 | 19 | #include "types.h" 20 | 21 | /*** 22 | 0xA0000200 -> IIC opration config address 23 | (bits[1-7]: dev address, bit[0]: read/write) 24 | (bits[8-15]: reg address valid in write mode) 25 | (bits[16-23]: data only support 1 byte valid in write mode) 26 | (bits[24-31]: reserved) 27 | 0xA0000204 -> IIC read buffer address 28 | (bits[1-7]: reserved, bit[0]: opration status 0 doing 1 complate) 29 | (bits[8-15]: data only support 1 byte valid in read mode) 30 | (bits[16-31]: reserved) 31 | */ 32 | 33 | #define IIC_OPERATION_ADDR 0xA0000200 34 | #define IIC_READBUF_ADDR 0xA0000204 35 | 36 | 37 | void iic_write(uint8_t dev_addr, uint8_t reg_addr, uint8_t data); 38 | uint8_t iic_read(uint8_t dev_addr, uint8_t reg_addr); 39 | 40 | #endif -------------------------------------------------------------------------------- /digital_soc/src/bsp/interrupt/interrupt.c: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | #include "interrupt.h" 17 | #include "uart.h" 18 | #include "common.h" 19 | 20 | static int_handler_t int_handler[PERIPHERAL_INT_NUM] = {NULL}; 21 | static int_handler_t timer_handler = NULL; 22 | 23 | static uint32_t cur_int_mode = 0; 24 | 25 | void register_peripheral_int_handler(int int_num, int_handler_t handler) { 26 | int_handler[int_num] = handler; 27 | if(cur_int_mode < PERIPHERAL_INT) { 28 | cur_int_mode |= PERIPHERAL_INT; 29 | set_mie(cur_int_mode); 30 | } 31 | } 32 | 33 | void register_timer_int_handler(int_handler_t handler) { 34 | timer_handler = handler; 35 | cur_int_mode |= TIMER_INT; 36 | set_mie(cur_int_mode); 37 | } 38 | 39 | void exception_handler() { 40 | return; 41 | } 42 | 43 | void int_timer_handler() { 44 | if(timer_handler) { 45 | timer_handler(); 46 | } 47 | return; 48 | } 49 | 50 | void int_peripheral_handler() { 51 | // send_string("int peripheral handler\n"); 52 | uint32_t int_code = *(uint32_t *)INT_CODE_ADDR; 53 | if(int_handler[int_code]) { 54 | int_handler[int_code](); 55 | } 56 | return; 57 | } 58 | 59 | void int_soft_handler() { 60 | return; 61 | } 62 | 63 | -------------------------------------------------------------------------------- /digital_soc/src/bsp/interrupt/interrupt.h: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | #ifndef INTERRUPT_H 17 | #define INTERRUPT_H 18 | #include "types.h" 19 | #include "addr.h" 20 | 21 | #define TIMER_INT 0x80 22 | #define PERIPHERAL_INT 0x800 23 | #define SOFT_INT 0x8 24 | 25 | #define INT_CODE_ADDR INT_ADDR_BASE 26 | 27 | #define PERIPHERAL_INT_NUM 5 28 | #define INT_GPIO 0x1 29 | #define INT_UART 0x2 30 | #define INT_IIC 0x3 31 | 32 | typedef void (*int_handler_t)(void); 33 | 34 | void register_peripheral_int_handler(int int_num, int_handler_t handler); 35 | void register_timer_int_handler(int_handler_t handler); 36 | 37 | extern void set_mie(int mie); 38 | 39 | #endif -------------------------------------------------------------------------------- /digital_soc/src/bsp/timer/timer.c: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | #include "timer.h" 17 | #include "interrupt.h" 18 | 19 | static soft_timer_t soft_timers[MAX_SOFT_TIMER_NUM]; 20 | 21 | uint64_t get_mtime_cur() { 22 | return *(uint64_t*)MTIME_LOW;; 23 | } 24 | 25 | uint64_t get_mtime_cmp() { 26 | return *(uint64_t*)MTIME_CMP_LOW;; 27 | } 28 | 29 | void set_mtime_cmp(uint64_t cmp) { 30 | *(uint32_t*)MTIME_CMP_HIGH = cmp >> 32; 31 | *(uint32_t*)MTIME_CMP_LOW = cmp & 0xffffffff; 32 | } 33 | 34 | static void set_timer_after(int ms) { 35 | uint64_t ctime = get_mtime_cur(); 36 | set_mtime_cmp(ctime + ms); 37 | } 38 | 39 | int add_soft_timer(uint64_t ms, soft_callback call_back) { 40 | for(int i = 0; i < MAX_SOFT_TIMER_NUM; i++) { 41 | if(soft_timers[i].call_back == NULL) { 42 | soft_timers[i].call_back = call_back; 43 | soft_timers[i].ms_wakeup = get_mtime_cur() + ms; 44 | return 0; 45 | } 46 | } 47 | return 1; // no space 48 | } 49 | 50 | void init_global_timer() { 51 | for(int i = 0; i < MAX_SOFT_TIMER_NUM; i++) { 52 | soft_timers[i].call_back = NULL; 53 | } 54 | set_timer_after(300); 55 | register_timer_int_handler(interrupt_timer_handler); 56 | } 57 | 58 | void interrupt_timer_handler() { 59 | for(int i = 0; i < MAX_SOFT_TIMER_NUM; i++) { 60 | if(soft_timers[i].call_back != NULL) { 61 | if(soft_timers[i].ms_wakeup <= get_mtime_cur()) { 62 | soft_timers[i].call_back(); 63 | soft_timers[i].call_back = NULL; 64 | } 65 | } 66 | } 67 | set_timer_after(100); 68 | } 69 | 70 | int check() { 71 | int a = 0; 72 | for(int i = 0; i < MAX_SOFT_TIMER_NUM; i++) { 73 | if(soft_timers[i].call_back != NULL) { 74 | a++; 75 | } 76 | } 77 | return a; 78 | } 79 | 80 | void sleep(uint64_t ms) { 81 | uint64_t ctime = get_mtime_cur() + ms; 82 | while(get_mtime_cur() < ctime) { 83 | __asm__ __volatile__("nop"); 84 | } 85 | } -------------------------------------------------------------------------------- /digital_soc/src/bsp/timer/timer.h: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | #ifndef TIMER_H 17 | #define TIMER_H 18 | #include "types.h" 19 | #include "addr.h" 20 | 21 | #define MTIME_CMP_LOW (TIMER_ADDR_BASE+8) 22 | #define MTIME_CMP_HIGH (TIMER_ADDR_BASE+12) 23 | #define MTIME_LOW TIMER_ADDR_BASE 24 | #define MTIME_HIGH (TIMER_ADDR_BASE+4) 25 | 26 | #define MAX_SOFT_TIMER_NUM 5 27 | 28 | typedef void (*soft_callback) (); 29 | 30 | typedef struct { 31 | uint64_t ms_wakeup; 32 | soft_callback call_back; 33 | } soft_timer_t; 34 | 35 | 36 | uint64_t get_mtime_cur(); 37 | uint64_t get_mtime_cmp(); 38 | 39 | int add_soft_timer(uint64_t ms, soft_callback call_back); 40 | 41 | /** 42 | * after kernel start, init a global timer 43 | * other timers in application can use soft timer 44 | * this global timer is used to recive timer interrupt and wake up soft timer 45 | */ 46 | void init_global_timer(); 47 | 48 | void interrupt_timer_handler(); 49 | 50 | void sleep(uint64_t ms); 51 | 52 | int check(); // for debug 53 | 54 | #endif -------------------------------------------------------------------------------- /digital_soc/src/bsp/uart/uart.c: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | #include "uart.h" 17 | #include "timer.h" 18 | #include "interrupt.h" 19 | 20 | static volatile uint8_t* write_buffer = (volatile uint8_t*)UART1_DATA_ADDR; 21 | static volatile uint8_t* read_buffer = (volatile uint8_t*)UART1_DATA_ADDR; 22 | static volatile uint32_t* fifo_status = (volatile uint32_t*)UART1_DATA_STATUS_ADDR; 23 | 24 | 25 | static volatile uint32_t uart_int_reg_status = 0; 26 | static volatile uint32_t uart_int_status = 0; 27 | static uint32_t is_init = 0; 28 | 29 | void uart_int_proc() { 30 | uart_int_status = 1; 31 | // send_string("Interrupt received\n"); 32 | } 33 | 34 | void uart_init(void) { 35 | if (!is_init) { 36 | // if(uart_int_reg_status == 0) { 37 | // register_peripheral_int_handler(INT_UART, uart_int_proc); 38 | // uart_int_reg_status = 1; 39 | // } 40 | // uart_int_status = 0; 41 | // 默认预置50mhz主频下的 115200波特率,无奇偶校验,8位数据位,1位停止位,关闭中断 42 | // 在指令集支持乘法和除法计算后这里做成动态计算配置 43 | *(volatile uint32_t*)UART1_CONFIG_ADDR = 0x08e2001b; 44 | is_init = 1; 45 | } 46 | } 47 | 48 | void send_char(uint8_t c) { 49 | // wait for write fifo to be not full 50 | while (*fifo_status & (0x2 << 2)); 51 | *write_buffer = c; 52 | } 53 | 54 | void send_data(uint8_t *data, uint32_t len) { 55 | for (uint32_t i = 0; i < len; i++) { 56 | send_char(data[i]); 57 | } 58 | } 59 | 60 | uint32_t read_data(uint8_t *data, uint32_t len) { 61 | uint32_t r_len = 0; 62 | while (((*fifo_status) & 0x3) && r_len < len) { 63 | data[r_len++] = *read_buffer; 64 | } 65 | return r_len; 66 | } 67 | 68 | void send_string(const char *str) { 69 | while (*str) { 70 | send_char(*str++); 71 | } 72 | } 73 | 74 | uint8_t getchar() { 75 | // waiting for the character to be received 76 | while (!((*fifo_status) & 0x3)); 77 | uint8_t c = *read_buffer; 78 | return c; 79 | } -------------------------------------------------------------------------------- /digital_soc/src/bsp/uart/uart.h: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | #ifndef UART_H 17 | #define UART_H 18 | 19 | #include "types.h" 20 | #include "addr.h" 21 | 22 | // Set baud rate, start bit, stop bit and other communication configurations 23 | // [15:0] 波特率时钟分频数,整数部分 主频/(波特率 * 16) 24 | // [20:16] 每16个整数周期中,小数分频添加个数 (主频 % (波特率 * 16)) * 16 25 | // [24:21] 小数添加间隔 1 / (主频 % (波特率 * 16)) 26 | // [26:25] parity_mode; // 0 none 1 even 2 odd 27 | // [28:27] stop_bit; 28 | // [29] // data ready int enable 29 | // [30] // write ready int enable 30 | #define UART1_CONFIG_ADDR UART1_ADDR_BASE 31 | // Read/Write data to the UART 32 | #define UART1_DATA_ADDR (UART1_ADDR_BASE + 0x4) 33 | // read/write fifo status 34 | // [1:0] read fifo 0 empty 1 not empty 2 full 35 | // [3:2] write fifo 0 empty 1 not empty 2 full 36 | #define UART1_DATA_STATUS_ADDR (UART1_ADDR_BASE + 0x8) 37 | 38 | void uart_init(void); 39 | 40 | void send_char(uint8_t c); 41 | void send_data(uint8_t *data, uint32_t len); 42 | uint32_t read_data(uint8_t *data, uint32_t len); 43 | // get char from uart keyboard 44 | uint8_t getchar(); 45 | void send_string(const char *str); 46 | 47 | #endif -------------------------------------------------------------------------------- /digital_soc/src/kernel.ld: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | /* boot rom */ 4 | FLASH (rwx) : ORIGIN = 0x00000000, LENGTH = 5120K 5 | /* gpio and so on */ 6 | PERIPHERAL(rwx): ORIGIN = 0xC0000000, LENGTH = 128K 7 | RAM (rwx) : ORIGIN = 0x10000000, LENGTH = 128K 8 | } 9 | 10 | ENTRY(_start) 11 | 12 | SECTIONS 13 | { 14 | . = ALIGN(4); 15 | .text 0x00000000: { 16 | . = 0x0; 17 | . = ALIGN(4); 18 | *(.starttext) 19 | . = ALIGN(4); 20 | _int_begin = .; 21 | *(.exceptiontext) 22 | . = ALIGN(4); 23 | . = (_int_begin + 0xC); 24 | *(.softinttext) 25 | . = ALIGN(4); 26 | . = (_int_begin + 0x1C); 27 | *(.timerinttext) 28 | . = ALIGN(4); 29 | . = (_int_begin + 0x2C); 30 | *(.peripheralinttext) 31 | . = ALIGN(4); 32 | *(.text) 33 | _etext = .; 34 | } > FLASH 35 | .rodata ALIGN(4) : {*(.rodata*)} > FLASH 36 | . = ALIGN(4); 37 | .data 0x10000000 : { *(.data) } > RAM 38 | __bss_start = .; 39 | .bss ALIGN(4) : { *(.bss) *(COMMON) } > RAM 40 | __bss_end = .; 41 | } 42 | -------------------------------------------------------------------------------- /digital_soc/src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | #include "gpio.h" 17 | #include "timer.h" 18 | #include "interrupt.h" 19 | #include "uart.h" 20 | 21 | static int mode = 0; 22 | 23 | void flash_by_sleep() { 24 | // set low 7 pins of port D as output 25 | set_all_pins_mode(0x7f); 26 | set_all_pins(0); 27 | for(;;) { 28 | mode = get_pin(10); 29 | if(mode) { 30 | set_all_pins(get_all_pins() | 0x7f); 31 | sleep(500); 32 | set_all_pins(get_all_pins() & ~0x7f); 33 | sleep(500); 34 | } else { 35 | for(int i=1;i<8 && mode==0;i++) { 36 | set_pin(i, 1); 37 | sleep(500); 38 | set_pin(i, 0); 39 | } 40 | } 41 | } 42 | } 43 | 44 | static int cur_pin = 0; 45 | static int cur_pins_status = 0; 46 | 47 | void flash_timer_handler() { 48 | // set low 20 pins of port D as output 49 | set_all_pins_mode(0xFFFFF); 50 | if(mode) { 51 | if(cur_pins_status) { 52 | set_all_pins(get_all_pins() & 0xFFF00000); 53 | cur_pins_status = 0; 54 | }else{ 55 | set_all_pins(get_all_pins() | 0xFFFFF); 56 | cur_pins_status = 1; 57 | } 58 | } else { 59 | set_all_pins(get_all_pins() & 0xFFF00000); 60 | cur_pin++; 61 | if(cur_pin > 20) { 62 | cur_pin = 1; 63 | } 64 | set_pin(cur_pin, 1); 65 | } 66 | send_string("led status changed\n"); 67 | add_soft_timer(500, flash_timer_handler); 68 | } 69 | 70 | void mode_change_handler() { 71 | mode = get_pin(32); 72 | clear_gpio_int(); 73 | send_string("led flash mode changed\n"); 74 | } 75 | 76 | void flash_by_interrupt() { 77 | init_global_timer(); 78 | add_soft_timer(500, flash_timer_handler); 79 | register_peripheral_int_handler(INT_GPIO,mode_change_handler); 80 | for(;;) {} 81 | } 82 | 83 | int main() { 84 | uart_init(); 85 | // flash_by_sleep(); 86 | flash_by_interrupt(); 87 | return 0; 88 | } -------------------------------------------------------------------------------- /digital_soc/src/mkhex.py: -------------------------------------------------------------------------------- 1 | boottext = 'v2.0 raw\n' 2 | kerneltext = 'v2.0 raw\n' 3 | testtext = '' 4 | 5 | with open('./kernel.bin',mode='rb') as f: 6 | bts = f.read() 7 | hexs = bts.hex(' ').split(' ') 8 | i = 0 9 | while i < len(hexs): 10 | kerneltext += f'{hexs[i]}\n' 11 | testtext += f'{hexs[i]}\n' 12 | i += 1 13 | 14 | with open('./kernel.hex',mode='w') as f: 15 | f.write(kerneltext) 16 | 17 | with open('./boot.bin',mode='rb') as f: 18 | bts = f.read() 19 | hexs = bts.hex(' ').split(' ') 20 | i = 0 21 | while i < len(hexs): 22 | boottext += f'{hexs[i]}\n' 23 | # testtext += f'{hexs[i]}\n' 24 | i += 1 25 | 26 | with open('./boot.hex',mode='w') as f: 27 | f.write(boottext) 28 | 29 | with open('./test.hex',mode='w') as f: 30 | f.write(testtext) 31 | -------------------------------------------------------------------------------- /digital_soc/src/start.s: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | .section .starttext 17 | .global _start 18 | .global set_mie 19 | _start: 20 | # set sp 21 | li sp, 0x3f000000 22 | # register interrupts handler 23 | la a5,int_handler 24 | addi a5,a5, 0x1 25 | csrrw t2,mtvec,a5 26 | # open interrupts 27 | li t3,0x1808 28 | csrrw t2,mstatus,t3 29 | # goto c main 30 | call main 31 | 32 | .section .exceptiontext 33 | int_handler: 34 | j inner_exception_handler 35 | mret_pos: 36 | mret 37 | 38 | 39 | .section .softinttext 40 | soft_handler: 41 | j inner_soft_handler 42 | 43 | .section .timerinttext 44 | timer_handler: 45 | j inner_timer_handler 46 | 47 | .section .peripheralinttext 48 | peripheral_handler: 49 | add sp,sp,-4 50 | sw ra,0(sp) 51 | call save_regs 52 | call int_peripheral_handler 53 | call restore_regs 54 | lw ra,0(sp) 55 | addi sp,sp,4 56 | mret 57 | 58 | .section .text 59 | set_mie: 60 | add sp,sp,-4 61 | sw ra,0(sp) 62 | csrrw t2,mie,a0 63 | lw ra,0(sp) 64 | addi sp,sp,4 65 | ret 66 | 67 | save_regs: 68 | addi sp, sp, -36 69 | sw a2, 0(sp) 70 | sw a3, 4(sp) 71 | sw a4, 8(sp) 72 | sw a5, 12(sp) 73 | sw a6, 16(sp) 74 | sw a7, 20(sp) 75 | sw a0, 24(sp) 76 | sw a1, 28(sp) 77 | ret 78 | 79 | restore_regs: 80 | lw a2, 0(sp) 81 | lw a3, 4(sp) 82 | lw a4, 8(sp) 83 | lw a5, 12(sp) 84 | lw a6, 16(sp) 85 | lw a7, 20(sp) 86 | lw a0, 24(sp) 87 | lw a1, 28(sp) 88 | addi sp, sp, 36 89 | ret 90 | 91 | inner_soft_handler: 92 | add sp,sp,-4 93 | sw ra,0(sp) 94 | call save_regs 95 | call int_soft_handler 96 | call restore_regs 97 | lw ra,0(sp) 98 | addi sp,sp,4 99 | j mret_pos 100 | 101 | inner_timer_handler: 102 | add sp,sp,-4 103 | sw ra,0(sp) 104 | call save_regs 105 | call int_timer_handler 106 | call restore_regs 107 | lw ra,0(sp) 108 | addi sp,sp,4 109 | j mret_pos 110 | 111 | inner_exception_handler: 112 | add sp,sp,-4 113 | sw ra,0(sp) 114 | call save_regs 115 | call exception_handler 116 | call restore_regs 117 | lw ra,0(sp) 118 | addi sp,sp,4 119 | j mret_pos -------------------------------------------------------------------------------- /digital_soc/verilog/dynsrc/Makefile: -------------------------------------------------------------------------------- 1 | CC := g++ 2 | 3 | ifeq ($(OS),Windows_NT) 4 | CPPFLAGS := -D_WIN32 -Id:/soft/verilator/include -I../obj_dir -shared 5 | DLL_EXT := .dll 6 | MKDIR := powershell -Command "New-Item -ItemType Directory -Force" 7 | RMDIR := powershell -Command "Remove-Item -Recurse -Force" 8 | RM := powershell -Command "Remove-Item -Recurse -Force" 9 | else 10 | CPPFLAGS := -shared -fPIC 11 | DLL_EXT := .so 12 | MKDIR := mkdir -p 13 | RMDIR := rm -rf 14 | RM := rm -f 15 | endif 16 | 17 | LDFLAGS := $(CPPFLAGS) -pthread -lpthread -latomic 18 | 19 | all: wrapper 20 | 21 | wrapper: wrapper.cpp 22 | @echo "wrapper compiled" 23 | @echo $(OS) 24 | $(CC) $(LDFLAGS) -o wrapper$(DLL_EXT) wrapper.cpp ../obj_dir/verilated.o ../obj_dir/verilated_threads.o ../obj_dir/Vdigital_soc_top__ALL.a 25 | 26 | clean: 27 | $(RM) wrapper$(DLL_EXT) 28 | -------------------------------------------------------------------------------- /digital_soc/verilog/dynsrc/Makefile.trace: -------------------------------------------------------------------------------- 1 | CC := g++ 2 | 3 | ifeq ($(OS),Windows_NT) 4 | CPPFLAGS := -D_WIN32 -Id:/soft/verilator/include -I../obj_dir -shared 5 | DLL_EXT := .dll 6 | MKDIR := powershell -Command "New-Item -ItemType Directory -Force" 7 | RMDIR := powershell -Command "Remove-Item -Recurse -Force" 8 | RM := powershell -Command "Remove-Item -Recurse -Force" 9 | else 10 | CPPFLAGS := -shared -fPIC 11 | DLL_EXT := .so 12 | MKDIR := mkdir -p 13 | RMDIR := rm -rf 14 | RM := rm -f 15 | endif 16 | 17 | LDFLAGS := $(CPPFLAGS) -pthread -lpthread -latomic 18 | 19 | all: wrapper 20 | 21 | wrapper: wrapper.cpp 22 | @echo "wrapper compiled" 23 | @echo $(OS) 24 | $(CC) $(LDFLAGS) -o wrapper$(DLL_EXT) wrapper.cpp ../obj_dir/verilated.o ../obj_dir/verilated_threads.o ../obj_dir/Vdigital_soc_top__ALL.a ../obj_dir/verilated_vcd_c.o 25 | 26 | clean: 27 | $(RM) wrapper$(DLL_EXT) 28 | -------------------------------------------------------------------------------- /digital_soc/verilog/dynsrc/test.c: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | extern void setInput(char* input, int size); 17 | extern void getOutput(char* output, int size); 18 | extern void cpuLoopInit(); 19 | void cpuLoopStop(); 20 | 21 | #include 22 | #include 23 | 24 | int main() { 25 | cpuLoopInit(); 26 | char input[4] = {0}; 27 | char output[20] = {0}; 28 | char in[4] = {0xef,0x00,0x00,0x00}; 29 | char flag = 0; 30 | int pos = 0; 31 | setInput(input, 4); 32 | usleep(100); 33 | input[0] = 2; 34 | int ins; 35 | for(int i = 0; i < 100; i++) { 36 | if(flag) { 37 | if((*(int*)output) > 0) { 38 | ins = 7; 39 | 40 | }else{ 41 | ins = ((0xFF & in[0]) << 3) + 7; 42 | } 43 | memcpy(input,&ins,4); 44 | flag = 0; 45 | }else{ 46 | if((*(int*)output) > 0) { 47 | ins = 2; 48 | 49 | }else{ 50 | ins = ((0xFF & in[0]) << 3) + 2; 51 | } 52 | memcpy(input,&ins,4); 53 | flag = 1; 54 | } 55 | setInput(input, 4); 56 | getOutput(output, 20); 57 | printf("output: 0x%X\n",*(int*)output); 58 | // printf("output1: 0x%X\n",*(int*)&output[4]); 59 | usleep(1000); 60 | } 61 | 62 | cpuLoopStop(); 63 | } -------------------------------------------------------------------------------- /digital_soc/verilog/dynsrc/wrapper.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | #ifdef _WIN32 17 | #define DLL_EXPORT __declspec(dllexport) 18 | #else 19 | #define DLL_EXPORT 20 | #endif 21 | #include "verilated.h" 22 | #include "Vdigital_soc_top.h" 23 | #include 24 | #include 25 | #include 26 | 27 | #define SIG_SIZE 128 28 | 29 | std::mutex mtx; 30 | 31 | static volatile char input_sig[SIG_SIZE]; 32 | static volatile char output_sig[SIG_SIZE]; 33 | static volatile char run_flag = 0; 34 | static volatile char cpu_thread_flag = 0; 35 | 36 | VerilatedContext *contextp; 37 | Vdigital_soc_top *topp; 38 | // const std::unique_ptr contextp{new VerilatedContext}; 39 | // const std::unique_ptr topp{new Vdigital_soc_top{contextp.get()}}; 40 | 41 | void cpu_loop() { 42 | contextp = new VerilatedContext(); 43 | topp = new Vdigital_soc_top{contextp}; 44 | // Verilated::debug(0); 45 | contextp->debug(0); 46 | contextp->randReset(2); 47 | contextp->traceEverOn(true); 48 | memset((void*)input_sig, 0, SIG_SIZE); 49 | struct timespec ns_sleep; 50 | ns_sleep.tv_sec = 0; 51 | ns_sleep.tv_nsec = 5; 52 | unsigned char clk = 0; 53 | 54 | // Simulate until $finish 55 | while (!contextp->gotFinish() && run_flag) { 56 | // Evaluate model 57 | topp->clk = clk; 58 | mtx.lock(); 59 | topp->input_sig = (*(QData*)input_sig); 60 | mtx.unlock(); 61 | topp->eval(); 62 | mtx.lock(); 63 | memcpy((void*)output_sig, (char*)&(topp->output_sig.m_storage[0]), sizeof(EData)*topp->output_sig.Words); 64 | mtx.unlock(); 65 | if (clk) { 66 | clk = 0; 67 | }else { 68 | clk = 1; 69 | } 70 | // Advance time 71 | contextp->timeInc(1); 72 | nanosleep(&ns_sleep,NULL); 73 | } 74 | 75 | // Execute 'final' processes 76 | topp->final(); 77 | contextp->statsPrintSummary(); 78 | delete topp; 79 | delete contextp; 80 | } 81 | 82 | extern "C" { 83 | 84 | DLL_EXPORT void cpuLoopInit() { 85 | if (!run_flag) { 86 | std::thread cpu_thread(cpu_loop); 87 | cpu_thread.detach(); 88 | run_flag = 1; 89 | } 90 | } 91 | 92 | DLL_EXPORT void setInput(char* input, int size) { 93 | int len = size > SIG_SIZE ? SIG_SIZE : size; 94 | std::lock_guard lock(mtx); 95 | memcpy((void*)input_sig, input, len); 96 | // topp->input_sig = (*(QData*)input_sig); 97 | // topp->eval(); 98 | // contextp->timeInc(1); 99 | } 100 | 101 | DLL_EXPORT void getOutput(char* output, int size) { 102 | int len = size > SIG_SIZE ? SIG_SIZE : size; 103 | std::lock_guard lock(mtx); 104 | memcpy(output, (void*)output_sig, len); 105 | } 106 | 107 | DLL_EXPORT void cpuLoopStop() { 108 | run_flag = 0; 109 | } 110 | 111 | DLL_EXPORT void nanoSleep(int ns) { 112 | struct timespec ns_sleep; 113 | ns_sleep.tv_sec = 0; 114 | ns_sleep.tv_nsec = ns; 115 | nanosleep(&ns_sleep,NULL); 116 | } 117 | } -------------------------------------------------------------------------------- /digital_soc/verilog/dynsrc/wrapper.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renyangang/riscv-mcu/51faad5b2843079a48ea5fe4b4ce74040e65b381/digital_soc/verilog/dynsrc/wrapper.dll -------------------------------------------------------------------------------- /digital_soc/verilog/dynsrc/wrapper_sync.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | #ifdef _WIN32 17 | #define DLL_EXPORT __declspec(dllexport) 18 | #else 19 | #define DLL_EXPORT 20 | #endif 21 | #include "verilated.h" 22 | #include "Vdigital_soc_top.h" 23 | #include 24 | 25 | #define SIG_SIZE 128 26 | 27 | static volatile char input_sig[SIG_SIZE]; 28 | static volatile char output_sig[SIG_SIZE]; 29 | static volatile char run_flag = 0; 30 | static volatile char cpu_thread_flag = 0; 31 | 32 | VerilatedContext *contextp; 33 | Vdigital_soc_top *topp; 34 | // const std::unique_ptr contextp{new VerilatedContext}; 35 | // const std::unique_ptr topp{new Vdigital_soc_top{contextp.get()}}; 36 | 37 | void cpu_loop() { 38 | contextp = new VerilatedContext(); 39 | topp = new Vdigital_soc_top{contextp}; 40 | // Verilated::debug(0); 41 | contextp->debug(0); 42 | contextp->randReset(2); 43 | contextp->traceEverOn(true); 44 | 45 | // Simulate until $finish 46 | // while (!contextp->gotFinish() && run_flag) { 47 | // // Evaluate model 48 | // topp->input_sig = (*(QData*)input_sig); 49 | // topp->eval(); 50 | // int pos = 0; 51 | // memcpy((void*)output_sig, (char*)&(topp->output_sig.m_storage[0]), sizeof(EData)*topp->output_sig.Words); 52 | // // Advance time 53 | // contextp->timeInc(1); 54 | // usleep(1); 55 | // } 56 | 57 | // if (!contextp->gotFinish()) { 58 | // VL_DEBUG_IF(VL_PRINTF("+ Exiting without $finish; no events left\n");); 59 | // } 60 | 61 | // Execute 'final' processes 62 | // topp->final(); 63 | // contextp->statsPrintSummary(); 64 | // delete topp; 65 | // delete contextp; 66 | } 67 | 68 | extern "C" { 69 | 70 | DLL_EXPORT void cpuLoopInit() { 71 | // std::thread cpu_thread(cpu_loop); 72 | // cpu_thread.detach(); 73 | if (!run_flag) { 74 | cpu_loop(); 75 | run_flag = 1; 76 | } 77 | } 78 | 79 | DLL_EXPORT void setInput(char* input, int size) { 80 | cpuLoopInit(); 81 | int len = size > SIG_SIZE ? SIG_SIZE : size; 82 | memcpy((void*)input_sig, input, len); 83 | topp->input_sig = (*(QData*)input_sig); 84 | topp->eval(); 85 | memcpy((void*)output_sig, (char*)&(topp->output_sig.m_storage[0]), sizeof(EData)*topp->output_sig.Words); 86 | // Advance time 87 | contextp->timeInc(1); 88 | } 89 | 90 | DLL_EXPORT void getOutput(char* output, int size) { 91 | cpuLoopInit(); 92 | topp->input_sig = (*(QData*)input_sig); 93 | topp->eval(); 94 | memcpy((void*)output_sig, (char*)&(topp->output_sig.m_storage[0]), sizeof(EData)*topp->output_sig.Words); 95 | // Advance time 96 | contextp->timeInc(1); 97 | int len = size > SIG_SIZE ? SIG_SIZE : size; 98 | memcpy(output, (void*)output_sig, len); 99 | } 100 | 101 | DLL_EXPORT void cpuLoopStop() { 102 | topp->final(); 103 | contextp->statsPrintSummary(); 104 | delete topp; 105 | delete contextp; 106 | run_flag = 0; 107 | } 108 | } -------------------------------------------------------------------------------- /digital_soc/verilog/file_list.f: -------------------------------------------------------------------------------- 1 | ./digital_soc_top.v 2 | +incdir+../../verilog/core 3 | ../../verilog/core/cache.v 4 | ../../verilog/core/config.v 5 | ../../verilog/core/cpu_pipeline.v 6 | ../../verilog/core/cpu_top.v 7 | ../../verilog/core/ex_alu.v 8 | ../../verilog/core/ex_branch.v 9 | ../../verilog/core/ex_csr.v 10 | ../../verilog/core/ex_mem.v 11 | ../../verilog/core/inst_decoder.v 12 | ../../verilog/core/inst_fetch.v 13 | ../../verilog/core/mem_controller.v 14 | ../../verilog/core/registers.v 15 | ../../verilog/core/registers_csr.v 16 | ../../verilog/core/sys_bus.v 17 | ../../verilog/peripherals/digital/digital_flash.v 18 | ../../verilog/peripherals/digital/digital_ram.v 19 | ../../verilog/peripherals/gpio_controller.v 20 | ../../verilog/peripherals/peripherals_bus.v 21 | ../../verilog/soc/digital_soc.v -------------------------------------------------------------------------------- /digital_soc/verilog/iverilog.bat: -------------------------------------------------------------------------------- 1 | iverilog.exe -y ../../verilog -y ../../verilog/core -y ../../verilog/testbench -y ../../verilog/peripherals/digital -y ../../verilog/soc -y ../../verilog/peripherals -I ../../verilog/core -o digital_soc.vvp ./digital_soc_top.v 2 | vvp.exe -M. -mnetm digital_soc.vvp -------------------------------------------------------------------------------- /digital_soc/verilog/vboard_plugin/Makefile: -------------------------------------------------------------------------------- 1 | CC := g++ 2 | 3 | ifeq ($(OS),Windows_NT) 4 | CPPFLAGS := -D_WIN32 -Id:/soft/verilator/include -I../obj_dir -shared 5 | DLL_EXT := .dll 6 | MKDIR := powershell -Command "New-Item -ItemType Directory -Force" 7 | RMDIR := powershell -Command "Remove-Item -Recurse -Force" 8 | RM := powershell -Command "Remove-Item -Recurse -Force" 9 | else 10 | CPPFLAGS := -shared -fPIC 11 | DLL_EXT := .so 12 | MKDIR := mkdir -p 13 | RMDIR := rm -rf 14 | RM := rm -f 15 | endif 16 | 17 | LDFLAGS := $(CPPFLAGS) -pthread -lpthread -latomic 18 | 19 | all: plugin 20 | 21 | plugin: plugin.cpp 22 | @echo "plugin compiled" 23 | @echo $(OS) 24 | $(CC) $(LDFLAGS) -o plugin$(DLL_EXT) plugin.cpp ../obj_dir/verilated.o ../obj_dir/verilated_threads.o ../obj_dir/Vdigital_soc__ALL.a 25 | 26 | clean: 27 | $(RM) plugin$(DLL_EXT) 28 | -------------------------------------------------------------------------------- /digital_soc/verilog/vboard_plugin/Makefile_trace.mk: -------------------------------------------------------------------------------- 1 | CC := g++ 2 | 3 | ifeq ($(OS),Windows_NT) 4 | CPPFLAGS := -D_WIN32 -Id:/soft/verilator/include -I../obj_dir -shared 5 | DLL_EXT := .dll 6 | MKDIR := powershell -Command "New-Item -ItemType Directory -Force" 7 | RMDIR := powershell -Command "Remove-Item -Recurse -Force" 8 | RM := powershell -Command "Remove-Item -Recurse -Force" 9 | else 10 | CPPFLAGS := -shared -fPIC 11 | DLL_EXT := .so 12 | MKDIR := mkdir -p 13 | RMDIR := rm -rf 14 | RM := rm -f 15 | endif 16 | 17 | LDFLAGS := $(CPPFLAGS) -pthread -lpthread -latomic 18 | 19 | all: plugin 20 | 21 | plugin: plugin.cpp 22 | @echo "plugin compiled" 23 | @echo $(OS) 24 | $(CC) $(LDFLAGS) -o plugin$(DLL_EXT) plugin.cpp ../obj_dir/verilated.o ../obj_dir/verilated_threads.o ../obj_dir/Vvboard_soc_top__ALL.a ../obj_dir/verilated_vcd_c.o 25 | 26 | clean: 27 | $(RM) plugin$(DLL_EXT) 28 | -------------------------------------------------------------------------------- /digital_soc/verilog/vboard_plugin/plugin.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | #ifdef _WIN32 17 | #define DLL_EXPORT __declspec(dllexport) 18 | #else 19 | #define DLL_EXPORT 20 | #endif 21 | #include "verilated.h" 22 | #include "verilated_vcd_c.h" 23 | #include "Vvboard_soc_top.h" 24 | #include 25 | #include 26 | #include 27 | 28 | #define SIG_SIZE 128 29 | 30 | std::mutex mtx; 31 | 32 | static volatile char run_flag = 0; 33 | static volatile char cpu_thread_flag = 0; 34 | 35 | VerilatedContext *contextp; 36 | Vvboard_soc_top *topp; 37 | VerilatedVcdC *tfp; 38 | 39 | void setInput(unsigned char* input,int input_size) { 40 | int pos = 0; 41 | topp->clk = input[pos]; 42 | pos++; 43 | topp->rst_n = input[pos]; 44 | pos++; 45 | topp->clk_timer = input[pos]; 46 | pos++; 47 | topp->digital_flash_data = input[pos]; 48 | pos++; 49 | topp->digital_flash_ready = input[pos]; 50 | pos++; 51 | topp->digital_mem_data = *(IData*)&(input[pos]); 52 | pos += sizeof(IData); 53 | topp->digital_mem_ready = input[pos]; 54 | pos++; 55 | topp->gpio_values_in = *(IData*)&(input[pos]); 56 | pos += sizeof(IData); 57 | topp->uart_rx = input[pos]; 58 | } 59 | 60 | void getOutput(unsigned char* output,int output_size) { 61 | int pos = 0; 62 | memcpy((void*)&(output[pos]), &(topp->digital_flash_addr), sizeof(IData)); 63 | pos += sizeof(IData); 64 | memcpy((void*)&(output[pos]), &(topp->digital_flash_read_en), sizeof(CData)); 65 | pos += sizeof(CData); 66 | memcpy((void*)&(output[pos]), &(topp->digital_flash_write_en), sizeof(CData)); 67 | pos += sizeof(CData); 68 | memcpy((void*)&(output[pos]), &(topp->digital_flash_byte_size), sizeof(CData)); 69 | pos += sizeof(CData); 70 | memcpy((void*)&(output[pos]), &(topp->digital_flash_wdata), sizeof(CData)); 71 | pos += sizeof(CData); 72 | memcpy((void*)&(output[pos]), &(topp->digital_mem_write_en), sizeof(CData)); 73 | pos += sizeof(CData); 74 | memcpy((void*)&(output[pos]), &(topp->digital_mem_read_en), sizeof(CData)); 75 | pos += sizeof(CData); 76 | memcpy((void*)&(output[pos]), &(topp->digital_mem_addr), sizeof(IData)); 77 | pos += sizeof(IData); 78 | memcpy((void*)&(output[pos]), &(topp->digital_mem_byte_size), sizeof(CData)); 79 | pos += sizeof(CData); 80 | memcpy((void*)&(output[pos]), &(topp->digital_mem_wdata), sizeof(IData)); 81 | pos += sizeof(IData); 82 | memcpy((void*)&(output[pos]), &(topp->gpio_values_out), sizeof(IData)); 83 | pos += sizeof(IData); 84 | memcpy((void*)&(output[pos]), &(topp->uart_tx), sizeof(CData)); 85 | } 86 | 87 | double sc_time_stamp() { return contextp->time(); } 88 | 89 | extern "C" { 90 | 91 | DLL_EXPORT void init() { 92 | if (!run_flag) { 93 | contextp = new VerilatedContext(); 94 | topp = new Vvboard_soc_top{contextp}; 95 | tfp = new VerilatedVcdC(); 96 | contextp->debug(0); 97 | contextp->randReset(0); 98 | contextp->traceEverOn(true); 99 | contextp->trace(tfp, 0); 100 | tfp->open("d:\\vboard_soc_top.vcd"); 101 | run_flag = 1; 102 | } 103 | } 104 | 105 | DLL_EXPORT void eval(unsigned char* input,int input_size,unsigned char* output,int output_size) { 106 | setInput(input,input_size); 107 | // printf("%d %d %d \n",input[0],input[1],input[2]); 108 | topp->eval(); 109 | contextp->timeInc(1); 110 | tfp->dump(contextp->time()); 111 | getOutput(output,output_size); 112 | } 113 | 114 | DLL_EXPORT void stop() { 115 | run_flag = 0; 116 | tfp->flush(); 117 | tfp->close(); 118 | topp->final(); 119 | contextp->statsPrintSummary(); 120 | contextp->traceEverOn(false); 121 | delete(topp); 122 | delete(tfp); 123 | delete(contextp); 124 | // delete topp; 125 | // delete contextp; 126 | } 127 | 128 | DLL_EXPORT void nanoSleep(int ns) { 129 | struct timespec ns_sleep; 130 | ns_sleep.tv_sec = 0; 131 | ns_sleep.tv_nsec = ns; 132 | nanosleep(&ns_sleep,NULL); 133 | } 134 | } -------------------------------------------------------------------------------- /digital_soc/verilog/vboard_plugin/plugin.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renyangang/riscv-mcu/51faad5b2843079a48ea5fe4b4ce74040e65b381/digital_soc/verilog/vboard_plugin/plugin.dll -------------------------------------------------------------------------------- /digital_soc/verilog/vboard_soc_top.v: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | `include "config.v" 17 | 18 | module vboard_soc_top( 19 | input wire clk, // 时钟信号 20 | input wire rst_n, // 复位信号 21 | input wire clk_timer, 22 | 23 | output wire [`MAX_BIT_POS:0] digital_flash_addr, 24 | output wire digital_flash_write_en, 25 | output wire digital_flash_read_en, 26 | output wire [2:0] digital_flash_byte_size, 27 | output wire [7:0] digital_flash_wdata, 28 | input wire [7:0] digital_flash_data, 29 | input wire digital_flash_ready, 30 | output wire [`MAX_BIT_POS:0] digital_mem_addr, 31 | output wire digital_mem_write_en, 32 | output wire digital_mem_read_en, 33 | output wire [3:0] digital_mem_byte_size, 34 | output wire [`MAX_BIT_POS:0] digital_mem_wdata, 35 | input wire [`MAX_BIT_POS:0] digital_mem_data, 36 | input wire digital_mem_ready, 37 | input wire [`GPIO_NUMS-1:0] gpio_values_in, 38 | output wire [`GPIO_NUMS-1:0] gpio_values_out, 39 | input wire uart_rx, 40 | output wire uart_tx 41 | ); 42 | 43 | 44 | // initial begin 45 | // // $dumpfile("D:\\work\\v-computer\\cpu-v\\digital_soc\\verilog\\digital.vcd"); 46 | // $dumpfile("D:\\work\\source\\linux\\cpu-v\\digital_soc\\verilog\\digital.vcd"); 47 | // $dumpvars(0, vboard_soc_top); 48 | // end 49 | 50 | wire [`GPIO_NUMS-1:0] gpio_values; 51 | 52 | assign gpio_values_out = gpio_values; 53 | 54 | genvar idx; 55 | generate 56 | for (idx = 0; idx < `GPIO_NUMS; idx = idx + 1) begin 57 | pulldown(gpio_values[idx]); 58 | end 59 | endgenerate 60 | 61 | // assign gpio_values[9] = gpio_values_in[9]; 62 | // assign gpio_values[10] = gpio_values_in[10]; 63 | 64 | genvar i; 65 | generate 66 | for (i = 20; i < `GPIO_NUMS; i = i + 1) begin : gpio_logic 67 | assign gpio_values[i] = gpio_values_in[i]; 68 | end 69 | endgenerate 70 | 71 | 72 | vboard_soc vboard_inst( 73 | .clk(clk), 74 | .rst_n(rst_n), 75 | .clk_timer(clk_timer), 76 | .digital_flash_addr(digital_flash_addr), 77 | .digital_flash_write_en(digital_flash_write_en), 78 | .digital_flash_read_en(digital_flash_read_en), 79 | .digital_flash_byte_size(digital_flash_byte_size), 80 | .digital_flash_wdata(digital_flash_wdata), 81 | .digital_flash_data(digital_flash_data), 82 | .digital_flash_ready(digital_flash_ready), 83 | .digital_mem_addr(digital_mem_addr), 84 | .digital_mem_write_en(digital_mem_write_en), 85 | .digital_mem_read_en(digital_mem_read_en), 86 | .digital_mem_byte_size(digital_mem_byte_size), 87 | .digital_mem_wdata(digital_mem_wdata), 88 | .digital_mem_data(digital_mem_data), 89 | .digital_mem_ready(digital_mem_ready), 90 | .gpio_values(gpio_values), 91 | .uart_rx(uart_rx), 92 | .uart_tx(uart_tx) 93 | ); 94 | 95 | 96 | 97 | 98 | endmodule -------------------------------------------------------------------------------- /digital_soc/verilog/vboard_top.f: -------------------------------------------------------------------------------- 1 | ./vboard_soc_top.v 2 | // ./digital_soc_top.v 3 | // ../../verilog/soc/digital_soc.v 4 | +incdir+../../verilog/soc 5 | +incdir+../../verilog/core 6 | +incdir+../../verilog/common 7 | +incdir+../../verilog/peripherals 8 | +incdir+../../verilog/peripherals/digital 9 | +incdir+../../verilog/peripherals/uart 10 | -------------------------------------------------------------------------------- /doc/image/arch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renyangang/riscv-mcu/51faad5b2843079a48ea5fe4b4ce74040e65b381/doc/image/arch.png -------------------------------------------------------------------------------- /doc/image/boot-firstaddr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renyangang/riscv-mcu/51faad5b2843079a48ea5fe4b4ce74040e65b381/doc/image/boot-firstaddr.png -------------------------------------------------------------------------------- /doc/image/data-bus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renyangang/riscv-mcu/51faad5b2843079a48ea5fe4b4ce74040e65b381/doc/image/data-bus.png -------------------------------------------------------------------------------- /doc/image/exception-int.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renyangang/riscv-mcu/51faad5b2843079a48ea5fe4b4ce74040e65b381/doc/image/exception-int.png -------------------------------------------------------------------------------- /doc/image/execution.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renyangang/riscv-mcu/51faad5b2843079a48ea5fe4b4ce74040e65b381/doc/image/execution.png -------------------------------------------------------------------------------- /doc/image/gpio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renyangang/riscv-mcu/51faad5b2843079a48ea5fe4b4ce74040e65b381/doc/image/gpio.png -------------------------------------------------------------------------------- /doc/image/instruction-decoder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renyangang/riscv-mcu/51faad5b2843079a48ea5fe4b4ce74040e65b381/doc/image/instruction-decoder.png -------------------------------------------------------------------------------- /doc/image/instuction-addr-selector.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renyangang/riscv-mcu/51faad5b2843079a48ea5fe4b4ce74040e65b381/doc/image/instuction-addr-selector.png -------------------------------------------------------------------------------- /doc/image/jmp-priority.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renyangang/riscv-mcu/51faad5b2843079a48ea5fe4b4ce74040e65b381/doc/image/jmp-priority.png -------------------------------------------------------------------------------- /doc/image/load-kernel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renyangang/riscv-mcu/51faad5b2843079a48ea5fe4b4ce74040e65b381/doc/image/load-kernel.png -------------------------------------------------------------------------------- /doc/image/modules.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renyangang/riscv-mcu/51faad5b2843079a48ea5fe4b4ce74040e65b381/doc/image/modules.png -------------------------------------------------------------------------------- /doc/image/output.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renyangang/riscv-mcu/51faad5b2843079a48ea5fe4b4ce74040e65b381/doc/image/output.gif -------------------------------------------------------------------------------- /doc/image/pc-ir.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renyangang/riscv-mcu/51faad5b2843079a48ea5fe4b4ce74040e65b381/doc/image/pc-ir.png -------------------------------------------------------------------------------- /doc/image/peripheral.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renyangang/riscv-mcu/51faad5b2843079a48ea5fe4b4ce74040e65b381/doc/image/peripheral.png -------------------------------------------------------------------------------- /doc/image/storage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renyangang/riscv-mcu/51faad5b2843079a48ea5fe4b4ce74040e65b381/doc/image/storage.png -------------------------------------------------------------------------------- /doc/image/uart-controller.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renyangang/riscv-mcu/51faad5b2843079a48ea5fe4b4ce74040e65b381/doc/image/uart-controller.png -------------------------------------------------------------------------------- /doc/image/uart-term.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renyangang/riscv-mcu/51faad5b2843079a48ea5fe4b4ce74040e65b381/doc/image/uart-term.png -------------------------------------------------------------------------------- /doc/image/uart-ttl-recv1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renyangang/riscv-mcu/51faad5b2843079a48ea5fe4b4ce74040e65b381/doc/image/uart-ttl-recv1.png -------------------------------------------------------------------------------- /doc/image/uart-ttl-recv2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renyangang/riscv-mcu/51faad5b2843079a48ea5fe4b4ce74040e65b381/doc/image/uart-ttl-recv2.png -------------------------------------------------------------------------------- /doc/image/uart-ttl-send.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renyangang/riscv-mcu/51faad5b2843079a48ea5fe4b4ce74040e65b381/doc/image/uart-ttl-send.png -------------------------------------------------------------------------------- /doc/image/uart.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renyangang/riscv-mcu/51faad5b2843079a48ea5fe4b4ce74040e65b381/doc/image/uart.gif -------------------------------------------------------------------------------- /doc/image/uart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renyangang/riscv-mcu/51faad5b2843079a48ea5fe4b4ce74040e65b381/doc/image/uart.png -------------------------------------------------------------------------------- /doc/uart_zh.md: -------------------------------------------------------------------------------- 1 | # UART 串口通信 2 | 3 | ## 1. 简介 4 | 5 | UART(Universal Asynchronous Receiver/Transmitter,通用异步收发传输器)是一种串行通信协议,用于在微控制器和其他设备之间传输数据。UART 通信使用串行数据线(TX)和串行接收线(RX)进行数据传输,通过设置波特率、数据位、停止位和校验位等参数来控制通信速率和数据格式。 6 | 7 | ## 2. 硬件实现 8 | ![uart控制器与外设连接图](image/uart.png) 9 | 10 | 1. UART控制器 11 | ![![uart控制器](image/uart-controller.png)](image/uart-controller.png) 12 | > 通过UART-TTL模块实现串口数据的收发,模块具体实现见后文。 13 | 14 | 控制器内存映射地址及用途如下: 15 | > | 地址 | 大小 | 用途 | 16 | | ---- | ---- | ---- | 17 | | 0xA0000100 | 4B | 串口配置寄存器,配置波特率、起始位、校验位、停止位等信息(硬件暂未实现) | 18 | | 0xA0000104 | 1B | 串口字节发送地址,通过将字节写入本地址将串口数据发送给外设 | 19 | | 0xA0000108 | 4B | 串口读取位置地址写入,通知控制器已经读取的缓存区位置,用于缓存区释放和中断取消 | 20 | | 0xA000010C | 4B | 串口接收到的数据缓存区末尾地址,读取时可以判断是否读取完毕,缓存区使用了DMA,所以程序中可以直接读取内存 | 21 | | 0xA0000110 | 4B | 串口控制器状态获取,目前只有最低位有效,为1时可以写入,为0时表示正在发送数据 | 22 | 发送部分TX和发送使能,分别与外部CPU进行接线,发送数据宽度8bits。 23 | 接受部分,在接收到数据后,会自动写入DMA,从0xC0000000基地址开始写入,并发送中断信号给PLIC控制器。 24 | 25 | 26 | 2. UART-TTL模块 27 | ![uart-ttl模块](image/uart-ttl-send.png) 28 | > UART-TTL模块发送部分,通过一个状态机实现。发送部分比较简单,分为三个状态:等待发送、发送、发送完成。 29 | 待发送的字节数据通过添加起始位和停止位,然后通过串口发送出去。 30 | 通过一个计数器将时钟进行分频,分频后按照顺序发送数据位。 31 | 32 | ![uart-ttl模块](image/uart-ttl-recv1.png) 33 | ![uart-ttl模块](image/uart-ttl-recv2.png) 34 | > UART-TTL模块接受部分,通过一个状态机实现。串口接收的部分比较复杂,分为4个状态:等待开始、接受、等待停止、等待写入缓存。 35 | 利用分频的时钟,实现16倍的采样电路,通过采样投票来实现数据位确定,避免串口通信中的抖动问题。(在仿真中只是演示过程,实际仿真中不会出现抖动杂波) 36 | 37 | 2. 串口中断外设 38 | ![uart-term](image/uart-term.png) 39 | > 通过UART-TTL模块接受串口字符,并显示到终端字符屏幕上,可以用作整个mcu系统的输出。 40 | 41 | ## 3. 软件实现 42 | 43 | 在bsp目录下增加uart封装,主要实现了三个接口: 44 | send_data、read_data、send_string,分别用于发送数据、读取数据、发送字符串。 45 | 46 | ```c 47 | #ifndef UART_H 48 | #define UART_H 49 | 50 | #include "types.h" 51 | 52 | // Set baud rate, start bit, stop bit and other communication configurations 53 | // note: this is reserved for future use 54 | #define UART_CONFIG_ADDR 0xA0000100 55 | // Write data to the UART 56 | #define UART_WRITE_ADDR 0xA0000104 57 | // after read data from the UART, set current read address for clear interupt 58 | #define UART_SET_READEND_ADDR 0xA0000108 59 | // current data bufer end address 60 | #define UART_CUR_BUFEND_ADDR 0xA000010C 61 | // get uart current status bit 0 writeable other bits reserved (read only) 62 | #define UART_STATUS_ADDR 0xA0000110 63 | // data buffer start address 64 | #define UART_DMA_BASE 0xC0000000 65 | 66 | 67 | void send_data(uint8_t *data, uint32_t len); 68 | uint32_t read_data(uint8_t *data, uint32_t len); 69 | 70 | void send_string(const char *str); 71 | 72 | #endif 73 | ``` 74 | 75 | 在示例程序中,在之前的gpio控制基础上,每次led切换和控制模式切换,增加了串口日志打印: 76 | ```c 77 | void flash_timer_handler() { 78 | ... 79 | send_string("led status changed\n"); 80 | add_soft_timer(500, flash_timer_handler); 81 | } 82 | 83 | void mode_change_handler() { 84 | mode = get_pin(10); 85 | clear_gpio_int(); 86 | send_string("led flash mode changed\n"); 87 | } 88 | ``` 89 | 90 | ## 4. 运行效果 91 | 92 | ![uart-term](image/uart.gif) -------------------------------------------------------------------------------- /fpga_soc/TODO: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renyangang/riscv-mcu/51faad5b2843079a48ea5fe4b4ce74040e65b381/fpga_soc/TODO -------------------------------------------------------------------------------- /netlist/digital/CUPL_risc-v-computer/CUPL.PLD: -------------------------------------------------------------------------------- 1 | Name risc-v-computer.dig ; 2 | PartNo 00 ; 3 | Date 04.09.2024 ; 4 | Revision 01 ; 5 | Designer ? ; 6 | Company unknown ; 7 | Assembly None ; 8 | Location unknown ; 9 | Device g16v8a ; 10 | 11 | /* inputs */ 12 | 13 | /* outputs */ 14 | PIN 12 = Y; 15 | 16 | /* combinatorial logic */ 17 | Y = 'b'0; 18 | -------------------------------------------------------------------------------- /netlist/digital/addr-compare.dig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 2 4 | 5 | 6 | backgroundColor 7 | 8 | 0 9 | 255 10 | 255 11 | 255 12 | 13 | 14 | 15 | Label 16 | addr-compare 17 | 18 | 19 | romContent 20 | 21 | 22 | 23 | 24 | 25 | Width 26 | 5 27 | 28 | 29 | 30 | 31 | In 32 | 33 | 34 | Label 35 | Addr_in1 36 | 37 | 38 | Bits 39 | 32 40 | 41 | 42 | 43 | 44 | 45 | In 46 | 47 | 48 | Label 49 | Addr_in2 50 | 51 | 52 | Bits 53 | 32 54 | 55 | 56 | 57 | 58 | 59 | Comparator 60 | 61 | 62 | Bits 63 | 32 64 | 65 | 66 | 67 | 68 | 69 | XOr 70 | 71 | 72 | Bits 73 | 32 74 | 75 | 76 | wideShape 77 | true 78 | 79 | 80 | 81 | 82 | 83 | Const 84 | 85 | 86 | Value 87 | 0 88 | 89 | 90 | Bits 91 | 32 92 | 93 | 94 | 95 | 96 | 97 | Out 98 | 99 | 100 | Label 101 | Eq_out 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /netlist/digital/mechine-op-unit.dig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 2 4 | 5 | 6 | Label 7 | mechine-op-unit 8 | 9 | 10 | romContent 11 | 12 | 13 | 14 | 15 | 16 | Width 17 | 8 18 | 19 | 20 | 21 | 22 | In 23 | 24 | 25 | Label 26 | mechine_op 27 | 28 | 29 | Bits 30 | 8 31 | 32 | 33 | 34 | 35 | 36 | Splitter 37 | 38 | 39 | Input Splitting 40 | 8 41 | 42 | 43 | Output Splitting 44 | 1,1,1,1,1,1,1,1 45 | 46 | 47 | 48 | 49 | 50 | Tunnel 51 | 52 | 53 | NetName 54 | ebreak 55 | 56 | 57 | 58 | 59 | 60 | Tunnel 61 | 62 | 63 | NetName 64 | ecall 65 | 66 | 67 | 68 | 69 | 70 | Tunnel 71 | 72 | 73 | NetName 74 | mret 75 | 76 | 77 | 78 | 79 | 80 | Tunnel 81 | 82 | 83 | NetName 84 | sfence.vma 85 | 86 | 87 | 88 | 89 | 90 | Tunnel 91 | 92 | 93 | NetName 94 | sret 95 | 96 | 97 | 98 | 99 | 100 | Tunnel 101 | 102 | 103 | NetName 104 | wfi 105 | 106 | 107 | 108 | 109 | 110 | Tunnel 111 | 112 | 113 | NetName 114 | fence 115 | 116 | 117 | 118 | 119 | 120 | Tunnel 121 | 122 | 123 | NetName 124 | fence.i 125 | 126 | 127 | 128 | 129 | 130 | Tunnel 131 | 132 | 133 | rotation 134 | 135 | 136 | 137 | NetName 138 | mret 139 | 140 | 141 | 142 | 143 | 144 | Out 145 | 146 | 147 | Label 148 | mret 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | -------------------------------------------------------------------------------- /netlist/src/Makefile: -------------------------------------------------------------------------------- 1 | LD := riscv32-unknown-linux-gnu-ld 2 | AS := riscv32-unknown-linux-gnu-as 3 | CC := riscv32-unknown-linux-gnu-gcc 4 | OBJCOPY := riscv32-unknown-linux-gnu-objcopy 5 | OBJDUMP := riscv32-unknown-linux-gnu-objdump 6 | 7 | OBJDIR := ./objs 8 | 9 | INCDIRS := examples \ 10 | bsp/common \ 11 | bsp/gpio \ 12 | bsp/interrupt \ 13 | bsp/uart \ 14 | bsp/iic \ 15 | bsp/timer 16 | 17 | SRCDIRS := . \ 18 | examples \ 19 | bsp/common \ 20 | bsp/gpio \ 21 | bsp/interrupt \ 22 | bsp/uart \ 23 | bsp/iic \ 24 | bsp/timer 25 | 26 | 27 | INCLUDE := $(patsubst %, -I %, $(INCDIRS)) 28 | 29 | SFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.S)) 30 | CFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.c)) 31 | 32 | SFILENDIR := $(notdir $(SFILES)) 33 | CFILENDIR := $(notdir $(CFILES)) 34 | 35 | SOBJS := $(patsubst %, $(OBJDIR)/%, $(SFILENDIR:.S=.o)) 36 | COBJS := $(patsubst %, $(OBJDIR)/%, $(CFILENDIR:.c=.o)) 37 | OBJS := $(SOBJS) $(COBJS) 38 | 39 | VPATH := $(SRCDIRS) 40 | 41 | all: boot.bin kernel.bin test.bin 42 | 43 | %.bin: $(OBJDIR)/%.elf 44 | $(OBJCOPY) -O binary -S $^ $@ 45 | 46 | $(OBJDIR)/test.elf: $(OBJDIR)/test.o 47 | $(LD) -o $@ $^ 48 | $(OBJDUMP) -D $@ > $@.asm 49 | 50 | $(OBJDIR)/boot.elf: $(OBJDIR)/boot.o 51 | $(LD) -T boot.ld -o $@ $^ 52 | $(OBJDUMP) -D $@ > $@.asm 53 | 54 | $(OBJDIR)/%.o: %.s 55 | mkdir -p $(OBJDIR) 56 | $(AS) -march=rv32i -mabi=ilp32 $(INCLUDE) -o $@ $^ 57 | 58 | $(COBJS) : $(OBJDIR)/%.o: %.c 59 | mkdir -p $(OBJDIR) 60 | $(CC) -march=rv32i -mabi=ilp32 -Wall -nostdlib -fno-builtin-memset $(INCLUDE) -c -O2 -o $@ $< 61 | 62 | $(OBJDIR)/kernel.elf: $(OBJDIR)/start.o $(COBJS) 63 | $(LD) -T kernel.ld -o $@ $^ 64 | $(OBJDUMP) -D $@ > $@.asm 65 | 66 | .PHONY: clean 67 | clean: 68 | rm -rf *.bin* *.o *.elf* *.hex objs -------------------------------------------------------------------------------- /netlist/src/boot.ld: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | /* boot rom */ 4 | FLASH (rwx) : ORIGIN = 0x80000000, LENGTH = 5120K 5 | /* gpio and so on */ 6 | PERIPHERAL(rwx): ORIGIN = 0xA0000000, LENGTH = 128K 7 | RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 128K 8 | } 9 | 10 | ENTRY(_start) 11 | 12 | SECTIONS 13 | { 14 | . = ALIGN(4); 15 | .text 0x80000000: { 16 | *(.text) 17 | _etext = .; 18 | } > FLASH 19 | } 20 | -------------------------------------------------------------------------------- /netlist/src/boot.s: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | .section .text 17 | .global _start 18 | _start: 19 | # cust flag set instruction code 20 | .insn 0x8000007F 21 | # close interrupts 22 | csrrw t0,mstatus,zero 23 | # ssd base address 24 | li t1, 0x40000000 25 | # offset 26 | li t2, 0x2000000 27 | # total 4096 bytes 28 | li t3, 0x2003000 29 | 30 | load: 31 | lbu a1, 0(t1) 32 | sb a1, 0(t2) 33 | addi t1, t1, 1 34 | addi t2, t2, 1 35 | bltu t2, t3, load 36 | # set boot status 37 | li t1, 0xC0000100 38 | csrrw t2,misa, t1 39 | csrrw t2,mvendorid,zero 40 | csrrw t2,marchid,zero 41 | csrrw t2,mimpid,zero 42 | csrrw t2,mhartid,zero 43 | csrrw t2,mtvec,zero 44 | csrrw t2,mepc,zero 45 | csrrw t2,mcause,zero 46 | csrrw t2,mtval,zero 47 | csrrw t2,mip,zero 48 | csrrw t2,mie,zero 49 | li t3,0x1808 50 | csrrw t2,mstatus,t3 51 | # clear all registers 52 | li t0, 0 53 | li t1, 0 54 | li t2, 0 55 | li t3, 0 56 | li t4, 0 57 | li a1, 0 58 | 59 | # jump to start 60 | call 0x2000000 61 | -------------------------------------------------------------------------------- /netlist/src/bsp/common/common.c: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | #include "common.h" 17 | 18 | #define HEAP_BASE 0x01100000 19 | 20 | 21 | void* memset(void* s, uint8_t c, size_t n) { 22 | unsigned char* p = s; 23 | while (n--) { 24 | *p++ = (unsigned char)c; 25 | } 26 | return s; 27 | } 28 | 29 | uint8_t atoi(const char* str) { 30 | uint8_t res = 0; 31 | while (*str) { 32 | res = res * 10 + (*str++ - '0'); 33 | } 34 | return res; 35 | } 36 | 37 | char* itoa(int value, char* str) { 38 | char digits[] = "0123456789"; 39 | str[3] = '\0'; 40 | char* ptr = &str[2]; 41 | 42 | do { 43 | int digit = 0; 44 | int temp = value; 45 | while (temp >= 10) { 46 | temp -= 10; 47 | digit++; 48 | } 49 | *ptr-- = digits[temp]; 50 | 51 | value = digit; 52 | } while (value > 0); 53 | return str; 54 | } -------------------------------------------------------------------------------- /netlist/src/bsp/common/common.h: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | #ifndef COMMON_H 17 | #define COMMON_H 18 | 19 | #include "types.h" 20 | 21 | void* memset(void* s, uint8_t c, size_t n); 22 | 23 | uint8_t atoi(const char* str); 24 | 25 | char* itoa(int value, char* str); 26 | 27 | #endif /* COMMON_H */ -------------------------------------------------------------------------------- /netlist/src/bsp/common/types.h: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | #ifndef TYPES_H 17 | #define TYPES_H 18 | 19 | typedef signed char int8_t; 20 | typedef unsigned char uint8_t; 21 | typedef signed short int16_t; 22 | typedef unsigned short uint16_t; 23 | typedef signed int int32_t; 24 | typedef unsigned int uint32_t; 25 | typedef signed long long int64_t; 26 | typedef unsigned long long uint64_t; 27 | 28 | typedef uint32_t size_t; 29 | #define NULL 0 30 | 31 | #endif -------------------------------------------------------------------------------- /netlist/src/bsp/gpio/gpio.c: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | #include "gpio.h" 17 | 18 | void set_pin_mode(int pin, int mode) { 19 | if(mode) { 20 | *(int*)GPIO_CONFIG_ADDR = *(int*)GPIO_CONFIG_ADDR | (mode << (pin - 1)); 21 | } else { 22 | *(int*)GPIO_CONFIG_ADDR = *(int*)GPIO_CONFIG_ADDR & ~(mode << (pin - 1)); 23 | } 24 | } 25 | 26 | void set_all_pins_mode(int mode) { 27 | *(int*)GPIO_CONFIG_ADDR = mode; 28 | } 29 | 30 | void set_pin(int pin, int value) { 31 | if(value) { 32 | *(int*)GPIO_DATA_ADDR = *(int*)GPIO_DATA_ADDR | (1 << (pin - 1)); 33 | } else { 34 | *(int*)GPIO_DATA_ADDR = *(int*)GPIO_DATA_ADDR & ~(1 << (pin - 1)); 35 | } 36 | } 37 | 38 | void set_all_pins(int value) { 39 | *(int*)GPIO_DATA_ADDR = value; 40 | } 41 | 42 | int get_all_pins() { 43 | return *(int*)GPIO_DATA_ADDR; 44 | } 45 | 46 | int get_pin(int pin) { 47 | return *(int*)GPIO_DATA_ADDR & (1 << (pin - 1)); 48 | } 49 | 50 | void clear_gpio_int() { 51 | *(int*)GPIO_INT_CLEAR_ADDR = 0; 52 | } -------------------------------------------------------------------------------- /netlist/src/bsp/gpio/gpio.h: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | #ifndef GPIO_H 17 | #define GPIO_H 18 | 19 | // GPIO address 20 | #define GPIO_CONFIG_ADDR 0xA0000000 21 | #define GPIO_DATA_ADDR 0xA0000004 22 | #define GPIO_INT_CLEAR_ADDR 0xA0000008 23 | 24 | #define GPIO_INPUT_MODE 0 25 | #define GPIO_OUTPUT_MODE 1 26 | 27 | // gpio mode set functions 28 | void set_pin_mode(int pin, int mode); 29 | void set_all_pins_mode(int mode); 30 | // gpio value set functions 31 | void set_pin(int pin, int value); 32 | void set_all_pins(int value); 33 | int get_pin(int pin); 34 | int get_all_pins(); 35 | // clear gpio interrupt 36 | void clear_gpio_int(); 37 | 38 | #endif -------------------------------------------------------------------------------- /netlist/src/bsp/iic/iic.c: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | #include "iic.h" 17 | #include "interrupt.h" 18 | 19 | static volatile uint32_t* iic_op = (volatile uint32_t*)IIC_OPERATION_ADDR; 20 | static volatile uint32_t* iic_res_buf = (volatile uint32_t*)IIC_READBUF_ADDR; 21 | static uint32_t iic_int_status = 0; 22 | static uint32_t iic_int_reg_status = 0; 23 | 24 | inline static void iic_int_proc() { 25 | iic_int_status = 1; 26 | } 27 | 28 | inline static void iin_int_status_clear() { 29 | iic_int_status = 0; 30 | } 31 | 32 | inline static void wait_iic_int() { 33 | // wait for interrupt or op flag complate ,this is not a good way, just for leaning 34 | while(iic_int_status == 0 && (*iic_res_buf & 0x1)); 35 | } 36 | 37 | void iic_init(void) { 38 | if(iic_int_reg_status == 0) { 39 | register_peripheral_int_handler(INT_IIC, iic_int_proc); 40 | iic_int_reg_status = 1; 41 | } 42 | iin_int_status_clear(); 43 | } 44 | 45 | void iic_write(uint8_t dev_addr, uint8_t reg_addr, uint8_t data) { 46 | iic_init(); 47 | uint32_t op = 0; 48 | op |= (dev_addr << 1); 49 | op |= (reg_addr << 8); 50 | op |= (data << 16); 51 | *iic_op = op; 52 | wait_iic_int(); 53 | } 54 | 55 | uint8_t iic_read(uint8_t dev_addr, uint8_t reg_addr) { 56 | iic_init(); 57 | uint32_t op = 0; 58 | op |= 0x1; 59 | op |= (dev_addr << 1); 60 | // reg_addr is ignored 61 | *iic_op = op; 62 | wait_iic_int(); 63 | // read data 64 | uint8_t r = (uint8_t)(((*iic_res_buf) >> 8) & 0xFF); 65 | return r; 66 | } -------------------------------------------------------------------------------- /netlist/src/bsp/iic/iic.h: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | #ifndef IIC_H 17 | #define IIC_H 18 | 19 | #include "types.h" 20 | 21 | /*** 22 | 0xA0000200 -> IIC opration config address 23 | (bits[1-7]: dev address, bit[0]: read/write) 24 | (bits[8-15]: reg address valid in write mode) 25 | (bits[16-23]: data only support 1 byte valid in write mode) 26 | (bits[24-31]: reserved) 27 | 0xA0000204 -> IIC read buffer address 28 | (bits[1-7]: reserved, bit[0]: opration status 0 doing 1 complate) 29 | (bits[8-15]: data only support 1 byte valid in read mode) 30 | (bits[16-31]: reserved) 31 | */ 32 | 33 | #define IIC_OPERATION_ADDR 0xA0000200 34 | #define IIC_READBUF_ADDR 0xA0000204 35 | 36 | 37 | void iic_write(uint8_t dev_addr, uint8_t reg_addr, uint8_t data); 38 | uint8_t iic_read(uint8_t dev_addr, uint8_t reg_addr); 39 | 40 | #endif -------------------------------------------------------------------------------- /netlist/src/bsp/interrupt/interrupt.c: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | #include "interrupt.h" 17 | #include "uart.h" 18 | #include "common.h" 19 | 20 | static int_handler_t int_handler[PERIPHERAL_INT_NUM] = {NULL}; 21 | static int_handler_t timer_handler = NULL; 22 | 23 | static uint32_t cur_int_mode = 0; 24 | 25 | void register_peripheral_int_handler(int int_num, int_handler_t handler) { 26 | int_handler[int_num] = handler; 27 | if(cur_int_mode < PERIPHERAL_INT) { 28 | cur_int_mode |= PERIPHERAL_INT; 29 | set_mie(cur_int_mode); 30 | } 31 | } 32 | 33 | void register_timer_int_handler(int_handler_t handler) { 34 | timer_handler = handler; 35 | cur_int_mode |= TIMER_INT; 36 | set_mie(cur_int_mode); 37 | } 38 | 39 | void exception_handler() { 40 | return; 41 | } 42 | 43 | void int_timer_handler() { 44 | if(timer_handler) { 45 | timer_handler(); 46 | } 47 | return; 48 | } 49 | 50 | void int_peripheral_handler() { 51 | // send_string("int peripheral handler\n"); 52 | uint32_t int_code = *(uint32_t *)INT_CODE_ADDR; 53 | if(int_handler[int_code]) { 54 | int_handler[int_code](); 55 | } 56 | return; 57 | } 58 | 59 | -------------------------------------------------------------------------------- /netlist/src/bsp/interrupt/interrupt.h: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | #ifndef INTERRUPT_H 17 | #define INTERRUPT_H 18 | #include "types.h" 19 | 20 | #define TIMER_INT 0x80 21 | #define PERIPHERAL_INT 0x800 22 | #define SOFT_INT 0x8 23 | 24 | #define INT_CODE_ADDR 0xB0001000 25 | 26 | #define PERIPHERAL_INT_NUM 5 27 | #define INT_GPIO 0x1 28 | #define INT_UART 0x2 29 | #define INT_IIC 0x3 30 | 31 | typedef void (*int_handler_t)(void); 32 | 33 | void register_peripheral_int_handler(int int_num, int_handler_t handler); 34 | void register_timer_int_handler(int_handler_t handler); 35 | 36 | extern void set_mie(int mie); 37 | 38 | #endif -------------------------------------------------------------------------------- /netlist/src/bsp/timer/timer.c: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | #include "timer.h" 17 | #include "interrupt.h" 18 | 19 | static soft_timer_t soft_timers[MAX_SOFT_TIMER_NUM]; 20 | 21 | uint64_t get_mtime_cur() { 22 | return *(uint64_t*)MTIME_LOW;; 23 | } 24 | 25 | uint64_t get_mtime_cmp() { 26 | return *(uint64_t*)MTIME_CMP_LOW;; 27 | } 28 | 29 | void set_mtime_cmp(uint64_t cmp) { 30 | *(uint32_t*)MTIME_CMP_HIGH = cmp >> 32; 31 | *(uint32_t*)MTIME_CMP_LOW = cmp & 0xffffffff; 32 | } 33 | 34 | static void set_timer_after(int ms) { 35 | uint64_t ctime = get_mtime_cur(); 36 | set_mtime_cmp(ctime + ms); 37 | } 38 | 39 | int add_soft_timer(uint64_t ms, soft_callback call_back) { 40 | for(int i = 0; i < MAX_SOFT_TIMER_NUM; i++) { 41 | if(soft_timers[i].call_back == NULL) { 42 | soft_timers[i].call_back = call_back; 43 | soft_timers[i].ms_wakeup = get_mtime_cur() + ms; 44 | return 0; 45 | } 46 | } 47 | return 1; // no space 48 | } 49 | 50 | void init_global_timer() { 51 | for(int i = 0; i < MAX_SOFT_TIMER_NUM; i++) { 52 | soft_timers[i].call_back = NULL; 53 | } 54 | set_timer_after(300); 55 | register_timer_int_handler(interrupt_timer_handler); 56 | } 57 | 58 | void interrupt_timer_handler() { 59 | for(int i = 0; i < MAX_SOFT_TIMER_NUM; i++) { 60 | if(soft_timers[i].call_back != NULL) { 61 | if(soft_timers[i].ms_wakeup <= get_mtime_cur()) { 62 | soft_timers[i].call_back(); 63 | soft_timers[i].call_back = NULL; 64 | } 65 | } 66 | } 67 | set_timer_after(100); 68 | } 69 | 70 | void sleep(uint64_t ms) { 71 | uint64_t ctime = get_mtime_cur() + ms; 72 | while(get_mtime_cur() < ctime) { 73 | __asm__ __volatile__("nop"); 74 | } 75 | } -------------------------------------------------------------------------------- /netlist/src/bsp/timer/timer.h: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | #ifndef TIMER_H 17 | #define TIMER_H 18 | #include "types.h" 19 | 20 | #define MTIME_CMP_LOW 0xB0000000 21 | #define MTIME_CMP_HIGH 0xB0000004 22 | #define MTIME_LOW 0xB0000008 23 | #define MTIME_HIGH 0xB000000C 24 | 25 | #define MAX_SOFT_TIMER_NUM 5 26 | 27 | typedef void (*soft_callback) (); 28 | 29 | typedef struct { 30 | uint64_t ms_wakeup; 31 | soft_callback call_back; 32 | } soft_timer_t; 33 | 34 | 35 | uint64_t get_mtime_cur(); 36 | uint64_t get_mtime_cmp(); 37 | 38 | int add_soft_timer(uint64_t ms, soft_callback call_back); 39 | 40 | /** 41 | * after kernel start, init a global timer 42 | * other timers in application can use soft timer 43 | * this global timer is used to recive timer interrupt and wake up soft timer 44 | */ 45 | void init_global_timer(); 46 | 47 | void interrupt_timer_handler(); 48 | 49 | void sleep(uint64_t ms); 50 | 51 | #endif -------------------------------------------------------------------------------- /netlist/src/bsp/uart/uart.c: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | #include "uart.h" 17 | #include "timer.h" 18 | #include "interrupt.h" 19 | 20 | static volatile uint8_t* write_buffer = (volatile uint8_t*)UART_WRITE_ADDR; 21 | static volatile uint8_t* read_buffer = (volatile uint8_t*)UART_DMA_BASE; 22 | static volatile uint32_t* buffer_end = (volatile uint32_t*)UART_CUR_BUFEND_ADDR; 23 | 24 | static volatile uint32_t uart_int_reg_status = 0; 25 | static volatile uint32_t uart_int_status = 0; 26 | 27 | void uart_int_proc() { 28 | uart_int_status = 1; 29 | // send_string("Interrupt received\n"); 30 | } 31 | 32 | void uart_init(void) { 33 | if(uart_int_reg_status == 0) { 34 | register_peripheral_int_handler(INT_UART, uart_int_proc); 35 | uart_int_reg_status = 1; 36 | } 37 | uart_int_status = 0; 38 | } 39 | 40 | 41 | void send_char(uint8_t c) { 42 | *write_buffer = c; 43 | while (!(*((volatile uint32_t*)UART_STATUS_ADDR) & 0x1)); // Wait for the previous byte to be sent 44 | } 45 | 46 | void send_data(uint8_t *data, uint32_t len) { 47 | for (uint32_t i = 0; i < len; i++) { 48 | send_char(data[i]); 49 | } 50 | } 51 | 52 | uint32_t read_data(uint8_t *data, uint32_t len) { 53 | uint32_t r_len = 0; 54 | uint8_t* ret_buffer = (uint8_t*)read_buffer; 55 | while (r_len < len && ret_buffer < (uint8_t*)(*buffer_end)) { 56 | data[r_len++] = *ret_buffer++; 57 | } 58 | *(volatile uint8_t**)UART_SET_READEND_ADDR = ret_buffer; 59 | return r_len; 60 | } 61 | 62 | void send_string(const char *str) { 63 | while (*str) { 64 | *write_buffer = *str++; 65 | while (!(*((volatile uint32_t*)UART_STATUS_ADDR) & 0x1)); // Wait for the previous byte to be sent 66 | } 67 | } 68 | 69 | uint8_t getchar() { 70 | // send keyboard enable command 71 | send_char((uint8_t)0xFF); 72 | // read the character 73 | 74 | // waiting for the character to be received 75 | while (uart_int_status == 0 && read_buffer >= (uint8_t*)(*buffer_end)); 76 | uint8_t c = *read_buffer; 77 | // sleep(200); 78 | *(volatile uint8_t**)UART_SET_READEND_ADDR = read_buffer+4; 79 | while((uint8_t*)(*buffer_end) > read_buffer); 80 | uart_int_status = 0; 81 | return c; 82 | } -------------------------------------------------------------------------------- /netlist/src/bsp/uart/uart.h: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | #ifndef UART_H 17 | #define UART_H 18 | 19 | #include "types.h" 20 | 21 | // Set baud rate, start bit, stop bit and other communication configurations 22 | // note: this is reserved for future use 23 | #define UART_CONFIG_ADDR 0xA0000100 24 | // Write data to the UART 25 | #define UART_WRITE_ADDR 0xA0000104 26 | // after read data from the UART, set current read address for clear interupt 27 | #define UART_SET_READEND_ADDR 0xA0000108 28 | // current data bufer end address 29 | #define UART_CUR_BUFEND_ADDR 0xA000010C 30 | // get uart current status bit 0 writeable other bits reserved (read only) 31 | #define UART_STATUS_ADDR 0xA0000110 32 | // data buffer start address 33 | #define UART_DMA_BASE 0xC0000000 34 | 35 | void uart_init(void); 36 | 37 | void send_char(uint8_t c); 38 | void send_data(uint8_t *data, uint32_t len); 39 | uint32_t read_data(uint8_t *data, uint32_t len); 40 | // get char from uart keyboard 41 | uint8_t getchar(); 42 | void send_string(const char *str); 43 | 44 | #endif -------------------------------------------------------------------------------- /netlist/src/examples/guess.c: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | #include "guess.h" 17 | #include "iic.h" 18 | #include "uart.h" 19 | #include "timer.h" 20 | #include "common.h" 21 | 22 | void run_guess_game() { 23 | uart_init(); 24 | while(1){ 25 | iic_write(DEV_ADDRESS, MIN_REG_ADDR, MIN_NUMBER); 26 | iic_write(DEV_ADDRESS, MAX_REG_ADDR, MAX_NUMBER); 27 | while(1) { 28 | uint8_t fact_num = iic_read(DEV_ADDRESS, 0); 29 | while(1) { 30 | send_string("Guess one number between [1,100]: "); 31 | uint8_t guess_num[4] = {0,0,0,0}; 32 | int i = 0; 33 | while(i < 3) { 34 | uint8_t c = getchar(); 35 | if (c == 0xa) { 36 | break; 37 | } 38 | send_char(c); 39 | guess_num[i++] = c; 40 | } 41 | send_string("\n"); 42 | uint8_t guess = atoi((char*)guess_num); 43 | if (guess == fact_num) { 44 | send_string("You win!\n"); 45 | break; 46 | } else if( guess > fact_num) { 47 | send_string("Too large!\n"); 48 | } else { 49 | send_string("Too small!\n"); 50 | } 51 | } 52 | } 53 | sleep(500); 54 | } 55 | } -------------------------------------------------------------------------------- /netlist/src/examples/guess.h: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | #ifndef GUESS_H 17 | #define GUESS_H 18 | 19 | #define MAX_NUMBER 100 20 | #define MIN_NUMBER 1 21 | 22 | #define DEV_ADDRESS 1 23 | #define MIN_REG_ADDR 1 24 | #define MAX_REG_ADDR 2 25 | 26 | 27 | void run_guess_game(); 28 | 29 | 30 | #endif -------------------------------------------------------------------------------- /netlist/src/kernel.ld: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | /* boot rom */ 4 | FLASH (rwx) : ORIGIN = 0x80000000, LENGTH = 5120K 5 | /* gpio and so on */ 6 | PERIPHERAL(rwx): ORIGIN = 0xA0000000, LENGTH = 128K 7 | RAM (rwx) : ORIGIN = 0x2000000, LENGTH = 128K 8 | } 9 | 10 | ENTRY(_start) 11 | 12 | SECTIONS 13 | { 14 | . = ALIGN(4); 15 | .text 0x2000000: { 16 | . = 0x0; 17 | . = ALIGN(4); 18 | *(.starttext) 19 | . = ALIGN(4); 20 | _int_begin = .; 21 | *(.exceptiontext) 22 | . = ALIGN(4); 23 | . = (_int_begin + 0x1C); 24 | *(.timerinttext) 25 | . = ALIGN(4); 26 | . = (_int_begin + 0x2C); 27 | *(.peripheralinttext) 28 | . = ALIGN(4); 29 | *(.text) 30 | _etext = .; 31 | } > RAM =0x13000000 32 | .rodata ALIGN(4) : {*(.rodata*)} > RAM 33 | .data ALIGN(4) : { *(.data) } > RAM 34 | __bss_start = .; 35 | .bss ALIGN(4) : { *(.bss) *(COMMON) } > RAM 36 | __bss_end = .; 37 | } 38 | -------------------------------------------------------------------------------- /netlist/src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | #include "gpio.h" 17 | #include "timer.h" 18 | #include "interrupt.h" 19 | #include "uart.h" 20 | #include "guess.h" 21 | 22 | static int mode = 0; 23 | 24 | void flash_by_sleep() { 25 | // set low 7 pins of port D as output 26 | set_all_pins_mode(0x7f); 27 | for(;;) { 28 | mode = get_pin(10); 29 | if(mode) { 30 | set_all_pins(get_all_pins() | 0x7f); 31 | sleep(500); 32 | set_all_pins(get_all_pins() & ~0x7f); 33 | sleep(500); 34 | } else { 35 | for(int i=1;i<8 && mode==0;i++) { 36 | set_pin(i, 1); 37 | sleep(500); 38 | set_pin(i, 0); 39 | } 40 | } 41 | } 42 | } 43 | 44 | static int cur_pin = 0; 45 | static int cur_pins_status = 0; 46 | 47 | void flash_timer_handler() { 48 | // set low 7 pins of port D as output 49 | set_all_pins_mode(0x7f); 50 | if(mode) { 51 | if(cur_pins_status) { 52 | set_all_pins(get_all_pins() & ~0x7f); 53 | cur_pins_status = 0; 54 | }else{ 55 | set_all_pins(get_all_pins() | 0x7f); 56 | cur_pins_status = 1; 57 | } 58 | } else { 59 | set_all_pins(get_all_pins() & ~0x7f); 60 | cur_pin++; 61 | if(cur_pin > 7) { 62 | cur_pin = 1; 63 | } 64 | set_pin(cur_pin, 1); 65 | } 66 | send_string("led status changed\n"); 67 | add_soft_timer(500, flash_timer_handler); 68 | } 69 | 70 | void mode_change_handler() { 71 | mode = get_pin(10); 72 | clear_gpio_int(); 73 | send_string("led flash mode changed\n"); 74 | } 75 | 76 | void flash_by_interrupt() { 77 | init_global_timer(); 78 | add_soft_timer(500, flash_timer_handler); 79 | register_peripheral_int_handler(INT_GPIO,mode_change_handler); 80 | for(;;) {} 81 | } 82 | 83 | int main() { 84 | flash_by_sleep(); 85 | flash_by_interrupt(); 86 | // run_guess_game(); 87 | return 0; 88 | } -------------------------------------------------------------------------------- /netlist/src/memory-map.txt: -------------------------------------------------------------------------------- 1 | 0xC0000000 -> uart DMA base (upward growth) 2 | 0x80000000 -> rom boot base 3 | 0x40000000 -> ssd load base 4 | 0x02000000 -> kernel memory base 5 | 0x01100000 -> kernel heap base (upward growth) 6 | 0x01000000 -> kernel stack base (downward growth) 7 | 8 | 9 | 0xB0000000 -> mtimecmp low 32bits 10 | 0xB0000004 -> mtimecmp high 32bits 11 | 0xB0000008 -> mtime low 32bits read only 12 | 0xB000000C -> mtime high 32bits read only 13 | 0xB0001000 -> peripheral interrupts code (read only) 14 | 15 | 0xA0000000 -> GPIO setbits 32bits (low 10bits are used, 1 output 0 input) 16 | 0xA0000004 -> GPIO bits 32bits (low 10bits are used) 17 | 0xA0000008 -> GPIO interrupts clear 32bits (set to 0x0) 18 | 19 | 0xA0000100 -> uart config address (reserved) 20 | 0xA0000104 -> uart write data buffer address 21 | 0xA0000108 -> set uart current read end address 22 | 0xA000010C -> get uart current read buffer end address (read only) 23 | 0xA0000110 -> get uart current status bit 0 writeable other bits reserved (read only) 24 | 25 | 0xA0000200 -> IIC opration config address 26 | (bits[1-7]: dev address, bit[0]: read/write) 27 | (bits[8-15]: reg address valid in write mode) 28 | (bits[16-23]: data only support 1 byte valid in write mode) 29 | (bits[24-31]: reserved) 30 | 0xA0000204 -> IIC read buffer address 31 | (bits[1-7]: reserved, bit[0]: opration status 0 doing 1 complate) 32 | (bits[8-15]: data only support 1 byte valid in read mode) 33 | (bits[16-31]: reserved) 34 | -------------------------------------------------------------------------------- /netlist/src/mkhex.py: -------------------------------------------------------------------------------- 1 | hex1text = 'v2.0 raw\n' 2 | hex2text = 'v2.0 raw\n' 3 | hex3text = 'v2.0 raw\n' 4 | hex4text = 'v2.0 raw\n' 5 | kerneltext = 'v2.0 raw\n' 6 | testtext = '' 7 | 8 | with open('./boot.bin',mode='rb') as f: 9 | bts = f.read() 10 | hexs = bts.hex(' ').split(' ') 11 | i = 0 12 | while i < len(hexs): 13 | hex1text += f'{hexs[i]}\n' 14 | hex2text += f'{hexs[i+1]}\n' 15 | hex3text += f'{hexs[i+2]}\n' 16 | hex4text += f'{hexs[i+3]}\n' 17 | i += 4 18 | 19 | with open('./1.hex',mode='w') as f: 20 | f.write(hex1text) 21 | 22 | with open('./2.hex',mode='w') as f: 23 | f.write(hex2text) 24 | 25 | with open('./3.hex',mode='w') as f: 26 | f.write(hex3text) 27 | 28 | with open('./4.hex',mode='w') as f: 29 | f.write(hex4text) 30 | 31 | with open('./kernel.bin',mode='rb') as f: 32 | bts = f.read() 33 | hexs = bts.hex(' ').split(' ') 34 | i = 0 35 | while i < len(hexs): 36 | kerneltext += f'{hexs[i]}\n' 37 | i += 1 38 | 39 | with open('./kernel.hex',mode='w') as f: 40 | f.write(kerneltext) 41 | 42 | # with open('./test.bin',mode='rb') as f: 43 | # bts = f.read() 44 | # hexs = bts.hex(' ').split(' ') 45 | # i = 0 46 | # while i < len(hexs): 47 | # testtext += f'{hexs[i]}\n' 48 | # i += 1 49 | 50 | # with open('../verilog/test.hex',mode='w') as f: 51 | # f.write(testtext) 52 | -------------------------------------------------------------------------------- /netlist/src/start.s: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | .section .starttext 17 | .global _start 18 | .global set_mie 19 | _start: 20 | # register interrupts handler 21 | la a5,int_handler 22 | addi a5,a5, 0x1 23 | csrrw t2,mtvec,a5 24 | # open interrupts 25 | li t3,0x1808 26 | csrrw t2,mstatus,t3 27 | # set sp 28 | li sp, 0x01000000 29 | # goto c main 30 | call main 31 | 32 | .section .exceptiontext 33 | int_handler: 34 | call inner_exception_handler 35 | mret 36 | 37 | .section .timerinttext 38 | timer_handler: 39 | call int_timer_handler 40 | mret 41 | 42 | .section .peripheralinttext 43 | peripheral_handler: 44 | call save_regs 45 | call int_peripheral_handler 46 | call restore_regs 47 | mret 48 | 49 | .section .text 50 | set_mie: 51 | csrrw t2,mie,a0 52 | ret 53 | 54 | save_regs: 55 | addi sp, sp, -24 56 | sw a2, 0(sp) 57 | sw a3, 4(sp) 58 | sw a4, 8(sp) 59 | sw a5, 12(sp) 60 | sw a6, 16(sp) 61 | sw a7, 20(sp) 62 | ret 63 | 64 | restore_regs: 65 | lw a2, 0(sp) 66 | lw a3, 4(sp) 67 | lw a4, 8(sp) 68 | lw a5, 12(sp) 69 | lw a6, 16(sp) 70 | lw a7, 20(sp) 71 | addi sp, sp, 24 72 | ret 73 | 74 | inner_timer_handler: 75 | call save_regs 76 | call int_timer_handler 77 | call restore_regs 78 | ret 79 | 80 | inner_exception_handler: 81 | call save_regs 82 | call exception_handler 83 | call restore_regs 84 | mret 85 | ret -------------------------------------------------------------------------------- /netlist/src/test.s: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | .section .text 17 | .global _start 18 | _start: 19 | li x1, 0x1 20 | li x2, 0x2 21 | b0: 22 | add x3, x1, x2 23 | li x4, 0x3 24 | # bne x3, x0, b0 25 | # beq x3, x0, b0 26 | # beq x3, x0, b1 27 | # bne x3, x0, b1 28 | # j b1 29 | lw x9, 68(x0) 30 | lw x10, 72(x0) 31 | li x5, 0x5 32 | addi x11, x3, 0x1 33 | # addi x10, x9, 0x1 34 | li x6, 0x6 35 | li x7, 0x7 36 | b1: 37 | li x8, 0x8 38 | li x12, 12 39 | li x13, 13 40 | li x14, 14 41 | 42 | d0: 43 | .rept 10 44 | .long 0x1 45 | .endr 46 | 47 | .end -------------------------------------------------------------------------------- /verilog/breath_led.v: -------------------------------------------------------------------------------- 1 | module breath_led( 2 | input clk_s, 3 | input clk_ss, 4 | input rst_n, 5 | output reg [7:0] led 6 | ); 7 | 8 | localparam COUNT_MAX = 15; 9 | 10 | reg [7:0] cnt_10ms; 11 | reg [7:0] cnt_100ms; 12 | reg [7:0] cnt_1s; 13 | reg led_en; 14 | 15 | always @(posedge clk_s or negedge rst_n) begin 16 | if(!rst_n) begin 17 | cnt_10ms <= 0; 18 | end 19 | else begin 20 | if (cnt_10ms == COUNT_MAX) begin 21 | cnt_10ms <= 0; 22 | end 23 | else begin 24 | cnt_10ms <= cnt_10ms + 1; 25 | end 26 | end 27 | end 28 | 29 | always @(posedge clk_s or negedge rst_n) begin 30 | if(!rst_n) begin 31 | cnt_100ms <= 0; 32 | end 33 | else begin 34 | if (cnt_100ms == COUNT_MAX) begin 35 | cnt_100ms <= 0; 36 | end 37 | else if(cnt_10ms == COUNT_MAX) begin 38 | cnt_100ms <= cnt_100ms + 1; 39 | end 40 | end 41 | end 42 | 43 | always @(posedge clk_s or negedge rst_n) begin 44 | if(!rst_n) begin 45 | cnt_1s <= 0; 46 | end 47 | else begin 48 | if (cnt_1s == COUNT_MAX) begin 49 | cnt_1s <= 0; 50 | end 51 | else if(cnt_100ms == COUNT_MAX) begin 52 | cnt_1s <= cnt_1s + 1; 53 | end 54 | end 55 | end 56 | 57 | always @(posedge clk_s or negedge rst_n) begin 58 | if(!rst_n) begin 59 | led_en <= 1'b0; 60 | end 61 | else begin 62 | if (cnt_1s == COUNT_MAX) begin 63 | led_en <= ~led_en; 64 | end 65 | end 66 | end 67 | 68 | always @(posedge clk_s or negedge rst_n) begin 69 | if(!rst_n) begin 70 | led <= 8'h00; 71 | end 72 | else begin 73 | if ((!led_en && cnt_100ms < cnt_1s) || (led_en && cnt_100ms >= cnt_1s)) begin 74 | led <= 8'hFF; 75 | end 76 | else begin 77 | led <= 8'h0; 78 | end 79 | end 80 | end 81 | 82 | endmodule -------------------------------------------------------------------------------- /verilog/common/fifo_async.v: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | Description: async fifo 17 | 18 | */ 19 | 20 | module fifo_async #(parameter DEPTH = 16, parameter WIDTH = 8) ( 21 | input wclk, 22 | input rclk, 23 | input rst_n, 24 | input wr_en, 25 | input rd_en, 26 | input [WIDTH-1:0] wr_data, 27 | output reg [WIDTH-1:0] rd_data, 28 | output wr_full, 29 | output rd_empty 30 | ); 31 | 32 | reg [WIDTH-1:0] data [DEPTH-1:0]; 33 | reg [$clog2(DEPTH):0] wr_ptr = 0; 34 | reg [$clog2(DEPTH):0] rd_ptr = 0; 35 | 36 | wire [$clog2(DEPTH)-1:0] wr_addr; 37 | wire [$clog2(DEPTH)-1:0] rd_addr; 38 | 39 | wire [$clog2(DEPTH):0] wr_ptr_gray; 40 | wire [$clog2(DEPTH):0] rd_ptr_gray; 41 | reg [$clog2(DEPTH):0] wr_ptr_gray_1; 42 | reg [$clog2(DEPTH):0] wr_ptr_gray_2; 43 | reg [$clog2(DEPTH):0] rd_ptr_gray_1; 44 | reg [$clog2(DEPTH):0] rd_ptr_gray_2; 45 | 46 | assign wr_addr = wr_ptr[$clog2(DEPTH)-1:0]; 47 | assign rd_addr = rd_ptr[$clog2(DEPTH)-1:0]; 48 | 49 | assign wr_ptr_gray = ((wr_ptr>>1) ^ wr_ptr); //指针转格雷码 50 | assign rd_ptr_gray = ((rd_ptr>>1) ^ rd_ptr); 51 | 52 | assign rd_empty = (rd_ptr_gray == wr_ptr_gray_2); 53 | assign wr_full = (wr_ptr_gray == {~rd_ptr_gray_2[$clog2(DEPTH):$clog2(DEPTH)-1], rd_ptr_gray_2[$clog2(DEPTH)-2:0]}); 54 | 55 | always@(posedge wclk or negedge rst_n) begin 56 | if(!rst_n) begin 57 | wr_ptr <= 0; 58 | end 59 | else if(wr_en && !wr_full)begin 60 | data[wr_addr] <= wr_data; 61 | wr_ptr <= wr_ptr + 1; 62 | end 63 | end 64 | 65 | always@(posedge rclk or negedge rst_n) begin 66 | if(!rst_n) 67 | rd_ptr <= 0; 68 | else if(rd_en && !rd_empty)begin 69 | rd_data <= data[rd_addr]; 70 | rd_ptr <= rd_ptr + 1; 71 | end 72 | end 73 | 74 | always@(posedge wclk or negedge rst_n) begin 75 | if(!rst_n)begin 76 | rd_ptr_gray_1 <= 0; 77 | rd_ptr_gray_2 <= 0; 78 | end 79 | else begin 80 | rd_ptr_gray_1 <= rd_ptr_gray; 81 | rd_ptr_gray_2 <= rd_ptr_gray_1; 82 | end 83 | end 84 | 85 | always@(posedge rclk or negedge rst_n) begin 86 | if(!rst_n)begin 87 | wr_ptr_gray_1 <= 0; 88 | wr_ptr_gray_2 <= 0; 89 | end 90 | else begin 91 | wr_ptr_gray_1 <= wr_ptr_gray; 92 | wr_ptr_gray_2 <= wr_ptr_gray_1; 93 | end 94 | end 95 | 96 | endmodule -------------------------------------------------------------------------------- /verilog/core/config.v: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | Description: global configuration and macros 17 | 18 | */ 19 | `define XLEN 32 20 | `define MAX_BIT_POS (`XLEN-1) 21 | `define CACHE_LINES 64 22 | `define CACHE_LINE_SIZE 16 23 | `define CACHE_LINE_WIDTH (`CACHE_LINE_SIZE*8) 24 | `define CACHE_WAYS 4 25 | 26 | `define BOOT_ADDR 32'h0000_0000 27 | 28 | `define GPIO_NUMS 32 29 | 30 | `define FLASH_ADDR_BASE `XLEN'h0000_0000 31 | `define FLASH_ADDR_END `XLEN'h00FF_FFFF 32 | `define INT_ADDR_BASE `XLEN'h0FFF_0000 33 | `define INT_ADDR_END `XLEN'h0FFF_F000 34 | `define TIMER_ADDR_BASE `XLEN'h0FFF_F000 35 | `define TIMER_ADDR_END `XLEN'h0FFF_FFFF 36 | `define SDRAM_ADDR_BASE `XLEN'h1000_0000 37 | `define SDRAM_ADDR_END `XLEN'h3FFF_FFFF 38 | `define GPIO_ADDR_BASE `XLEN'hC000_0000 39 | `define GPIO_ADDR_END `XLEN'hC000_0FFF 40 | `define UART_ADDR_BASE `XLEN'hC001_0000 41 | `define UART_ADDR_END `XLEN'hC001_0fff 42 | `define I2C_ADDR_BASE `XLEN'hC003_0000 43 | `define I2C_ADDR_END `XLEN'hC003_0fff 44 | `define SPI_ADDR_BASE `XLEN'hC005_0000 45 | `define SPI_ADDR_END `XLEN'hC005_0fff 46 | 47 | `define EXCEPT_ILLEGAL_INSTR `XLEN'd2 48 | `define EXCEPT_NONALIGNED_INST_ADDR `XLEN'd0 49 | 50 | // interrupt defines 51 | `define INT_CODE_WIDTH 8 52 | `define INT_CODE_NONE `INT_CODE_WIDTH'd0 53 | `define INT_CODE_GPIO `INT_CODE_WIDTH'd1 54 | `define INT_CODE_UART1_RX_READY `INT_CODE_WIDTH'd11 55 | `define INT_CODE_UART1_TX_READY `INT_CODE_WIDTH'd12 -------------------------------------------------------------------------------- /verilog/core/cpu_top.v: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | Description: CPU top module 17 | 封装CPU核心和总线模块,提供外部soc集成接口 18 | */ 19 | `include "config.v" 20 | module cpu_top( 21 | input wire clk, // 时钟信号 22 | input wire rst_n, // 复位信号 23 | input wire clk_timer, 24 | 25 | output wire [`MAX_BIT_POS:0] io_addr, 26 | output wire io_read, 27 | output wire io_write, 28 | output wire burst, 29 | output wire [2:0] burst_size, 30 | output wire read_ready, 31 | output wire [`MAX_BIT_POS:0] io_wdata, 32 | output wire [1:0] io_byte_size, 33 | input wire [`MAX_BIT_POS:0] io_rdata, 34 | input wire io_ready, 35 | input wire [`INT_CODE_WIDTH-1:0]peripheral_int_code 36 | ); 37 | 38 | wire read_en; 39 | wire [`MAX_BIT_POS:0] mem_addr; 40 | wire [`MAX_BIT_POS:0] rdata; 41 | wire write_en; 42 | wire [`MAX_BIT_POS:0] wdata; 43 | wire [1:0] byte_size; 44 | wire mem_busy; 45 | wire mem_ready; 46 | 47 | // interrupts and exceptions 48 | 49 | wire [`MAX_BIT_POS:0] exp_pc; 50 | wire [`MAX_BIT_POS:0] exp_pc_next; 51 | wire [`MAX_BIT_POS:0]exception_code; 52 | wire exception_en; 53 | wire [`MAX_BIT_POS:0] int_jmp_pc; 54 | wire int_jmp_en; 55 | wire mret_en; 56 | wire int_en; 57 | wire int_jmp_ready; 58 | 59 | // csr operations 60 | wire [11:0] csr_read_addr; 61 | wire [`MAX_BIT_POS:0] csr_data; 62 | wire [11:0] wb_csr_addr; 63 | wire wb_csr_out_en; 64 | wire [`MAX_BIT_POS:0] wb_csrw_data; 65 | 66 | // fetch 67 | wire inst_read_en; 68 | wire [`MAX_BIT_POS:0] cur_inst_addr; 69 | wire [`MAX_BIT_POS:0] next_inst_addr; 70 | wire inst_ready; 71 | wire [`MAX_BIT_POS:0] jmp_pc; 72 | wire jmp_en; 73 | wire fetch_en; 74 | wire [`MAX_BIT_POS:0] inst_data; 75 | wire inst_mem_ready; 76 | 77 | cpu_pipeline cpu_pipeline( 78 | .clk(clk), 79 | .rst_n(rst_n), 80 | .read_en, 81 | .mem_addr(mem_addr), 82 | .rdata(rdata), 83 | .write_en(write_en), 84 | .wdata(wdata), 85 | .byte_size(byte_size), 86 | .mem_busy(mem_busy), 87 | .mem_ready(mem_ready), 88 | .exp_pc(exp_pc), 89 | .exp_pc_next(exp_pc_next), 90 | .exception_code(exception_code), 91 | .exception_en(exception_en), 92 | .int_jmp_ready(int_jmp_ready), 93 | .int_en(int_en), 94 | .mret_en(mret_en), 95 | .int_jmp_pc(int_jmp_pc), 96 | .int_jmp_en(int_jmp_en), 97 | .csr_read_addr(csr_read_addr), 98 | .csr_data(csr_data), 99 | .wb_csr_addr(wb_csr_addr), 100 | .wb_csr_out_en(wb_csr_out_en), 101 | .wb_csrw_data(wb_csrw_data), 102 | .inst_read_en(inst_read_en), 103 | .cur_inst_addr(cur_inst_addr), 104 | .next_inst_addr(next_inst_addr), 105 | .inst_ready(inst_ready), 106 | .jmp_pc(jmp_pc), 107 | .jmp_en(jmp_en), 108 | .fetch_en(fetch_en), 109 | .inst_data(inst_data), 110 | .inst_mem_ready(inst_mem_ready) 111 | ); 112 | 113 | sys_bus sys_bus( 114 | .clk(clk), 115 | .rst_n(rst_n), 116 | .inst_read_en(inst_read_en), 117 | .inst_read_addr(cur_inst_addr), 118 | .inst_rdata(inst_data), 119 | .inst_read_ready(inst_mem_ready), 120 | .read_en(read_en), 121 | .mem_addr(mem_addr), 122 | .rdata(rdata), 123 | .write_en(write_en), 124 | .wdata(wdata), 125 | .byte_size(byte_size), 126 | .mem_busy(mem_busy), 127 | .mem_ready(mem_ready), 128 | .exp_pc(exp_pc), 129 | .exp_pc_next(exp_pc_next), 130 | .exception_code(exception_code), 131 | .int_jmp_ready(int_jmp_ready), 132 | .int_en(int_en), 133 | .exception_en(exception_en), 134 | .mret_en(mret_en), 135 | .jmp_en(int_jmp_en), 136 | .jmp_pc(int_jmp_pc), 137 | .clk_timer(clk_timer), 138 | .peripheral_int_code(peripheral_int_code), 139 | 140 | .csr_read_addr(csr_read_addr), 141 | .csrw_addr(wb_csr_addr), 142 | .w_data(wb_csrw_data), 143 | .csr_write_en(wb_csr_out_en), 144 | .csr_out(csr_data), 145 | 146 | .io_addr(io_addr), 147 | .io_read(io_read), 148 | .io_write(io_write), 149 | .burst(burst), 150 | .burst_size(burst_size), 151 | .read_ready(read_ready), 152 | .io_wdata(io_wdata), 153 | .io_byte_size(io_byte_size), 154 | .io_rdata(io_rdata), 155 | .io_ready(io_ready) 156 | ); 157 | 158 | endmodule -------------------------------------------------------------------------------- /verilog/core/ex_csr.v: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | Description: ex_csr.v 17 | CSR寄存器执行单元 18 | */ 19 | `include "config.v" 20 | module ex_csr ( 21 | input rst_n, 22 | input [4:0] rd, 23 | input [4:0] imm_1519, 24 | input [`MAX_BIT_POS:0] rs1_data, csr_data, 25 | input [11:0] imm_2031, 26 | input [47:0] inst_flags, 27 | output reg [4:0] rd_out, 28 | output reg out_en, 29 | output reg [`MAX_BIT_POS:0] rd_data, 30 | output reg csr_out_en, 31 | output reg [`MAX_BIT_POS:0] csrw_data, 32 | output reg [11:0] csrw_addr 33 | ); 34 | 35 | wire inst_csrrc; 36 | wire inst_csrrci; 37 | wire inst_csrrs; 38 | wire inst_csrrsi; 39 | wire inst_csrrw; 40 | wire inst_csrrwi; 41 | 42 | assign inst_csrrc = inst_flags[37]; 43 | assign inst_csrrci = inst_flags[38]; 44 | assign inst_csrrs = inst_flags[39]; 45 | assign inst_csrrsi = inst_flags[40]; 46 | assign inst_csrrw = inst_flags[41]; 47 | assign inst_csrrwi = inst_flags[42]; 48 | 49 | /* verilator lint_off LATCH */ 50 | always @(*) begin 51 | if (rst_n) begin 52 | rd_out = rd; 53 | csrw_addr = imm_2031; 54 | if (inst_csrrc) begin 55 | out_en = 1'b1; 56 | csr_out_en = 1'b1; 57 | rd_data = csr_data; 58 | csrw_data = csr_data & ~rs1_data; 59 | end 60 | else if (inst_csrrci) begin 61 | out_en = 1'b1; 62 | csr_out_en = 1'b1; 63 | rd_data = csr_data; 64 | csrw_data = csr_data & ~{27'b0,imm_1519}; 65 | end 66 | else if (inst_csrrsi) begin 67 | out_en = 1'b1; 68 | csr_out_en = 1'b1; 69 | csrw_data = csr_data & {27'b0,imm_1519}; 70 | rd_data = csr_data; 71 | end 72 | else if (inst_csrrs) begin 73 | out_en = 1'b1; 74 | csr_out_en = 1'b1; 75 | csrw_data = csr_data & rs1_data; 76 | rd_data = csr_data; 77 | end 78 | else if (inst_csrrwi) begin 79 | out_en = 1'b1; 80 | csr_out_en = 1'b1; 81 | csrw_data = {27'b0,imm_1519}; 82 | rd_data = csr_data; 83 | end 84 | else if (inst_csrrw) begin 85 | out_en = 1'b1; 86 | csr_out_en = 1'b1; 87 | csrw_data = rs1_data; 88 | rd_data = csr_data; 89 | end 90 | else begin 91 | out_en = 1'b0; 92 | csr_out_en = 1'b0; 93 | end 94 | end 95 | else begin 96 | out_en = 1'b0; 97 | csr_out_en = 1'b0; 98 | end 99 | end 100 | 101 | endmodule -------------------------------------------------------------------------------- /verilog/core/registers.v: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | Description: register file 17 | 寄存器文件 x0-x31, 32个32位寄存器 18 | 写入读取都是单周期完成 19 | */ 20 | `include "config.v" 21 | module registers( 22 | input wire clk, 23 | input wire rst_n, 24 | input wire [4:0] rs1_addr, 25 | input wire [4:0] rs2_addr, 26 | input wire [4:0] rd_addr, 27 | input wire [`MAX_BIT_POS:0] rd_data, 28 | input wire rd_en, 29 | output wire [`MAX_BIT_POS:0] rs1_out, 30 | output wire [`MAX_BIT_POS:0] rs2_out 31 | ); 32 | reg [`MAX_BIT_POS:0] reg_file[`MAX_BIT_POS:0]; 33 | integer i; 34 | wire [`MAX_BIT_POS:0] x1_out; 35 | wire [`MAX_BIT_POS:0] x2_out; 36 | 37 | assign rs1_out = (rs1_addr == 5'd0) ? `XLEN'd0 : reg_file[rs1_addr]; 38 | assign rs2_out = (rs2_addr == 5'd0) ? `XLEN'd0 : reg_file[rs2_addr]; 39 | 40 | assign x1_out = reg_file[1]; 41 | assign x2_out = reg_file[2]; 42 | 43 | always @(posedge clk or negedge rst_n) begin 44 | if (!rst_n) begin 45 | for (i = 0; i < `XLEN; i = i + 1) begin 46 | reg_file[i] <= `XLEN'h00000000; 47 | end 48 | end 49 | else begin 50 | if (rd_en & (rd_addr != 5'd0)) begin 51 | reg_file[rd_addr] <= rd_data; 52 | end 53 | end 54 | end 55 | endmodule -------------------------------------------------------------------------------- /verilog/led_water_ctrl.v: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | module led_water_ctrl ( 17 | input clk_ss, 18 | input rst_n, 19 | output led1, 20 | output led2, 21 | output led3 22 | ); 23 | 24 | reg [2:0] led_state; 25 | reg [24:0] counter; 26 | 27 | assign led1 = led_state[0]; 28 | assign led2 = led_state[1]; 29 | assign led3 = led_state[2]; 30 | 31 | localparam COUTER_MAX = 25'd999; 32 | 33 | always @(posedge clk_ss or negedge rst_n) begin 34 | if (!rst_n) begin 35 | led_state <= 3'b001; 36 | counter <= 25'b0; 37 | end 38 | else begin 39 | counter <= counter + 1; 40 | if (counter == COUTER_MAX) begin 41 | counter <= 25'b0; 42 | led_state <= {led_state[1:0], led_state[2]}; 43 | end 44 | else if (!(|led_state)) begin 45 | led_state <= 3'b001; 46 | end 47 | end 48 | end 49 | 50 | endmodule -------------------------------------------------------------------------------- /verilog/make.bat: -------------------------------------------------------------------------------- 1 | iverilog.exe -y . -y ./core -y ./common -y ./testbench -y ./peripherals/digital -y ./peripherals/uart -y ./peripherals/iic -y ./peripherals/spi -y ./soc -y ./peripherals -I ./core -o testbench.vvp ./testbench/%1_tb.v 2 | vvp.exe ./testbench.vvp 3 | -------------------------------------------------------------------------------- /verilog/peripherals/digital/digital_flash.v: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | Description: digital flash 17 | 片外存储读取,支持digital软件中的rom 18 | */ 19 | `include "config.v" 20 | 21 | module digital_flash( 22 | input wire flashclk, 23 | input wire rst_n, 24 | input wire [`MAX_BIT_POS:0] flash_io_addr, 25 | input wire flash_io_read, 26 | input wire flash_io_write, 27 | input wire flash_read_ready, 28 | input wire [`MAX_BIT_POS:0] flash_io_wdata, 29 | input wire [1:0] io_byte_size, 30 | output reg [`MAX_BIT_POS:0] flash_io_rdata, 31 | output reg flash_io_ready, 32 | 33 | //digital外部接口 34 | output reg [`MAX_BIT_POS:0] digital_flash_addr, 35 | output reg digital_flash_write_en, 36 | output reg digital_flash_read_en, 37 | output reg [2:0] digital_flash_byte_size, 38 | output reg [7:0] digital_flash_wdata, 39 | input wire [7:0] digital_flash_data, 40 | input wire digital_flash_ready 41 | ); 42 | localparam IDLE = 2'd0; 43 | localparam WAIT_PROC = 2'd1; 44 | localparam DO_PROC = 2'd2; 45 | localparam COMPLATE_PROC = 2'd3; 46 | 47 | 48 | reg [1:0] byte_count; 49 | wire [1:0] byte_size; 50 | reg [1:0] state; 51 | reg [1:0] next_state; 52 | 53 | assign byte_size = (io_byte_size == 0) ? 2'd3 : (io_byte_size - 2'd1); 54 | 55 | always @(*) begin 56 | if (state == IDLE && (flash_io_read || flash_io_write)) begin 57 | next_state = WAIT_PROC; 58 | end 59 | else if (state == WAIT_PROC) begin 60 | next_state = (flash_io_read | flash_io_write) ? DO_PROC : IDLE; 61 | end 62 | else if (state == DO_PROC) begin 63 | next_state = (flash_io_read | flash_io_write) ? (flash_io_ready ? COMPLATE_PROC : DO_PROC) : IDLE; 64 | end 65 | else if (state == COMPLATE_PROC) begin 66 | //保持一个周期读取 67 | next_state = IDLE; 68 | end 69 | else begin 70 | next_state = IDLE; 71 | end 72 | end 73 | 74 | always @(posedge flashclk or negedge rst_n) begin 75 | if(!rst_n) begin 76 | state <= IDLE; 77 | end 78 | else begin 79 | state <= next_state; 80 | end 81 | end 82 | 83 | always @(posedge flashclk or negedge rst_n) begin 84 | if(!rst_n) begin 85 | flash_io_ready <= 1'b0; 86 | // digital 固定位4字节 87 | digital_flash_byte_size <= 0; 88 | digital_flash_write_en <= 1'b0; 89 | byte_count <= 0; 90 | end 91 | else begin 92 | case (state) 93 | IDLE: begin 94 | byte_count <= 0; 95 | flash_io_ready <= 1'b0; 96 | digital_flash_write_en <= 1'b0; 97 | digital_flash_read_en <= 1'b0; 98 | end 99 | WAIT_PROC: begin 100 | flash_io_rdata <= 0; 101 | digital_flash_addr <= flash_io_addr; 102 | digital_flash_read_en <= flash_io_read; 103 | end 104 | DO_PROC: begin 105 | if(flash_io_read && !flash_io_ready) begin 106 | if (byte_count <= byte_size && digital_flash_ready) begin 107 | flash_io_rdata[byte_count*8 +: 8] <= digital_flash_data; 108 | digital_flash_addr <= digital_flash_addr + `XLEN'd1; 109 | flash_io_ready <= (byte_count == byte_size); 110 | byte_count <= byte_count + 1; 111 | end 112 | end 113 | else if(flash_io_write && !flash_io_ready) begin 114 | digital_flash_write_en <= 1'b1; 115 | if (byte_count <= byte_size && digital_flash_ready) begin 116 | digital_flash_wdata <= flash_io_wdata[byte_count*8 +: 8]; 117 | digital_flash_addr <= digital_flash_addr + `XLEN'd1; 118 | flash_io_ready <= (byte_count == byte_size); 119 | byte_count <= byte_count + 1; 120 | end 121 | end 122 | end 123 | COMPLATE_PROC: begin 124 | digital_flash_write_en <= 1'b0; 125 | digital_flash_read_en <= 1'b0; 126 | end 127 | endcase 128 | end 129 | end 130 | 131 | endmodule -------------------------------------------------------------------------------- /verilog/peripherals/digital/digital_ram.v: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | Description: digital ram 17 | 片外内存读写,支持Digital模拟软件内存 18 | */ 19 | `include "config.v" 20 | 21 | module digital_ram( 22 | input wire ramclk, 23 | input wire rst_n, 24 | input wire [`MAX_BIT_POS:0] mem_io_addr, 25 | input wire mem_io_read, 26 | input wire mem_io_write, 27 | input wire mem_read_ready, 28 | input wire [`MAX_BIT_POS:0] mem_io_wdata, 29 | input wire [1:0] io_byte_size, 30 | output wire [`MAX_BIT_POS:0] mem_io_rdata, 31 | output reg mem_io_ready, 32 | 33 | //digital外部接口 34 | output wire [`MAX_BIT_POS:0] digital_mem_addr, 35 | output reg digital_mem_write_en, 36 | output reg digital_mem_read_en, 37 | output reg [3:0] digital_mem_byte_size, 38 | output reg [`MAX_BIT_POS:0] digital_mem_wdata, 39 | input wire [`MAX_BIT_POS:0] digital_mem_data, 40 | input wire digital_mem_ready 41 | ); 42 | localparam IDLE = 2'd0, WAIT_PROC = 2'd1, DO_PROC = 2'd2, COMPLATE_PROC = 2'd3; 43 | 44 | reg [1:0] byte_count; 45 | wire [1:0] byte_size; 46 | reg [1:0]state; 47 | reg [1:0]next_state; 48 | 49 | assign byte_size = (io_byte_size == 0) ? 2'd3 : (io_byte_size - 2'd1); 50 | assign digital_mem_addr = mem_io_addr; 51 | assign mem_io_rdata = digital_mem_data; 52 | 53 | always @(*) begin 54 | if (state == IDLE && (mem_io_read || mem_io_write)) begin 55 | next_state = WAIT_PROC; 56 | end 57 | else if (state == WAIT_PROC) begin 58 | next_state = (mem_io_read | mem_io_write) ? DO_PROC : IDLE; 59 | end 60 | else if (state == DO_PROC) begin 61 | next_state = (mem_io_read | mem_io_write) ? (mem_io_ready ? COMPLATE_PROC : DO_PROC) : IDLE; 62 | end 63 | else if (state == COMPLATE_PROC) begin 64 | //保持一个周期读取 65 | next_state = IDLE; 66 | end 67 | else begin 68 | next_state = IDLE; 69 | end 70 | end 71 | 72 | integer i; 73 | always @(mem_io_wdata or io_byte_size) begin 74 | byte_count = 0; 75 | if (mem_io_write) begin 76 | digital_mem_wdata = `XLEN'd0; 77 | digital_mem_byte_size = 4'b0000; 78 | for (i = 0; i < `XLEN/8; i = i + 1) begin 79 | if (byte_count <= byte_size) begin 80 | digital_mem_wdata[i*8 +: 8] = mem_io_wdata[i*8 +: 8]; 81 | byte_count = byte_count + 1; 82 | end 83 | end 84 | digital_mem_byte_size[byte_count-1] = 1'b1; 85 | end 86 | else begin 87 | // digital 固定位4字节 88 | digital_mem_byte_size = 4'b1111; 89 | end 90 | end 91 | 92 | always @(posedge ramclk or negedge rst_n) begin 93 | if(!rst_n) begin 94 | state <= IDLE; 95 | end 96 | else begin 97 | state <= next_state; 98 | end 99 | end 100 | 101 | always @(posedge ramclk or negedge rst_n) begin 102 | if(!rst_n) begin 103 | mem_io_ready <= 1'b0; 104 | digital_mem_write_en <= 1'b0; 105 | end 106 | else begin 107 | case (state) 108 | IDLE: begin 109 | mem_io_ready <= 1'b0; 110 | digital_mem_write_en <= 1'b0; 111 | digital_mem_read_en <= 1'b0; 112 | end 113 | WAIT_PROC: begin 114 | digital_mem_read_en <= mem_io_read; 115 | end 116 | DO_PROC: begin 117 | if(mem_io_read && !mem_io_ready) begin 118 | mem_io_ready <= digital_mem_ready; 119 | digital_mem_write_en <= 1'b0; 120 | end 121 | else if(mem_io_write && !mem_io_ready) begin 122 | digital_mem_write_en <= 1'b1; 123 | mem_io_ready <= digital_mem_ready; 124 | end 125 | end 126 | COMPLATE_PROC: begin 127 | mem_io_ready <= 1'b1; 128 | digital_mem_write_en <= 1'b0; 129 | digital_mem_read_en <= 1'b0; 130 | end 131 | endcase 132 | end 133 | end 134 | 135 | 136 | endmodule -------------------------------------------------------------------------------- /verilog/peripherals/iic/iic_scl.v: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | File Name : iic_scl.v 16 | Description: iic_scl 17 | */ 18 | module iic_scl( 19 | input wire clk, 20 | input wire rst_n, 21 | input [31:0] scl_count_max, 22 | input [31:0] scl_sample_count_max, 23 | output reg sample_scl_out, 24 | output reg scl_out 25 | ); 26 | 27 | reg [24:0] counter_scl; 28 | reg [24:0] counter_sample_scl; 29 | 30 | always @(posedge clk or negedge rst_n) begin 31 | if (!rst_n || scl_count_max == 0) begin 32 | scl_out <= 1'b1; 33 | counter_scl <= 25'd0; 34 | end 35 | else if (counter_scl == scl_count_max) begin 36 | scl_out <= ~scl_out; 37 | counter_scl <= 25'd0; 38 | end 39 | else begin 40 | counter_scl <= counter_scl + 25'd1; 41 | end 42 | end 43 | 44 | always @(posedge clk or negedge rst_n) begin 45 | if (!rst_n || scl_sample_count_max == 0) begin 46 | sample_scl_out <= 1'b1; 47 | counter_sample_scl <= 25'd0; 48 | end 49 | else if (counter_sample_scl == scl_sample_count_max) begin 50 | sample_scl_out <= ~sample_scl_out; 51 | counter_sample_scl <= 25'd0; 52 | end 53 | else begin 54 | counter_sample_scl <= counter_sample_scl + 25'd1; 55 | end 56 | end 57 | 58 | endmodule -------------------------------------------------------------------------------- /verilog/peripherals/spi/spi_master.v: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | File Name : spi_master.v 16 | Description : SPI master module 17 | */ 18 | 19 | module spi_master #( 20 | parameter DATA_WIDTH = 8, // 数据宽度,例如 8 位、16 位 21 | parameter FIFO_DEPTH = 16 // FIFO 缓冲深度 22 | ) ( 23 | input wire clk, // 系统时钟 24 | input wire rst_n, // 复位信号,低电平有效 25 | input wire start, // 启动信号,高电平有效 26 | input wire op_mode, // 操作模式, 0: 发送数据 1: 接收数据 2: 发送接收 27 | input wire [1:0] spi_mode, // SPI 模式 (Mode 0-3: CPOL, CPHA) 28 | input wire [15:0] clk_div, // SPI 时钟分频值 (控制速度) 29 | input wire [DATA_WIDTH-1:0] tx_data, // 要发送的数据 30 | output wire [DATA_WIDTH-1:0] rx_data, // 接收到的数据 31 | output wire op_ready, 32 | 33 | output wire spi_clk, // SPI 时钟信号 34 | output wire spi_mosi, // 主输出从输入 (MOSI) 35 | input wire spi_miso, // 主输入从输出 (MISO) 36 | output wire spi_cs // 片选信号 37 | ); 38 | 39 | // 内部信号定义 40 | reg [15:0] clk_cnt; // 时钟分频计数器 41 | reg spi_clk_reg; // SPI时钟寄存器 42 | reg spi_cs_reg; // 片选寄存器 43 | reg spi_mosi_reg; // MOSI数据寄存器 44 | reg [DATA_WIDTH-1:0] tx_shift_reg; // 发送移位寄存器 45 | reg [DATA_WIDTH-1:0] rx_shift_reg; // 接收移位寄存器 46 | reg [3:0] bit_cnt; // 位计数器 47 | reg busy; // 忙状态标志 48 | wire cpol; // 时钟极性 49 | wire cpha; // 时钟相位 50 | wire change_edge; // 变化时刻 51 | wire sample_edge; // 采样时刻 52 | // 状态机定义 53 | localparam IDLE = 2'b00; // 空闲状态 54 | localparam TRANSFER = 2'b01; // 传输状态 55 | 56 | localparam OP_MODE_SEND = 2'b00; 57 | localparam OP_MODE_RECEIVE = 2'b01; 58 | localparam OP_MODE_BOTH = 2'b10; 59 | 60 | 61 | reg [1:0] state; 62 | 63 | assign cpol = spi_mode[0]; 64 | assign cpha = spi_mode[1]; 65 | assign sample_edge = ((cpol == 1'b0 && cpha == 1'b0) || (cpol == 1'b1 && cpha == 1'b1)) ? spi_clk_reg : ~spi_clk_reg; 66 | assign change_edge = ((cpol == 1'b0 && cpha == 1'b1) || (cpol == 1'b1 && cpha == 1'b0)) ? spi_clk_reg : ~spi_clk_reg; 67 | 68 | // SPI时钟生成 69 | always @(posedge clk or negedge rst_n) begin 70 | if (!rst_n) begin 71 | clk_cnt <= 16'd0; 72 | spi_clk_reg <= cpol; 73 | end else if (busy) begin 74 | if (clk_cnt == clk_div - 1) begin 75 | clk_cnt <= 16'd0; 76 | spi_clk_reg <= ~spi_clk_reg; 77 | end else begin 78 | clk_cnt <= clk_cnt + 1'b1; 79 | end 80 | end else begin 81 | spi_clk_reg <= cpol; 82 | clk_cnt <= 16'd0; 83 | end 84 | end 85 | 86 | 87 | always @(posedge clk or negedge rst_n) begin 88 | if (!rst_n) begin 89 | busy <= 1'b0; 90 | state <= IDLE; 91 | bit_cnt <= 4'd0; 92 | spi_cs_reg <= 1'b1; 93 | tx_shift_reg <= {DATA_WIDTH{1'b0}}; 94 | rx_shift_reg <= {DATA_WIDTH{1'b0}}; 95 | end else begin 96 | case (state) 97 | IDLE: begin 98 | if (start) begin 99 | busy <= 1'b1; 100 | spi_cs_reg <= 1'b0; 101 | tx_shift_reg <= tx_data; 102 | bit_cnt <= 4'd0; 103 | state <= TRANSFER; 104 | end else begin 105 | busy <= 1'b0; 106 | spi_cs_reg <= 1'b1; 107 | state <= IDLE; 108 | end 109 | end 110 | TRANSFER: begin 111 | if (bit_cnt == DATA_WIDTH) begin 112 | busy <= 1'b0; 113 | spi_cs_reg <= 1'b1; 114 | state <= IDLE; 115 | end 116 | else if (change_edge) begin 117 | bit_cnt <= bit_cnt + 1'b1; 118 | if (OP_MODE_SEND == op_mode || OP_MODE_BOTH == op_mode) begin 119 | tx_shift_reg <= {tx_shift_reg[DATA_WIDTH-2:0], 1'b0}; 120 | end 121 | end 122 | else if (sample_edge) begin 123 | if (OP_MODE_RECEIVE == op_mode || OP_MODE_BOTH == op_mode) begin 124 | rx_shift_reg[bit_cnt] <= spi_miso; 125 | end 126 | end 127 | end 128 | endcase 129 | end 130 | end 131 | 132 | 133 | // 输出赋值 134 | assign spi_clk = spi_clk_reg; 135 | assign spi_cs = spi_cs_reg; 136 | assign spi_mosi = tx_shift_reg[DATA_WIDTH-1]; 137 | assign rx_data = rx_shift_reg; 138 | assign rx_valid = !busy && (state == IDLE); 139 | assign tx_ready = !busy && (state == IDLE); 140 | 141 | 142 | endmodule 143 | -------------------------------------------------------------------------------- /verilog/peripherals/uart/uart_clk_div.v: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | Description: UART RX module 17 | 18 | */ 19 | 20 | module uart_clk_div( 21 | input clk, 22 | input rst_n, 23 | input [15:0] uart_clk_div, // 波特率时钟分频数,整数部分 主频/(波特率 * 16) 24 | input [4:0] uart_clk_frag_total, // 每16个整数周期中,小数分频添加个数 (主频 % (波特率 * 16)) * 16 25 | input [3:0] uart_clk_frag_i, // 小数添加间隔 1 / (主频 % (波特率 * 16)) 26 | output reg clk_sample, 27 | output reg clk_uart 28 | ); 29 | 30 | reg [15:0] div_cnt; 31 | reg [4:0] frag_cnt_16; 32 | reg frag_en; 33 | reg [3:0] frag_cnt_i; 34 | reg [4:0] frag_cnt; 35 | reg [1:0] uart_cnt; 36 | 37 | 38 | always @(posedge clk or negedge rst_n) begin 39 | if (!rst_n) begin 40 | div_cnt <= 16'b0; 41 | clk_sample <= 1'b0; 42 | end 43 | else begin 44 | if (((div_cnt == uart_clk_div - 1) && !frag_en) || ((div_cnt == uart_clk_div) && frag_en)) begin 45 | clk_sample <= ~clk_sample; 46 | div_cnt <= 16'b0; 47 | end 48 | else begin 49 | div_cnt <= div_cnt + 1; 50 | end 51 | end 52 | end 53 | 54 | always @(posedge clk_sample or negedge rst_n) begin 55 | if (!rst_n) begin 56 | frag_cnt_16 <= 5'b0; 57 | frag_cnt_i <= 4'b0; 58 | frag_cnt <= 5'b0; 59 | frag_en <= 1'b0; 60 | end 61 | else begin 62 | if (frag_cnt_16 == 15) begin 63 | frag_cnt_16 <= 0; 64 | frag_cnt <= 5'b0; 65 | end 66 | else begin 67 | frag_cnt_16 <= frag_cnt_16 + 1; 68 | end 69 | if (frag_cnt_i == uart_clk_frag_i) begin 70 | frag_en <= frag_cnt > uart_clk_frag_total ? 1'b0 : 1'b1; 71 | frag_cnt <= frag_cnt > uart_clk_frag_total ? frag_cnt : (frag_cnt + 1); 72 | frag_cnt_i <= 0; 73 | end 74 | else begin 75 | frag_cnt_i <= frag_cnt_i + 1; 76 | frag_en <= 1'b0; 77 | end 78 | end 79 | end 80 | 81 | always @(posedge clk_sample or negedge rst_n) begin 82 | if (!rst_n) begin 83 | uart_cnt <= 2'b0; 84 | clk_uart <= 1'b0; 85 | end 86 | else begin 87 | if (uart_cnt == 3) begin 88 | uart_cnt <= 2'b0; 89 | clk_uart <= ~clk_uart; 90 | end 91 | else begin 92 | uart_cnt <= uart_cnt + 1; 93 | end 94 | end 95 | end 96 | 97 | endmodule -------------------------------------------------------------------------------- /verilog/peripherals/uart/uart_tx.v: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | Description: UART TX module 17 | 18 | */ 19 | 20 | module uart_tx( 21 | input clk_uart, 22 | input rst_n, 23 | input [7:0] tx_data, 24 | input tx_start, 25 | input [1:0] parity_mode, 26 | input [1:0] stop_bit, 27 | output wire tx_out, 28 | output reg tx_busy 29 | ); 30 | 31 | reg [2:0] tx_cnt; 32 | reg rx_parity; 33 | reg [1:0] tx_state; 34 | reg [4:0] tx_h_cnt; 35 | 36 | localparam TX_IDLE = 0, TX_DATA = 1, TX_PARITY = 2, TX_STOP = 3; 37 | localparam PARITY_NONE = 0, PARITY_EVEN = 1, PARITY_ODD = 2; 38 | 39 | reg tx; 40 | 41 | assign tx_out = (rst_n && tx_state != TX_IDLE) ? tx : 1'b1; 42 | 43 | 44 | always @(posedge clk_uart or negedge rst_n) begin 45 | if (!rst_n) begin 46 | tx_cnt <= 3'b0; 47 | tx_state <= TX_IDLE; 48 | tx_busy <= 1'b0; 49 | tx <= 1'b1; 50 | end 51 | else begin 52 | case (tx_state) 53 | TX_IDLE: begin 54 | if (tx_start) begin 55 | tx_cnt <= 3'b0; 56 | tx_state <= TX_DATA; 57 | tx_busy <= 1'b1; 58 | tx <= 1'b0; 59 | end 60 | else begin 61 | tx_busy <= 1'b0; 62 | tx <= 1'b1; 63 | end 64 | end 65 | TX_DATA: begin 66 | tx_cnt <= tx_cnt + 1; 67 | tx <= tx_data[tx_cnt]; 68 | tx_h_cnt <= tx_data[tx_cnt] ? (tx_h_cnt + 1) : tx_h_cnt; 69 | if (tx_cnt == 7) begin 70 | tx_state <= parity_mode == PARITY_NONE ? TX_STOP : TX_PARITY; 71 | tx_cnt <= 3'b0; 72 | end 73 | end 74 | TX_PARITY: begin 75 | if (parity_mode == PARITY_EVEN) begin 76 | tx <= tx_h_cnt[0]; 77 | end 78 | else if (parity_mode == PARITY_ODD) begin 79 | tx <= (~tx_h_cnt[0]); 80 | end 81 | tx_h_cnt <= 5'b0; 82 | tx_state <= TX_STOP; 83 | end 84 | TX_STOP: begin 85 | tx_cnt <= tx_cnt + 1; 86 | tx <= 1'b1; 87 | if (tx_cnt >= {1'b0,stop_bit}) begin 88 | tx_cnt <= 3'b0; 89 | tx_state <= TX_IDLE; 90 | tx_busy <= 1'b0; 91 | end 92 | end 93 | endcase 94 | end 95 | end 96 | 97 | endmodule -------------------------------------------------------------------------------- /verilog/soc/digital_soc.v: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | Description: digital soc 17 | 封装用于digital模拟软件的接口 18 | */ 19 | 20 | `include "config.v" 21 | 22 | module digital_soc( 23 | input wire clk, // 时钟信号 24 | input wire rst_n, // 复位信号 25 | input wire clk_timer, 26 | 27 | output wire [`MAX_BIT_POS:0] digital_flash_addr, 28 | output wire digital_flash_write_en, 29 | output wire digital_flash_read_en, 30 | output wire [2:0] digital_flash_byte_size, 31 | output wire [7:0] digital_flash_wdata, 32 | input wire [7:0] digital_flash_data, 33 | input wire digital_flash_ready, 34 | output wire [`MAX_BIT_POS:0] digital_mem_addr, 35 | output wire digital_mem_write_en, 36 | output wire digital_mem_read_en, 37 | output wire [3:0] digital_mem_byte_size, 38 | output wire [`MAX_BIT_POS:0] digital_mem_wdata, 39 | input wire [`MAX_BIT_POS:0] digital_mem_data, 40 | input wire digital_mem_ready, 41 | inout wire [`GPIO_NUMS-1:0] gpio_values 42 | ); 43 | 44 | wire [`MAX_BIT_POS:0] io_addr; 45 | wire io_read; 46 | wire io_write; 47 | wire burst; 48 | wire [2:0] burst_size; 49 | wire read_ready; 50 | wire [`MAX_BIT_POS:0] io_wdata; 51 | wire [1:0] io_byte_size; 52 | wire [`MAX_BIT_POS:0] io_rdata; 53 | wire io_ready; 54 | wire [`INT_CODE_WIDTH-1:0]peripheral_int_code; 55 | 56 | cpu_top cpu( 57 | .clk(clk), 58 | .rst_n(rst_n), 59 | .clk_timer(clk_timer), 60 | .io_addr(io_addr), 61 | .io_read(io_read), 62 | .io_write(io_write), 63 | .burst(burst), 64 | .burst_size(burst_size), 65 | .read_ready(read_ready), 66 | .io_wdata(io_wdata), 67 | .io_byte_size(io_byte_size), 68 | .io_rdata(io_rdata), 69 | .io_ready(io_ready), 70 | .peripheral_int_code(peripheral_int_code) 71 | ); 72 | 73 | peripherals_bus peripherals_bus( 74 | .pclk(clk), 75 | .rst_n(rst_n), 76 | .io_addr(io_addr), 77 | .io_read(io_read), 78 | .io_write(io_write), 79 | .burst(burst), 80 | .burst_size(burst_size), 81 | .read_ready(read_ready), 82 | .io_wdata(io_wdata), 83 | .io_byte_size(io_byte_size), 84 | .io_rdata(io_rdata), 85 | .io_ready(io_ready), 86 | .digital_flash_addr(digital_flash_addr), 87 | .digital_flash_write_en(digital_flash_write_en), 88 | .digital_flash_read_en(digital_flash_read_en), 89 | .digital_flash_byte_size(digital_flash_byte_size), 90 | .digital_flash_wdata(digital_flash_wdata), 91 | .digital_flash_data(digital_flash_data), 92 | .digital_flash_ready(digital_flash_ready), 93 | .digital_mem_addr(digital_mem_addr), 94 | .digital_mem_write_en(digital_mem_write_en), 95 | .digital_mem_read_en(digital_mem_read_en), 96 | .digital_mem_byte_size(digital_mem_byte_size), 97 | .digital_mem_wdata(digital_mem_wdata), 98 | .digital_mem_data(digital_mem_data), 99 | .digital_mem_ready(digital_mem_ready), 100 | .gpio_values(gpio_values), 101 | .peripheral_int_code(peripheral_int_code) 102 | ); 103 | 104 | endmodule -------------------------------------------------------------------------------- /verilog/soc/vboard_soc.v: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | Description: vboard soc 17 | 封装用于fpga vboard虚拟开发板的soc 18 | */ 19 | 20 | `include "config.v" 21 | 22 | module vboard_soc( 23 | input wire clk, // 时钟信号 24 | input wire rst_n, // 复位信号 25 | input wire clk_timer, 26 | 27 | output wire [`MAX_BIT_POS:0] digital_flash_addr, 28 | output wire digital_flash_write_en, 29 | output wire digital_flash_read_en, 30 | output wire [2:0] digital_flash_byte_size, 31 | output wire [7:0] digital_flash_wdata, 32 | input wire [7:0] digital_flash_data, 33 | input wire digital_flash_ready, 34 | output wire [`MAX_BIT_POS:0] digital_mem_addr, 35 | output wire digital_mem_write_en, 36 | output wire digital_mem_read_en, 37 | output wire [3:0] digital_mem_byte_size, 38 | output wire [`MAX_BIT_POS:0] digital_mem_wdata, 39 | input wire [`MAX_BIT_POS:0] digital_mem_data, 40 | input wire digital_mem_ready, 41 | inout wire [`GPIO_NUMS-1:0] gpio_values, 42 | input uart_rx, 43 | output uart_tx 44 | ); 45 | 46 | wire [`MAX_BIT_POS:0] io_addr; 47 | wire io_read; 48 | wire io_write; 49 | wire burst; 50 | wire [2:0] burst_size; 51 | wire read_ready; 52 | wire [`MAX_BIT_POS:0] io_wdata; 53 | wire [1:0] io_byte_size; 54 | wire [`MAX_BIT_POS:0] io_rdata; 55 | wire io_ready; 56 | wire [`INT_CODE_WIDTH-1:0]peripheral_int_code; 57 | 58 | cpu_top cpu( 59 | .clk(clk), 60 | .rst_n(rst_n), 61 | .clk_timer(clk_timer), 62 | .io_addr(io_addr), 63 | .io_read(io_read), 64 | .io_write(io_write), 65 | .burst(burst), 66 | .burst_size(burst_size), 67 | .read_ready(read_ready), 68 | .io_wdata(io_wdata), 69 | .io_byte_size(io_byte_size), 70 | .io_rdata(io_rdata), 71 | .io_ready(io_ready), 72 | .peripheral_int_code(peripheral_int_code) 73 | ); 74 | 75 | peripherals_bus peripherals_bus( 76 | .pclk(clk), 77 | .rst_n(rst_n), 78 | .io_addr(io_addr), 79 | .io_read(io_read), 80 | .io_write(io_write), 81 | .burst(burst), 82 | .burst_size(burst_size), 83 | .read_ready(read_ready), 84 | .io_wdata(io_wdata), 85 | .io_byte_size(io_byte_size), 86 | .io_rdata(io_rdata), 87 | .io_ready(io_ready), 88 | .digital_flash_addr(digital_flash_addr), 89 | .digital_flash_write_en(digital_flash_write_en), 90 | .digital_flash_read_en(digital_flash_read_en), 91 | .digital_flash_byte_size(digital_flash_byte_size), 92 | .digital_flash_wdata(digital_flash_wdata), 93 | .digital_flash_data(digital_flash_data), 94 | .digital_flash_ready(digital_flash_ready), 95 | .digital_mem_addr(digital_mem_addr), 96 | .digital_mem_write_en(digital_mem_write_en), 97 | .digital_mem_read_en(digital_mem_read_en), 98 | .digital_mem_byte_size(digital_mem_byte_size), 99 | .digital_mem_wdata(digital_mem_wdata), 100 | .digital_mem_data(digital_mem_data), 101 | .digital_mem_ready(digital_mem_ready), 102 | .gpio_values(gpio_values), 103 | .uart_rx(uart_rx), 104 | .uart_tx(uart_tx), 105 | .peripheral_int_code(peripheral_int_code) 106 | ); 107 | 108 | endmodule -------------------------------------------------------------------------------- /verilog/testbench/cpu_tb.v: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | `timescale 1ns/1ns 17 | `include "config.v" 18 | `include "cpu_pipeline.v" 19 | 20 | module cpu_tb; 21 | reg clk; 22 | reg rst_n; 23 | reg clk_timer; 24 | 25 | // 片外内存 26 | reg [(`CACHE_LINE_SIZE*8)-1:0] offchip_mem_data; 27 | reg offchip_mem_ready; 28 | wire [(`CACHE_LINE_SIZE*8)-1:0] offchip_mem_wdata; 29 | output wire offchip_mem_write_en; 30 | output wire offchip_mem_read_en; 31 | output wire [`MAX_BIT_POS:0] offchip_mem_addr; 32 | 33 | // cpu_pipeline cpu_pipeline( 34 | // .clk(clk), 35 | // .rst_n(rst_n), 36 | // .clk_timer(clk_timer), 37 | // .offchip_mem_data(offchip_mem_data), 38 | // .offchip_mem_ready(offchip_mem_ready), 39 | // .offchip_mem_wdata(offchip_mem_wdata), 40 | // .offchip_mem_write_en(offchip_mem_write_en), 41 | // .offchip_mem_read_en(offchip_mem_read_en), 42 | // .offchip_mem_addr(offchip_mem_addr) 43 | // ); 44 | 45 | reg [7:0] memory [0:255]; // 假设要加载 256 个字节的内容 46 | integer i; 47 | 48 | initial begin 49 | // 读取 hex 文件 50 | $readmemh("test.hex", memory); 51 | 52 | // // 打印每个字节以确保数据正确加载 53 | // for (i = 0; i < 256; i = i + 1) begin 54 | // $display("memory[%0d] = %02x", i, memory[i]); 55 | // end 56 | end 57 | 58 | always @(posedge offchip_mem_read_en) begin 59 | for (i = 0; i < 16; i = i + 1) begin 60 | offchip_mem_data[i*8 +: 8] = memory[offchip_mem_addr+i]; // 逐字节赋值 61 | end 62 | offchip_mem_ready = 1'd1; 63 | #20; 64 | offchip_mem_ready = 1'd0; 65 | end 66 | 67 | initial begin 68 | $dumpfile("cpu_pipeline.vcd"); 69 | $dumpvars; // dump all vars 70 | end 71 | 72 | initial begin 73 | clk = 0; 74 | rst_n = 0; 75 | clk_timer = 0; 76 | offchip_mem_ready = 0; 77 | #10 rst_n = 1; 78 | 79 | #500; 80 | $finish; 81 | end 82 | 83 | always #5 clk = ~clk; 84 | always #100 clk_timer = ~clk_timer; 85 | 86 | 87 | endmodule -------------------------------------------------------------------------------- /verilog/testbench/digital_soc_tb.v: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | `timescale 1ns/1ns 17 | `include "config.v" 18 | 19 | module cpu_tb; 20 | reg clk; 21 | reg rst_n; 22 | reg clk_timer; 23 | 24 | wire [`MAX_BIT_POS:0] digital_flash_addr; 25 | wire digital_flash_write_en; 26 | wire digital_flash_read_en; 27 | wire [2:0] digital_flash_byte_size; 28 | wire [7:0] digital_flash_wdata; 29 | reg [7:0] digital_flash_data; 30 | reg digital_flash_ready; 31 | wire [`MAX_BIT_POS:0] digital_mem_addr; 32 | wire digital_mem_write_en; 33 | wire digital_mem_read_en; 34 | wire [3:0] digital_mem_byte_size; 35 | wire [`MAX_BIT_POS:0] digital_mem_wdata; 36 | reg [`MAX_BIT_POS:0] digital_mem_data; 37 | reg digital_mem_ready; 38 | wire [`GPIO_NUMS-1:0] gpio_values; 39 | 40 | digital_soc digital_soc( 41 | .clk(clk), 42 | .rst_n(rst_n), 43 | .clk_timer(clk_timer), 44 | .digital_flash_addr(digital_flash_addr), 45 | .digital_flash_write_en(digital_flash_write_en), 46 | .digital_flash_read_en(digital_flash_read_en), 47 | .digital_flash_byte_size(digital_flash_byte_size), 48 | .digital_flash_wdata(digital_flash_wdata), 49 | .digital_flash_data(digital_flash_data), 50 | .digital_flash_ready(digital_flash_ready), 51 | .digital_mem_addr(digital_mem_addr), 52 | .digital_mem_write_en(digital_mem_write_en), 53 | .digital_mem_read_en(digital_mem_read_en), 54 | .digital_mem_byte_size(digital_mem_byte_size), 55 | .digital_mem_wdata(digital_mem_wdata), 56 | .digital_mem_data(digital_mem_data), 57 | .digital_mem_ready(digital_mem_ready), 58 | .gpio_values(gpio_values) 59 | ); 60 | 61 | reg [7:0] flash [0:4000]; 62 | reg [`MAX_BIT_POS:0] memory [0:8000]; 63 | integer i; 64 | 65 | initial begin 66 | // 读取 hex 文件 67 | $readmemh("../digital_soc/src/test.hex", flash); 68 | 69 | for(i=0;i<8000;i=i+1) begin 70 | memory[i] = 0; 71 | end 72 | end 73 | 74 | always @(posedge digital_mem_write_en or digital_mem_addr or posedge digital_mem_read_en) begin 75 | digital_mem_ready = 1'd0; 76 | if (digital_mem_write_en) begin 77 | memory[{digital_mem_addr[12:0]}] = digital_mem_wdata; 78 | digital_mem_ready = 1'd1; 79 | end 80 | if (digital_mem_read_en) begin 81 | digital_mem_data = memory[{digital_mem_addr[12:0]}]; 82 | digital_mem_ready = 1'd1; 83 | end 84 | end 85 | 86 | always @(posedge digital_flash_read_en or digital_flash_addr) begin 87 | digital_flash_ready = 1'd0; 88 | if (digital_flash_read_en) begin 89 | digital_flash_data = flash[digital_flash_addr]; 90 | digital_flash_ready = 1'd1; 91 | end 92 | // offchip_mem_ready = 1'd1; 93 | // #20; 94 | // offchip_mem_ready = 1'd0; 95 | end 96 | 97 | initial begin 98 | $dumpfile("digital_soc.vcd"); 99 | $dumpvars; // dump all vars 100 | end 101 | 102 | genvar idx; 103 | generate 104 | for (idx = 0; idx < `GPIO_NUMS; idx = idx + 1) begin 105 | pulldown(gpio_values[idx]); 106 | end 107 | endgenerate 108 | 109 | reg gpio_10; 110 | assign gpio_values[9] = gpio_10; 111 | 112 | initial begin 113 | clk = 0; 114 | rst_n = 0; 115 | clk_timer = 0; 116 | gpio_10 = 1'b0; 117 | digital_flash_ready = 1'd0; 118 | digital_mem_ready = 1'd0; 119 | 120 | // offchip_mem_ready = 0; 121 | #10 rst_n = 1; 122 | #200000; 123 | gpio_10 = 1'b1; 124 | #100000; 125 | gpio_10 = 1'b0; 126 | #100000; 127 | $finish; 128 | end 129 | 130 | always #5 clk = ~clk; 131 | always #20 clk_timer = ~clk_timer; 132 | 133 | 134 | endmodule -------------------------------------------------------------------------------- /verilog/testbench/iic_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ps/1ps 2 | 3 | module iic_tb; 4 | 5 | reg clk; 6 | reg rst_n; 7 | wire iic_scl; 8 | wire iic_sda; 9 | reg iic_reg_wr_en; 10 | reg iic_reg_rd_en; 11 | reg [31:0] iic_reg_addr; 12 | reg [31:0] iic_reg_wdata; 13 | wire [31:0] iic_reg_rdata; 14 | wire iic_ready; 15 | wire data_ready_int; 16 | wire write_ready_int; 17 | 18 | iic_top iic_top_inst( 19 | .clk(clk), 20 | .rst_n(rst_n), 21 | .iic_scl(iic_scl), 22 | .iic_sda(iic_sda), 23 | .iic_reg_wr_en(iic_reg_wr_en), 24 | .iic_reg_rd_en(iic_reg_rd_en), 25 | .iic_reg_addr(iic_reg_addr), 26 | .iic_reg_wdata(iic_reg_wdata), 27 | .iic_reg_rdata(iic_reg_rdata), 28 | .iic_ready(iic_ready), 29 | .data_ready_int(data_ready_int), 30 | .write_ready_int(write_ready_int) 31 | ); 32 | 33 | reg reg1_w_en; 34 | reg reg2_w_en; 35 | 36 | reg [7:0] reg1_in; 37 | reg [31:0] reg2_in; 38 | 39 | wire [7:0] reg1_out; 40 | wire [31:0] reg2_out; 41 | 42 | iic_slave iic_slave_inst( 43 | .clk(clk), 44 | .rst_n(rst_n), 45 | .scl(iic_scl), 46 | .sda(iic_sda), 47 | .reg1_w_en(reg1_w_en), 48 | .reg2_w_en(reg2_w_en), 49 | .reg1_in(reg1_in), 50 | .reg2_in(reg2_in), 51 | .reg1_out(reg1_out), 52 | .reg2_out(reg2_out) 53 | ); 54 | 55 | pullup(iic_sda); 56 | 57 | initial begin 58 | $dumpfile("iic_tb.vcd"); 59 | $dumpvars(0, iic_tb); 60 | end 61 | 62 | task set_iic_reg(input [31:0] addr, input [31:0] wdata); 63 | if (rst_n) begin 64 | iic_reg_wr_en = 1; 65 | iic_reg_addr = addr; 66 | iic_reg_wdata = wdata; 67 | wait(iic_ready); 68 | iic_reg_wr_en = 0; 69 | #21; 70 | end 71 | endtask 72 | 73 | task get_iic_reg(input [31:0] addr); 74 | if (rst_n) begin 75 | iic_reg_rd_en = 1; 76 | iic_reg_addr = addr; 77 | wait(iic_ready); 78 | $display("reg = %h", iic_reg_rdata); 79 | iic_reg_rd_en = 0; 80 | #21; 81 | end 82 | endtask 83 | 84 | initial begin 85 | clk = 0; 86 | rst_n = 0; 87 | reg1_w_en = 0; 88 | reg2_w_en = 0; 89 | reg1_in = 0; 90 | reg2_in = 0; 91 | iic_reg_wr_en = 0; 92 | iic_reg_rd_en = 0; 93 | iic_reg_addr = 0; 94 | iic_reg_wdata = 0; 95 | #21; 96 | rst_n = 1; 97 | #21; 98 | set_iic_reg(32'h00, (500000000/3000000) - 1); 99 | set_iic_reg(32'h04, (500000000/3000000/8) - 1); 100 | set_iic_reg(32'h14, 32'h18); 101 | #51; 102 | reg1_in = 8'h0f; 103 | reg1_w_en = 1; 104 | #21; 105 | reg1_w_en = 0; 106 | #51; 107 | set_iic_reg(32'h08, 32'h03010003); 108 | wait(data_ready_int); 109 | get_iic_reg(32'h10); 110 | #51; 111 | set_iic_reg(32'h08, 32'h03010002); 112 | wait(write_ready_int); 113 | $display("reg1_out = %h", reg1_out); 114 | #51; 115 | set_iic_reg(32'h08, 32'h03010003); 116 | wait(data_ready_int); 117 | get_iic_reg(32'h10); 118 | #51; 119 | reg2_in = 32'h04030201; 120 | reg2_w_en = 1; 121 | #21; 122 | reg2_w_en = 0; 123 | #51; 124 | set_iic_reg(32'h08, 32'h03040103); 125 | wait(data_ready_int); 126 | get_iic_reg(32'h10); 127 | set_iic_reg(32'h14, 32'h18); 128 | #51; 129 | set_iic_reg(32'h08, 32'h05040102); 130 | set_iic_reg(32'h10, 32'h00080706); 131 | wait(write_ready_int); 132 | $display("reg2_out = %h", reg2_out); 133 | set_iic_reg(32'h14, 32'h18); 134 | #51; 135 | set_iic_reg(32'h08, 32'h03040103); 136 | wait(data_ready_int); 137 | get_iic_reg(32'h10); 138 | set_iic_reg(32'h14, 32'h18); 139 | #100; 140 | $finish; 141 | end 142 | 143 | always #10 clk = ~clk; 144 | 145 | endmodule -------------------------------------------------------------------------------- /verilog/testbench/instdecoder-tb.v: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | `timescale 1ns/1ns 17 | `include "config.v" 18 | `include "instruction_decoder.v" 19 | 20 | module instdecoder_tb(); 21 | reg [`MAX_BIT_POS:0] instruction_code; 22 | reg en; 23 | wire [`MAX_BIT_POS:0] invalid_instruction; 24 | wire [18:0] alu_op; 25 | wire [8:0] jmp_op; 26 | wire [8:0] mem_op; 27 | wire cust_op; 28 | wire [5:0] csr_op; 29 | wire [7:0] mechie_op; 30 | wire [4:0] rd; 31 | wire [4:0] rs1; 32 | wire [4:0] rs2; 33 | wire [6:0] imm_2531; 34 | wire [19:0] imm_1231; 35 | wire [11:0] imm_2032; 36 | 37 | instruction_decoder dut( 38 | .instruction_code(instruction_code), 39 | .en(en), 40 | .invalid_instruction(invalid_instruction), 41 | .alu_op(alu_op), 42 | .jmp_op(jmp_op), 43 | .mem_op(mem_op), 44 | .cust_op(cust_op), 45 | .csr_op(csr_op), 46 | .mechie_op(mechie_op), 47 | .rd(rd), 48 | .rs1(rs1), 49 | .rs2(rs2), 50 | .imm_2531(imm_2531), 51 | .imm_1231(imm_1231), 52 | .imm_2032(imm_2032) 53 | ); 54 | 55 | initial begin 56 | $dumpfile("instdecoder.vcd"); 57 | $dumpvars(0, instdecoder_tb); 58 | end 59 | 60 | initial begin 61 | en = 1; 62 | instruction_code = 32'd0; // invalid instruction 63 | #200; 64 | instruction_code = 32'h00000797; // auipc a5,0x0 65 | #200; 66 | instruction_code = 32'd0; 67 | #10; 68 | instruction_code = 32'h02c78793; // addi a5,a5,44 69 | #200; 70 | instruction_code = 32'd0; 71 | #10; 72 | instruction_code = 32'h305793f3; // csrrw t2,mtvec,a5 73 | #200; 74 | instruction_code = 32'd0; 75 | #10; 76 | instruction_code = 32'h1a5000ef; // jal 20009c4 77 | #200; 78 | instruction_code = 32'd0; 79 | #10; 80 | instruction_code = 32'h00112623; // sw ra,12(sp) 81 | #200; 82 | instruction_code = 32'd0; 83 | #10; 84 | instruction_code = 32'h30200073; // mret 85 | #200; 86 | instruction_code = 32'd0; 87 | #10; 88 | instruction_code = 32'h04079263; // bnez a5,20000cc (bne rs,x0,offset) 89 | #200; 90 | instruction_code = 32'd0; 91 | #10; 92 | instruction_code = 32'h07f56513; // ori a0,a0,127 93 | #200; 94 | instruction_code = 32'd0; 95 | #10; 96 | instruction_code = 32'h8000007F; // cust op 97 | #200; 98 | $finish; 99 | end 100 | 101 | 102 | endmodule -------------------------------------------------------------------------------- /verilog/testbench/t.v: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | module t( 17 | input clk, 18 | input rst_n, 19 | output reg [3:0] leds 20 | ); 21 | 22 | always @(posedge clk or rst_n) begin 23 | if (!rst_n) begin 24 | leds <= 4'b0001; 25 | end 26 | else begin 27 | leds <= {leds[2:0], leds[3]}; 28 | end 29 | end 30 | endmodule -------------------------------------------------------------------------------- /verilog/testbench/tt_tb.v: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | `timescale 1ms/1ms 17 | 18 | module tt_tb; 19 | reg [42:0] inputsig; 20 | reg [81:0] inputsig1; 21 | wire [81:0] outputsig; 22 | 23 | reg clk; 24 | reg rst_n; 25 | 26 | reg [2:0] leds; 27 | assign outputsig = inputsig1; 28 | 29 | always @(posedge clk or negedge rst_n) begin 30 | if (!rst_n) begin 31 | leds <= 3'b000; 32 | inputsig1 <= 82'h22ee_22ee_33ff_33ff; 33 | end 34 | else begin 35 | $refresh; 36 | $display("inputsig = %b", inputsig1); 37 | $display("inputsig = %b", inputsig); 38 | leds <= inputsig[2:0]; 39 | end 40 | end 41 | 42 | initial begin 43 | rst_n = 0; 44 | clk = 0; 45 | $setSignalNames("tt_tb.inputsig", "tt_tb.outputsig"); 46 | #20; 47 | rst_n = 1; 48 | $refresh; 49 | end 50 | 51 | always #20000000 clk = ~clk; 52 | 53 | endmodule -------------------------------------------------------------------------------- /verilog/testbench/uart_div_tb.v: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | `timescale 1ps/1ps 17 | 18 | module uart_div_tb(); 19 | 20 | reg clk; 21 | reg rst_n; 22 | reg [15:0] uart_clk_div; 23 | reg [4:0] uart_clk_frag_total; // 每16个整数周期中,多少个添加个数 24 | reg [3:0] uart_clk_frag_i; // 小数添加间隔 25 | wire clk_sample; 26 | wire clk_uart; 27 | 28 | uart_clk_div uut ( 29 | .clk(clk), 30 | .rst_n(rst_n), 31 | .uart_clk_div(uart_clk_div), 32 | .uart_clk_frag_total(uart_clk_frag_total), 33 | .uart_clk_frag_i(uart_clk_frag_i), 34 | .clk_sample(clk_sample), 35 | .clk_uart(clk_uart) 36 | ); 37 | 38 | initial begin 39 | $dumpfile("uart_div.vcd"); 40 | $dumpvars; // dump all vars 41 | end 42 | 43 | initial begin 44 | clk = 0; 45 | rst_n = 0; 46 | uart_clk_div = 16'd27; 47 | uart_clk_frag_total = 5'd2; 48 | uart_clk_frag_i = 4'd7; 49 | #20; 50 | rst_n = 1; 51 | #30000; 52 | $finish; 53 | end 54 | 55 | 56 | always #10 clk = ~clk; 57 | 58 | endmodule -------------------------------------------------------------------------------- /verilog/testbench/uart_top_tb.v: -------------------------------------------------------------------------------- 1 | /* 2 | Designer : Renyangang 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | `timescale 1ns/1ns 17 | 18 | module uart_top_tb(); 19 | 20 | reg clk; 21 | reg rst_n; 22 | wire uart_rx; 23 | wire uart_tx; 24 | reg wr_en_1; 25 | reg rd_en_1; 26 | reg wr_en_2; 27 | reg rd_en_2; 28 | reg [31:0] addr1; // offset [7:0] 8'h00 config 8'h04 data 8'h08 data status(empty/full) 29 | reg [31:0] wdata1; 30 | wire [31:0] rdata1; 31 | wire uart_ready_1; 32 | wire data_ready_int_1; // data ready interrupt 33 | reg [31:0] addr2; // offset [7:0] 8'h00 config 8'h04 data 8'h08 data status(empty/full) 34 | reg [31:0] wdata2; 35 | wire [31:0] rdata2; 36 | wire uart_ready_2; 37 | wire data_ready_int_2; // data ready interrupt 38 | 39 | uart_top dut( 40 | .clk(clk), 41 | .rst_n(rst_n), 42 | .uart_rx(uart_rx), 43 | .uart_tx(uart_tx), 44 | .uart_reg_wr_en(wr_en_1), 45 | .uart_reg_rd_en(rd_en_1), 46 | .uart_reg_addr(addr1), 47 | .uart_reg_wdata(wdata1), 48 | .uart_reg_rdata(rdata1), 49 | .uart_ready(uart_ready_1), 50 | .data_ready_int(data_ready_int_1) 51 | ); 52 | 53 | uart_top dut1( 54 | .clk(clk), 55 | .rst_n(rst_n), 56 | .uart_rx(uart_tx), 57 | .uart_tx(uart_rx), 58 | .uart_reg_wr_en(wr_en_2), 59 | .uart_reg_rd_en(rd_en_2), 60 | .uart_reg_addr(addr2), 61 | .uart_reg_wdata(wdata2), 62 | .uart_reg_rdata(rdata2), 63 | .uart_ready(uart_ready_2), 64 | .data_ready_int(data_ready_int_2) 65 | ); 66 | 67 | initial begin 68 | $dumpfile("uart_top.vcd"); 69 | $dumpvars; // dump all vars 70 | end 71 | 72 | 73 | reg [31:0] uart_config; 74 | reg [31:0] uart_data; 75 | 76 | task uart1_send( 77 | input [31:0] data, 78 | input [31:0] addr 79 | ); 80 | if (rst_n) begin 81 | addr1 = addr; 82 | wdata1 = data; 83 | wr_en_1 = 1; 84 | wait(uart_ready_1); 85 | #21; 86 | wr_en_1 = 0; 87 | wait(!uart_ready_1); 88 | end 89 | endtask 90 | 91 | task uart2_send( 92 | input [31:0] data, 93 | input [31:0] addr 94 | ); 95 | if (rst_n) begin 96 | addr2 = addr; 97 | wdata2 = data; 98 | wr_en_2 = 1; 99 | wait(uart_ready_2); 100 | #21; 101 | wr_en_2 = 0; 102 | wait(!uart_ready_2); 103 | end 104 | endtask 105 | 106 | task uart1_read( 107 | input [31:0] addr 108 | ); 109 | if (rst_n) begin 110 | wait(data_ready_int_1); 111 | addr1 = addr; 112 | rd_en_1 = 1; 113 | wait(uart_ready_1); 114 | #21; 115 | rd_en_1 = 0; 116 | wait(!uart_ready_1); 117 | end 118 | endtask 119 | 120 | task uart2_read( 121 | input [31:0] addr 122 | ); 123 | if (rst_n) begin 124 | wait(data_ready_int_2); 125 | addr2 = addr; 126 | rd_en_2 = 1; 127 | wait(uart_ready_2); 128 | #21; 129 | rd_en_2 = 0; 130 | wait(!uart_ready_2); 131 | end 132 | endtask 133 | 134 | integer i,j; 135 | 136 | initial begin 137 | clk = 0; 138 | rst_n = 0; 139 | wr_en_1 = 0; 140 | rd_en_1 = 0; 141 | wr_en_2 = 0; 142 | rd_en_2 = 0; 143 | addr1 = 0; 144 | addr2 = 0; 145 | wdata1 = 0; 146 | wdata2 = 0; 147 | uart_config[15:0] = 16'd27; 148 | uart_config[20:16] = 5'd2; 149 | uart_config[24:21] = 4'd7; 150 | uart_config[26:25] = 2'd0; // parity none 151 | uart_config[28:27] = 2'd1; // stop bit 1 152 | uart_config[29] = 1'd1; // data read interrupt enable 153 | uart_config[31:30] = 2'd0; 154 | #100; 155 | rst_n = 1; 156 | // set baudrate to 115200 157 | uart1_send(uart_config, 32'h00000000); 158 | #10; 159 | uart2_send(uart_config, 32'h00000000); 160 | 161 | #21; 162 | // send data 163 | for (i = 0; i < 10; i = i + 1) begin 164 | uart1_send(i, 32'h00000004); 165 | #21; 166 | end 167 | for (i = 32'h80; i < 32'h90; i = i + 1) begin 168 | uart2_send(i, 32'h00000004); 169 | #21; 170 | end 171 | 172 | // read data 173 | #21; 174 | uart1_read(32'h00000008); 175 | #21; 176 | for (i = 0; i < 10; i = i + 1) begin 177 | uart1_read(32'h00000004); 178 | #21; 179 | end 180 | #21; 181 | // read data 182 | uart2_read(32'h00000008); 183 | #21; 184 | for (i = 0; i < 10; i = i + 1) begin 185 | uart2_read(32'h00000004); 186 | #21; 187 | end 188 | 189 | $finish; 190 | end 191 | 192 | always #10 clk = ~clk; 193 | 194 | endmodule --------------------------------------------------------------------------------