module cfg_reg ( // ===== 标准 APB 总线接口 ===== input pclk, // APB 时钟 input presetn, // APB 复位(低有效) input [11:0] paddr, // APB 偏移地址 input pwrite, // 1=写,0=读 input [31:0] pwdata, // 写数据 output reg [31:0] prdata, // 读数据 input psel, // 本模块片选 input penable, // APB使能 // ===== 输出信号 ADC部分 ===== output reg adc_en, // ADC 使能 output reg [7:0] adc_clk_div, // 时钟分频 output reg [3:0] adc_chnl_sel, // 通道选择 output reg [11:0] trig_threshold, // 触发阈值 output reg [15:0] trig_pulse_width, // 触发脉宽 output reg [1:0] trig_edge, // 触发边沿(00=上升 01=下降 10=双边 11=脉宽) output reg [1:0] trig_mode, // 触发模式(00=自动 01=普通 10=单次) output reg [4:0] trig_time_slot, // 时间档位 output reg [15:0] trig_auto_timeout, // 自动模式触发超时值 output reg adc_run, // 开始/停止 output reg adc_restart, // 重置采样 // ===== 输出信号 DAC部分 ===== output reg dac_en, // DAC 使能 output reg dac_run, // 运行/停止 output reg [1:0] wave_type, // 波形类型 (00=方波 01=正弦波 10=三角波 11=锯齿波) output reg [9:0] max_vol, // 最大输出电压(DAC格式) output reg [9:0] min_vol, // 最小输出电压(DAC格式) output reg [31:0] frequency, // 频率 output reg [7:0] duty_cycle // 占空比 ); // ==================== ADC 相关 ==================== parameter ADDR_CTRL = 'h00; parameter ADDR_CLK_DIV = 'h04; parameter ADDR_TRIG_TH = 'h08; parameter ADDR_TRIG_PW = 'h0C; parameter ADDR_TRIG_CFG = 'h10; parameter ADDR_TRIG_TOUT = 'h14; parameter ADDR_RUN_CTRL = 'h18; // ==================== DAC 相关 ==================== parameter ADDR_DAC_CTRL = 'h1C; // DAC 总控 parameter ADDR_DAC_WAVE = 'h20; // 波形类型 parameter ADDR_DAC_AMP = 'h24; // max + min parameter ADDR_DAC_FREQ = 'h28; // 频率 parameter ADDR_DAC_DUTY = 'h2C; // 占空比 wire apb_data_phase = psel && penable; //--------------------------- // 1. APB 写逻辑 //--------------------------- always @(posedge pclk or negedge presetn) begin if (!presetn) begin adc_en <= 1'b0; adc_clk_div <= 8'd3; adc_chnl_sel <= 4'd13; trig_threshold <= 12'd2048; trig_pulse_width<= 16'd10; trig_edge <= 2'b00; trig_mode <= 2'b00; trig_time_slot <= 5'd1; trig_auto_timeout<=16'd1024; adc_run <= 1'b0; adc_restart <= 1'b0; // ==================== DAC 复位 ==================== dac_en <= 1'b0; dac_run <= 1'b0; wave_type <= 2'b00; max_vol <= 10'd900; // 默认最大值 min_vol <= 10'd100; // 默认最小值 frequency <= 32'd1000; // 默认频率 duty_cycle <= 8'd50; // 默认 50% end else if (apb_data_phase && pwrite) begin case (paddr) ADDR_CTRL: begin adc_en <= pwdata[0]; adc_chnl_sel <= pwdata[4:1]; end ADDR_CLK_DIV: adc_clk_div <= pwdata[7:0]; ADDR_TRIG_TH: trig_threshold <= pwdata[11:0]; ADDR_TRIG_PW: trig_pulse_width <= pwdata[15:0]; ADDR_TRIG_CFG: begin trig_edge <= pwdata[1:0]; trig_mode <= pwdata[3:2]; trig_time_slot <= pwdata[8:4]; end ADDR_TRIG_TOUT: trig_auto_timeout <= pwdata[15:0]; ADDR_RUN_CTRL: begin adc_run <= pwdata[0]; adc_restart <= pwdata[1]; end // ==================== DAC 写配置 ==================== ADDR_DAC_CTRL: begin dac_en <= pwdata[0]; dac_run <= pwdata[1]; end ADDR_DAC_WAVE: wave_type <= pwdata[1:0]; ADDR_DAC_AMP: begin max_vol <= pwdata[9:0]; min_vol <= pwdata[25:16]; end ADDR_DAC_FREQ: frequency <= pwdata; ADDR_DAC_DUTY: duty_cycle <= pwdata[7:0]; endcase end end //--------------------------- // 2. APB 读逻辑 //--------------------------- always @(posedge pclk or negedge presetn) begin if (!presetn) begin prdata <= 32'd0; end else if (psel && !penable && !pwrite) begin case (paddr) ADDR_CTRL: prdata <= {27'd0, adc_chnl_sel, adc_en}; ADDR_CLK_DIV: prdata <= {24'd0, adc_clk_div}; ADDR_TRIG_TH: prdata <= {20'd0, trig_threshold}; ADDR_TRIG_PW: prdata <= {16'd0, trig_pulse_width}; ADDR_TRIG_CFG: prdata <= {23'd0, trig_time_slot, trig_mode, trig_edge}; ADDR_TRIG_TOUT:prdata <= {16'd0, trig_auto_timeout}; ADDR_RUN_CTRL: prdata <= {30'd0, adc_restart, adc_run}; // ==================== DAC 读 ==================== ADDR_DAC_CTRL: prdata <= {30'd0, dac_run, dac_en}; ADDR_DAC_WAVE: prdata <= {30'd0, wave_type}; ADDR_DAC_AMP: prdata = {6'd0, min_vol, 6'd0, max_vol}; ADDR_DAC_FREQ: prdata <= frequency; ADDR_DAC_DUTY: prdata <= {24'd0, duty_cycle}; default: prdata <= 32'd0; endcase end end endmodule