18new

package components

  

import chisel3._

import chisel3.util._

import components.Constants._ // 确保导入常量

  

/**

 * IF/ID流水线寄存器

 */

class IFIDBundle extends Bundle {

  val inst = UInt(32.W)

  val pc   = UInt(32.W)

}

  

/**

 * ID/EX流水线寄存器

 */

class IDEXBundle extends Bundle {

  val pc      = UInt(32.W)

  val alu_a   = UInt(32.W)

  val alu_b   = UInt(32.W)

  val rd_addr = UInt(5.W)

  val rs1_addr = UInt(5.W)

  val rs2_addr = UInt(5.W)

  val ctrl    = new ControlSigs

}

  

/**

 * EX/MEM流水线寄存器

 */

class EXMEMBundle extends Bundle {

  val pc           = UInt(32.W)

  val alu_out      = UInt(32.W)

  val alu_b        = UInt(32.W) // 用于访存写数据 (已前递)

  val rd_addr      = UInt(5.W)

  val alu_zero     = Bool()

  val ctrl         = new ControlSigs

}

  

/**

 * MEM/WB流水线寄存器

 */

class MEMWBBundle extends Bundle {

  val pc           = UInt(32.W)

  val wb_data      = UInt(32.W)

  val rd_addr      = UInt(5.W)

  val reg_write_en = Bool()

}

  

/**

 * 主CPU模块 (最终重构版)

 */

class MyCPU extends Module {

  val io = IO(new Bundle {

    val rst = Input(Bool())

    val imem_addr = Output(UInt(32.W))

    val imem_inst = Input(UInt(32.W))

    val debug_reg_out = Output(Vec(32, UInt(32.W)))

    val debug_pc_out  = Output(UInt(32.W))

    val total_cycles = Output(UInt(32.W))

    val total_instructions = Output(UInt(32.W))

    val stall_cycles = Output(UInt(32.W))

    val dmem_addr = Output(UInt(32.W))

    val dmem_write_data = Output(UInt(32.W))

    val dmem_write_en = Output(Bool())

    val dmem_read_en = Output(Bool())

    val dmem_size = Output(UInt(2.W))

    val dmem_read_data = Input(UInt(32.W))

    val stall_from_bus = Input(Bool())

    val debug_next_pc = Output(UInt(32.W))

    val debug_pc_write_en = Output(Bool())

  })

  // 模块实例化

  val alu     = Module(new ALU(32))

  val regFile = withReset(io.rst) { Module(new RegFile) }

  val decoder = Module(new Decoder)

  val immGen  = Module(new ImmGen)

  val forwardingUnit = Module(new ForwardingUnit)

  val hazardDetection = Module(new HazardDetection)

  

  // 流水线寄存器

  val ifid_reg  = RegInit(0.U.asTypeOf(new IFIDBundle))

  val idex_reg  = RegInit(0.U.asTypeOf(new IDEXBundle))

  val exmem_reg = RegInit(0.U.asTypeOf(new EXMEMBundle))

  val memwb_reg = RegInit(0.U.asTypeOf(new MEMWBBundle))

  val idex_imm = RegInit(0.U(32.W))

  // 性能计数器

  val total_cycles = RegInit(0.U(32.W))

  val total_instructions = RegInit(0.U(32.W))

  val stall_cycles = RegInit(0.U(32.W))

  val last_counted_pc = RegInit(0.U(32.W))

  

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

  // ========== IF/ID/EX 信号 (按数据流顺序定义) ==========

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

  

  // --- IF阶段信号 ---

  val pc = RegInit("h_80000000".U(32.W))

  val pc_next = RegInit("h_80000000".U(32.W))

  val pc_base = "h_80000000".U(32.W)

  val pc_max = "h_807FFFFF".U(32.W)

  val ex_jump_taken_reg = RegInit(false.B)

  val ex_jump_target_reg = RegInit(0.U(32.W))

  

  // --- ID阶段信号 ---

  val id_inst  = ifid_reg.inst

  val id_pc    = ifid_reg.pc

  decoder.io.inst := id_inst

  val ctrl_sigs = decoder.io.sigs

