项目目标

在你设计的五级流水线 RISC-V 处理器上运行 RT-Thread 实时操作系统!

思考:为什么要运行操作系统?

  • 验证处理器的正确性
  • 测试特权级切换
  • 检验中断处理
  • 体验真实软件运行

项目要求

硬件要求

你的处理器需要支持:

  1. RV32I 基本指令集
    • 算术、逻辑、访存、分支指令
    • 至少通过 riscv-tests
  2. 特权级支持
    • M-mode(机器模式)
    • CSR 寄存器(mstatus, mtvec, mepc, mcause)
    • ecall/mret 指令
  3. 中断支持
    • 定时器中断
    • 外部中断(可选)
  4. 内存映射
    0x80000000: RAM 起始地址
    0x02000000: CLINT(定时器)
    

问题:你的处理器现在支持这些吗?如果不支持,需要添加什么?

步骤 1:添加 CSR 支持

1.1 CSR 寄存器文件

// CSR 寄存器
reg [31:0] mstatus;   // 机器状态
reg [31:0] mtvec;     // 中断向量基址
reg [31:0] mepc;      // 异常 PC
reg [31:0] mcause;    // 异常原因
reg [31:0] mie;       // 中断使能
reg [31:0] mip;       // 中断挂起

1.2 CSR 读写

// CSRRW: rd = csr; csr = rs1
case (csr_addr)
    12'h300: csr_rdata = mstatus;
    12'h305: csr_rdata = mtvec;
    12'h341: csr_rdata = mepc;
    12'h342: csr_rdata = mcause;
endcase

思考:CSR 指令在哪个阶段执行?会产生数据冒险吗?

步骤 2:实现异常处理

2.1 ecall 指令

当执行 ecall 时:

  1. mepc <= pc(保存返回地址)
  2. mcause <= 11(环境调用)
  3. pc <= mtvec(跳转到中断处理)

2.2 mret 指令

当执行 mret 时:

  1. pc <= mepc(恢复 PC)
  2. 恢复 mstatus 中的中断使能位

问题:这些操作在流水线的哪个阶段完成?需要冲刷流水线吗?

步骤 3:添加定时器中断

3.1 CLINT 模块

// 定时器比较寄存器
reg [63:0] mtimecmp;
reg [63:0] mtime;

always @(posedge clk) begin
    mtime <= mtime + 1;
end

// 产生中断信号
wire timer_irq = (mtime >= mtimecmp);

3.2 中断响应

timer_irq 有效且中断使能时:

  1. mepc <= pc
  2. mcause <= 0x80000007(定时器中断)
  3. pc <= mtvec
  4. 关闭中断使能

思考:中断可能在任何时刻发生,如何保证流水线状态的一致性?

步骤 4:移植 RT-Thread

4.1 获取源码

git clone https://github.com/RT-Thread/rt-thread.git
cd rt-thread/bsp/qemu-virt32-riscv

4.2 修改链接脚本

MEMORY
{
    RAM : ORIGIN = 0x80000000, LENGTH = 8M
}

SECTIONS
{
    .text : { *(.text) } > RAM
    .data : { *(.data) } > RAM
    .bss  : { *(.bss)  } > RAM
}

4.3 配置 BSP

修改 rtconfig.py

  • 设置工具链路径
  • 配置内存地址
  • 设置时钟频率

4.4 编译

scons

生成 rtthread.binrtthread.elf

步骤 5:仿真测试

5.1 加载程序

initial begin
    $readmemh("rtthread.hex", mem);
end

5.2 观察输出

RT-Thread 启动后会输出:

 \ | /
- RT -     Thread Operating System
 / | \     4.1.0 build Dec 25 2023
 2006 - 2023 Copyright by RT-Thread team
msh >

问题:如果没有输出,可能是什么原因?

步骤 6:上板运行

6.1 生成比特流

在 Vivado 中综合、实现、生成比特流。

6.2 下载到 FPGA

使用 JTAG 下载到开发板。

6.3 串口调试

连接串口,波特率 115200,观察 RT-Thread 启动信息。

调试技巧

常见问题

  1. 程序跑飞
    • 检查 PC 跳转逻辑
    • 验证分支指令
    • 查看异常处理
  2. 中断不响应
    • 检查 mstatus.MIE
    • 验证 mie 寄存器
    • 确认中断信号
  3. 访存错误
    • 检查地址对齐
    • 验证内存映射
    • 查看总线信号

思考:如何系统地定位问题?

项目总结

完成这个项目,你将:

  • 掌握完整的处理器设计流程
  • 理解软硬件协同工作
  • 具备调试复杂系统的能力

恭喜你完成 C 级课程!

下一步

继续挑战 B 级和 A 级课程,探索更高级的处理器设计!

更新时间: