【PicoRV32】學習過程紀錄 & 文章素材


!!! 個人零碎筆記,未來整個架構搞懂了才會重新整理

設計架構

1. 怎麼理解整個設計架構

------- 模組介紹 ---------

模組名稱描述
picorv32_wrapper.sv整合picorv32axi4_memory_bhv
picorv32使用 native memory interface 的主 CPU
picorv32_axi提供 AXI4-Lite master 介面的 CPU
picorv32_axi_adapternative memory ↔ AXI4 bridge
picorv32_wbWishbone master 介面
picorv32_pcpi_*外接乘法 / 除法協同處理器
axi4_memory_bhv.sv在模擬環境中充當 AXI4-Lite 介面Slave端的記憶體模型

先大致畫出整個module 階層的block digram
PicoRV32 module 架構圖

接著從程式碼中可以得知編譯好的firmware.hex檔,在picorv32_wrapper.sv中讀入,到axi4_memory_bhv.sv中的memory陣列(模擬ram)
picorv32_wrapper.sv 讀入firmware.hex檔

下一步就是去axi4_memory_bhv.sv查看他的行為

介面通道省去了LNE、ID、BURST、RESP等完整AXI訊號


picorv32.sv

picorv32.sv 主要分為三個部分

  1. Memory Interface
    look-ahead 訊號 : 下一拍會讀或寫哪個位址、資料與 byte enable

  2. Instruction Decoder

  3. Main State Machine

- mem_state

mem_state 是 PicoRV32 記憶體存取狀態機的核心暫存器,用來:
• 區分 CPU 當前是否在 取指、讀資料、寫資料,或閒置。
• 控制 mem_valid / mem_instr / mem_wstrb 等訊號的組合。
• 等待外部記憶體或匯流排的 mem_ready 回應。
• 配合 RVC(壓縮指令集) 處理跨 32-bit 邊界的抓取。

