RISC-V CPU实践——从零开始(一)quartus跑picorv32

经过一番查资料,最终决定用picorv32,一个开源软核,

还要用到工具链(riscv-gnu-toolchain-master)才能编译c语言程序,感觉必须得运行在linux系统中,windows环境的资料太少了。

开发环境想选quartus,感觉资料太少,一步一步来吧。

2025.6.13

尝试在Windows环境下使用Quartus Prime运行PicoRV32软核CPU

1.安装Quartus Prime

2.PicoRV32是RISC-V架构的CPU,需安装RISC-V GCC工具链(如riscv-none-embed-gcc)。(工具链有什么用,干什么的??暂时不管,暂时不安装,继续)

3.获取PicoRV32源码,从GitHub克隆仓库:git clone https://github.com/cliffordwolf/picorv32.git

得到一个压缩包

4. 生成PicoRV32的Verilog文件

PicoRV32的Verilog代码已包含在仓库中(picorv32.v),但可能需要根据需求调整配置(如缓存、乘法器等)。

5. 创建Quartus工程

添加picorv32.v到工程中,顶层文件top.v中的代码如下:

// =============================================
// 文件:top.v
// 描述:基于PicoRV32的顶层模块,支持BRAM程序加载
// 特点:
//   1. 使用HEX文件初始化BRAM(支持Quartus综合)
//   2. 分离式读写逻辑(组合逻辑读+时序逻辑写)
//   3. GPIO外设接口(地址:0x1000_0000)
//   4. 添加仿真专用初始化块(不影响综合)
// =============================================

module top (
    input wire clk,          // 主时钟输入(50MHz)
    input wire resetn,       // 低电平复位信号(0复位)
    output reg [31:0] gpio_out // 32位GPIO输出
);

    // ======================
    // CPU接口信号定义
    // ======================
    wire mem_valid;         // 存储器访问使能
    wire [31:0] mem_addr;   // 存储器地址
    wire [31:0] mem_wdata;  // 写入数据
    wire [3:0] mem_wstrb;   // 字节写使能(低字节到高字节)
    reg [31:0] mem_rdata;   // 读取数据

    // ======================
    // PicoRV32处理器实例化
    // ======================
    picorv32 #(
        .ENABLE_MUL(1),     // 启用乘法器
        .ENABLE_DIV(1)      // 启用除法器
    ) cpu (
        .clk(clk),
        .resetn(resetn),
        .mem_valid(mem_valid),
        .mem_addr(mem_addr),
        .mem_wdata(mem_wdata),
        .mem_wstrb(mem_wstrb),
        .mem_rdata(mem_rdata)
    );

    // ======================
    // BRAM存储器配置
    // ======================
    // Quartus专用初始化语法(综合时生效)
    // 将ramdata.hex放在项目根目录
    // 格式要求:每行1个32位十六进制值(如"93000000")
    reg [31:0] bram[0:1023] /* synthesis ram_init_file = "ramdata.hex" */;

    // ======================
    // 仿真专用初始化块(仅仿真时生效)
    // ======================
    // 使用ifdef确保不影响综合
    `ifdef SIMULATION
    initial begin
        $display("[SIM] 正在加载ramdata.hex文件...");
        $readmemh("ramdata.hex", bram);
        
        // 可选:打印前4个地址内容用于验证
        $display("[SIM] BRAM初始化数据:");
        for (integer i = 0; i < 4; i = i+1) begin
            $display("  bram[%0d] = 0x%h", i, bram[i]);
        end
    end
    `endif

    // ======================
    // BRAM写逻辑(时序逻辑)
    // ======================
    always @(posedge clk) begin
        if (mem_valid && (|mem_wstrb)) begin
            // 按字节使能信号分段写入
            if (mem_wstrb[0]) bram[mem_addr[11:2]][7:0]   <= mem_wdata[7:0];   // 字节0
            if (mem_wstrb[1]) bram[mem_addr[11:2]][15:8]  <= mem_wdata[15:8];  // 字节1
            if (mem_wstrb[2]) bram[mem_addr[11:2]][23:16] <= mem_wdata[23:16]; // 字节2
            if (mem_wstrb[3]) bram[mem_addr[11:2]][31:24] <= mem_wdata[31:24]; // 字节3
            
            // 仿真时打印写入信息(可选)
            `ifdef SIMULATION
            $display("[SIM] BRAM写入:addr=0x%h data=0x%h strb=4'b%b", 
                     mem_addr, mem_wdata, mem_wstrb);
            `endif
        end
    end

    // ======================
    // GPIO控制逻辑(地址:0x1000_0000)
    // ======================
    localparam GPIO_ADDR = 32'h1000_0000;  // GPIO映射地址
    
    always @(posedge clk or negedge resetn) begin
        if (!resetn) begin
            gpio_out <= 32'h0;  // 复位时清零
        end
        else if (mem_valid && (|mem_wstrb) && (mem_addr == GPIO_ADDR)) begin
            gpio_out <= mem_wdata;  // 写入GPIO寄存器
            
            // 仿真时打印GPIO写入(可选)
            `ifdef SIMULATION
            $display("[SIM] GPIO写入:0x%h", mem_wdata);
            `endif
        end
    end

    // ======================

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值