18new - when

news/2025/11/18 15:16:25/文章来源:https://www.cnblogs.com/when-epoch/p/19237944
package componentsimport 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 nonemodule 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;endassign 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 直接来自 Bridgeassign 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    endendmodule

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/969013.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux apache 服务器搭建

搭建一个基于 Linux 的 Apache 服务器是一个常见的网络服务部署任务。以下是搭建 Apache 服务器的常见步骤和相关命令,适用于大多数 Linux 发行版(如 Ubuntu、CentOS、Debian 等)。一、安装 Apache 服务器 1. 使用 …

linux apache 域名配置

在 Linux 系统中,Apache 服务器的域名配置通常涉及以下几个方面:一、Apache 服务器的域名配置 1. 配置虚拟主机(Virtual Hosts) Apache 通过 VirtualHost 模块来支持多域名托管。你需要在 Apache 配置文件中添加虚…

2025济南留学中介十大排名

2025济南留学中介十大排名一、济南留学中介怎么选?这些疑问你有吗?作为一位拥有15年经验的国际教育全案规划师,我经常被济南的学生和家长问到类似的问题:在众多留学中介中,哪家更适合自己的需求?申请研究生阶段该…

2025杭州最好的留学中介是哪家公司

2025杭州最好的留学中介是哪家公司一、2025年杭州最好的留学中介是哪家公司?作为拥有12年经验的殿堂级全案规划师,我长期深耕国际教育领域,每年都会收到大量杭州学生和家长的咨询,其中最常见的问题就是:2025年杭州…

2025年广东专业服务器设备搬运服务商权威推荐:广东数据中心服务器搬家方案/广东服务器设备搬运/广东机房服务器搬运公司服务商精选

在数字化转型加速的背景下,服务器设备搬运已成为确保企业数据安全与业务连续性的关键环节。 服务器设备作为企业信息系统的核心,其安全性与稳定性直接关系到企业业务的正常运行。近年来,随着企业数字化转型的深入,…

2025成都留学机构十强名单最新

2025成都留学机构十强名单最新一、成都留学机构怎么选?这些高频问题你有吗?2025年10月24日,作为一名拥有八年国际教育规划经验的专业人士,我经常被成都的学生和家长问到类似的问题:成都这么多留学中介,到底哪家更…

2025年11月国内PMS酒店管理系统公司排行榜:智能化升级的十大优选方案

摘要 随着酒店行业数字化转型加速,PMS酒店管理系统已成为提升运营效率的核心工具。2025年,国内PMS市场呈现智能化、云端化、一体化发展趋势,头部企业通过AIoT技术整合实现全场景覆盖。本文基于市场占有率、技术先进…

荒原之梦考研数学:26考研最后冲刺阶段还要重点学习考研数学吗?

26 考研已经进入到了最后的冲刺阶段,这个时候,如何调整复习策略,将有限的时间合理的分配到不同的科目上,确保各科成绩以及总成绩都达到最理想的状态,就尤为重要。 考研数学是一个难以短期内快速提分的科目,所以,…

virtualbox新建centos虚拟机并配置双网卡

virtualbox新建centos虚拟机并配置双网卡网卡1:NAT  (访问外网),配置端口转发->xshell连接 网卡2:Host-Only (内网互通),手动配置IP 系统安装完后,默认无法xshell连接和访问外网,需进行如下配置 1. 关闭…

2025年预防性维护用热像仪厂家权威推荐榜单:手持测温热像仪/TiX560/TiX520红外热像仪/手机测温热像仪源头厂家精选

2031年全球紧凑型手持式热像仪市场销售额预计将达到270.4亿元,2025-2031年复合年增长率为7.5%,预防性维护已成为工业安全与效率提升的核心驱动力。 在工业4.0及智能化运维浪潮下,热像仪凭借其非接触、可视化、高效率…

荒原之梦考研数学 | 做选填题,就不要局限于所用的方法

做选择题或者填空题的时候,我们可以不按照标准的解法一步步求解,因为选填题要的只是一个最终的结果。 所以,我们在考研备考的时候,会遇到一些“选填技巧”——在本文中,「荒原之梦考研数学」就给同学们提供一个与…

drf 查找

drf 查找 setting.py:REST_FRAMEWORK = {DEFAULT_FILTER_BACKENDS: [django_filters.rest_framework.DjangoFilterBackend,"rest_framework.filters.SearchFilter",] }view.py : from rest_framework.fi…

nacos集群安装

环境OS:Centos 7nacos:2.5.2 三台集群组成集群192.168.1.108192.168.1.105192.168.1.106 安装所需要得条件配置1.jdk安装的是:21.0.62.maven安装的是:3.9.93.mysql安装的是:mysql-5.7.431.下载地址https://github.com/…

使用UCS 音频(效)文件通用分类系统 Universal Category System整理音效文件

做后期最痛苦的就是其实你就需要一个1秒的音效,你去网上搜半天都是卖给你几百个G的资源包。。。下载解压大半天还要挨个寻找,真的日了狗了。 最近发现国外一个UCS分类系统,UCS是英文Universal Category System的缩写…

GO2 APP SRC

com.unitree.* - 这是 宇树科技(Unitree) 的包名 com.unitree.doggo2 - 应该是主要的应用包 com.unitree.baselibrary - 基础库 com.unitree.lib_ble - 蓝牙库 com.unitree.lib_db - 数据库库 com.unitree.webrtc - …

PC端的安卓文件管理器(基于ADB)

PC端的安卓文件管理器(基于ADB)https://github.com/gregko/AdbExplorer/releases

CF2172H - Shuffling Cards with Problem Solver 68!

Aru loves playing card games (Poker, Texas hold em, Balatro, etc.) and she has perfected the art of shuffling cards, especially the riffle shuffle. She is playing with Mutsuki now, and its her turn to …

2025年福祉座椅定制厂家权威推荐榜单:轮椅升降平台/轮椅升降机/福祉车源头厂家精选

中国60岁及以上人口在2025年预计突破3亿,占总人口比例达22%,其中失能老人数量超550万,庞大的需求推动福祉设备市场快速发展。 福祉座椅作为提升老年人和残障人士生活质量的关键设备,正成为康复器械市场的重要组成部…