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