`timescale 1ns/1ps module analog_ip ( inout BAUD_RATE, inout TEST_SINGLE, inout UART1_RX, inout UART1_TX, inout so_io1, input csn_out_data, input csn_out_en, output tri0 rxd1_ip_in, input sck_out_data, input sck_out_en, output tri0 so_io1_in, input so_io1_out_data, input so_io1_out_en, input txd1_ip_out_data, input txd1_ip_out_en, input sys_clock, input bus_clock, input resetn, input stop, input [1:0] mem_ahb_htrans, input mem_ahb_hready, input mem_ahb_hwrite, input [31:0] mem_ahb_haddr, input [2:0] mem_ahb_hsize, input [2:0] mem_ahb_hburst, input [31:0] mem_ahb_hwdata, output tri1 mem_ahb_hreadyout, output tri0 mem_ahb_hresp, output tri0 [31:0] mem_ahb_hrdata, output tri0 slave_ahb_hsel, output tri1 slave_ahb_hready, input slave_ahb_hreadyout, output tri0 [1:0] slave_ahb_htrans, output tri0 [2:0] slave_ahb_hsize, output tri0 [2:0] slave_ahb_hburst, output tri0 slave_ahb_hwrite, output tri0 [31:0] slave_ahb_haddr, output tri0 [31:0] slave_ahb_hwdata, input slave_ahb_hresp, input [31:0] slave_ahb_hrdata, output tri0 [3:0] ext_dma_DMACBREQ, output tri0 [3:0] ext_dma_DMACLBREQ, output tri0 [3:0] ext_dma_DMACSREQ, output tri0 [3:0] ext_dma_DMACLSREQ, input [3:0] ext_dma_DMACCLR, input [3:0] ext_dma_DMACTC, output tri0 [3:0] local_int ); assign UART1_TX = txd1_ip_out_en ? txd1_ip_out_data : 1'bz; assign rxd1_ip_in = UART1_RX; assign slave_ahb_hsel = 1'b0; assign slave_ahb_hready = 1'b1; assign slave_ahb_htrans = 2'b00; assign slave_ahb_hsize = 3'b000; assign slave_ahb_hburst = 3'b000; assign slave_ahb_hwrite = 1'b0; assign slave_ahb_haddr = 32'b0; assign slave_ahb_hwdata = 32'b0; assign ext_dma_DMACBREQ = 4'b0000; // 禁用DMA assign ext_dma_DMACLBREQ = 4'b0000; assign ext_dma_DMACSREQ = 4'b0000; assign ext_dma_DMACLSREQ = 4'b0000; assign local_int = 4'b0000; // 禁用中断 // ============================================== // 核心RAM参数定义 // ============================================== parameter RAM_SIZE = 2048; // 总容量:1024*16bit = 2048字节 parameter RAM_DEPTH = 1024; // 数据深度:1024个 parameter RAM_WIDTH = 16; // 数据位宽:16bit parameter ADDR_BITS = 16; parameter DATA_BITS = 32; parameter PER_BITS = 12; parameter PER_CNT = 4; // APB外设:ADC0(0)、DAC0(1),这里设置4是为了兼容3000地址的DAC0 // 前四个地址用作说明 未实际使用对应变量 // parameter ADC0_ADDR = 'h0000; // ADC0地址 // parameter CFG_REG_ADDR = 'h1000; // 配置参数模块偏移地址 // parameter TRIG_CTRL_ADDR= 'h2000; // 触发模块偏移地址 // parameter DAC0_ADDR = 'h3000; // DAC0地址 parameter RAM_BASE_ADDR = 'h6000; // 双口RAM APB地址 实际应用 // ============================================== // AHB2APB 桥 // ============================================== wire apb_psel; wire apb_penable; wire apb_pwrite; wire [ADDR_BITS-1:0] apb_paddr; wire [DATA_BITS-1:0] apb_pwdata; wire [3:0] apb_pstrb; wire [2:0] apb_pprot; wire apb_pready = 1'b1; wire apb_pslverr = 1'b0; reg [DATA_BITS-1:0] apb_prdata; wire apb_clock = bus_clock; ahb2apb #(ADDR_BITS, DATA_BITS) ahb2apb_inst( .reset (!resetn ), .ahb_clock (sys_clock ), .ahb_hmastlock(1'b0 ), .ahb_htrans (mem_ahb_htrans ), .ahb_hsel (1'b1 ), .ahb_hready (mem_ahb_hready ), .ahb_hwrite (mem_ahb_hwrite ), .ahb_haddr (mem_ahb_haddr[ADDR_BITS-1:0]), .ahb_hsize (mem_ahb_hsize ), .ahb_hburst (mem_ahb_hburst ), .ahb_hprot (4'b0011 ), .ahb_hwdata (mem_ahb_hwdata ), .ahb_hrdata (mem_ahb_hrdata ), .ahb_hreadyout(mem_ahb_hreadyout ), .ahb_hresp (mem_ahb_hresp ), .apb_clock (apb_clock ), .apb_psel (apb_psel ), .apb_penable (apb_penable ), .apb_pwrite (apb_pwrite ), .apb_paddr (apb_paddr ), .apb_pwdata (apb_pwdata ), .apb_pstrb (apb_pstrb ), .apb_pprot (apb_pprot ), .apb_pready (apb_pready ), .apb_pslverr (apb_pslverr ), .apb_prdata (apb_prdata ) ); // ============================================== // APB 外设选择 // ============================================== wire [PER_CNT-1:0] select = 1 << (apb_paddr[ADDR_BITS-1:PER_BITS]); wire per_psel[PER_CNT]; wire per_penable[PER_CNT]; wire per_pwrite[PER_CNT]; wire [PER_BITS-1:0] per_paddr[PER_CNT]; wire [DATA_BITS-1:0] per_pwdata[PER_CNT]; wire [DATA_BITS-1:0] per_prdata[PER_CNT]; genvar i; generate for (i = 0; i < PER_CNT; i = i + 1) begin : gen_per assign per_psel[i] = apb_psel & select[i]; assign per_penable[i] = apb_penable & select[i]; assign per_pwrite[i] = apb_pwrite; assign per_paddr[i] = apb_paddr[PER_BITS-1:0]; assign per_pwdata[i] = apb_pwdata; end endgenerate // ============================================== // 实例化 cfg_reg // ============================================== wire cfg_adc_en; wire [7:0] cfg_adc_clk_div; wire [3:0] cfg_adc_chnl_sel; wire [11:0] cfg_trig_threshold; wire [15:0] cfg_trig_pulse_width; wire [1:0] cfg_trig_edge; wire [1:0] cfg_trig_mode; wire [4:0] cfg_trig_time_slot; wire [15:0] cfg_trig_auto_timeout; wire cfg_adc_run; wire cfg_adc_restart; // 新增:DAC 配置信号 wire cfg_dac_en; wire cfg_dac_run; wire [1:0] cfg_wave_type; wire [9:0] cfg_max_vol; wire [9:0] cfg_min_vol; wire [31:0] cfg_frequency; wire [7:0] cfg_duty_cycle; cfg_reg cfg_reg_inst( .pclk (apb_clock), .presetn (resetn), .paddr (per_paddr[1]), .pwrite (per_pwrite[1]), .pwdata (per_pwdata[1]), .prdata (per_prdata[1]), .psel (per_psel[1]), .penable (per_penable[1]), .adc_en (cfg_adc_en), .adc_clk_div (cfg_adc_clk_div), .adc_chnl_sel (cfg_adc_chnl_sel), .trig_threshold (cfg_trig_threshold), .trig_pulse_width (cfg_trig_pulse_width), .trig_edge (cfg_trig_edge), .trig_mode (cfg_trig_mode), .trig_time_slot (cfg_trig_time_slot), .trig_auto_timeout (cfg_trig_auto_timeout), .adc_run (cfg_adc_run), .adc_restart (cfg_adc_restart), // ********************** 新增:DAC 输出 ********************** .dac_en (cfg_dac_en), .dac_run (cfg_dac_run), .wave_type (cfg_wave_type), .max_vol (cfg_max_vol), .min_vol (cfg_min_vol), .frequency (cfg_frequency), .duty_cycle (cfg_duty_cycle) ); // ============================================== // 实例化 ADC0 // ============================================== wire adc0_eoc; wire [11:0] adc0_data; apb_adc #( .SCLK_BIT(16) ) apb_adc0_inst( // APB接口 .stop (stop ), .dma_req (), // 不使用DMA .dma_clr (1'b0), // DMA清零置0 .apb_clock (apb_clock ), .apb_resetn (resetn ), .apb_psel (per_psel[0] ), .apb_penable(per_penable[0] ), .apb_pwrite (per_pwrite[0] ), .apb_paddr (per_paddr[0] ), .apb_pwdata (per_pwdata[0] ), .apb_prdata (per_prdata[0] ), // ADC采集数据输出信号 .adc_eoc_out(adc0_eoc ), .adc_data_out(adc0_data ), // CFG信号 .cfg_adc_en (cfg_adc_en), .cfg_adc_clk_div (cfg_adc_clk_div), .cfg_adc_chnl_sel (cfg_adc_chnl_sel) ); // ============================================== // ADC 12位 → 16位:高4位补0 // ============================================== // wire [RAM_WIDTH-1:0] adc0_data_16bit; // assign adc0_data_16bit = {4'b0000, adc0_data}; //assign TEST_CLK = adc0_eoc; //assign TEST_APB_CLK = apb_clock; // ============================================== // 实例化 trig_ctrl // ============================================== wire [9:0] trig_ram_wr_addr; wire trig_ram_wren; wire [RAM_WIDTH-1:0] trig_ram_data_16bit; trig_ctrl trig_ctrl_inst( .pclk (apb_clock), .presetn (resetn), .paddr (per_paddr[2]), .pwrite (per_pwrite[2]), .pwdata (per_pwdata[2]), .prdata (per_prdata[2]), .psel (per_psel[2]), .penable (per_penable[2]), .trig_threshold (cfg_trig_threshold), .trig_pulse_width (cfg_trig_pulse_width), .trig_edge (cfg_trig_edge), .trig_mode (cfg_trig_mode), .trig_time_slot (cfg_trig_time_slot), .trig_auto_timeout (cfg_trig_auto_timeout), .adc_en (cfg_adc_en), .adc_run (cfg_adc_run), .adc_restart (cfg_adc_restart), .adc_eoc (adc0_eoc), .adc_data (adc0_data), .ram_wren_b (trig_ram_wren), .ram_wr_addr (trig_ram_wr_addr), .ram_wr_data_b (trig_ram_data_16bit), .trig_done (), .trigger_ptr () ); // ============================================== // 实例化 DAC0 // ============================================== apb_dac apb_dac0_inst( .stop (stop), .dma_req (), // 不使用DMA .dma_clr (1'b0), .apb_clock (apb_clock ), .apb_resetn (resetn ), .apb_psel (per_psel[3] ), .apb_penable(per_penable[3] ), .apb_pwrite (per_pwrite[3] ), .apb_paddr (per_paddr[3] ), .apb_pwdata (per_pwdata[3] ), .apb_prdata (per_prdata[3] ), // ********************** 新增:波形控制参数 ********************** .dac_en (cfg_dac_en), .dac_run (cfg_dac_run), .wave_type (cfg_wave_type), .max_vol (cfg_max_vol), .min_vol (cfg_min_vol), .frequency (cfg_frequency), .duty_cycle (cfg_duty_cycle), ); // assign TEST_SINGLE = dac_test; // ============================================== // 实例化 波特率检测模块 // ============================================== wire [31:0] baud_rate; baud_detect u_baud_detect ( .sys_clock (sys_clock), .rst_n (resetn), // 顶层的复位信号(低有效) .UART1_DETECT (BAUD_RATE), // UART1_RX的FPGA输入信号 .baud_rate (baud_rate) // 检测到的波特率 ); // ============================================== // 双口 RAM 配置(1024×16bit) // ============================================== wire [9:0] ram_addr_a; // MCU读地址(10bit,1024深度) wire [RAM_WIDTH-1:0] ram_data_a; // MCU写数据(不用) wire [RAM_WIDTH-1:0] ram_q_a; // MCU读数据(16位) wire ram_wren_a; // MCU写使能(不用) wire ram_rden_a; // MCU读使能 wire [1:0] ram_byteena_a; // 16位RAM对应2位字节使能wire信号 wire [9:0] ram_addr_b; // ADC写地址(10bit) wire [RAM_WIDTH-1:0] ram_data_b; // ADC写数据(16位) wire ram_wren_b; // ADC写使能(EOC控制) wire [RAM_WIDTH-1:0] ram_q_b; // 不用 // 字节使能信号赋值(全使能) assign ram_byteena_a = 2'b11; // RAM B口地址自增(10bit,循环1024) // reg [9:0] ram_wr_addr_b_reg; // always @(posedge apb_clock or negedge resetn) begin // if(!resetn) // ram_wr_addr_b_reg <= 10'd0; // else if(adc0_eoc) // ram_wr_addr_b_reg <= ram_wr_addr_b_reg + 1'b1; // end // assign ram_addr_b = ram_wr_addr_b_reg; // assign ram_data_b = adc0_data_16bit; // 写入补0后的16位数据 // assign ram_wren_b = adc0_eoc; // ADC采样完成立即写入RAM assign ram_wren_b = trig_ram_wren; // trig模块使能写 assign ram_addr_b = trig_ram_wr_addr; // trig模块传输地址 assign ram_data_b = trig_ram_data_16bit; // trig输出补位后的16位数据 altsyncram u_dual_port_ram( .wren_a (ram_wren_a ), // MCU端口写使能 .wren_b (ram_wren_b ), // ADC端口写使能 .rden_a (ram_rden_a ), // MCU端口读使能 .rden_b (1'b0 ), // ADC端口始终读使能 .data_a (16'd0 ), // MCU端口写入数据(不用) .data_b (ram_data_b ), // ADC写入16bit数据 .address_a (ram_addr_a ), // MCU地址(10bit) .address_b (ram_addr_b ), // ADC地址(10bit) .clock0 (apb_clock ), // 时钟端口0 .clock1 (apb_clock ), // 时钟端口1 .clocken0 (1'b1 ), // 时钟使能0 .clocken1 (1'b1 ), // 时钟使能1 .clocken2 (1'b1 ), // 时钟使能2 .clocken3 (1'b1 ), // 时钟使能3 .aclr0 (1'b0 ), // 清零0(禁用) .aclr1 (1'b0 ), // 清零1(禁用) .byteena_a (ram_byteena_a), // 连接wire信号,而非常量 .byteena_b (2'b11 ), // ADC写全使能 .addressstall_a(1'b0 ), // 地址暂停禁用 .addressstall_b(1'b0 ), // 地址暂停禁用 .q_a (ram_q_a ), // MCU读出16bit数据 .q_b (), // ADC端口不读 .eccstatus ( ) // ECC不用 ); // 适配1024×16bit defparam u_dual_port_ram.byte_size = 8, u_dual_port_ram.clock_enable_input_a = "BYPASS", u_dual_port_ram.clock_enable_output_a = "BYPASS", u_dual_port_ram.intended_device_family = "Cyclone IV E", u_dual_port_ram.lpm_hint = "ENABLE_RUNTIME_MOD=NO", u_dual_port_ram.operation_mode = "BIDIR_DUAL_PORT", u_dual_port_ram.numwords_a = 1024, // 深度1024 u_dual_port_ram.widthad_a = 10, // 10bit地址 u_dual_port_ram.width_a = 16, // 16bit位宽 u_dual_port_ram.width_byteena_a = 2, // 2字节使能 u_dual_port_ram.outdata_aclr_a = "NONE", u_dual_port_ram.outdata_reg_a = "UNREGISTERED", u_dual_port_ram.numwords_b = 1024, // 深度1024 u_dual_port_ram.widthad_b = 10, // 10bit地址 u_dual_port_ram.width_b = 16, // 16bit位宽 u_dual_port_ram.width_byteena_b = 2, // 2字节使能 u_dual_port_ram.outdata_aclr_b = "NONE", u_dual_port_ram.outdata_reg_b = "UNREGISTERED", u_dual_port_ram.ram_block_type = "M9K", u_dual_port_ram.read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ"; // ============================================== // APB2RAM 例化(供MCU读取16位RAM数据) // ============================================== wire mem_apb_psel; wire mem_apb_penable; wire mem_apb_pwrite; wire [15:0] mem_apb_paddr; wire [31:0] mem_apb_pwdata; wire [3:0] mem_apb_pstrb; wire [2:0] mem_apb_pprot; wire mem_apb_pready; wire mem_apb_pslverr; wire [31:0] mem_apb_prdata; // 仅由apb2ram驱动,无外部赋值 // RAM 地址选择 assign mem_apb_psel = apb_psel && (apb_paddr[ADDR_BITS-1:PER_BITS] == RAM_BASE_ADDR[ADDR_BITS-1:PER_BITS]); assign mem_apb_penable = apb_penable; assign mem_apb_pwrite = apb_pwrite; assign mem_apb_paddr = apb_paddr; assign mem_apb_pwdata = apb_pwdata; assign mem_apb_pstrb = apb_pstrb; assign mem_apb_pprot = apb_pprot; apb2ram #(16) u_apb2ram( .resetn (resetn ), .apb_clock (bus_clock ), .apb_psel (mem_apb_psel ), .apb_penable(mem_apb_penable), .apb_pwrite (mem_apb_pwrite ), .apb_paddr (mem_apb_paddr ), .apb_pwdata (mem_apb_pwdata ), .apb_pstrb (mem_apb_pstrb ), .apb_pprot (mem_apb_pprot ), .apb_pready (mem_apb_pready ), .apb_pslverr(mem_apb_pslverr), .apb_prdata (mem_apb_prdata ), // 唯一驱动源 .ram_addr (ram_addr_a ), .ram_byteena(ram_byteena_a ), // 连接wire信号,而非常量 .ram_data (ram_data_a ), .ram_wren (ram_wren_a ), .ram_rden (ram_rden_a ), .ram_q (ram_q_a ) ); // ============================================== // APB 读数据合并 // ============================================== reg [PER_CNT-1:0] pr_select; always @(posedge apb_clock or negedge resetn) begin if (!resetn) pr_select <= 'b0; else if (apb_psel && !apb_penable) pr_select <= select; end always @ (*) begin apb_prdata = 32'd0; if(mem_apb_psel) begin apb_prdata = mem_apb_prdata; // 读RAM end else begin // 关键:根据 pr_select 选择对应外设的读数据(多选一) case (pr_select) 4'b0001: apb_prdata = per_prdata[0]; // 读ADC0 4'b0010: apb_prdata = per_prdata[1]; // 读CFG_REG(TRIG_CONFIG 正常) 4'b0100: apb_prdata = per_prdata[2]; // 读TRIG_CTRL(TRIG_PTR 正常) 4'b1000: apb_prdata = per_prdata[3]; // 读DAC0 default: apb_prdata = 32'd0; endcase end end // integer j; // always @ (*) begin // apb_prdata = 32'd0; // if(mem_apb_psel) // apb_prdata = mem_apb_prdata; // 读RAM // else // for (j = 0; j < PER_CNT; j = j + 1) // apb_prdata = apb_prdata | per_prdata[j]; // end endmodule module apb_adc ( input stop, output dma_req, input dma_clr, input apb_clock, input apb_resetn, input apb_psel, input apb_penable, input apb_pwrite, input [11:0] apb_paddr, input [31:0] apb_pwdata, output [31:0] apb_prdata, // ===================== ADC模块输出信号 ===================== output adc_eoc_out, // 采集完成脉冲 output [11:0] adc_data_out, // 通道12稳定数据 // ===================== CFG全局配置输入信号(现在生效!) ===================== input cfg_adc_en, // ADC总使能(取代原ADC_CONT_EN) input [7:0] cfg_adc_clk_div, // 时钟分频(取代原SCLK_DIV) input [3:0] cfg_adc_chnl_sel // 通道选择(取代原FIXED_CHANNEL) ); parameter SCLK_BIT = 16; // 核心信号 reg apb_eoc; reg [11:0] apb_db; wire adc_eoc; wire [11:0] adc_db; wire eoc_rising = (!adc_eoc) && apb_eoc; // 采集完成上升沿 // 时钟分频信号 reg [SCLK_BIT-1:0] sclk_counter; reg sclk; // EOC同步(标准2拍同步,稳定可靠) always @(posedge apb_clock or negedge apb_resetn) begin if (!apb_resetn) apb_eoc <= 1'b0; else apb_eoc <= adc_eoc; end // 数据锁存(仅ADC使能时,采集完成锁存数据) always @(posedge apb_clock or negedge apb_resetn) begin if (!apb_resetn) apb_db <= 12'b0; else if (cfg_adc_en && eoc_rising) //使用cfg使能 apb_db <= adc_db; end // 时钟分频逻辑(分频值 来自cfg_adc_clk_div) always @(posedge apb_clock or negedge apb_resetn) begin if (!apb_resetn) begin sclk_counter <= 0; sclk <= 1'b0; end else if (!cfg_adc_en) begin // ADC关闭时,分频器复位 sclk_counter <= 0; sclk <= 1'b0; end else begin // ADC使能时,正常分频 if (sclk_counter == cfg_adc_clk_div) begin //分频值用cfg配置 sclk_counter <= 0; sclk <= !sclk; end else begin sclk_counter <= sclk_counter + 1'b1; end end end // 输出信号 assign adc_eoc_out = eoc_rising; assign adc_data_out = apb_db; wire [4:0] chnl_sel = cfg_adc_chnl_sel; assign dma_req = 1'b0; assign apb_prdata = 32'd0; // ADC硬核(所有配置均来自外部CFG,无任何硬编码!) alta_adc adc_inst( .enb (!cfg_adc_en), // 使能来自cfg .sclk (sclk), // 分频时钟来自cfg配置 .insel(chnl_sel), // 通道来自cfg配置 .stop (stop), .db (adc_db), .eoc (adc_eoc) ); endmodule // ============================================== // apb_dac 模块 // ============================================== module apb_dac ( input stop, output dma_req, input dma_clr, input apb_clock, input apb_resetn, input apb_psel, input apb_penable, input apb_pwrite, input [11:0] apb_paddr, input [31:0] apb_pwdata, output [31:0] apb_prdata, input dac_en, // 来自 CFG input dac_run, // 来自 CFG input [1:0] wave_type, // 来自 CFG input [9:0] max_vol, // 来自 CFG input [9:0] min_vol, // 来自 CFG input [31:0] frequency, // 来自 CFG input [7:0] duty_cycle // 来自 CFG ); assign dma_req = 1'b0; assign apb_prdata = 32'd0; // ------------------- DDS 相位累加器(核心,只有加法)------------------- reg [31:0] phase_acc; always @(posedge apb_clock or negedge apb_resetn) begin if (!apb_resetn) begin phase_acc <= 32'd0; end else begin if (!dac_en || !dac_run) begin phase_acc <= 32'd0; end else begin phase_acc <= phase_acc + frequency; end end end wire [9:0] phase_comb = phase_acc[31:22]; // 10 位相位(组合) // // ========== 正弦查找表 ROM(组合读取) ========== (* ram_style = "distributed" *) // 强制综合为分布式 RAM,允许组合读出 reg [9:0] sine_rom [0:1023]; //(* ram_style = "block" *) reg [9:0] sine_rom [0:1023]; initial begin $readmemh("sine.hex", sine_rom); end // // 组合读取:用 phase_r 作为地址直接出数据 wire [9:0] sin_raw; assign sin_raw = sine_rom[phase_r]; // ---------- 同步所有参与运算的信号 ---------- // 目的:让 max_vol, min_vol, phase 在时钟沿后稳定,消除输入跳变引起的毛刺 reg [9:0] max_vol_r, min_vol_r; reg [9:0] phase_r; reg phase_msb_r; // phase_acc[31] 用于方波 always @(posedge apb_clock) begin max_vol_r <= max_vol; min_vol_r <= min_vol; phase_r <= phase_comb; phase_msb_r <= phase_acc[31]; end // ---------- 组合逻辑:波形计算(纯组合,无毛刺输入)---------- reg [9:0] wave_data_comb; reg [9:0] diff; reg [19:0] mult; reg [9:0] step; always @(*) begin // 使用寄存后的稳定值进行计算 diff = max_vol_r - min_vol_r; case(wave_type) 2'b00: begin // 方波 wave_data_comb = (phase_msb_r == 1'b0) ? max_vol_r : min_vol_r; end 2'b01: begin // 正弦波(查表 + 幅度缩放) mult = diff * sin_raw; // sin_raw 为 0~1023,中心 512 step = mult >> 10; // 除以 1024 wave_data_comb = min_vol_r + step; end 2'b10: begin // 三角波 if (phase_r[9] == 1'b0) begin // 上升支:phase 0~511 mult = diff * phase_r[8:0]; step = mult >> 9; wave_data_comb = min_vol_r + step; end else begin // 下降支:phase 512~1023,phase_r[8:0] 实际等于 phase-512 mult = diff * phase_r[8:0]; step = mult >> 9; // 理论上 step <= diff,这里加个安全钳位 wave_data_comb = (max_vol_r > step) ? (max_vol_r - step) : min_vol_r; end end 2'b11: begin // 锯齿波 mult = diff * phase_r; step = mult >> 10; // 除以 1024,近似斜坡 wave_data_comb = min_vol_r + step; end default: wave_data_comb = 10'd0; endcase end // ------------------------------ // 关键:完全对齐官方极性 // ------------------------------ wire dac_dout; alta_dac dac_inst( .enb (!dac_en), // 低有效 .bufenb (!dac_en), // 低有效 (用dac_en控制即可) .din (wave_data_comb), // 波形数据 .stop (stop), .dout (dac_dout) ); endmodule