经过一番查资料,最终决定用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
// ======================

最低0.47元/天 解锁文章
6386

被折叠的 条评论
为什么被折叠?



