trig_ctrl.v 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. module trig_ctrl (
  2. input pclk, presetn,
  3. input [11:0] paddr,
  4. input pwrite,
  5. input [31:0] pwdata,
  6. output reg [31:0] prdata,
  7. input psel, penable,
  8. input [11:0] trig_threshold,
  9. input [15:0] trig_pulse_width,
  10. input [1:0] trig_edge,
  11. input [1:0] trig_mode,
  12. input [4:0] trig_time_slot,
  13. input [15:0] trig_auto_timeout,
  14. input adc_en, adc_run, adc_restart,
  15. input adc_eoc,
  16. input [11:0] adc_data,
  17. output reg ram_wren_b,
  18. output reg [9:0] ram_wr_addr,
  19. output reg [15:0] ram_wr_data_b,
  20. output reg trig_done,
  21. output reg [9:0] trigger_ptr
  22. );
  23. localparam POST_TRIG_CNT = 512;
  24. localparam RAM_DEPTH = 1024;
  25. localparam INTERVAL_MIN = 1023;
  26. localparam IDLE = 3'b000;
  27. localparam PRE_FILL = 3'b001;
  28. localparam SAMPLING = 3'b010;
  29. localparam POST_TRIG = 3'b011;
  30. localparam DONE = 3'b100;
  31. localparam ADDR_TRIG_DONE = 'h00;
  32. localparam ADDR_TRIG_PTR = 'h04;
  33. // ========== 时基抽取相关信号 ===================================
  34. reg [15:0] decim_factor; // 抽取因子
  35. reg [15:0] eoc_cnt; // EOC 计数器
  36. reg write_strobe; // 间隔写脉冲
  37. always @(posedge pclk or negedge presetn) begin
  38. if(!presetn)
  39. decim_factor <= 15'd1;
  40. else begin
  41. case (trig_time_slot)
  42. 5'd1: decim_factor <= 15'd1; // 50µs/div
  43. 5'd2: decim_factor <= 15'd2; // 100µs/div
  44. 5'd3: decim_factor <= 15'd4; // 200µs/div
  45. 5'd4: decim_factor <= 15'd10; // 500µs/div
  46. 5'd5: decim_factor <= 15'd20; // 1ms/div
  47. 5'd6: decim_factor <= 15'd40; // 2ms/div
  48. 5'd7: decim_factor <= 15'd100; // 5ms/div
  49. 5'd8: decim_factor <= 15'd200; // 10ms/div
  50. 5'd9: decim_factor <= 15'd400; // 20ms/div
  51. 5'd10: decim_factor <= 15'd1000; // 50ms/div
  52. 5'd11: decim_factor <= 15'd2000; // 100ms/div
  53. 5'd12: decim_factor <= 15'd4000; // 200ms/div
  54. 5'd13: decim_factor <= 15'd10000; // 500ms/div
  55. 5'd14: decim_factor <= 15'd20000; // 1s/div
  56. default: decim_factor <= 15'd1;
  57. endcase
  58. end
  59. end
  60. // ========== 写脉冲生成 ================
  61. always @(posedge pclk or negedge presetn) begin
  62. if (!presetn) begin
  63. eoc_cnt <= 15'd0;
  64. write_strobe <= 1'b0;
  65. end else if (adc_restart_ris) begin
  66. eoc_cnt <= 15'd0;
  67. write_strobe <= 1'b0;
  68. end else begin
  69. write_strobe <= 1'b0;
  70. if (adc_eoc_ris && adc_en && adc_run && !single_shot_lock &&
  71. (curr_state == PRE_FILL || curr_state == SAMPLING || curr_state == POST_TRIG)) begin
  72. if (eoc_cnt >= decim_factor - 1) begin
  73. eoc_cnt <= 15'd0;
  74. write_strobe <= 1'b1;
  75. end else begin
  76. eoc_cnt <= eoc_cnt + 1'b1;
  77. end
  78. end
  79. end
  80. end
  81. // =====================================================================
  82. // 状态机
  83. reg [2:0] curr_state, next_state;
  84. // 同步与边沿
  85. reg adc_eoc_sync1, adc_eoc_sync2;
  86. wire adc_eoc_ris;
  87. reg adc_rst_sync1, adc_rst_sync2, adc_rst_sync3;
  88. wire adc_restart_ris;
  89. reg [11:0] adc_data_prev;
  90. reg [8:0] post_trig_cnt;
  91. reg single_shot_lock;
  92. // ========== 用于边沿触发的间隔保护(地址差值法) ==========
  93. reg [9:0] last_trig_end_addr_edge; // 边沿触发专用的上次触发结束地址
  94. wire [9:0] addr_diff_edge;
  95. wire trig_interval_ok_edge;
  96. // ========== 用于自动超时触发的间隔保护(计数器法) ==========
  97. reg [10:0] gap_cnt_auto; // 自动模式专用的间隔计数器
  98. wire trig_interval_ok_auto;
  99. reg [9:0] auto_wait_cnt; // 自动触发等待计数器
  100. // 触发条件
  101. wire sample_valid;
  102. wire edge_trigger;
  103. wire auto_force_trigger;
  104. wire trig_hit_comb;
  105. reg trig_hit_reg;
  106. // ========== 新增:脉宽触发相关信号 ===================================
  107. reg pulse_trigger; // 脉宽触发条件满足标志
  108. reg [15:0] pulse_cnt; // 脉宽计数器(最大65535,足够)
  109. reg pulse_active; // 脉宽检测激活标志
  110. reg pulse_level; // 当前检测的电平(1:高于阈值,0:低于阈值)
  111. // =====================================================================
  112. // --------------------------- 同步与边沿检测 ---------------------------
  113. always @(posedge pclk or negedge presetn) begin
  114. if (!presetn) begin
  115. adc_eoc_sync1 <= 1'b0;
  116. adc_eoc_sync2 <= 1'b0;
  117. end else begin
  118. adc_eoc_sync1 <= adc_eoc;
  119. adc_eoc_sync2 <= adc_eoc_sync1;
  120. end
  121. end
  122. assign adc_eoc_ris = adc_eoc_sync1 & ~adc_eoc_sync2;
  123. always @(posedge pclk or negedge presetn) begin
  124. if (!presetn) begin
  125. adc_rst_sync1 <= 1'b0;
  126. adc_rst_sync2 <= 1'b0;
  127. adc_rst_sync3 <= 1'b0;
  128. end else begin
  129. adc_rst_sync1 <= adc_restart;
  130. adc_rst_sync2 <= adc_rst_sync1;
  131. adc_rst_sync3 <= adc_rst_sync2;
  132. end
  133. end
  134. assign adc_restart_ris = adc_rst_sync2 & ~adc_rst_sync3;
  135. // --------------------------- 有效采样时刻 ---------------------------
  136. assign sample_valid = write_strobe && adc_en && adc_run && !single_shot_lock &&
  137. (curr_state == PRE_FILL || curr_state == SAMPLING);
  138. // ==============================================================
  139. // 边沿触发的间隔保护(地址差值法)
  140. // ==============================================================
  141. assign addr_diff_edge = (ram_wr_addr - last_trig_end_addr_edge + RAM_DEPTH) % RAM_DEPTH;
  142. assign trig_interval_ok_edge = (curr_state == SAMPLING) && (addr_diff_edge >= INTERVAL_MIN);
  143. // 边沿触发条件
  144. assign edge_trigger = sample_valid && (curr_state == SAMPLING) && trig_interval_ok_edge && (trig_edge != 2'b11) &&
  145. ( (trig_edge == 2'b00 && (adc_data_prev < trig_threshold) && (adc_data >= trig_threshold)) ||
  146. (trig_edge == 2'b01 && (adc_data_prev > trig_threshold) && (adc_data <= trig_threshold)) ||
  147. (trig_edge == 2'b10 && ( ((adc_data_prev < trig_threshold) && (adc_data >= trig_threshold)) ||
  148. ((adc_data_prev > trig_threshold) && (adc_data <= trig_threshold)) )) );
  149. // ========== 脉宽触发逻辑 =======================================
  150. // 在 sample_valid 且 trig_edge == 2'b11 时进行脉宽检测
  151. always @(posedge pclk or negedge presetn) begin
  152. if (!presetn) begin
  153. pulse_active <= 1'b0;
  154. pulse_cnt <= 16'd0;
  155. pulse_level <= 1'b0;
  156. pulse_trigger <= 1'b0;
  157. end else if (adc_restart_ris) begin
  158. pulse_active <= 1'b0;
  159. pulse_cnt <= 16'd0;
  160. pulse_level <= 1'b0;
  161. pulse_trigger <= 1'b0;
  162. end else if (curr_state == SAMPLING && trig_edge == 2'b11 && adc_en && adc_run && !single_shot_lock) begin
  163. pulse_trigger <= 1'b0;
  164. if(write_strobe) begin
  165. if (!pulse_active) begin
  166. if (trig_interval_ok_edge) begin
  167. // 检测边沿启动脉宽测量
  168. if ((adc_data_prev < trig_threshold) && (adc_data >= trig_threshold)) begin
  169. pulse_active <= 1'b1;
  170. pulse_level <= 1'b1; // 高电平脉宽
  171. pulse_cnt <= 16'd0; // 从0开始计数(边沿点不计入)
  172. pulse_trigger <= 1'b0;
  173. end else if ((adc_data_prev > trig_threshold) && (adc_data <= trig_threshold)) begin
  174. pulse_active <= 1'b1;
  175. pulse_level <= 1'b0; // 低电平脉宽
  176. pulse_cnt <= 16'd0;
  177. pulse_trigger <= 1'b0;
  178. end else begin
  179. pulse_trigger <= 1'b0;
  180. end
  181. end
  182. end else begin
  183. // 已激活,检查电平是否保持
  184. if (((adc_data >= trig_threshold) && pulse_level) ||
  185. ((adc_data <= trig_threshold) && !pulse_level)) begin
  186. if (pulse_cnt < trig_pulse_width - 1) begin
  187. pulse_cnt <= pulse_cnt + 1'b1;
  188. pulse_trigger <= 1'b0;
  189. end else begin
  190. // 达到设定宽度(采样点数达到 trig_pulse_width)
  191. pulse_trigger <= 1'b1;
  192. pulse_active <= 1'b0;
  193. pulse_cnt <= 16'd0;
  194. end
  195. end else begin
  196. // 电平改变,脉宽不足,停止测量
  197. pulse_active <= 1'b0;
  198. pulse_cnt <= 16'd0;
  199. pulse_trigger <= 1'b0;
  200. end
  201. end
  202. end
  203. end else begin
  204. // 非脉宽模式或条件不满足时,清零
  205. pulse_active <= 1'b0;
  206. pulse_cnt <= 16'd0;
  207. pulse_trigger <= 1'b0;
  208. end
  209. end
  210. // ===================================================================
  211. // ==============================================================
  212. // 自动超时触发的间隔保护(计数法)
  213. // ==============================================================
  214. always @(posedge pclk or negedge presetn) begin
  215. if (!presetn) begin
  216. gap_cnt_auto <= 11'd0;
  217. end else if (adc_restart_ris) begin
  218. gap_cnt_auto <= 11'd0;
  219. end else if (curr_state == PRE_FILL && next_state == SAMPLING) begin
  220. gap_cnt_auto <= 11'd0; // 进入SAMPLING时清零
  221. end else if (sample_valid) begin
  222. if (auto_force_trigger || edge_trigger || pulse_trigger) // 任何触发都清零
  223. gap_cnt_auto <= 11'd0;
  224. else if (curr_state == SAMPLING)
  225. gap_cnt_auto <= gap_cnt_auto + 1'b1;
  226. end
  227. end
  228. assign trig_interval_ok_auto = (curr_state == SAMPLING) && (gap_cnt_auto >= 11'd1023);
  229. // 自动触发等待计数器
  230. always @(posedge pclk or negedge presetn) begin
  231. if (!presetn) begin
  232. auto_wait_cnt <= 10'd0;
  233. end else if (adc_restart_ris) begin
  234. auto_wait_cnt <= 10'd0;
  235. end else if (curr_state == SAMPLING && sample_valid) begin
  236. if (edge_trigger) begin
  237. auto_wait_cnt <= 10'd0;
  238. end else if (trig_interval_ok_auto && trig_mode == 2'b00) begin
  239. auto_wait_cnt <= auto_wait_cnt + 1'b1;
  240. end else begin
  241. auto_wait_cnt <= auto_wait_cnt; // 保持,防绕回清零
  242. end
  243. end else if (curr_state != SAMPLING) begin
  244. auto_wait_cnt <= 10'd0;
  245. end
  246. end
  247. // 自动强制触发条件
  248. assign auto_force_trigger = (curr_state == SAMPLING) && sample_valid &&
  249. (auto_wait_cnt >= 10'd511) &&
  250. trig_interval_ok_auto && !edge_trigger && !pulse_trigger;
  251. // ==============================================================
  252. // 综合触发信号
  253. // ==============================================================
  254. assign trig_hit_comb = edge_trigger || auto_force_trigger || pulse_trigger;
  255. always @(posedge pclk or negedge presetn) begin
  256. if (!presetn)
  257. trig_hit_reg <= 1'b0;
  258. else
  259. trig_hit_reg <= trig_hit_comb;
  260. end
  261. // --------------------------- 状态机 ---------------------------
  262. always @(posedge pclk or negedge presetn) begin
  263. if (!presetn)
  264. curr_state <= IDLE;
  265. else
  266. curr_state <= next_state;
  267. end
  268. always @(*) begin
  269. next_state = curr_state;
  270. case (curr_state)
  271. IDLE: if (adc_en && adc_run && !single_shot_lock) next_state = PRE_FILL;
  272. PRE_FILL: if (!adc_en || !adc_run || single_shot_lock) next_state = IDLE;
  273. else if (sample_valid && ram_wr_addr == RAM_DEPTH - 1) next_state = SAMPLING;
  274. SAMPLING: if (!adc_en || !adc_run || single_shot_lock) next_state = IDLE;
  275. else if (trig_hit_reg) next_state = POST_TRIG;
  276. POST_TRIG: if (!adc_en) next_state = IDLE;
  277. else if (post_trig_cnt == POST_TRIG_CNT - 1) next_state = DONE;
  278. DONE: if (adc_restart_ris || !adc_en) next_state = IDLE;
  279. default: next_state = IDLE;
  280. endcase
  281. end
  282. // --------------------------- 写控制与寄存器 ---------------------------
  283. always @(posedge pclk or negedge presetn) begin
  284. if (!presetn) begin
  285. ram_wr_addr <= 10'd0;
  286. ram_wren_b <= 1'b0;
  287. ram_wr_data_b <= 16'd0;
  288. post_trig_cnt <= 9'd0;
  289. trig_done <= 1'b0;
  290. trigger_ptr <= 10'd0;
  291. single_shot_lock <= 1'b0;
  292. adc_data_prev <= 12'd0;
  293. last_trig_end_addr_edge<= 10'd0;
  294. end else if (adc_restart_ris) begin
  295. ram_wr_addr <= 10'd0;
  296. ram_wren_b <= 1'b0;
  297. post_trig_cnt <= 9'd0;
  298. trig_done <= 1'b0;
  299. trigger_ptr <= 10'd0;
  300. single_shot_lock <= 1'b0;
  301. adc_data_prev <= 12'd0;
  302. last_trig_end_addr_edge<= 10'd0;
  303. end else begin
  304. ram_wren_b <= 1'b0;
  305. // if (adc_eoc_ris && adc_en && adc_run && !single_shot_lock &&
  306. // (curr_state == PRE_FILL || curr_state == SAMPLING || curr_state == POST_TRIG)) begin
  307. // adc_data_prev <= adc_data; // 保持1µs一次的更新
  308. // end
  309. case (curr_state)
  310. PRE_FILL, SAMPLING, POST_TRIG: begin
  311. if (write_strobe) begin
  312. ram_wr_addr <= ram_wr_addr + 1'b1;
  313. ram_wren_b <= 1'b1;
  314. ram_wr_data_b <= {4'd0, adc_data};
  315. adc_data_prev <= adc_data;
  316. if (curr_state == POST_TRIG)
  317. post_trig_cnt <= post_trig_cnt + 1'b1;
  318. // 触发记录:边沿触发更新边沿专用结束地址,自动触发也更新
  319. if (curr_state == SAMPLING && (edge_trigger || auto_force_trigger || pulse_trigger)) begin
  320. trigger_ptr <= ram_wr_addr;
  321. last_trig_end_addr_edge <= (ram_wr_addr + POST_TRIG_CNT) % RAM_DEPTH;
  322. end
  323. end
  324. end
  325. DONE: begin
  326. trig_done <= 1'b1;
  327. if (trig_mode == 2'b10) begin
  328. single_shot_lock <= 1'b1;
  329. end
  330. end
  331. default: ;
  332. endcase
  333. end
  334. end
  335. // --------------------------- APB 读 ---------------------------
  336. always @(posedge pclk or negedge presetn) begin
  337. if (!presetn)
  338. prdata <= 32'd0;
  339. else if (psel && !penable && !pwrite) begin
  340. case (paddr)
  341. ADDR_TRIG_DONE: prdata <= {31'd0, trig_done};
  342. ADDR_TRIG_PTR: prdata <= {22'd0, trigger_ptr};
  343. default: prdata <= 32'd0;
  344. endcase
  345. end
  346. end
  347. endmodule