- rtl/:12 个可综合的处理器源文件(顶层 cpu21_riscv_redirect_int_bpb.v,其余为各功能单元)。 - board/:板级顶层 cpu21_board_top.v、引脚约束 cpu21_board_top.xdc、片内 ROM 初始化 cpu21_board_rom.vh 与短延时版本 cpu21_board_rom_fast.vh。 - testbench/:保留三个测试平台;ROM 镜像统一放到 testbench/rom/,测试程序源码与期望值 仍在 testbench/programs/(其中的 .hex 是 RARS 原始输出,与 rom/ 里改过显示方式的版本 内容不同,两者都保留)。 - 同步更新:两个测试平台的 ROM 探测路径改为 testbench/rom/(并在头注释里补充说明: PowerShell 会把 -generic_top/--testplusarg 参数里的 "=" 拆开、Verilog 字符串中的 路径要用正斜杠);tools/hex2vh.py 的用法示例指向 board/cpu21_board_top.v; 说明文档新增“目录结构”一节并同步所有路径引用;.gitignore 补充 .Xil/。 - 清理:删除 *.hex.lst 中间文件与空的 .Xil/ 目录。 - 验证:isa_test 24/24、lui_test 4/4、mmio_test 5/5 三项回归通过;两个基线(5560 / 6003 周期)与整理前一致;板级仿真(默认 ROM 首次写入 LED=0001、快速 ROM 跑马灯循环)正常; Vivado 工程源文件路径同步到 rtl/ 与 board/ 后综合通过(LUT 5276、23 个引脚,与整理前 完全一致),因此已有 bit 文件仍然有效。
63 lines
2.5 KiB
Verilog
63 lines
2.5 KiB
Verilog
`timescale 1ns / 1ps
|
|
`default_nettype none
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// MMIO:把外设寄存器映射到数据存储器地址空间。
|
|
//
|
|
// 目前实现 LED 数据寄存器(LED_ADDR 默认 0x0000_1000,位于 4 KB 数据 RAM 之外):
|
|
// * 写:sw / sb 命中该地址(按字对齐,即同一 32 位寄存器内的任意字节偏移
|
|
// 都算命中)时更新 LED 寄存器,led_valid_o 拉高一拍;sb 依据 wstrb_i 只
|
|
// 修改对应的字节通道(与 RAM 的字节写语义一致)。
|
|
// * 读:lw 命中该地址时 rdata_hit_o 拉高,顶层据此选择本模块的 rdata_o
|
|
// 而不是外部 data_rdata_i,从而支持把 LED 值读回。
|
|
//
|
|
// 以后要增加外设(拨码开关、UART 等)时只需在这里扩展地址译码,
|
|
// 处理器核心与流水线时序不需要改动。
|
|
// -----------------------------------------------------------------------------
|
|
module cpu21_mmio #(
|
|
parameter [31:0] LED_ADDR = 32'h0000_1000
|
|
) (
|
|
input wire clk,
|
|
input wire reset,
|
|
// MEM 级的访存请求(来自 EX/MEM 流水寄存器)
|
|
input wire mem_valid_i,
|
|
input wire mem_write_i,
|
|
input wire mem_read_i,
|
|
input wire [31:0] addr_i,
|
|
input wire [31:0] wdata_i,
|
|
input wire [ 3:0] wstrb_i,
|
|
// MMIO 读回
|
|
output wire [31:0] rdata_o,
|
|
output wire rdata_hit_o,
|
|
// LED 外设
|
|
output reg [31:0] led_data_o,
|
|
output reg led_valid_o
|
|
);
|
|
// 地址译码按“字”对齐:同一 32 位寄存器内的任意字节偏移都算命中,
|
|
// 具体修改哪几个字节由 wstrb_i 决定(sw 全字、sb 单字节)。
|
|
wire led_wr = mem_valid_i && mem_write_i && (addr_i[31:2] == LED_ADDR[31:2]);
|
|
wire led_rd = mem_valid_i && mem_read_i && (addr_i[31:2] == LED_ADDR[31:2]);
|
|
|
|
assign rdata_hit_o = led_rd;
|
|
assign rdata_o = led_data_o;
|
|
|
|
always @(posedge clk or posedge reset) begin
|
|
if (reset) begin
|
|
led_data_o <= 32'b0;
|
|
led_valid_o <= 1'b0;
|
|
end else begin
|
|
// led_valid_o 只拉高一拍,作为“本周期有 LED 写入”的指示。
|
|
led_valid_o <= 1'b0;
|
|
if (led_wr) begin
|
|
if (wstrb_i[0]) led_data_o[7:0] <= wdata_i[7:0];
|
|
if (wstrb_i[1]) led_data_o[15:8] <= wdata_i[15:8];
|
|
if (wstrb_i[2]) led_data_o[23:16] <= wdata_i[23:16];
|
|
if (wstrb_i[3]) led_data_o[31:24] <= wdata_i[31:24];
|
|
led_valid_o <= 1'b1;
|
|
end
|
|
end
|
|
end
|
|
endmodule
|
|
|
|
`default_nettype wire
|