  val rd_addr  = id_inst(4, 0)

  val rj_addr  = id_inst(9, 5)

  val rk_addr  = id_inst(14, 10)

  val actual_rs2_addr = Mux(ctrl_sigs.branch_type.orR, rd_addr, Mux(ctrl_sigs.mem_write_en, rd_addr, rk_addr))

  // --- EX阶段信号 ---

  val ex_ctrl = idex_reg.ctrl

  val alu_a_forwarded = MuxCase(idex_reg.alu_a, Seq((forwardingUnit.io.forward_a === 1.U) -> exmem_reg.alu_out, (forwardingUnit.io.forward_a === 2.U) -> memwb_reg.wb_data))

  val alu_b_forwarded = MuxCase(idex_reg.alu_b, Seq((forwardingUnit.io.forward_b === 1.U) -> exmem_reg.alu_out, (forwardingUnit.io.forward_b === 2.U) -> memwb_reg.wb_data))

  val alu_a_final = MuxCase(alu_a_forwarded, Seq(

    (ex_ctrl.alu_a_sel === A_ZERO) -> 0.U(32.W),

    (ex_ctrl.alu_a_sel === A_PC)   -> idex_reg.pc

  ))

  val alu_b_final = Mux(ex_ctrl.alu_b_sel === B_IMM, idex_imm, alu_b_forwarded)

  alu.io.op := ex_ctrl.alu_op

  alu.io.a  := alu_a_final

  alu.io.b  := alu_b_final

  val branch_taken = (ex_ctrl.branch_type === BR_JUMP) || (ex_ctrl.branch_type === BR_EQ && alu.io.zero) || (ex_ctrl.branch_type === BR_NE && !alu.io.zero)

  

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

  // ========== 冒险检测与流水线控制 ==========

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

  

  // --- 冒险检测单元连接 ---

  hazardDetection.io.ex_mem_read := idex_reg.ctrl.mem_read_en

  hazardDetection.io.ex_rd_addr := idex_reg.rd_addr

  hazardDetection.io.id_rs1_addr := rj_addr

  hazardDetection.io.id_rs2_addr := rk_addr // 简化处理, 见之前讨论

  hazardDetection.io.ex_jump_taken := branch_taken

  

  // --- 流水线控制信号 ---

  val stall_if = hazardDetection.io.stall_if || io.stall_from_bus

  val stall_id = hazardDetection.io.stall_id

  val flush_if = hazardDetection.io.flush_if

  val flush_id = hazardDetection.io.flush_id

  val flush_ex = hazardDetection.io.flush_ex || io.stall_from_bus

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

  // ========== 流水线寄存器更新 ==========

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

  // --- PC更新逻辑 ---

  when(io.rst) {

    pc := pc_base

    pc_next := pc_base + 4.U

    ex_jump_taken_reg := false.B

    ex_jump_target_reg := 0.U

  } .elsewhen(!stall_if) {

    pc := pc_next

    val next_pc_candidate = Mux(ex_jump_taken_reg, ex_jump_target_reg, pc + 4.U)

    pc_next := Mux(next_pc_candidate < pc_base, pc_base, Mux(next_pc_candidate > pc_max, pc_max, next_pc_candidate))

    ex_jump_taken_reg := false.B

  }

  // --- IF/ID寄存器更新 ---

  io.imem_addr := pc_next

  val inst_reg = RegNext(io.imem_inst, 0.U)

  when(flush_if) {

    ifid_reg.inst := 0.U

    ifid_reg.pc   := 0.U

  } .elsewhen(stall_if) { /* 保持不变 */ }

  .otherwise {

    ifid_reg.inst := inst_reg

    ifid_reg.pc   := RegNext(pc, "h_80000000".U(32.W))

  }

  

  // --- ID/EX寄存器更新 ---

  immGen.io.inst := id_inst

  immGen.io.imm_type := ctrl_sigs.imm_type

  regFile.io.rs1_addr := rj_addr

  regFile.io.rs2_addr := actual_rs2_addr

  when(flush_ex) {

    idex_reg := 0.U.asTypeOf(new IDEXBundle)

    idex_imm := 0.U

  } .elsewhen(stall_id) { /* 保持不变 */ }

