lr_start_transaction/lr_end_transaction事物组合

51Testing软件测试网a]'x4k/E0\W
    int lr_start_transaction (const char * transaction_name);
Gk"|;@Z*f9t$yna0
F:F9{rQcZ0    int lr_end_transaction (const char * transaction_name,int status);
:N3xi3yO[;e lKd|G0
g ^@B3g%d0     transacton为事物名称,status为事物的结束状态,共有LR_PASS(通过)、LR_FAIL(失败)、LR_AUTO(自动)、 LR_STOP(暂停),其中LR_PASS默认的是LR_PASS,可以在事物结束前通过lr_set_transaction_status进行修 改。如果在lr_end_transaction中没有指定结束事物状态是LR_AUTO,而是明确制定为LR_PASS、LR_FAIL、 LR_STOP其中的其中,则事物将以最后制定状态来结束。需要注意,事物开始没有lr_end_transaction没有结束的时候,不能用相同的事 物名称,除非这个事物已经通过lr_end_transaction结束。
|-d%M(Vv0       
[ Rd_+h(gDy3FmG\0    Action() {
d0br"`TT-{%m0          lr_start_transaction("test");51Testing软件测试网7N8@j%G&sO,[/jqLi
                  //事物内容///////////////////51Testing软件测试网/{\Tc/Kz\_,i
          lr_start_transaction("test");
y)kx4m SxZ0                 //事物内容/////////////////// 
q`+S6S IF-e0          lr_end_transaction("test",LR_AUTO);
7R(f4\9L1yK }051Testing软件测试网~&?b4A!dz(ET}wPx
          lr_end_transaction("test",LR_AUTO);51Testing软件测试网"U$fecG@j;h/R
             //事物内容///////////////////        51Testing软件测试网dT{0Ub]K0P
                          return 0;51Testing软件测试网sWq0d+v~,Z8Iz[G
}//没有结束的事物一定会出现错误。51Testing软件测试网ZS(g:VN!])wc_ `

"XM#s'cax$dQ8D%|W051Testing软件测试网Y#umP#eO
Action() {51Testing软件测试网8g;Rj%ezgbK
          lr_start_transaction("test");51Testing软件测试网9A:Y(O*E+ZGc9vyb4R4Ss
                  //事物内容///////////////////51Testing软件测试网gy%_ t%p9H,n |p\f
          lr_end_transaction("test",LR_AUTO);51Testing软件测试网nl XHFLzG
             51Testing软件测试网+k,@ y3m5I'Xg^H
          lr_start_transaction("test");51Testing软件测试网/[;?CJV_
                  //事物内容///////////////////
k'PZO$c#J0          lr_end_transaction("test",LR_AUTO);
WS$QG.E/fw0                     return 0;51Testing软件测试网#W5F-M A0\9rSWU
}
0a$A8PC7E0      虽然以上代码包含了两个"test"事物,但在LR的Analysis分析中将会做为一个事物来进行统计,Analysis 主要是按照事物的名称来进行系统分析,不考虑事物
B^E\9NF_w0
&BC0H)iI*k#o0语法格式如下:51Testing软件测试网a]'x4k/E0\W
    int lr_start_transaction (const char * transaction_name);
Gk"|;@Z*f9t$yna0
F:F9{rQcZ0    int lr_end_transaction (const char * transaction_name,int status);
:N3xi3yO[;e lKd|G0
g ^@B3g%d0     transacton为事物名称,status为事物的结束状态,共有LR_PASS(通过)、LR_FAIL(失败)、LR_AUTO(自动)、 LR_STOP(暂停),其中LR_PASS默认的是LR_PASS,可以在事物结束前通过lr_set_transaction_status进行修 改。如果在lr_end_transaction中没有指定结束事物状态是LR_AUTO,而是明确制定为LR_PASS、LR_FAIL、 LR_STOP其中的其中,则事物将以最后制定状态来结束。需要注意,事物开始没有lr_end_transaction没有结束的时候,不能用相同的事 物名称,除非这个事物已经通过lr_end_transaction结束。
|-d%M(Vv0       
[ Rd_+h(gDy3FmG\0    Action() {
d0br"`TT-{%m0          lr_start_transaction("test");51Testing软件测试网7N8@j%G&sO,[/jqLi
                  //事物内容///////////////////51Testing软件测试网/{\Tc/Kz\_,i
          lr_start_transaction("test");
y)kx4m SxZ0                 //事物内容/////////////////// 
q`+S6S IF-e0          lr_end_transaction("test",LR_AUTO);
7R(f4\9L1yK }051Testing软件测试网~&?b4A!dz(ET}wPx
          lr_end_transaction("test",LR_AUTO);51Testing软件测试网"U$fecG@j;h/R
             //事物内容///////////////////        51Testing软件测试网dT{0Ub]K0P
                          return 0;51Testing软件测试网sWq0d+v~,Z8Iz[G
}//没有结束的事物一定会出现错误。51Testing软件测试网ZS(g:VN!])wc_ `

"XM#s'cax$dQ8D%|W051Testing软件测试网Y#umP#eO
Action() {51Testing软件测试网8g;Rj%ezgbK
          lr_start_transaction("test");51Testing软件测试网9A:Y(O*E+ZGc9vyb4R4Ss
                  //事物内容///////////////////51Testing软件测试网gy%_ t%p9H,n |p\f
          lr_end_transaction("test",LR_AUTO);51Testing软件测试网nl XHFLzG
             51Testing软件测试网+k,@ y3m5I'Xg^H
          lr_start_transaction("test");51Testing软件测试网/[;?CJV_
                  //事物内容///////////////////
k'PZO$c#J0          lr_end_transaction("test",LR_AUTO);
WS$QG.E/fw0                     return 0;51Testing软件测试网#W5F-M A0\9rSWU
}
0a$A8PC7E0      虽然以上代码包含了两个"test"事物,但在LR的Analysis分析中将会做为一个事物来进行统计,Analysis 主要是按照事物的名称来进行系统分析,不考虑事物具体包含的操作。

Action() { //提前token web_reg_save_param_ex( "ParamName=token", "LB=\"token\":\"",//修正左边界 "RB=\"", SEARCH_FILTERS, LAST); //登录 web_custom_request("login", "URL=http://192.168.1.250:10003/gkgsbg_sz/login", "Method=POST", "Resource=0", "RecContentType=application/json", "Referer=http://192.168.1.250:10003/gkgsbg/", "Snapshot=t2.inf", "Mode=HTML", "EncType=application/json", "Body={\"username\":\"{name}\",\"password\":\"{pwd}\"}", LAST); //lr_output_message("获取的token:%s",lr_eval_string("{token}")); //查询操作检查点 web_reg_save_param_ex( "ParamName=msg", "LB=\"msg\":\"", "RB=\"", SEARCH_FILTERS, LAST); //开始事物 lr_start_transaction("CX"); //添加认证头 web_add_header("Authorization",lr_eval_string("Bearer {token}")); //公式库查询 web_custom_request("list_3", "URL=http://192.168.1.250:10003/gkgsbg_sz/gkgsGskInfo/list?pageNum=1&pageSize=20", "Method=POST", "Resource=0", "RecContentType=application/json", "Referer=http://192.168.1.250:10003/gkgsbg/", "Snapshot=t9.inf", "Mode=HTML", "EncType=application/json", "Body={\"kssj\":[],\"jssj\":[],\"name\":\"{GSMC}\"}", LAST); web_cleanup_header(); //lr_output_message("服务器返回消息:%s",lr_eval_string("{msg}")); //结束事物 lr_end_transaction("CX",LR_AUTO); return 0; } Action.c(38): 警告 -26593: 将添加的标头应用于生成的所有代表下一个脚本函数的 URL 时,可能会导致不可预测的结果。它只适用于主 URL。 [MsgId: MWAR-26593] Action.c(38): web_add_header("Authorization") 最高严重级别为“warning” [MsgId: MMSG-26391] Action.c(41): web_custom_request("list_3") 已启动 [MsgId: MMSG-26355] Action.c(41): 通知: 参数替换:参数“GSMC”=“木渎分区调度负荷” Action.c(41): 通知: 正在保存参数“msg = 查询成功”。 Action.c(41): web_custom_request("list_3") 已成功,2149 个正文字节,424 个标头字节,12 个分块开销字节 [MsgId: MMSG-26385] Action.c(52): 错误: C 解释器运行时间错误: Action.c (52): Error -- Unresolved symbol : web_cleanup_header。
最新发布
08-13
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // 模块名称: ad7606_top // 功能: 顶层模块,集成 AD7606 控制, OLED 显示和 UART 通信. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ module ad7606_top( input wire clk_50m, input wire rst_n, input wire busy, input wire frstdata, input wire [15:0] data_bus, output wire convst, output wire rd_n, output wire cs_n, output wire [2:0] os, output wire range_ad, // "range" 是Verilog关键字, 已重命名 output wire reset_ad, output wire [2:0] mux_addr, output wire mux_en, output wire oled_sclk, output wire oled_mosi, output wire oled_res, output wire oled_dc, output wire oled_cs, output wire uart_tx_pin, // UART 发送引脚 output wire led_sampling_busy ); wire [3:0] ctrl_reg_ad_top = {1'b0, 3'b000}; // 重命名以避免与 ad7606_ctrl 内部的 ctrl_reg 混淆 wire signed [15:0] ch1_data_raw; wire signed [15:0] ch2_data_raw; wire signed [15:0] ch3_data_raw; wire signed [15:0] ch4_data_raw; wire signed [15:0] ch5_data_raw; wire signed [15:0] ch6_data_raw; wire signed [15:0] ch7_data_raw; wire signed [15:0] ch8_data_raw; wire data_vld_from_adc_ctrl; wire ctrl_mode_busy; ad7606_ctrl u_ad7606_ctrl ( .clk (clk_50m), .rst_n (rst_n), .ctrl_reg (ctrl_reg_ad_top), .busy (busy), .frstdata (frstdata), .data_bus (data_bus), .os (os), .range (range_ad), .convst_a (convst), .convst_b (), .reset (reset_ad), .rd_n (rd_n), .cs_n (cs_n), .mux_addr (mux_addr), .mux_en (mux_en), .ch1_data (ch1_data_raw), .ch2_data (ch2_data_raw), .ch3_data (ch3_data_raw), .ch4_data (ch4_data_raw), .ch5_data (ch5_data_raw), .ch6_data (ch6_data_raw), .ch7_data (ch7_data_raw), .ch8_data (ch8_data_raw), .mode_busy(ctrl_mode_busy), .data_vld (data_vld_from_adc_ctrl), .led_sampling_busy_blink (led_sampling_busy) ); // 修改OLED驱动模块连接,传递ADC数据 oled_096inch_driver u_oled_driver ( .clk (clk_50m), .rst_n (rst_n), .ch1_data (ch1_data_raw), .ch2_data (ch2_data_raw), .ch3_data (ch3_data_raw), .ch4_data (ch4_data_raw), .ch5_data (ch5_data_raw), .ch6_data (ch6_data_raw), .ch7_data (ch7_data_raw), .ch8_data (ch8_data_raw), .data_valid (data_vld_from_adc_ctrl), .oled_sclk (oled_sclk), .oled_mosi (oled_mosi), .oled_res (oled_res), .oled_dc (oled_dc), .oled_cs (oled_cs) ); // --- UART 逻辑 --- localparam CLK_FREQ_UART = 50_000_000; // 为UART参数使用不同的名称 localparam BAUD_RATE_UART = 115200; localparam UART_CLK_DIV_RATIO_UART = 16; localparam BAUD_CLK_MAX_COUNT_UART = CLK_FREQ_UART / (BAUD_RATE_UART * UART_CLK_DIV_RATIO_UART) - 1 ; reg [$clog2(BAUD_CLK_MAX_COUNT_UART+1)-1:0] baud_clk_counter_uart; wire uart_tick; always @(posedge clk_50m or negedge rst_n) begin if (!rst_n) baud_clk_counter_uart <= 0; else if (baud_clk_counter_uart == BAUD_CLK_MAX_COUNT_UART) baud_clk_counter_uart <= 0; else baud_clk_counter_uart <= baud_clk_counter_uart + 1; end assign uart_tick = (baud_clk_counter_uart == BAUD_CLK_MAX_COUNT_UART); wire uart_tx_busy_signal; reg [7:0] uart_data_to_send; reg uart_start_tx_pulse_signal; uart_tx_module u_uart_tx ( .clk(clk_50m), .rst_n(rst_n), .clk_enable(uart_tick), .data_in(uart_data_to_send), .start_tx(uart_start_tx_pulse_signal), .tx_busy(uart_tx_busy_signal), .tx_serial_out(uart_tx_pin) ); reg signed [15:0] adc_data_uart_buffer [7:0]; reg data_ready_for_uart_tx; always @(posedge clk_50m or negedge rst_n) begin if (!rst_n) data_ready_for_uart_tx <= 1'b0; else if (data_vld_from_adc_ctrl) begin adc_data_uart_buffer[0] <= ch1_data_raw; adc_data_uart_buffer[1] <= ch2_data_raw; adc_data_uart_buffer[2] <= ch3_data_raw; adc_data_uart_buffer[3] <= ch4_data_raw; adc_data_uart_buffer[4] <= ch5_data_raw; adc_data_uart_buffer[5] <= ch6_data_raw; adc_data_uart_buffer[6] <= ch7_data_raw; adc_data_uart_buffer[7] <= ch8_data_raw; data_ready_for_uart_tx <= 1'b1; end else if (uart_tx_state == S_UART_TX_DONE_TOP) data_ready_for_uart_tx <= 1'b0; end localparam S_UART_TX_IDLE_TOP = 3'd0; localparam S_UART_TX_START_FRAME_TOP = 3'd1; localparam S_UART_TX_SEND_HIGH_BYTE_TOP = 3'd2; localparam S_UART_TX_SEND_LOW_BYTE_TOP = 3'd3; localparam S_UART_TX_NEXT_CHANNEL_TOP = 3'd4; localparam S_UART_TX_END_FRAME_TOP = 3'd5; localparam S_UART_TX_DONE_TOP = 3'd6; localparam S_UART_TX_WAIT_BUSY_LOW_TOP = 3'd7; reg [2:0] uart_tx_state_prev_top; reg [2:0] uart_tx_state; reg [2:0] current_uart_channel_idx_top; always @(posedge clk_50m or negedge rst_n) begin if (!rst_n) begin uart_tx_state <= S_UART_TX_IDLE_TOP; current_uart_channel_idx_top <= 3'd0; uart_data_to_send <= 8'd0; uart_start_tx_pulse_signal <= 1'b0; uart_tx_state_prev_top <= S_UART_TX_IDLE_TOP; end else begin uart_start_tx_pulse_signal <= 1'b0; case (uart_tx_state) S_UART_TX_IDLE_TOP: if (data_ready_for_uart_tx && !uart_tx_busy_signal) begin current_uart_channel_idx_top <= 3'd0; uart_tx_state <= S_UART_TX_START_FRAME_TOP; end S_UART_TX_START_FRAME_TOP: if (!uart_tx_busy_signal) begin uart_data_to_send <= 8'hAA; uart_start_tx_pulse_signal <= 1'b1; uart_tx_state_prev_top <= S_UART_TX_SEND_HIGH_BYTE_TOP; uart_tx_state <= S_UART_TX_WAIT_BUSY_LOW_TOP; end S_UART_TX_SEND_HIGH_BYTE_TOP: if (!uart_tx_busy_signal) begin uart_data_to_send <= adc_data_uart_buffer[current_uart_channel_idx_top][15:8]; uart_start_tx_pulse_signal <= 1'b1; uart_tx_state_prev_top <= S_UART_TX_SEND_LOW_BYTE_TOP; uart_tx_state <= S_UART_TX_WAIT_BUSY_LOW_TOP; end S_UART_TX_SEND_LOW_BYTE_TOP: if (!uart_tx_busy_signal) begin uart_data_to_send <= adc_data_uart_buffer[current_uart_channel_idx_top][7:0]; uart_start_tx_pulse_signal <= 1'b1; uart_tx_state_prev_top <= S_UART_TX_NEXT_CHANNEL_TOP; uart_tx_state <= S_UART_TX_WAIT_BUSY_LOW_TOP; end S_UART_TX_NEXT_CHANNEL_TOP: if (current_uart_channel_idx_top < 7) begin current_uart_channel_idx_top <= current_uart_channel_idx_top + 1; uart_tx_state <= S_UART_TX_SEND_HIGH_BYTE_TOP; end else uart_tx_state <= S_UART_TX_END_FRAME_TOP; S_UART_TX_END_FRAME_TOP: if (!uart_tx_busy_signal) begin uart_data_to_send <= 8'h55; uart_start_tx_pulse_signal <= 1'b1; uart_tx_state_prev_top <= S_UART_TX_DONE_TOP; uart_tx_state <= S_UART_TX_WAIT_BUSY_LOW_TOP; end S_UART_TX_DONE_TOP: uart_tx_state <= S_UART_TX_IDLE_TOP; S_UART_TX_WAIT_BUSY_LOW_TOP: if (!uart_tx_busy_signal) uart_tx_state <= uart_tx_state_prev_top; default: uart_tx_state <= S_UART_TX_IDLE_TOP; endcase end end endmodule//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // 模块名称: ad7606_ctrl // 功能: 控制 AD7606 ADC 和 ADG408 MUX 进行差分测量。 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ module ad7606_ctrl ( input clk, input rst_n, input [3:0] ctrl_reg, input busy, input frstdata, input [15:0] data_bus, output [2:0] os, output range, output reg convst_a, output reg convst_b, output reg reset, output reg rd_n, output reg cs_n, output reg [2:0] mux_addr, output reg mux_en, output reg signed [15:0] ch1_data, output reg signed [15:0] ch2_data, output reg signed [15:0] ch3_data, output reg signed [15:0] ch4_data, output reg signed [15:0] ch5_data, output reg signed [15:0] ch6_data, output reg signed [15:0] ch7_data, output reg signed [15:0] ch8_data, output reg mode_busy, output reg data_vld, output reg led_sampling_busy_blink ); parameter DATA_W = 16; parameter RD_LOW_CYCLES = 2; parameter DATA_VALID_CYCLE = 1; parameter RD_HIGH_CYCLES = 1; parameter MUX_SETTLE_CYCLES = 10; localparam [3:0] S_IDLE = 4'b0000; localparam [3:0] S_RESET_ADC = 4'b0001; localparam [3:0] S_SET_MUX = 4'b0010; localparam [3:0] S_MUX_SETTLE = 4'b0011; localparam [3:0] S_START_CONV = 4'b0100; localparam [3:0] S_WAIT_CONV_FINISH = 4'b0101; localparam [3:0] S_READ_START = 4'b0110; localparam [3:0] S_READ_RD_LOW = 4'b0111; localparam [3:0] S_READ_RD_HIGH = 4'b1000; localparam [3:0] S_READ_NEXT_CH = 4'b1001; localparam [3:0] S_READ_END = 4'b1010; localparam [3:0] S_CALC_DIFF = 4'b1011; localparam [3:0] S_CHECK_DONE = 4'b1100; localparam [3:0] S_FINISH = 4'b1101; reg [3:0] current_state, next_state; reg reset_pulse_done; always @(posedge clk or negedge rst_n) begin if (!rst_n) begin reset_pulse_done <= 1'b0; end else if (current_state == S_RESET_ADC) begin reset_pulse_done <= 1'b1; end end reg busy_ff0, busy_ff1; wire busy_falling_edge; always @(posedge clk or negedge rst_n) begin if (!rst_n) begin busy_ff0 <= 1'b1; busy_ff1 <= 1'b1; end else begin busy_ff0 <= busy; busy_ff1 <= busy_ff0; end end assign busy_falling_edge = busy_ff1 && !busy_ff0; assign os = ctrl_reg[2:0]; assign range = ctrl_reg[3]; reg [2:0] current_mux_channel; reg [7:0] cnt_mux_settle; reg start_conv_pulse; reg [3:0] cnt_rd_adc_channel; reg [7:0] cnt_rd_timing; reg [DATA_W-1:0] temp_ch_A_data; reg [DATA_W-1:0] temp_ch_B_data; reg signed [DATA_W-1:0] diff_results [7:0]; always @(posedge clk or negedge rst_n) begin if (!rst_n) begin current_state <= S_IDLE; end else begin current_state <= next_state; end end always @(*) begin next_state = current_state; start_conv_pulse = 1'b0; convst_a = 1'b1; convst_b = 1'b1; cs_n = 1'b1; rd_n = 1'b1; reset = 1'b0; mux_en = mux_en; mux_addr = mux_addr; data_vld = 1'b0; mode_busy = mode_busy; case (current_state) S_IDLE: begin mode_busy = 1'b0; mux_en = 1'b0; if (!reset_pulse_done) begin next_state = S_RESET_ADC; end else begin next_state = S_SET_MUX; current_mux_channel = 3'd0; mode_busy = 1'b1; end end S_RESET_ADC: begin reset = 1'b1; next_state = S_IDLE; end S_SET_MUX: begin mux_addr = current_mux_channel; mux_en = 1'b1; cnt_mux_settle = {8{1'b0}}; next_state = S_MUX_SETTLE; end S_MUX_SETTLE: begin mux_en = 1'b1; if (cnt_mux_settle < MUX_SETTLE_CYCLES - 1) begin cnt_mux_settle = cnt_mux_settle + 1'b1; next_state = S_MUX_SETTLE; end else begin next_state = S_START_CONV; end end S_START_CONV: begin mux_en = 1'b1; start_conv_pulse = 1'b1; next_state = S_WAIT_CONV_FINISH; end S_WAIT_CONV_FINISH: begin mux_en = 1'b1; if (busy_falling_edge) begin next_state = S_READ_START; end else begin next_state = S_WAIT_CONV_FINISH; end end S_READ_START: begin mux_en = 1'b1; cs_n = 1'b0; rd_n = 1'b1; cnt_rd_adc_channel = 4'd0; cnt_rd_timing = 8'd0; next_state = S_READ_RD_LOW; end S_READ_RD_LOW: begin mux_en = 1'b1; cs_n = 1'b0; rd_n = 1'b0; if (cnt_rd_timing < RD_LOW_CYCLES - 1) begin cnt_rd_timing = cnt_rd_timing + 1'b1; next_state = S_READ_RD_LOW; end else begin cnt_rd_timing = 8'd0; next_state = S_READ_RD_HIGH; end end S_READ_RD_HIGH: begin mux_en = 1'b1; cs_n = 1'b0; rd_n = 1'b1; if (cnt_rd_timing < RD_HIGH_CYCLES - 1) begin cnt_rd_timing = cnt_rd_timing + 1'b1; next_state = S_READ_RD_HIGH; end else begin next_state = S_READ_NEXT_CH; end end S_READ_NEXT_CH: begin mux_en = 1'b1; cs_n = 1'b0; rd_n = 1'b1; if (cnt_rd_adc_channel < 7) begin cnt_rd_adc_channel = cnt_rd_adc_channel + 1'b1; cnt_rd_timing = 8'd0; next_state = S_READ_RD_LOW; end else begin next_state = S_READ_END; end end S_READ_END: begin mux_en = 1'b1; cs_n = 1'b1; rd_n = 1'b1; next_state = S_CALC_DIFF; end S_CALC_DIFF: begin mux_en = 1'b1; diff_results[current_mux_channel] = $signed(temp_ch_A_data) - $signed(temp_ch_B_data); next_state = S_CHECK_DONE; end S_CHECK_DONE: begin mux_en = 1'b1; if (current_mux_channel < 7) begin current_mux_channel = current_mux_channel + 1'b1; next_state = S_SET_MUX; end else begin next_state = S_FINISH; end end S_FINISH: begin mux_en = 1'b0; data_vld = 1'b1; mode_busy = 1'b0; ch1_data = diff_results[0]; ch2_data = diff_results[1]; ch3_data = diff_results[2]; ch4_data = diff_results[3]; ch5_data = diff_results[4]; ch6_data = diff_results[5]; ch7_data = diff_results[6]; ch8_data = diff_results[7]; next_state = S_IDLE; end default: begin next_state = S_IDLE; start_conv_pulse = 1'b0; convst_a = 1'b1; convst_b = 1'b1; cs_n = 1'b1; rd_n = 1'b1; reset = 1'b0; mux_en = 1'b0; data_vld = 1'b0; mode_busy = 1'b0; end endcase if (start_conv_pulse) begin convst_a = 1'b0; convst_b = 1'b0; end else begin convst_a = 1'b1; convst_b = 1'b1; end end wire capture_data = (current_state == S_READ_RD_HIGH) && (cnt_rd_timing == 0); always @(posedge clk or negedge rst_n) begin if (!rst_n) begin temp_ch_A_data <= {DATA_W{1'b0}}; temp_ch_B_data <= {DATA_W{1'b0}}; end else if (capture_data) begin if (cnt_rd_adc_channel == 4'd0) begin temp_ch_A_data <= data_bus; end else if (cnt_rd_adc_channel == 4'd1) begin temp_ch_B_data <= data_bus; end end end parameter BLINK_RATE_DIV_BITS = 25; reg [BLINK_RATE_DIV_BITS-1:0] led_blink_cnt; always @(posedge clk or negedge rst_n) begin if (!rst_n) begin led_blink_cnt <= {BLINK_RATE_DIV_BITS{1'b0}}; led_sampling_busy_blink <= 1'b0; end else if (mode_busy) begin led_blink_cnt <= led_blink_cnt + 1'b1; led_sampling_busy_blink <= led_blink_cnt[BLINK_RATE_DIV_BITS-1]; end else begin led_blink_cnt <= {BLINK_RATE_DIV_BITS{1'b0}}; led_sampling_busy_blink <= 1'b0; end end endmodulemodule oled_096inch_driver ( input wire clk, input wire rst_n, // 输入数据接口 (当前代码未使用 prepare_display_buffer 中的实际数据) input wire signed [15:0] ch1_data, input wire signed [15:0] ch2_data, input wire signed [15:0] ch3_data, input wire signed [15:0] ch4_data, input wire signed [15:0] ch5_data, input wire signed [15:0] ch6_data, input wire signed [15:0] ch7_data, input wire signed [15:0] ch8_data, input wire data_valid, // ADC 数据有效信号 // OLED 接口 output reg oled_sclk, output reg oled_mosi, output reg oled_res, output reg oled_dc, output reg oled_cs ); // 参数定义 localparam INIT_DELAY_COUNT = 24'd1000000; // 20ms @ 50MHz localparam RESET_DELAY_COUNT = 24'd250000; // 5ms @ 50MHz localparam SPI_CLK_DIV = 8'd100; // SPI时钟分频 (50MHz / (50+1) ~= 1MHz) localparam SPI_DELAY_VAL = 6'd50; // *** 增加 SPI字节后延时值 *** // OLED状态机状态 - 使用中间状态简化逻辑 localparam S_INIT_DELAY = 5'd0; // 使用5位以容纳中间状态 localparam S_RESET_OLED = 5'd1; localparam S_INIT_OLED = 5'd2; // Clear Screen States localparam S_CLEAR_SET_PAGE = 5'd3; localparam S_CLEAR_SET_COL_L = 5'd4; localparam S_CLEAR_SET_COL_H = 5'd5; localparam S_CLEAR_SEND_DATA = 5'd6; localparam S_CLEAR_INC_COL = 5'd7; // Display States localparam S_DISP_SET_PAGE = 5'd8; localparam S_DISP_SET_COL_L = 5'd9; localparam S_DISP_SET_COL_H = 5'd10; localparam S_DISP_SEND_DATA = 5'd11; localparam S_DISP_INC_COL = 5'd12; // Common States localparam S_DISPLAY_DONE = 5'd13; // Frame finished localparam S_WAIT_SPI_IDLE = 5'd14; // Wait for SPI transaction end // SPI状态机状态 localparam SPI_IDLE = 3'd0; localparam SPI_TRANSMIT = 3'd1; localparam SPI_DONE = 3'd2; localparam SPI_POST_DELAY = 3'd3; // 寄存器定义 reg [4:0] oled_state; // OLED 主状态机状态 (5位) reg [4:0] oled_state_next; // 用于 WAIT_SPI_IDLE 后跳转 reg [2:0] spi_state; // SPI 状态机状态 reg [7:0] spi_data; // 要发送的 SPI 数据 reg [3:0] spi_bit_count; // SPI 位计数 reg [7:0] cmd_index; // 初始化命令索引 reg [2:0] page_addr; // 当前页地址 (0-7) reg [7:0] col_addr; // 当前列地址 (0-127) reg [23:0] delay_count; // 通用延时计数器 reg [2:0] channel_index; // 当前显示的通道索引 (用于测试图案) reg spi_start; // SPI 启动请求信号 (单周期脉冲) reg spi_request_latch; // SPI 启动请求锁存 (确保请求不丢失) reg spi_busy; // SPI 忙信号 (包括字节后延时) reg is_command; // 标记 spi_data 是命令(1)还是数据(0) reg [7:0] display_buffer[0:127]; // 简单的单页显示缓冲区 (8KB) reg [7:0] spi_clk_div_cnt; // SPI 时钟分频计数器 reg [5:0] spi_delay_cnt; // SPI 字节后延时计数器 // 输入数据存储 (当前未使用,仅用于未来扩展) reg signed [15:0] stored_adc_data [0:7]; reg data_updated; // 标志是否有新的 ADC 数据进来 reg [19:0] display_timer; // 用于轮流显示不同通道数据 (测试用) // SPI时钟分频逻辑 always @(posedge clk or negedge rst_n) begin if (!rst_n) spi_clk_div_cnt <= 8'd0; else spi_clk_div_cnt <= (spi_clk_div_cnt >= SPI_CLK_DIV) ? 8'd0 : spi_clk_div_cnt + 1'b1; end wire spi_clk_en = (spi_clk_div_cnt == SPI_CLK_DIV); // SPI 时钟使能信号 // 初始化命令序列 (共25条) reg [7:0] init_commands [0:24]; initial begin init_commands[ 0] = 8'hAE; // Display off init_commands[ 1] = 8'hD5; // Set display clock divide init_commands[ 2] = 8'h80; // Suggested ratio init_commands[ 3] = 8'hA8; // Set multiplex ratio init_commands[ 4] = 8'h3F; // 1/64 duty init_commands[ 5] = 8'hD3; // Set display offset init_commands[ 6] = 8'h00; // No offset init_commands[ 7] = 8'h40; // Set display start line (0) init_commands[ 8] = 8'h8D; // Charge pump setting init_commands[ 9] = 8'h14; // Enable charge pump init_commands[10] = 8'h20; // Set Memory Addressing Mode init_commands[11] = 8'h00; // Horizontal Addressing Mode (might need 0x01 for Vertical or 0x02 for Page) -> Let's stick to Page Addressing Mode (0x02) for this driver // Correcting Memory Addressing Mode to Page Addressing Mode init_commands[10] = 8'h20; // Set Memory Addressing Mode command init_commands[11] = 8'h02; // Page Addressing Mode ( crucial for B0-B7 commands) init_commands[12] = 8'hA0; // Segment remap (尝试正常映射) init_commands[13] = 8'hC0; // COM output scan direction (尝试正常扫描) init_commands[14] = 8'hDA; // Set COM pins hardware configuration init_commands[15] = 8'h12; // Alternative COM pin config / Sequential COM pin config init_commands[16] = 8'h81; // Contrast control init_commands[17] = 8'hCF; // Contrast value (try different values if needed) init_commands[18] = 8'hD9; // Set pre-charge period init_commands[19] = 8'hF1; // Precharge period init_commands[20] = 8'hDB; // Set VCOMH deselect level init_commands[21] = 8'h40; // VCOMH level (~0.77 Vcc) init_commands[22] = 8'hA4; // Entire display ON from RAM (disable force on) init_commands[23] = 8'hA6; // Normal display (A7=inverse) init_commands[24] = 8'hAF; // Display on end // ADC 数据锁存逻辑 (当 data_valid 有效时锁存) always @(posedge clk or negedge rst_n) begin if (!rst_n) begin stored_adc_data[0] <= 16'd0; stored_adc_data[1] <= 16'd0; stored_adc_data[2] <= 16'd0; stored_adc_data[3] <= 16'd0; stored_adc_data[4] <= 16'd0; stored_adc_data[5] <= 16'd0; stored_adc_data[6] <= 16'd0; stored_adc_data[7] <= 16'd0; data_updated <= 1'b0; end else if (data_valid) begin // 当 ADC 数据有效时锁存 stored_adc_data[0] <= ch1_data; stored_adc_data[1] <= ch2_data; stored_adc_data[2] <= ch3_data; stored_adc_data[3] <= ch4_data; stored_adc_data[4] <= ch5_data; stored_adc_data[5] <= ch6_data; stored_adc_data[6] <= ch7_data; stored_adc_data[7] <= ch8_data; data_updated <= 1'b1; // 设置更新标志 end else begin data_updated <= 1'b0; // 清除更新标志 end end // 轮流显示通道计时器 (用于 prepare_display_buffer 中的测试图案切换) always @(posedge clk or negedge rst_n) begin if (!rst_n) begin display_timer <= 20'd0; channel_index <= 3'd0; end else if (oled_state == S_DISPLAY_DONE) begin // 只在每帧完成后切换 if (display_timer >= 20'd500000) begin // ~10ms @ 50MHz 更新一次图案 display_timer <= 20'd0; channel_index <= (channel_index == 3'd7) ? 3'd0 : channel_index + 1'b1; end else begin display_timer <= display_timer + 1'b1; end end else begin display_timer <= 20'd0; // 在其他状态重置计时器 end end // 准备显示缓冲区 - 使用测试图案 task prepare_display_buffer; integer i; begin // *** 简化测试: 将整个缓冲区填充为静态值 0xFF *** for (i = 0; i < 128; i = i + 1) begin display_buffer[i] = 8'hFF; // 或者 8'hAA, 8'h55 end $display("Filled display buffer with static test pattern (0xFF)."); end endtask // SPI 通信状态机 - 带字节后延时 always @(posedge clk or negedge rst_n) begin if (!rst_n) begin spi_state <= SPI_IDLE; spi_bit_count <= 4'd0; spi_busy <= 1'b0; oled_cs <= 1'b1; oled_dc <= 1'b1; // D/C 空闲时状态不重要,会在启动时设置 oled_sclk <= 1'b1; // SPI Mode 0: CPOL=0, CPHA=0. SCLK空闲时为低,但设为高也可以 oled_mosi <= 1'b0; spi_request_latch <= 1'b0; spi_delay_cnt <= 5'd0; end else begin // 锁存 spi_start 请求 if (spi_start && spi_state == SPI_IDLE && !spi_request_latch) begin spi_request_latch <= 1'b1; end case (spi_state) SPI_IDLE: begin oled_sclk <= 1'b1; // 保持 SCLK 高电平(或低电平,取决于偏好) oled_cs <= 1'b1; // 保持 CS 高电平 spi_busy <= 1'b0; // SPI 空闲 if (spi_request_latch) begin // 如果有锁存的请求 spi_state <= SPI_TRANSMIT; spi_bit_count <= 4'd0; spi_busy <= 1'b1; // 设置 SPI 忙 oled_cs <= 1'b0; // 拉低 CS oled_dc <= !is_command; // 设置 D/C (0=CMD, 1=DATA) oled_sclk <= 1'b1; // 确保 SCLK 在第一个下降沿前为高 spi_request_latch <= 1'b0; // 清除锁存请求 // 第一个数据位在 TRANSMIT 状态的第一个 spi_clk_en 时钟周期发送 end end SPI_TRANSMIT: begin // SPI Mode 0: 数据在上升沿采样,下降沿改变 if (spi_clk_en) begin // 仅在 SPI 时钟使能时动作 if (spi_bit_count < 4'd8) begin if (oled_sclk) begin // SCLK 为高 -> 拉低 SCLK, 改变 MOSI oled_sclk <= 1'b0; oled_mosi <= spi_data[7-spi_bit_count]; end else begin // SCLK 为低 -> 拉高 SCLK (此时从设备采样 MOSI) oled_sclk <= 1'b1; spi_bit_count <= spi_bit_count + 1'b1; // 增加位计数 end end else begin // 8位已发送 (在第8个上升沿之后) oled_sclk <= 1'b1; // 确保 SCLK 在 CS 变高前为高 spi_state <= SPI_DONE; end end else if (!oled_sclk && spi_bit_count < 4'd8) begin // 如果 SCLK 为低且 spi_clk_en 无效,保持低电平 oled_sclk <= 1'b0; end else begin // 如果 SCLK 为高且 spi_clk_en 无效,保持高电平 oled_sclk <= 1'b1; end end SPI_DONE: begin // SPI 传输完成,进入字节后延时 oled_cs <= 1'b1; // 拉高 CS oled_sclk <= 1'b1; // 保持 SCLK 高电平 spi_delay_cnt <= 5'd0; // 复位延时计数器 spi_state <= SPI_POST_DELAY; // spi_busy 保持为高 end SPI_POST_DELAY: begin // 字节发送后的延时 oled_cs <= 1'b1; // 保持 CS 高 oled_sclk <= 1'b1; // 保持 SCLK 高 if (spi_delay_cnt < SPI_DELAY_VAL) begin spi_delay_cnt <= spi_delay_cnt + 1'b1; // 计数 end else begin spi_busy <= 1'b0; // 延时结束,SPI 真正空闲 spi_state <= SPI_IDLE; end end default: spi_state <= SPI_IDLE; endcase end end // OLED 控制状态机 (使用简化逻辑) always @(posedge clk or negedge rst_n) begin if (!rst_n) begin oled_state <= S_INIT_DELAY; oled_state_next <= S_INIT_DELAY; // 初始化跳转状态 delay_count <= 24'd0; cmd_index <= 8'd0; page_addr <= 3'd0; // 页地址是 3 位 col_addr <= 8'd0; spi_start <= 1'b0; is_command <= 1'b0; // 默认值 spi_data <= 8'd0; oled_res <= 1'b0; // 复位有效 end else begin spi_start <= 1'b0; // 默认每周期清零 spi_start case (oled_state) S_INIT_DELAY: begin // 上电延时 oled_res <= 1'b0; // 保持复位 if (delay_count < INIT_DELAY_COUNT) begin delay_count <= delay_count + 1'b1; end else begin delay_count <= 24'd0; oled_res <= 1'b1; // 释放复位 oled_state <= S_RESET_OLED; end end S_RESET_OLED: begin // 复位后延时 oled_res <= 1'b1; // 保持复位无效 if (delay_count < RESET_DELAY_COUNT) begin delay_count <= delay_count + 1'b1; end else begin delay_count <= 24'd0; cmd_index <= 8'd0; // 准备发送初始化命令 oled_state <= S_INIT_OLED; end end S_INIT_OLED: begin // 发送初始化命令序列 if (!spi_busy) begin // 等待 SPI 空闲 if (cmd_index >= 25) begin // 所有初始化命令发送完毕 cmd_index <= 8'd0; // 重置索引 page_addr <= 3'd0; col_addr <= 8'd0; oled_state <= S_CLEAR_SET_PAGE; // 跳转到清屏状态 $display("OLED Initialization Complete. Starting Clear Screen."); end else begin // 发送下一条初始化命令 spi_data <= init_commands[cmd_index]; is_command <= 1'b1; // 这是命令 spi_start <= 1'b1; // 请求 SPI 发送 oled_state_next <= S_INIT_OLED; // 完成后回到这里继续发送下一条 oled_state <= S_WAIT_SPI_IDLE; // 等待 SPI 完成 cmd_index <= cmd_index + 1'b1; // 准备下一条命令的索引 end end // else: 保持当前状态,等待 spi_busy 变低 end // --- 清屏流程 --- S_CLEAR_SET_PAGE: begin // 1. 设置页地址 if (!spi_busy) begin if (page_addr < 8) begin spi_data <= 8'hB0 | page_addr; // B0-B7 命令 is_command <= 1'b1; spi_start <= 1'b1; oled_state_next <= S_CLEAR_SET_COL_L; // 下一步: 设置列低位 oled_state <= S_WAIT_SPI_IDLE; end else begin // 所有页已清空 page_addr <= 3'd0; // 重置页地址 col_addr <= 8'd0; // 重置列地址 prepare_display_buffer(); // 准备第一帧显示内容 oled_state <= S_DISP_SET_PAGE; // 跳转到显示流程 $display("Clear Screen Complete. Starting Display."); end end end S_CLEAR_SET_COL_L: begin // 2. 设置列地址低位 (0x00) if (!spi_busy) begin spi_data <= 8'h00; is_command <= 1'b1; spi_start <= 1'b1; oled_state_next <= S_CLEAR_SET_COL_H; // 下一步: 设置列高位 oled_state <= S_WAIT_SPI_IDLE; end end S_CLEAR_SET_COL_H: begin // 3. 设置列地址高位 (0x10) if (!spi_busy) begin spi_data <= 8'h10; is_command <= 1'b1; spi_start <= 1'b1; col_addr <= 8'd0; // 重置列计数器,准备发送数据 oled_state_next <= S_CLEAR_SEND_DATA; // 下一步: 发送清屏数据 oled_state <= S_WAIT_SPI_IDLE; end end S_CLEAR_SEND_DATA: begin // 4. 发送清屏数据 (0x00) if (!spi_busy) begin if (col_addr < 128) begin spi_data <= 8'h00; // 发送数据 0 is_command <= 1'b0; // 这是数据 spi_start <= 1'b1; oled_state_next <= S_CLEAR_INC_COL; // 下一步: 增加列计数 oled_state <= S_WAIT_SPI_IDLE; end else begin // 当前页的128字节发送完毕 page_addr <= page_addr + 1'b1; // 移动到下一页 oled_state <= S_CLEAR_SET_PAGE; // 回到设置页地址状态处理下一页 end end end S_CLEAR_INC_COL: begin // 5. 增加列计数 (中间状态) if (!spi_busy) begin col_addr <= col_addr + 1'b1; oled_state <= S_CLEAR_SEND_DATA; // 返回发送下一个数据字节 end end // --- 显示流程 --- S_DISP_SET_PAGE: begin // 1. 设置页地址 if (!spi_busy) begin spi_data <= 8'hB0 | page_addr; // B0-B7 命令 is_command <= 1'b1; spi_start <= 1'b1; oled_state_next <= S_DISP_SET_COL_L; // 下一步: 设置列低位 oled_state <= S_WAIT_SPI_IDLE; end end S_DISP_SET_COL_L: begin // 2. 设置列地址低位 (0x00) if (!spi_busy) begin spi_data <= 8'h00; is_command <= 1'b1; spi_start <= 1'b1; oled_state_next <= S_DISP_SET_COL_H; // 下一步: 设置列高位 oled_state <= S_WAIT_SPI_IDLE; end end S_DISP_SET_COL_H: begin // 3. 设置列地址高位 (0x10) if (!spi_busy) begin spi_data <= 8'h10; is_command <= 1'b1; spi_start <= 1'b1; col_addr <= 8'd0; // 重置列计数器,准备发送数据 oled_state_next <= S_DISP_SEND_DATA; // 下一步: 发送显示数据 oled_state <= S_WAIT_SPI_IDLE; end end S_DISP_SEND_DATA: begin // 4. 发送显示数据 (从 buffer) if (!spi_busy) begin if (col_addr < 128) begin spi_data <= display_buffer[col_addr]; // 从缓冲区获取数据 is_command <= 1'b0; // 这是数据 spi_start <= 1'b1; oled_state_next <= S_DISP_INC_COL; // 下一步: 增加列计数 oled_state <= S_WAIT_SPI_IDLE; end else begin // 当前页的128字节发送完毕 if (page_addr < 7) begin // 是否所有页都发送完了? page_addr <= page_addr + 1'b1; // 移动到下一页 oled_state <= S_DISP_SET_PAGE; // 回到设置页地址状态处理下一页 end else begin // 所有页都发送完毕 oled_state <= S_DISPLAY_DONE; // 一帧完成 end end end end S_DISP_INC_COL: begin // 5. 增加列计数 (中间状态) if (!spi_busy) begin col_addr <= col_addr + 1'b1; oled_state <= S_DISP_SEND_DATA; // 返回发送下一个数据字节 end end S_DISPLAY_DONE: begin // 一帧显示完成 page_addr <= 3'd0; // 重置页地址 col_addr <= 8'd0; // 重置列地址 prepare_display_buffer(); // 准备下一帧的数据 (基于变化的 channel_index) oled_state <= S_DISP_SET_PAGE; // 开始下一帧的显示流程 // $display("Display Frame Done. Starting next frame."); // 可以取消注释以调试 end S_WAIT_SPI_IDLE: begin // 等待 SPI 完成 (包括字节后延时) if (!spi_busy) begin oled_state <= oled_state_next; // 跳转到预定的下一个状态 end // else: 继续等待 end default: oled_state <= S_INIT_DELAY; // 异常状态则返回初始状态 endcase end end endmodule//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // 模块名称: uart_tx_module // 功能: UART发送模块 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ module uart_tx_module ( input wire clk, input wire rst_n, input wire clk_enable, input wire [7:0] data_in, input wire start_tx, output wire tx_busy, output wire tx_serial_out ); localparam OVERSAMPLING_CNT_WIDTH = 4; localparam OVERSAMPLING_MAX_CNT = (1 << OVERSAMPLING_CNT_WIDTH) - 1; localparam BIT_CNT_WIDTH = 4; localparam NUM_DATA_BITS = 8; localparam STOP_BIT_VAL = 1'b1; localparam START_BIT_VAL = 1'b0; localparam S_IDLE = 2'b00; localparam S_TX_START_BIT = 2'b01; localparam S_TX_DATA_BITS = 2'b10; localparam S_TX_STOP_BIT = 2'b11; reg tx_busy_reg; reg tx_serial_out_reg; reg [OVERSAMPLING_CNT_WIDTH-1:0] sample_cnt; reg [BIT_CNT_WIDTH-1:0] bit_cnt; reg [NUM_DATA_BITS-1:0] data_latch; reg [1:0] current_state; wire end_of_bit_tick; assign tx_busy = tx_busy_reg; assign tx_serial_out = tx_serial_out_reg; assign end_of_bit_tick = (sample_cnt == OVERSAMPLING_MAX_CNT); always @(posedge clk or negedge rst_n) begin if (!rst_n) sample_cnt <= 0; else if (current_state == S_IDLE) sample_cnt <= 0; else if (clk_enable) begin if (end_of_bit_tick) sample_cnt <= 0; else sample_cnt <= sample_cnt + 1'b1; end end always @(posedge clk or negedge rst_n) begin if (!rst_n) begin current_state <= S_IDLE; tx_busy_reg <= 1'b0; tx_serial_out_reg <= 1'b1; bit_cnt <= 0; data_latch <= 8'd0; end else begin case (current_state) S_IDLE: begin tx_serial_out_reg <= 1'b1; tx_busy_reg <= 1'b0; bit_cnt <= 0; if (start_tx) begin tx_busy_reg <= 1'b1; data_latch <= data_in; current_state <= S_TX_START_BIT; end end S_TX_START_BIT: begin tx_serial_out_reg <= START_BIT_VAL; if (clk_enable && end_of_bit_tick) begin bit_cnt <= bit_cnt + 1'b1; current_state <= S_TX_DATA_BITS; end end S_TX_DATA_BITS: begin tx_serial_out_reg <= data_latch[bit_cnt - 1]; if (clk_enable && end_of_bit_tick) begin if (bit_cnt < NUM_DATA_BITS) begin bit_cnt <= bit_cnt + 1'b1; current_state <= S_TX_DATA_BITS; end else begin bit_cnt <= bit_cnt + 1'b1; current_state <= S_TX_STOP_BIT; end end end S_TX_STOP_BIT: begin tx_serial_out_reg <= STOP_BIT_VAL; if (clk_enable && end_of_bit_tick) begin bit_cnt <= 0; tx_busy_reg <= 1'b0; current_state <= S_IDLE; end end default: begin current_state <= S_IDLE; tx_busy_reg <= 1'b0; tx_serial_out_reg <= 1'b1; bit_cnt <= 0; end endcase end end endmodule我想用modlesim测试我的oled黑屏和ad7606数据采集的情况
05-14
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值