mem_state實際語意(依你的程式)關鍵行為摘要
0Idle(閒置)若 `mem_do_prefetch
1Read/Fetch 進行中這一態處理「指令抓取或資料讀取」的實際握手。mem_xfer 成功後:— 若有 RVC 需要第二半字,可能設 mem_la_secondword 繼續讀;— 否則結束讀取:若這次是「rinst/rdata」→ 回 0;若這次只是 prefetch → 轉 3。
2Write 進行中實際資料寫入(mem_wstrb != 0)。mem_xfer 成功後清 mem_valid,回 0。
3Prefetch-hold(只預取、暫停等真正取指)僅在「做過 prefetch 但尚未真的 rinst」時短暫停留;一旦 mem_do_rinst 成立即回 0。

RISCV 壓縮指令集

  1. 什麼是 RISC-V 壓縮指令集(RVC)
    • RVC 是 RISC-V 的 C 擴展(Compressed Extension),將常用的 32 位元指令(4 bytes) 壓縮成 16 位元指令(2 bytes)。
    • 主要目標:
    1. 減少程式碼體積(code size)。
    2. 提升指令快取(I-Cache)命中率。
    3. 降低指令記憶體頻寬需求(對嵌入式、低功耗系統特別有用)。

  1. RVC 判斷與基本規則
    • 判斷指令是否為壓縮格式:

    RISC-V 定義:

    若指令低 2 bits (instr[1:0]) ≠ 11(二進制),則為壓縮指令(16-bit)
    若 instr[1:0] == 11(二進制),則為標準 32-bit 指令

    instr[1:0]指令類型
    00, 01, 1016-bit RVC
    1132-bit RVC
  2. 取指流程與 PicoRV32 處理邏輯
    因為 16-bit 壓縮指令與 32-bit 指令混用,取指單元需要特別處理:

    1. 取第一個 32-bit word(可能只用前半 16-bit)。
    2. 判斷是否為壓縮指令:
      • 是 → 直接解碼執行,剩下的 16-bit 暫存在 mem_16bit_buffer。
      • 否 → 需要讀取完整的 32-bit 再解碼。
    3. 連續壓縮指令處理:
      • 如果前一個 cycle 已有剩下的高 16-bit,下一條指令直接使用它,不需要再讀記憶體。

另一個要注意的是壓縮指令使否跨過不同的word(4-byte),先舉個簡單的例子:
假設記憶體內容(每格是 1 byte,地址右邊是位址的 hex):

Word0:  [Byte0] [Byte1] [Byte2] [Byte3]
         0x00    0x01    0x02    0x03
Word1:  [Byte4] [Byte5] [Byte6] [Byte7]
         0x04    0x05    0x06    0x07
  • 情況: RVC 跨 word
    PC = 0x03
    不可能是合法的 32-bit 指令對齊,但對 RVC 來說是合法的(因為 RVC 只要對齊 2 bytes)。
    指令第一半在 Word0 的 Byte3,第二半在 Word1 的 Byte4
    必須多抓 下一個 word(Word1),才能湊滿 16-bit
    這時 mem_la_firstword_xfer = 1,mem_la_addr = {next_pc[31:2] + 1, 2’b00} → 去抓 Word1

picorv32.sv中,349行就是在確認上述的情況,
可以清楚的看到next_pc[1]這個條件,就是在檢測"跨 word",
因為在沒有"跨 word"的情況下,指令是對齊4byte,也就是地址最低兩位一定是 2'b00
在这里插入图片描述

Assert用法

在這段程式碼中,assert(…) 是用來在模擬(simulation)期間檢查條件是否成立的斷言(assertion),如果條件不成立,就會在模擬時報錯,方便開發者及早發現邏輯錯誤。

MEM_STATE_FETCH_OR_READ: begin
          assert(mem_wstrb == 0);
          assert(mem_do_prefetch || mem_do_rinst || mem_do_rdata);
          assert(mem_valid == !mem_la_use_prefetched_high_word);
          assert(mem_instr == (mem_do_prefetch || mem_do_rinst));
          if (mem_xfer) begin
            if (COMPRESSED_ISA && mem_la_read) begin
              mem_valid <= 1;
              mem_la_secondword <= 1;
              if (!mem_la_use_prefetched_high_word)
                mem_16bit_buffer <= mem_rdata[31:16];
            end else begin
              mem_valid <= 0;
              mem_la_secondword <= 0;
              if (COMPRESSED_ISA && !mem_do_rdata) begin
                if (~&mem_rdata[1:0] || mem_la_secondword) begin
                  mem_16bit_buffer <= mem_rdata[31:16];
                  prefetched_high_word <= 1;
                end else begin
                  prefetched_high_word <= 0;
                end
              end
              mem_state <= mem_do_rinst || mem_do_rdata ? MEM_STATE_IDEL : MEM_STATE_PREFETCH;
            end
          end
        end
┌──────────────────────────────────────────────────────────────┐
│  State: MEM_STATE_FETCH_OR_READ                              │
│  ※ 進入此狀態時,以下斷言必須成立:                            │
│    A1) mem_wstrb == 0                                        │
│    A2) mem_do_prefetch || mem_do_rinst || mem_do_rdata       │
│    A3) mem_valid == !mem_la_use_prefetched_high_word         │
│    A4) mem_instr == (mem_do_prefetch || mem_do_rinst)        │
└──────────────┬───────────────────────────────────────────────┘
               │
               │  等待資料交換完成
               ▼
          ┌───────────┐   mem_xfer = 1 ?
          │ mem_xfer? │────────────────────────┐
          └─────┬─────┘       否(No)           │ 是(Yes)
                │                              ▼
                │                         ┌───────────────┐
                │                         │  COMPRESSED?  │  (COMPRESSED_ISA && mem_la_read)
                │                         └──────┬────────┘
                │                                │
                │                          是(Yes)│ 否(No)
                │                                ▼
                │                     ┌───────────────────────────────┐
                │                     │  for C-ISA 取「第二個 half」   │
                │                     │  mem_valid <= 1               │
                │                     │  mem_la_secondword <= 1       │
                │                     │  if (!mem_la_use_prefetched_  │
                │                     │      high_word)               │
                │                     │    mem_16bit_buffer <=        │
                │                     │      mem_rdata[31:16];        │
                │                     └───────────┬───────────────────┘
                │                                 │
                │                                 └─────→ (留在本狀態等待下一拍)
                │
                ▼
      (No path change,本拍什麼都不做)

                               ┌──────────────────────────────────────────────┐
                        否(No) │    一般情形(或讀資料 load)                   │
                               │    mem_valid <= 0                            │
                               │    mem_la_secondword <= 0                    │
                               │    if (COMPRESSED_ISA && !mem_do_rdata) {    │
                               │      if (~&mem_rdata[1:0] ||                 │
                               │          mem_la_secondword) {                │
                               │        mem_16bit_buffer <= mem_rdata[31:16]; │
                               │        prefetched_high_word <= 1;            │
                               │      } else {                                │
                               │        prefetched_high_word <= 0;            │
                               │      }                                       │
                               │    }                                         │
                               │    mem_state <= (mem_do_rinst ||             │
                               │                  mem_do_rdata) ?             │
                               │                 MEM_STATE_IDLE :             │
                               │                 MEM_STATE_PREFETCH;          │
                               └──────────────────────────────────────────────┘

訊號意義

mem_valid

mem_validPicoRV32 裡的作用,就是 CPU 對外宣告「我有一筆記憶體存取請求要送出」,直到外部用 mem_ready=1 回應為止。
它是 CPU 端主動拉高 的信號,外部只讀它、不會去驅動它。

mem_ready

mem_readyPicoRV32 裡的作用,就是 外部記憶體或匯流排介面回應「資料已經準備好」或「寫入已完成」的握手訊號。
它是 由外部模組(記憶體模型、AXI adapter 等)驅動,CPU 只是讀它來判斷是否可以結束這次 bus transaction。

mem_instr

PicoRV32mem_instr 是 CPU 與外部記憶體介面之間的一條標記訊號,作用是:
CPU跟MEM(或arbiter)說,這次 mem_valid 發出的存取是「取指令」而不是資料讀寫。

&lt;think&gt;好的,我现在需要回答用户关于PicoRV32的使用方法、文档下载等问题。首先,我应该回忆一下PicoRV32的基本信息,它是由Clifford Wolf开发的一个轻量级RISC-V CPU核心,主要针对FPGA实现。用户需要知道如何获取文档和使用方法,可能还涉及如何下载源码以及合成的步骤。 首先,用户提到的&ldquo;合成&rdquo;应该是指将PicoRV32的硬件描述代码综合到FPGA上。所以需要指导用户如何获取源码,可能来自GitHub仓库。接下来,用户可能需要安装相关的工具链,比如Verilog仿真工具(如Icarus Verilog)、FPGA开发工具(Vivado或Quartus)。然后,编译和仿真的步骤,确保设计正确。最后是部署到具体的FPGA开发板上,比如Xilinx或Altera的板子。 文档方面,PicoRV32的官方文档通常包含在代码仓库的README文件中,或者项目Wiki里。用户可能需要访问GitHub页面查看详细说明。此外,Clifford Wolf的博客或者相关论坛可能有更多使用案例和优化建议。 还要注意用户提到的引用[1],其中提到了PicoRV32作为教学和演示平台,可能用户的应用场景是教育或原型开发,因此需要强调其轻量级和易用性。同时,可能涉及到的生态项目如PlatformIO,虽然主要用于软件开发,但可能需要说明如何与PicoRV32配合使用。 用户可能遇到的问题包括环境配置、综合过程中的错误、如何连接外设等,应该在回答中简要提及解决方案或提供资源链接。需要确保步骤清晰,分点说明,让用户能够逐步操作。同时,提供相关链接,比如GitHub仓库地址、官方文档链接,方便用户直接访问。 最后,生成的相关问题需要围绕PicoRV32的扩展功能、优化方法、应用案例以及调试工具,这些可以帮助用户深入学习和解决问题。&lt;/think&gt;### PicoRV32 RISC-V 核心使用方法指南 #### 1. 源码获取与结构 PicoRV32采用Verilog硬件描述语言实现,源码托管在GitHub: ```bash git clone https://github.com/cliffordwolf/picorv32.git ``` 核心文件为$picorv32.v$,包含RV32IMC指令集配置选项[^1]。 #### 2. 开发环境搭建 推荐工具链配置: - **仿真工具**:Icarus Verilog + GTKWave - **综合工具**:Xilinx Vivado / Intel Quartus - **RISC-V工具链**:riscv-gnu-toolchain ```bash sudo apt-get install iverilog gtkwave # Ubuntu安装示例 ``` #### 3. FPGA综合流程(以Xilinx为例) ```tcl # Vivado Tcl脚本示例 read_verilog picorv32.v synth_design -top picorv32 implement_design generate_bitstream ``` #### 4. 软件开发流程 编译示例程序: ```bash riscv32-unknown-elf-gcc -nostartfiles -march=rv32i -o firmware.elf firmware.c ``` #### 5. 关键配置参数 | 参数名 | 功能说明 | 典型值 | |-----------------|----------------------------|---------| | ENABLE_COUNTERS | 启用性能计数器 | 1 | | TWO_STAGE_ALU | 流水线优化 | 1 | | COMPRESSED_ISA | 支持C扩展指令 | 1 | #### 6. 文档资源 - [官方使用手册](https://github.com/cliffordwolf/picorv32/blob/master/README.md) - [RISC-V特权架构规范](https://riscv.org/technical/specifications/) - [FPGA开发板兼容列表](https://github.com/cliffordwolf/picorv32/wiki/Board-Support)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值