  .otherwise {

    idex_reg.pc      := id_pc

    idex_reg.alu_a   := regFile.io.rs1_data

    idex_reg.alu_b   := regFile.io.rs2_data

    idex_reg.rd_addr := rd_addr

    idex_reg.rs1_addr := rj_addr

    idex_reg.rs2_addr := actual_rs2_addr

    idex_reg.ctrl    := ctrl_sigs

    idex_imm         := immGen.io.imm_out

  }

  

  // --- EX/MEM寄存器更新 ---

  val jump_target = alu.io.out

  val target_clamped = Mux(jump_target < pc_base, pc_base, Mux(jump_target > pc_max, pc_max, jump_target))

  when(branch_taken) {

    ex_jump_taken_reg := true.B

    ex_jump_target_reg := target_clamped

  }

  exmem_reg.pc           := idex_reg.pc

  exmem_reg.alu_out      := alu.io.out

  exmem_reg.alu_b        := alu_b_forwarded // <<<<<<<< 已修正潜在Bug

  exmem_reg.rd_addr      := idex_reg.rd_addr

  exmem_reg.alu_zero     := alu.io.zero

  exmem_reg.ctrl         := ex_ctrl

  

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

  // ========== MEM/WB 阶段 ==========

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

  

  // --- MEM阶段 ---

  val mem_ctrl = exmem_reg.ctrl

  io.dmem_addr := exmem_reg.alu_out

  io.dmem_write_data := exmem_reg.alu_b

  io.dmem_write_en := mem_ctrl.mem_write_en

  io.dmem_read_en := mem_ctrl.mem_read_en

  io.dmem_size := mem_ctrl.mem_size

  val wb_data = MuxCase(exmem_reg.alu_out, Seq(

    (exmem_reg.ctrl.wb_sel === WB_MEM) -> io.dmem_read_data,

    (exmem_reg.ctrl.wb_sel === WB_PC4) -> (exmem_reg.pc + 4.U)

  ))

  // --- MEM/WB寄存器更新 ---

  memwb_reg.pc           := exmem_reg.pc

  memwb_reg.wb_data      := wb_data

  memwb_reg.rd_addr      := exmem_reg.rd_addr

  memwb_reg.reg_write_en := exmem_reg.ctrl.reg_write_en

  

  // --- WB阶段 ---

  forwardingUnit.io.ex_rs1_addr := idex_reg.rs1_addr

  forwardingUnit.io.ex_rs2_addr := idex_reg.rs2_addr

  forwardingUnit.io.mem_rd_addr := exmem_reg.rd_addr

  forwardingUnit.io.mem_reg_write := exmem_reg.ctrl.reg_write_en

  forwardingUnit.io.wb_rd_addr := memwb_reg.rd_addr

  forwardingUnit.io.wb_reg_write := memwb_reg.reg_write_en

  

  val allowWriteBack = RegInit(false.B)

  when (io.rst) { allowWriteBack := false.B } .otherwise { allowWriteBack := true.B }

  regFile.io.rd_addr := memwb_reg.rd_addr

  regFile.io.rd_data := memwb_reg.wb_data

  regFile.io.rd_en   := (memwb_reg.reg_write_en && allowWriteBack)

  

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

  // ========== 性能计数器与调试输出 ==========

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

  when(!io.rst) {

    total_cycles := total_cycles + 1.U

    when((stall_if || stall_id) && (stall_cycles < total_cycles)) { stall_cycles := stall_cycles + 1.U }

    val wb_pc_valid = (memwb_reg.pc =/= 0.U) && (memwb_reg.pc >= pc_base) && (memwb_reg.pc <= pc_max)

    val wb_pc_changed = (memwb_reg.pc =/= last_counted_pc) && wb_pc_valid && allowWriteBack

    when(wb_pc_changed) {

      last_counted_pc := memwb_reg.pc

      total_instructions := total_instructions + 1.U

    }

  } .otherwise {

    last_counted_pc := 0.U

  }

  io.debug_reg_out := regFile.io.debug_regs_out

  io.debug_pc_out  := pc

