| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- `timescale 1ns / 1ps
- module tb;
- // ======================== 参数 ========================
- localparam CLK_PERIOD = 9.615; // 104MHz
- localparam ADC_PERIOD = 1000; // 1MHz -> 1000ns
- // ======================== 信号 ========================
- reg pclk;
- reg presetn;
- reg [11:0] paddr;
- reg pwrite;
- reg [31:0] pwdata;
- wire [31:0] prdata;
- reg psel;
- reg penable;
- reg [11:0] trig_threshold;
- reg [15:0] trig_pulse_width;
- reg [1:0] trig_edge;
- reg [1:0] trig_mode;
- reg [4:0] trig_time_slot;
- reg [15:0] trig_auto_timeout;
- reg adc_en;
- reg adc_run;
- reg adc_restart;
- reg adc_eoc;
- reg [11:0] adc_data;
- wire ram_wren_b;
- wire [9:0] ram_wr_addr;
- wire [15:0] ram_wr_data_b;
- wire trig_done;
- wire [9:0] trigger_ptr;
- // 辅助变量(必须在模块顶部声明)
- real triangle_phase;
- real triangle_step;
- real tri_val;
- real volt;
- integer code;
- reg [11:0] adc_data_next=0;
- reg adc_eoc_dly;
- integer trigger_count;
- // ======================== DUT 实例 ========================
- trig_ctrl uut (
- .pclk (pclk),
- .presetn (presetn),
- .paddr (paddr),
- .pwrite (pwrite),
- .pwdata (pwdata),
- .prdata (prdata),
- .psel (psel),
- .penable (penable),
- .trig_threshold (trig_threshold),
- .trig_pulse_width(trig_pulse_width),
- .trig_edge (trig_edge),
- .trig_mode (trig_mode),
- .trig_time_slot (trig_time_slot),
- .trig_auto_timeout(trig_auto_timeout),
- .adc_en (adc_en),
- .adc_run (adc_run),
- .adc_restart (adc_restart),
- .adc_eoc (adc_eoc),
- .adc_data (adc_data),
- .ram_wren_b (ram_wren_b),
- .ram_wr_addr (ram_wr_addr),
- .ram_wr_data_b (ram_wr_data_b),
- .trig_done (trig_done),
- .trigger_ptr (trigger_ptr)
- );
- // ======================== 时钟与复位 ========================
- initial begin
- pclk = 0;
- forever #(CLK_PERIOD/2) pclk = ~pclk;
- end
- initial begin
- presetn = 0;
- #200;
- presetn = 1;
- end
- // ======================== 三角波生成 ========================
- initial begin
- triangle_phase = 0.0;
- triangle_step = (2.0 * 50000) / 1000000; // 50kHz / 1MHz
- end
- always #(ADC_PERIOD) begin
- // 更新相位
- triangle_phase = triangle_phase + triangle_step;
- if (triangle_phase > 1.0)
- triangle_phase = triangle_phase - 2.0;
-
- // 三角波值 (-1.0 ~ 1.0)
- if (triangle_phase >= 0)
- tri_val = 1.0 - 2.0 * triangle_phase;
- else
- tri_val = 1.0 + 2.0 * triangle_phase;
-
- // 映射到电压:中心1.65V,幅度1.5V -> 0.15V~3.15V
- volt = 1.65 + 1.5 * tri_val;
-
- // 转换为12位ADC码值
- code = (volt / 3.3) * 4095.0;
- if (code > 4095) code = 4095;
- if (code < 0) code = 0;
- adc_data_next = code[11:0];
- end
- // ======================== ADC EOC 脉冲 ========================
- always @(posedge pclk or negedge presetn) begin
- if (!presetn) begin
- adc_eoc <= 1'b0;
- adc_data <= 12'd0;
- adc_eoc_dly <= 1'b0;
- end else begin
- adc_eoc <= 1'b0;
- if (adc_eoc_dly) begin
- adc_eoc <= 1'b1;
- adc_data <= adc_data_next;
- end
- end
- end
- initial begin
- adc_eoc_dly = 1'b0;
- forever begin
- #(ADC_PERIOD - 10);
- adc_eoc_dly = 1'b1;
- #10;
- adc_eoc_dly = 1'b0;
- end
- end
- // ======================== 测试主流程(自动模式) ========================
- initial begin
- // 初始化
- paddr = 12'd0;
- pwdata = 32'd0;
- pwrite = 1'b0;
- psel = 1'b0;
- penable= 1'b0;
-
- trig_threshold = 12'd2048; // 1.65V
- trig_pulse_width = 16'd0;
- trig_edge = 2'b00;
- trig_mode = 2'b00; // 自动模式
- trig_time_slot = 5'd0;
- trig_auto_timeout = 16'd200; // 超时值
- adc_en = 1'b0;
- adc_run = 1'b0;
- adc_restart = 1'b0;
- trigger_count = 0;
- wait(presetn == 1'b1);
- repeat(50) @(posedge pclk);
-
- $display("========================================");
- $display(" Auto Mode Test - Waiting for triggers");
- $display("========================================");
- // 启动采集
- adc_en = 1'b1;
- adc_run = 1'b1;
-
- // 等待至少两次触发完成
- while (trigger_count < 5) begin
- @(posedge pclk);
- if (trig_done) begin
- trigger_count = trigger_count + 1;
- $display("[%0t] *** Trigger #%0d occurred! trigger_ptr = %d, ram_wr_addr = %d",
- $time, trigger_count, trigger_ptr, ram_wr_addr);
-
- // 模拟上位机读取后重启
- repeat(100) @(posedge pclk);
- adc_restart <= 1'b1;
- repeat(20) @(posedge pclk); // 给20个时钟宽脉冲
- adc_restart <= 1'b0;
- $display("[%0t] Restart issued, waiting for next trigger...", $time);
- end
- end
-
- $display("[%0t] Two triggers observed. Test finished.", $time);
- #10000;
- $stop;
- end
- // ======================== 波形记录 ========================
- initial begin
- $dumpfile("tb_auto.vcd");
- $dumpvars(0, tb);
- $dumpvars(1, uut.curr_state);
- $dumpvars(1, uut.trig_hit_comb);
- $dumpvars(1, uut.trig_hit_comb_reg);
- end
- endmodule
|