trig_ctrl_tb.v 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. `timescale 1ns / 1ps
  2. module tb;
  3. // ======================== 参数 ========================
  4. localparam CLK_PERIOD = 9.615; // 104MHz
  5. localparam ADC_PERIOD = 1000; // 1MHz -> 1000ns
  6. // ======================== 信号 ========================
  7. reg pclk;
  8. reg presetn;
  9. reg [11:0] paddr;
  10. reg pwrite;
  11. reg [31:0] pwdata;
  12. wire [31:0] prdata;
  13. reg psel;
  14. reg penable;
  15. reg [11:0] trig_threshold;
  16. reg [15:0] trig_pulse_width;
  17. reg [1:0] trig_edge;
  18. reg [1:0] trig_mode;
  19. reg [4:0] trig_time_slot;
  20. reg [15:0] trig_auto_timeout;
  21. reg adc_en;
  22. reg adc_run;
  23. reg adc_restart;
  24. reg adc_eoc;
  25. reg [11:0] adc_data;
  26. wire ram_wren_b;
  27. wire [9:0] ram_wr_addr;
  28. wire [15:0] ram_wr_data_b;
  29. wire trig_done;
  30. wire [9:0] trigger_ptr;
  31. // 辅助变量(必须在模块顶部声明)
  32. real triangle_phase;
  33. real triangle_step;
  34. real tri_val;
  35. real volt;
  36. integer code;
  37. reg [11:0] adc_data_next=0;
  38. reg adc_eoc_dly;
  39. integer trigger_count;
  40. // ======================== DUT 实例 ========================
  41. trig_ctrl uut (
  42. .pclk (pclk),
  43. .presetn (presetn),
  44. .paddr (paddr),
  45. .pwrite (pwrite),
  46. .pwdata (pwdata),
  47. .prdata (prdata),
  48. .psel (psel),
  49. .penable (penable),
  50. .trig_threshold (trig_threshold),
  51. .trig_pulse_width(trig_pulse_width),
  52. .trig_edge (trig_edge),
  53. .trig_mode (trig_mode),
  54. .trig_time_slot (trig_time_slot),
  55. .trig_auto_timeout(trig_auto_timeout),
  56. .adc_en (adc_en),
  57. .adc_run (adc_run),
  58. .adc_restart (adc_restart),
  59. .adc_eoc (adc_eoc),
  60. .adc_data (adc_data),
  61. .ram_wren_b (ram_wren_b),
  62. .ram_wr_addr (ram_wr_addr),
  63. .ram_wr_data_b (ram_wr_data_b),
  64. .trig_done (trig_done),
  65. .trigger_ptr (trigger_ptr)
  66. );
  67. // ======================== 时钟与复位 ========================
  68. initial begin
  69. pclk = 0;
  70. forever #(CLK_PERIOD/2) pclk = ~pclk;
  71. end
  72. initial begin
  73. presetn = 0;
  74. #200;
  75. presetn = 1;
  76. end
  77. // ======================== 三角波生成 ========================
  78. initial begin
  79. triangle_phase = 0.0;
  80. triangle_step = (2.0 * 50000) / 1000000; // 50kHz / 1MHz
  81. end
  82. always #(ADC_PERIOD) begin
  83. // 更新相位
  84. triangle_phase = triangle_phase + triangle_step;
  85. if (triangle_phase > 1.0)
  86. triangle_phase = triangle_phase - 2.0;
  87. // 三角波值 (-1.0 ~ 1.0)
  88. if (triangle_phase >= 0)
  89. tri_val = 1.0 - 2.0 * triangle_phase;
  90. else
  91. tri_val = 1.0 + 2.0 * triangle_phase;
  92. // 映射到电压:中心1.65V,幅度1.5V -> 0.15V~3.15V
  93. volt = 1.65 + 1.5 * tri_val;
  94. // 转换为12位ADC码值
  95. code = (volt / 3.3) * 4095.0;
  96. if (code > 4095) code = 4095;
  97. if (code < 0) code = 0;
  98. adc_data_next = code[11:0];
  99. end
  100. // ======================== ADC EOC 脉冲 ========================
  101. always @(posedge pclk or negedge presetn) begin
  102. if (!presetn) begin
  103. adc_eoc <= 1'b0;
  104. adc_data <= 12'd0;
  105. adc_eoc_dly <= 1'b0;
  106. end else begin
  107. adc_eoc <= 1'b0;
  108. if (adc_eoc_dly) begin
  109. adc_eoc <= 1'b1;
  110. adc_data <= adc_data_next;
  111. end
  112. end
  113. end
  114. initial begin
  115. adc_eoc_dly = 1'b0;
  116. forever begin
  117. #(ADC_PERIOD - 10);
  118. adc_eoc_dly = 1'b1;
  119. #10;
  120. adc_eoc_dly = 1'b0;
  121. end
  122. end
  123. // ======================== 测试主流程(自动模式) ========================
  124. initial begin
  125. // 初始化
  126. paddr = 12'd0;
  127. pwdata = 32'd0;
  128. pwrite = 1'b0;
  129. psel = 1'b0;
  130. penable= 1'b0;
  131. trig_threshold = 12'd2048; // 1.65V
  132. trig_pulse_width = 16'd0;
  133. trig_edge = 2'b00;
  134. trig_mode = 2'b00; // 自动模式
  135. trig_time_slot = 5'd0;
  136. trig_auto_timeout = 16'd200; // 超时值
  137. adc_en = 1'b0;
  138. adc_run = 1'b0;
  139. adc_restart = 1'b0;
  140. trigger_count = 0;
  141. wait(presetn == 1'b1);
  142. repeat(50) @(posedge pclk);
  143. $display("========================================");
  144. $display(" Auto Mode Test - Waiting for triggers");
  145. $display("========================================");
  146. // 启动采集
  147. adc_en = 1'b1;
  148. adc_run = 1'b1;
  149. // 等待至少两次触发完成
  150. while (trigger_count < 5) begin
  151. @(posedge pclk);
  152. if (trig_done) begin
  153. trigger_count = trigger_count + 1;
  154. $display("[%0t] *** Trigger #%0d occurred! trigger_ptr = %d, ram_wr_addr = %d",
  155. $time, trigger_count, trigger_ptr, ram_wr_addr);
  156. // 模拟上位机读取后重启
  157. repeat(100) @(posedge pclk);
  158. adc_restart <= 1'b1;
  159. repeat(20) @(posedge pclk); // 给20个时钟宽脉冲
  160. adc_restart <= 1'b0;
  161. $display("[%0t] Restart issued, waiting for next trigger...", $time);
  162. end
  163. end
  164. $display("[%0t] Two triggers observed. Test finished.", $time);
  165. #10000;
  166. $stop;
  167. end
  168. // ======================== 波形记录 ========================
  169. initial begin
  170. $dumpfile("tb_auto.vcd");
  171. $dumpvars(0, tb);
  172. $dumpvars(1, uut.curr_state);
  173. $dumpvars(1, uut.trig_hit_comb);
  174. $dumpvars(1, uut.trig_hit_comb_reg);
  175. end
  176. endmodule