  io.debug_next_pc := pc_next

  io.debug_pc_write_en := !stall_if

  io.total_cycles := total_cycles

  io.total_instructions := total_instructions

  io.stall_cycles := stall_cycles

}
`default_nettype none

  

module thinpad_top(

    input wire clk_50M,           //50MHz 时钟输入

    input wire clk_11M0592,       //11.0592MHz 时钟输入(备用,可不用)

    input wire clock_btn,         //BTN5手动时钟按钮开关,带消抖电路,按下时为1

    input wire reset_btn,         //BTN6手动复位按钮开关,带消抖电路,按下时为1

    input  wire[3:0]  touch_btn,  //BTN1~BTN4,按钮开关,按下时为1

    input  wire[31:0] dip_sw,     //32位拨码开关,拨到"ON"时为1

    output wire[15:0] leds,       //16位LED,输出时1点亮

    output wire[7:0]  dpy0,       //数码管低位信号,包括小数点,输出1点亮

    output wire[7:0]  dpy1,       //数码管高位信号,包括小数点,输出1点亮

    //BaseRAM信号

    inout wire[31:0] base_ram_data,  //BaseRAM数据,低8位与CPLD串口控制器共享

    output wire[19:0] base_ram_addr, //BaseRAM地址

    output wire[3:0] base_ram_be_n,  //BaseRAM字节使能,低有效。如果不使用字节使能,请保持为0

    output wire base_ram_ce_n,       //BaseRAM片选,低有效

    output wire base_ram_oe_n,       //BaseRAM读使能,低有效

    output wire base_ram_we_n,       //BaseRAM写使能,低有效

    //ExtRAM信号

    inout wire[31:0] ext_ram_data,  //ExtRAM数据

    output wire[19:0] ext_ram_addr, //ExtRAM地址

    output wire[3:0] ext_ram_be_n,  //ExtRAM字节使能,低有效。如果不使用字节使能,请保持为0

    output wire ext_ram_ce_n,       //ExtRAM片选,低有效

    output wire ext_ram_oe_n,       //ExtRAM读使能,低有效

    output wire ext_ram_we_n,       //ExtRAM写使能,低有效

    //直连串口信号

    output wire txd,  //直连串口发送端

    input  wire rxd,  //直连串口接收端

    //Flash存储器信号,参考 JS28F640 芯片手册

    output wire [22:0]flash_a,      //Flash地址,a0仅在8bit模式有效,16bit模式无意义

    inout  wire [15:0]flash_d,      //Flash数据

    output wire flash_rp_n,         //Flash复位信号,低有效

    output wire flash_vpen,         //Flash写保护信号,低电平时不能擦除、烧写

    output wire flash_ce_n,         //Flash片选信号,低有效

    output wire flash_oe_n,         //Flash读使能信号,低有效

    output wire flash_we_n,         //Flash写使能信号,低有效

    output wire flash_byte_n,       //Flash 8bit模式选择,低有效。在使用flash的16位模式时请设为1

    //图像输出信号

    output wire[2:0] video_red,    //红色像素,3位

    output wire[2:0] video_green,  //绿色像素,3位

    output wire[1:0] video_blue,   //蓝色像素,2位

    output wire video_hsync,       //行同步(水平同步)信号

    output wire video_vsync,       //场同步(垂直同步)信号

    output wire video_clk,         //像素时钟输出

    output wire video_de           //行数据有效信号,用于区分消隐区

);

  

// =========== CPU接口信号定义 ===========

wire cpu_clock;

wire cpu_reset;

wire cpu_io_rst;

wire [31:0] cpu_io_imem_addr;

wire [31:0] cpu_io_imem_inst;

wire [31:0] cpu_io_dmem_addr;

wire [31:0] cpu_io_dmem_write_data;

wire cpu_io_dmem_write_en;

wire cpu_io_dmem_read_en;

wire [1:0] cpu_io_dmem_size;

wire [31:0] cpu_io_dmem_read_data;

  

// =========== PLL分频 ===========

wire locked, clk_10M, clk_20M;

pll_example clock_gen (

    .clk_in1(clk_50M),  // 外部时钟输入

    .clk_out1(clk_10M), // 时钟输出1

    .clk_out2(clk_20M), // 时钟输出2

    .reset(reset_btn), // PLL复位输入

    .locked(locked)    // PLL锁定指示输出

);

  

reg reset_of_clk10M;

// 异步复位,同步释放

always @(posedge clk_10M or negedge locked) begin

    if (~locked) reset_of_clk10M <= 1'b1;

    else         reset_of_clk10M <= 1'b0;

end

  

// =========== 时钟和复位适配 ===========

assign cpu_clock = clk_10M;

assign cpu_reset = reset_of_clk10M;  // Chisel reset是低电平有效

assign cpu_io_rst = reset_of_clk10M;

  

// =========== CPU实例化 ===========

MyCPU u_cpu (

    .clock(cpu_clock),

    .reset(cpu_reset),  

    .io_rst(cpu_io_rst),

    .io_imem_addr(cpu_io_imem_addr),

    .io_imem_inst(cpu_io_imem_inst),

    .io_dmem_addr(cpu_io_dmem_addr),

    .io_dmem_write_data(cpu_io_dmem_write_data),

    .io_dmem_write_en(cpu_io_dmem_write_en),

    .io_dmem_read_en(cpu_io_dmem_read_en),

    .io_dmem_size(cpu_io_dmem_size),

    .io_dmem_read_data(cpu_io_dmem_read_data),

    .io_debug_reg_out_0(),

    .io_debug_reg_out_1(),

    .io_debug_reg_out_2(),

    .io_debug_reg_out_3(),

    .io_debug_reg_out_4(),

    .io_debug_reg_out_5(),

    .io_debug_reg_out_6(),

    .io_debug_reg_out_7(),

    .io_debug_reg_out_8(),

    .io_debug_reg_out_9(),

    .io_debug_reg_out_10(),

    .io_debug_reg_out_11(),

    .io_debug_reg_out_12(),

    .io_debug_reg_out_13(),

    .io_debug_reg_out_14(),

    .io_debug_reg_out_15(),

    .io_debug_reg_out_16(),

    .io_debug_reg_out_17(),

    .io_debug_reg_out_18(),

    .io_debug_reg_out_19(),

    .io_debug_reg_out_20(),

    .io_debug_reg_out_21(),

    .io_debug_reg_out_22(),

    .io_debug_reg_out_23(),

    .io_debug_reg_out_24(),

    .io_debug_reg_out_25(),

    .io_debug_reg_out_26(),

    .io_debug_reg_out_27(),

    .io_debug_reg_out_28(),

    .io_debug_reg_out_29(),

    .io_debug_reg_out_30(),

    .io_debug_reg_out_31(),

    .io_debug_pc_out(),

    .io_debug_next_pc(),

    .io_debug_pc_write_en(),

    .io_total_cycles(),

    .io_total_instructions(),

    .io_stall_cycles()

);

  

// =========== 指令端口(直接挂在 BaseRAM 上) ===========

localparam MEM_BASE = 32'h8000_0000;

localparam MEM_END  = 32'h807F_FFFF;

  

wire imem_access = (cpu_io_imem_addr >= MEM_BASE) && (cpu_io_imem_addr <= MEM_END);

wire [11:0] imem_low = cpu_io_imem_addr[11:0];

wire imem_use_base = imem_access && (imem_low < 12'h400);

wire [19:0] imem_base_addr = cpu_io_imem_addr[21:2];

  

reg [31:0] imem_data_reg;

always @(posedge clk_10M or posedge reset_of_clk10M) begin

    if (reset_of_clk10M)

        imem_data_reg <= 32'h0;

    else if (imem_use_base)

        imem_data_reg <= base_ram_data;

end

assign cpu_io_imem_inst = imem_data_reg;

  

// BaseRAM 控制信号(指令读)

wire base_ce_n_imem = ~imem_use_base;

wire base_oe_n_imem = ~imem_use_base;

wire base_we_n_imem = 1'b1;

wire [19:0] base_addr_imem = imem_base_addr;

  

// =========== 数据端口通过 1x2 Bridge ===========

wire [19:0] bridge_base_addr;

wire [19:0] bridge_ext_addr;

wire [3:0]  bridge_base_be_n;

wire [3:0]  bridge_ext_be_n;

wire bridge_base_ce_n;

wire bridge_base_oe_n;

wire bridge_base_we_n;

wire bridge_ext_ce_n;

wire bridge_ext_oe_n;

wire bridge_ext_we_n;

wire bridge_base_drive_en;

wire [31:0] bridge_base_drive_data;

wire bridge_ext_drive_en;

wire [31:0] bridge_ext_drive_data;

wire bridge_base_active;

  

MemBridge1x2 u_mem_bridge (

    .clk          (clk_10M),

    .rst          (reset_of_clk10M),

    .addr         (cpu_io_dmem_addr),

    .wdata        (cpu_io_dmem_write_data),

    .write_en     (cpu_io_dmem_write_en),

    .read_en      (cpu_io_dmem_read_en),

    .size         (cpu_io_dmem_size),

    .base_data_in (base_ram_data),

    .ext_data_in  (ext_ram_data),

    .rdata        (cpu_io_dmem_read_data),

    .base_addr    (bridge_base_addr),

    .base_be_n    (bridge_base_be_n),

    .base_ce_n    (bridge_base_ce_n),

    .base_oe_n    (bridge_base_oe_n),

    .base_we_n    (bridge_base_we_n),

    .base_drive_en   (bridge_base_drive_en),

    .base_drive_data (bridge_base_drive_data),

    .base_active     (bridge_base_active),

    .ext_addr     (bridge_ext_addr),

    .ext_be_n     (bridge_ext_be_n),

    .ext_ce_n     (bridge_ext_ce_n),

    .ext_oe_n     (bridge_ext_oe_n),

    .ext_we_n     (bridge_ext_we_n),

    .ext_drive_en   (bridge_ext_drive_en),

    .ext_drive_data (bridge_ext_drive_data)

);

  

// BaseRAM 总线仲裁(指令优先)

assign base_ram_addr = bridge_base_active ? bridge_base_addr : base_addr_imem;

assign base_ram_ce_n = base_ce_n_imem & bridge_base_ce_n;

assign base_ram_oe_n = base_oe_n_imem & bridge_base_oe_n;

assign base_ram_we_n = bridge_base_we_n;

assign base_ram_be_n = bridge_base_active ? bridge_base_be_n : 4'b0000;

  

assign base_ram_data = bridge_base_drive_en ? bridge_base_drive_data : 32'hZZZZ_ZZZZ;

  

// ExtRAM 直接来自 Bridge

assign ext_ram_addr   = bridge_ext_addr;

assign ext_ram_be_n   = bridge_ext_be_n;

assign ext_ram_ce_n   = bridge_ext_ce_n;

assign ext_ram_oe_n   = bridge_ext_oe_n;

assign ext_ram_we_n   = bridge_ext_we_n;

assign ext_ram_data   = bridge_ext_drive_en ? bridge_ext_drive_data : 32'hZZZZ_ZZZZ;

  

// =========== 简易IO占空 ===========

assign leds = 16'h0;

assign dpy0 = 8'h0;

assign dpy1 = 8'h0;

assign txd  = 1'b1;

  

assign flash_a = 23'h0;

assign flash_rp_n = 1'b1;

assign flash_vpen = 1'b1;

assign flash_ce_n = 1'b1;

assign flash_oe_n = 1'b1;

assign flash_we_n = 1'b1;

assign flash_byte_n = 1'b1;

assign flash_d = 16'hZZZZ;

  

assign video_red   = 3'h0;

assign video_green = 3'h0;

assign video_blue  = 2'h0;

assign video_hsync = 1'b0;

assign video_vsync = 1'b0;

assign video_clk   = 1'b0;

assign video_de    = 1'b0;

  

endmodule

  

// ==================== 1x2 Memory Bridge ====================

module MemBridge1x2(

    input  wire        clk,

    input  wire        rst,

    input  wire [31:0] addr,

    input  wire [31:0] wdata,

    input  wire        write_en,

    input  wire        read_en,

    input  wire [1:0]  size,

    input  wire [31:0] base_data_in,

    input  wire [31:0] ext_data_in,

    output reg  [31:0] rdata,

    output wire [19:0] base_addr,

    output reg  [3:0]  base_be_n,

    output wire        base_ce_n,

    output wire        base_oe_n,

    output wire        base_we_n,

    output wire        base_drive_en,

    output wire [31:0] base_drive_data,

    output wire        base_active,

    output wire [19:0] ext_addr,

    output reg  [3:0]  ext_be_n,

    output wire        ext_ce_n,

    output wire        ext_oe_n,

    output wire        ext_we_n,

    output wire        ext_drive_en,

    output wire [31:0] ext_drive_data

);

    localparam MEM_BASE = 32'h8000_0000;

    localparam MEM_END  = 32'h807F_FFFF;

  

    wire addr_valid = (addr >= MEM_BASE) && (addr <= MEM_END);

    wire [11:0] low = addr[11:0];

    wire select_base = addr_valid && (low < 12'h400);

    wire select_ext  = addr_valid && (low >= 12'h400);

  

    reg [31:0] write_aligned;

    reg [3:0]  write_mask_n;

    always @(*) begin

        case (size)

            2'd0: begin

                write_aligned = wdata << (8 * addr[1:0]);

                write_mask_n  = ~(4'b0001 << addr[1:0]);

            end

            2'd1: begin

                write_aligned = addr[1] ?

                    {wdata[15:0], 16'h0} :

                    {16'h0, wdata[15:0]};

                write_mask_n  = addr[1] ? 4'b0011 : 4'b1100;

            end

            default: begin

                write_aligned = wdata;

                write_mask_n  = 4'b0000;

            end

        endcase

    end

  

    function automatic [31:0] format_read;

        input [31:0] data_in;

        input [1:0]  size_in;

        input [1:0]  addr_low;

        begin

            case (size_in)

                2'd0: begin

                    case (addr_low)

                        2'd0: format_read = {24'h0, data_in[7:0]};

                        2'd1: format_read = {24'h0, data_in[15:8]};

                        2'd2: format_read = {24'h0, data_in[23:16]};

                        default: format_read = {24'h0, data_in[31:24]};

                    endcase

                end

                2'd1: begin

                    format_read = addr_low[1] ?

                        {16'h0, data_in[31:16]} :

                        {16'h0, data_in[15:0]};

                end

                default: format_read = data_in;

            endcase

        end

    endfunction

  

    wire [31:0] base_read_data = format_read(base_data_in, size, addr[1:0]);

    wire [31:0] ext_read_data  = format_read(ext_data_in,  size, addr[1:0]);

  

    always @(posedge clk or posedge rst) begin

        if (rst)

            rdata <= 32'h0;

        else if (select_base && read_en)

            rdata <= base_read_data;

        else if (select_ext && read_en)

            rdata <= ext_read_data;

        else if (!read_en)

            rdata <= 32'h0;

    end

  

    assign base_addr = addr[21:2];

    assign ext_addr  = addr[21:2];

  

    assign base_ce_n = ~(select_base && (read_en || write_en));

    assign base_oe_n = ~(select_base && read_en);

    assign base_we_n = ~(select_base && write_en);

    assign base_drive_en   = select_base && write_en;

    assign base_drive_data = write_aligned;

    assign base_active     = select_base && (read_en || write_en);

  

    assign ext_ce_n = ~(select_ext && (read_en || write_en));

    assign ext_oe_n = ~(select_ext && read_en);

    assign ext_we_n = ~(select_ext && write_en);

    assign ext_drive_en   = select_ext && write_en;

    assign ext_drive_data = write_aligned;

  

    always @(*) begin

        if (select_base) begin

            base_be_n = write_en ? write_mask_n : 4'b0000;

        end else begin

            base_be_n = 4'b1111;

        end

  

        if (select_ext) begin

            ext_be_n = write_en ? write_mask_n : 4'b0000;

        end else begin

            ext_be_n = 4'b1111;

        end

    end

  

endmodule
posted @ 2025-11-18 15:14  when-epoch  阅读(14)  评论(0)    收藏  举报