RISC-V GNU Compiler Toolchain
必要(または強く推奨される)設計ツール
RISC‑V ソフトウェアツールチェイン
GNU Toolchain for RISC‑V(GCC, binutils, assembler)
→ riscv-gnu-toolchain リポジトリなどを使ってクロスコンパイル環境を整える。
GitHub
ISA シミュレータ:Spike
→ RISC‑V 命令をシミュレーションして動作確認。 riscv-tools リポジトリに含まれる。
GitHub
Proxy Kernel (PK)
→ Spike 上でシステムコールをエミュレートするための簡易カーネル。 riscv-tools に含まれる。
GitHub
テスト・ベンチ用 ISA テスト
→ riscv-tests や riscv-opcodes など、命令の正当性確認に使える。
GitHub
HDL / FPGA 合成・シミュレーションツール
Yosys
→ オープンソース Verilog 合成ツール。FPGA 向け RTL 合成に必須。
GitHub
+1
nextpnr
→ place-and-route ツール。ベンダー中立 (open-source) でタイミング駆動。
yosyshq.com
+1
シミュレータ / 検証
Verilator:高速 Verilog シミュレーション。Debian パッケージでも提供。
blends.debian.org
GHDL (必要であれば VHDL を使う場合):VHDL のシミュレーション。
ウィキペディア
SoC / CPU コア設計フレームワーク(オプション)
LiteX
→ Python ベースで RISC‑V ソC を構成するフレームワーク。IP コア(CPU、UART など)を統合しやすい。
arXiv
Formal/検証ツール (任意)
→ riscv-formal などを使えば、命令セットの正しさや CPU コアの設計検証が可能。
yosyshq.com
FPGA ベンダー/ツール
Gowin IDE(または Gowin EDA ツール)
→ Tang Nano 9K のような Gowin FPGA を使う場合には、Gowin 純正の IDE(合成・配置・書き込みツール)が必要。 IAR の資料でも Gowin Designer を使った方法が紹介されている。
iar.com
プログラミング / JTAG ツール
→ FPGA にビットストリームを書き込むためのツール。Gowin IDE に付属または併用。
デバッグ / 波形可視化ツール
GTKWave
→ シミュレーション波形 (VCD, FST など) を可視化・分析するためのツール。
GDB / デバッグツール
→ RISC-V クロスコンパイラ + Spike を用いたリモートデバッグ (例えば riscv‑gnu‑toolchain + GDB) を使える。
補助ツール
Python / スクリプト言語
→ スクリプト (ビルド、テスト、シミュレーション制御) を自動化するのに有用。
Make / CMake
→ ソフトウェア (C コード) やハード (RTL) のビルド管理。
推奨構成例(講習用途向け)
ソフトウェア側:riscv-gnu-toolchain + spike + PK
ハードウェア側:Yosys + nextpnr + Verilator(または GHDL)
FPGA 書き込み:Gowin IDE
デバッグ・可視化:GTKWave + GDB
設計自動化:Python スクリプト + Makefile
もしよければ、Tang Nano 9K + PicoRV32 講習環境 (GitHub 配布 + スクリプト込み) 向けに推奨ツール&バージョン付きのセットアップ手順を僕が設計できます。やりましょうか?
RISC-V GNU Compiler Toolchain
This is the RISC-V C and C++ cross-compiler. It supports two build modes: a generic ELF/Newlib toolchain and a more sophisticated Linux-ELF/glibc toolchain.
RARS
RARS -- RISC-V Assembler and Runtime Simulator
RARS, the RISC-V Assembler, Simulator, and Runtime, will assemble and simulate the execution of RISC-V assembly language programs. Its primary goal is to be an effective development environment for people getting started with RISC-V.
Icarus Verilog
Icarus Verilog is an implementation of the Verilog hardware description language compiler that generates netlists in the desired format (EDIF) and a simulator. It supports the 1995, 2001 and 2005 versions of the standard, portions of SystemVerilog, and some extensions.
Icarus Verilog is available for Linux, FreeBSD, OpenSolaris, AIX, Microsoft Windows, and Mac OS X. Released under the GNU General Public License, Icarus Verilog is free software, an alternative to proprietary software like Cadence's Verilog-XL.
As of release 0.9, Icarus is composed of a Verilog compiler (including a Verilog preprocessor) with support for plug-in backends, and a virtual machine that simulates the design. To view waveforms, a program like GTKWave can be used. Release v10.0, besides general improvements and bug fixes, added preliminary support for VHDL, but the VHDL support has been abandoned as of 2018.
GTKwave
GTKWave
GTKWave is a fully featured GTK+ based wave viewer for Unix and Win32 which reads FST, and GHW files as well as standard Verilog VCD/EVCD files and allows their viewing.
GTK (formerly GIMP ToolKit[3] and GTK+[4]) is a free open-source widget toolkit for creating graphical user interfaces (GUIs)[5] targeted at Linux and specifically GNOME (though with some use in other desktop environments). It is licensed under the terms of the GNU LGPL, allowing both free and proprietary software to use it.[6]
The GTK team releases new versions on a regular basis.[7] GTK 4 and GTK 3 are actively maintained, while GTK 2 is no longer supported.[8] GTK 1 is independently maintained by the CinePaint project.[9]
Yosys
yosys – Yosys Open SYnthesis Suite
This is a framework for RTL synthesis tools. It currently has extensive Verilog-2005 support and provides a basic set of synthesis algorithms for various application domains.
Yosys can be adapted to perform any synthesis job by combining the existing passes (algorithms) using synthesis scripts and adding additional passes as needed by extending the yosys C++ code base.
Yosys is free software licensed under the ISC license (a GPL compatible license that is similar in terms to the MIT license or the 2-clause BSD license).
Third-party software distributed alongside this software is licensed under compatible licenses. Please refer to abc and libs subdirectories for their license terms.
Yosys is a logic synthesis (RTL synthesis) software suite that can convert logic circuits described in hardware description languages (HDLs) such as Verilog or VHDL into a register transfer level (RTL) bitstream that can be used by programmable circuits such as FPGAs. It can also perform formal verification tasks [2]. It was developed by Claire Wolf [3].
nextpnr
FPGA place and route tool for Lattice iCE40
nextpnr is a FPGA place and route tool. Its purpose is to turn a topological description of digital hardware produced by an FPGA logic synthesis tool such as yosys into an elaborate map of connections between the hardwired functional units available inside the FPGA's fabric.
In order to verify the fully implemented design for proper operation at high speed timing-analysis of the design is also supported.
nextpnr-ice40 supports the Lattice iCE40 series of FPGAs and uses the hardware description chipdb from the fpga-icestorm package.
This package supports only the command-line interface, there is also a GUI version in the nextpnr-ice40-qt package.
ICEpack
This tool can be used to create binary bitstreams for Lattice FPGA from readable .txt file.
FPGA board iCE40
3. Connect Your Board
Hardware Connection: Connect your development board to your computer using the appropriate cable (e.g., a USB cable for USB-powered boards).
Driver Installation (if needed):
For the open-source toolchain, you may need to use the Zadig tool to assign the libusbK or WinUSB drivers to your device's interfaces.
For proprietary Lattice tools, ensure you have the correct drivers installed for the programmer.
4. Upload the Bitstream
Using apio: Run the upload command for your board: apio upload.
Using Lattice Diamond Programmer: Use the software's programming interface to load the bitstream onto the onboard SPI flash or directly into the FPGA.
Using a Download Cable: Connect a dedicated download cable and use the corresponding tool (e.g., iceprog for the open-source chain) to upload the bitstream.
PicoRV32
PicoRV32 - A Size-Optimized RISC-V CPU
PicoRV32 is a CPU core that implements the RISC-V RV32IMC Instruction Set. It can be configured as RV32E, RV32I, RV32IC, RV32IM, or RV32IMC core, and optionally contains a built-in interrupt controller.
Tools (gcc, binutils, etc..) can be obtained via the RISC-V Website. The examples bundled with PicoRV32 expect various RV32 toolchains to be installed in /opt/riscv32i[m][c]. See the build instructions below for details. Many Linux distributions now include the tools for RISC-V (for example Ubuntu 20.04 has gcc-riscv64-unknown-elf). To compile using those set TOOLCHAIN_PREFIX accordingly (eg. make TOOLCHAIN_PREFIX=riscv64-unknown-elf-).
PicoRV32 is free and open hardware licensed under the ISC license (a license that is similar in terms to the MIT license or the 2-clause BSD license).
Fibonacci C program
// C Program to print the fibonacci series using loops
#include
void printFib(int n) {
// If the number of terms is smaller than 1
if (n < 1) {
printf("Invalid Number of terms\n");
return;
}
// First two terms of the series
int prev1 = 1;
int prev2 = 0;
// for loop that prints n terms of fibonacci series
for (int i = 1; i <= n; i++) { // Print current term and update previous terms if (i > 2) {
int curr = prev1 + prev2;
prev2 = prev1;
prev1 = curr;
printf("%d ", curr);
}
else if (i == 1)
printf("%d ", prev2);
else if (i == 2)
printf("%d ", prev1);
}
}
int main() {
int n = 9;
// Printing first n fibonacci terms
printFib(n);
return 0;
}
Fibonacci assemble language
.data
n: .word 47
.text
.globl main
main:
li x2, 0 # Used to determine if n (x7) equals 0
li x3, 1 # Used to determine if n (x7) equals 1
li x5, 0 # First number
li x6, 1 # Second number
lw x7, n # Limit
li x8, 1 # Counter
beq x7, x2, DO # If n == 0 then jump to DO (Which shoud print 0). Implements f(0) = 0
beq x7, x3, WRITE # if n == 1 then jump to WRITE (Which should print 1). Implements f(1) = 1
LOOP: beq x8, x7, EXIT # Comparse the counter x8 which starts with 1 to n (limit). If x8 == x7 jump to EXIT
add x4, x5, x6 # Add x5 to x6 and store in x4
ori x5, x6, 0 # Assign the second number to my first number
ori x6, x4, 0 # Assign the sum of x5 and x6 to my second number
addi x8, x8, 1 # Add 1 to my counter
j LOOP # Jump to loop
EXIT:
li x17, 1 # Load constant 1 to x17
add x10,x4,x0 # Add x4 (which contains the result after the above coe) to x10
ecall # Issue an SystemCall which prints an integer (Because of the 1 in x17)
li x17, 5
ecall
li x17, 10
ecall # Reads an int from input console (Because of the 10 in x17)
DO:
li x4, 0 # load 0 in x10 (x10 will be used by the SysCall to print) and print
add x10,x4,x0
li x17, 1
ecall
li x17, 5
ecall
li x17, 10
ecall
WRITE: li x4, 1 # load 1 in x10 and print
add x10,x4,x0
li x17,1
ecall
li x17, 5
ecall
li x17, 10
ecall
picoRV32 verilog
/*
* PicoSoC - A simple example SoC using PicoRV32
*
* Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
`ifndef PICORV32_REGS
`ifdef PICORV32_V
`error "picosoc.v must be read before picorv32.v!"
`endif
`define PICORV32_REGS picosoc_regs
`endif
`ifndef PICOSOC_MEM
`define PICOSOC_MEM picosoc_mem
`endif
// this macro can be used to check if the verilog files in your
// design are read in the correct order.
`define PICOSOC_V
module picosoc (
input clk,
input resetn,
output iomem_valid,
input iomem_ready,
output [ 3:0] iomem_wstrb,
output [31:0] iomem_addr,
output [31:0] iomem_wdata,
input [31:0] iomem_rdata,
input irq_5,
input irq_6,
input irq_7,
output ser_tx,
input ser_rx,
output flash_csb,
output flash_clk,
output flash_io0_oe,
output flash_io1_oe,
output flash_io2_oe,
output flash_io3_oe,
output flash_io0_do,
output flash_io1_do,
output flash_io2_do,
output flash_io3_do,
input flash_io0_di,
input flash_io1_di,
input flash_io2_di,
input flash_io3_di
);
parameter [0:0] BARREL_SHIFTER = 1;
parameter [0:0] ENABLE_MUL = 1;
parameter [0:0] ENABLE_DIV = 1;
parameter [0:0] ENABLE_FAST_MUL = 0;
parameter [0:0] ENABLE_COMPRESSED = 1;
parameter [0:0] ENABLE_COUNTERS = 1;
parameter [0:0] ENABLE_IRQ_QREGS = 0;
parameter integer MEM_WORDS = 256;
parameter [31:0] STACKADDR = (4*MEM_WORDS); // end of memory
parameter [31:0] PROGADDR_RESET = 32'h 0010_0000; // 1 MB into flash
parameter [31:0] PROGADDR_IRQ = 32'h 0000_0000;
reg [31:0] irq;
wire irq_stall = 0;
wire irq_uart = 0;
always @* begin
irq = 0;
irq[3] = irq_stall;
irq[4] = irq_uart;
irq[5] = irq_5;
irq[6] = irq_6;
irq[7] = irq_7;
end
wire mem_valid;
wire mem_instr;
wire mem_ready;
wire [31:0] mem_addr;
wire [31:0] mem_wdata;
wire [3:0] mem_wstrb;
wire [31:0] mem_rdata;
wire spimem_ready;
wire [31:0] spimem_rdata;
reg ram_ready;
wire [31:0] ram_rdata;
assign iomem_valid = mem_valid && (mem_addr[31:24] > 8'h 01);
assign iomem_wstrb = mem_wstrb;
assign iomem_addr = mem_addr;
assign iomem_wdata = mem_wdata;
wire spimemio_cfgreg_sel = mem_valid && (mem_addr == 32'h 0200_0000);
wire [31:0] spimemio_cfgreg_do;
wire simpleuart_reg_div_sel = mem_valid && (mem_addr == 32'h 0200_0004);
wire [31:0] simpleuart_reg_div_do;
wire simpleuart_reg_dat_sel = mem_valid && (mem_addr == 32'h 0200_0008);
wire [31:0] simpleuart_reg_dat_do;
wire simpleuart_reg_dat_wait;
assign mem_ready = (iomem_valid && iomem_ready) || spimem_ready || ram_ready || spimemio_cfgreg_sel ||
simpleuart_reg_div_sel || (simpleuart_reg_dat_sel && !simpleuart_reg_dat_wait);
assign mem_rdata = (iomem_valid && iomem_ready) ? iomem_rdata : spimem_ready ? spimem_rdata : ram_ready ? ram_rdata :
spimemio_cfgreg_sel ? spimemio_cfgreg_do : simpleuart_reg_div_sel ? simpleuart_reg_div_do :
simpleuart_reg_dat_sel ? simpleuart_reg_dat_do : 32'h 0000_0000;
picorv32 #(
.STACKADDR(STACKADDR),
.PROGADDR_RESET(PROGADDR_RESET),
.PROGADDR_IRQ(PROGADDR_IRQ),
.BARREL_SHIFTER(BARREL_SHIFTER),
.COMPRESSED_ISA(ENABLE_COMPRESSED),
.ENABLE_COUNTERS(ENABLE_COUNTERS),
.ENABLE_MUL(ENABLE_MUL),
.ENABLE_DIV(ENABLE_DIV),
.ENABLE_FAST_MUL(ENABLE_FAST_MUL),
.ENABLE_IRQ(1),
.ENABLE_IRQ_QREGS(ENABLE_IRQ_QREGS)
) cpu (
.clk (clk ),
.resetn (resetn ),
.mem_valid (mem_valid ),
.mem_instr (mem_instr ),
.mem_ready (mem_ready ),
.mem_addr (mem_addr ),
.mem_wdata (mem_wdata ),
.mem_wstrb (mem_wstrb ),
.mem_rdata (mem_rdata ),
.irq (irq )
);
spimemio spimemio (
.clk (clk),
.resetn (resetn),
.valid (mem_valid && mem_addr >= 4*MEM_WORDS && mem_addr < 32'h 0200_0000),
.ready (spimem_ready),
.addr (mem_addr[23:0]),
.rdata (spimem_rdata),
.flash_csb (flash_csb ),
.flash_clk (flash_clk ),
.flash_io0_oe (flash_io0_oe),
.flash_io1_oe (flash_io1_oe),
.flash_io2_oe (flash_io2_oe),
.flash_io3_oe (flash_io3_oe),
.flash_io0_do (flash_io0_do),
.flash_io1_do (flash_io1_do),
.flash_io2_do (flash_io2_do),
.flash_io3_do (flash_io3_do),
.flash_io0_di (flash_io0_di),
.flash_io1_di (flash_io1_di),
.flash_io2_di (flash_io2_di),
.flash_io3_di (flash_io3_di),
.cfgreg_we(spimemio_cfgreg_sel ? mem_wstrb : 4'b 0000),
.cfgreg_di(mem_wdata),
.cfgreg_do(spimemio_cfgreg_do)
);
simpleuart simpleuart (
.clk (clk ),
.resetn (resetn ),
.ser_tx (ser_tx ),
.ser_rx (ser_rx ),
.reg_div_we (simpleuart_reg_div_sel ? mem_wstrb : 4'b 0000),
.reg_div_di (mem_wdata),
.reg_div_do (simpleuart_reg_div_do),
.reg_dat_we (simpleuart_reg_dat_sel ? mem_wstrb[0] : 1'b 0),
.reg_dat_re (simpleuart_reg_dat_sel && !mem_wstrb),
.reg_dat_di (mem_wdata),
.reg_dat_do (simpleuart_reg_dat_do),
.reg_dat_wait(simpleuart_reg_dat_wait)
);
always @(posedge clk)
ram_ready <= mem_valid && !mem_ready && mem_addr < 4*MEM_WORDS;
`PICOSOC_MEM #(
.WORDS(MEM_WORDS)
) memory (
.clk(clk),
.wen((mem_valid && !mem_ready && mem_addr < 4*MEM_WORDS) ? mem_wstrb : 4'b0),
.addr(mem_addr[23:2]),
.wdata(mem_wdata),
.rdata(ram_rdata)
);
endmodule
// Implementation note:
// Replace the following two modules with wrappers for your SRAM cells.
module picosoc_regs (
input clk, wen,
input [5:0] waddr,
input [5:0] raddr1,
input [5:0] raddr2,
input [31:0] wdata,
output [31:0] rdata1,
output [31:0] rdata2
);
reg [31:0] regs [0:31];
always @(posedge clk)
if (wen) regs[waddr[4:0]] <= wdata;
assign rdata1 = regs[raddr1[4:0]];
assign rdata2 = regs[raddr2[4:0]];
endmodule
module picosoc_mem #(
parameter integer WORDS = 256
) (
input clk,
input [3:0] wen,
input [21:0] addr,
input [31:0] wdata,
output reg [31:0] rdata
);
reg [31:0] mem [0:WORDS-1];
always @(posedge clk) begin
rdata <= mem[addr];
if (wen[0]) mem[addr][ 7: 0] <= wdata[ 7: 0];
if (wen[1]) mem[addr][15: 8] <= wdata[15: 8];
if (wen[2]) mem[addr][23:16] <= wdata[23:16];
if (wen[3]) mem[addr][31:24] <= wdata[31:24];
end
endmodule
picoRV32 verilog
/*
* PicoSoC - A simple example SoC using PicoRV32
*
* Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
`ifndef PICORV32_REGS
`ifdef PICORV32_V
`error "picosoc.v must be read before picorv32.v!"
`endif
`define PICORV32_REGS picosoc_regs
`endif
`ifndef PICOSOC_MEM
`define PICOSOC_MEM picosoc_mem
`endif
// this macro can be used to check if the verilog files in your
// design are read in the correct order.
`define PICOSOC_V
module picosoc (
input clk,
input resetn,
output iomem_valid,
input iomem_ready,
output [ 3:0] iomem_wstrb,
output [31:0] iomem_addr,
output [31:0] iomem_wdata,
input [31:0] iomem_rdata,
input irq_5,
input irq_6,
input irq_7,
output ser_tx,
input ser_rx,
output flash_csb,
output flash_clk,
output flash_io0_oe,
output flash_io1_oe,
output flash_io2_oe,
output flash_io3_oe,
output flash_io0_do,
output flash_io1_do,
output flash_io2_do,
output flash_io3_do,
input flash_io0_di,
input flash_io1_di,
input flash_io2_di,
input flash_io3_di
);
parameter [0:0] BARREL_SHIFTER = 1;
parameter [0:0] ENABLE_MUL = 1;
parameter [0:0] ENABLE_DIV = 1;
parameter [0:0] ENABLE_FAST_MUL = 0;
parameter [0:0] ENABLE_COMPRESSED = 1;
parameter [0:0] ENABLE_COUNTERS = 1;
parameter [0:0] ENABLE_IRQ_QREGS = 0;
parameter integer MEM_WORDS = 256;
parameter [31:0] STACKADDR = (4*MEM_WORDS); // end of memory
parameter [31:0] PROGADDR_RESET = 32'h 0010_0000; // 1 MB into flash
parameter [31:0] PROGADDR_IRQ = 32'h 0000_0000;
reg [31:0] irq;
wire irq_stall = 0;
wire irq_uart = 0;
always @* begin
irq = 0;
irq[3] = irq_stall;
irq[4] = irq_uart;
irq[5] = irq_5;
irq[6] = irq_6;
irq[7] = irq_7;
end
wire mem_valid;
wire mem_instr;
wire mem_ready;
wire [31:0] mem_addr;
wire [31:0] mem_wdata;
wire [3:0] mem_wstrb;
wire [31:0] mem_rdata;
wire spimem_ready;
wire [31:0] spimem_rdata;
reg ram_ready;
wire [31:0] ram_rdata;
assign iomem_valid = mem_valid && (mem_addr[31:24] > 8'h 01);
assign iomem_wstrb = mem_wstrb;
assign iomem_addr = mem_addr;
assign iomem_wdata = mem_wdata;
wire spimemio_cfgreg_sel = mem_valid && (mem_addr == 32'h 0200_0000);
wire [31:0] spimemio_cfgreg_do;
wire simpleuart_reg_div_sel = mem_valid && (mem_addr == 32'h 0200_0004);
wire [31:0] simpleuart_reg_div_do;
wire simpleuart_reg_dat_sel = mem_valid && (mem_addr == 32'h 0200_0008);
wire [31:0] simpleuart_reg_dat_do;
wire simpleuart_reg_dat_wait;
assign mem_ready = (iomem_valid && iomem_ready) || spimem_ready || ram_ready || spimemio_cfgreg_sel ||
simpleuart_reg_div_sel || (simpleuart_reg_dat_sel && !simpleuart_reg_dat_wait);
assign mem_rdata = (iomem_valid && iomem_ready) ? iomem_rdata : spimem_ready ? spimem_rdata : ram_ready ? ram_rdata :
spimemio_cfgreg_sel ? spimemio_cfgreg_do : simpleuart_reg_div_sel ? simpleuart_reg_div_do :
simpleuart_reg_dat_sel ? simpleuart_reg_dat_do : 32'h 0000_0000;
picorv32 #(
.STACKADDR(STACKADDR),
.PROGADDR_RESET(PROGADDR_RESET),
.PROGADDR_IRQ(PROGADDR_IRQ),
.BARREL_SHIFTER(BARREL_SHIFTER),
.COMPRESSED_ISA(ENABLE_COMPRESSED),
.ENABLE_COUNTERS(ENABLE_COUNTERS),
.ENABLE_MUL(ENABLE_MUL),
.ENABLE_DIV(ENABLE_DIV),
.ENABLE_FAST_MUL(ENABLE_FAST_MUL),
.ENABLE_IRQ(1),
.ENABLE_IRQ_QREGS(ENABLE_IRQ_QREGS)
) cpu (
.clk (clk ),
.resetn (resetn ),
.mem_valid (mem_valid ),
.mem_instr (mem_instr ),
.mem_ready (mem_ready ),
.mem_addr (mem_addr ),
.mem_wdata (mem_wdata ),
.mem_wstrb (mem_wstrb ),
.mem_rdata (mem_rdata ),
.irq (irq )
);
spimemio spimemio (
.clk (clk),
.resetn (resetn),
.valid (mem_valid && mem_addr >= 4*MEM_WORDS && mem_addr < 32'h 0200_0000),
.ready (spimem_ready),
.addr (mem_addr[23:0]),
.rdata (spimem_rdata),
.flash_csb (flash_csb ),
.flash_clk (flash_clk ),
.flash_io0_oe (flash_io0_oe),
.flash_io1_oe (flash_io1_oe),
.flash_io2_oe (flash_io2_oe),
.flash_io3_oe (flash_io3_oe),
.flash_io0_do (flash_io0_do),
.flash_io1_do (flash_io1_do),
.flash_io2_do (flash_io2_do),
.flash_io3_do (flash_io3_do),
.flash_io0_di (flash_io0_di),
.flash_io1_di (flash_io1_di),
.flash_io2_di (flash_io2_di),
.flash_io3_di (flash_io3_di),
.cfgreg_we(spimemio_cfgreg_sel ? mem_wstrb : 4'b 0000),
.cfgreg_di(mem_wdata),
.cfgreg_do(spimemio_cfgreg_do)
);
simpleuart simpleuart (
.clk (clk ),
.resetn (resetn ),
.ser_tx (ser_tx ),
.ser_rx (ser_rx ),
.reg_div_we (simpleuart_reg_div_sel ? mem_wstrb : 4'b 0000),
.reg_div_di (mem_wdata),
.reg_div_do (simpleuart_reg_div_do),
.reg_dat_we (simpleuart_reg_dat_sel ? mem_wstrb[0] : 1'b 0),
.reg_dat_re (simpleuart_reg_dat_sel && !mem_wstrb),
.reg_dat_di (mem_wdata),
.reg_dat_do (simpleuart_reg_dat_do),
.reg_dat_wait(simpleuart_reg_dat_wait)
);
always @(posedge clk)
ram_ready <= mem_valid && !mem_ready && mem_addr < 4*MEM_WORDS;
`PICOSOC_MEM #(
.WORDS(MEM_WORDS)
) memory (
.clk(clk),
.wen((mem_valid && !mem_ready && mem_addr < 4*MEM_WORDS) ? mem_wstrb : 4'b0),
.addr(mem_addr[23:2]),
.wdata(mem_wdata),
.rdata(ram_rdata)
);
endmodule
// Implementation note:
// Replace the following two modules with wrappers for your SRAM cells.
module picosoc_regs (
input clk, wen,
input [5:0] waddr,
input [5:0] raddr1,
input [5:0] raddr2,
input [31:0] wdata,
output [31:0] rdata1,
output [31:0] rdata2
);
reg [31:0] regs [0:31];
always @(posedge clk)
if (wen) regs[waddr[4:0]] <= wdata;
assign rdata1 = regs[raddr1[4:0]];
assign rdata2 = regs[raddr2[4:0]];
endmodule
module picosoc_mem #(
parameter integer WORDS = 256
) (
input clk,
input [3:0] wen,
input [21:0] addr,
input [31:0] wdata,
output reg [31:0] rdata
);
reg [31:0] mem [0:WORDS-1];
always @(posedge clk) begin
rdata <= mem[addr];
if (wen[0]) mem[addr][ 7: 0] <= wdata[ 7: 0];
if (wen[1]) mem[addr][15: 8] <= wdata[15: 8];
if (wen[2]) mem[addr][23:16] <= wdata[23:16];
if (wen[3]) mem[addr][31:24] <= wdata[31:24];
end
endmodule