diff --git a/rtl/digital_top.v b/rtl/digital_top.v index ef7c89c..b657eaa 100644 --- a/rtl/digital_top.v +++ b/rtl/digital_top.v @@ -55,7 +55,9 @@ wire [23:0] therm_out; .o_addr (w_addr), .o_wren (w_wren), .o_rden (w_rden), - .i_rddata (w_rddata) + .i_rddata (w_rddata), + .i_report_data (therm_out), + .i_report_vld (therm_vld) ); system_regfile u_system_regfile ( diff --git a/rtl/uart_ctrl_sysreg.v b/rtl/uart_ctrl_sysreg.v index 8fa0edc..c233384 100644 --- a/rtl/uart_ctrl_sysreg.v +++ b/rtl/uart_ctrl_sysreg.v @@ -15,6 +15,9 @@ module uart_ctrl_sysreg #( ,output reg o_wren //write enable sram ,output reg o_rden //rden enable sram ,input [31:0] i_rddata //read data from sram + //主动上报机制 + ,input [23:0] i_report_data + ,input i_report_vld ); // --- uart_top --- @@ -38,7 +41,6 @@ module uart_ctrl_sysreg #( reg [63:0] cmd_reg; reg [31:0]wr_data_buff; reg [19:0] data_bytes_len; - // 状态机定义 reg [2:0] state; @@ -47,9 +49,26 @@ module uart_ctrl_sysreg #( S_PARSE = 3'd2, S_WAIT_RD = 3'd3, S_RD_DATA = 3'd4, - S_WR_DATA = 3'd5; + S_WR_DATA = 3'd5, + S_REPORT = 3'd6; //主动上报状态 +// --- 主动上报数据先锁存着 --- + reg [23:0] report_data_latch; + reg report_pending; + + // 捕捉上报脉冲:如果当前忙,先存起来 + always @(posedge clk or negedge rst_n) begin + if(!rst_n) begin + report_pending <= 1'b0; + report_data_latch <= 24'd0; + end else if(i_report_vld) begin + report_pending <= 1'b1; + report_data_latch <= i_report_data; + end else if(state == S_REPORT) begin + report_pending <= 1'b0; // 进入上报状态后清除标志 + end + end always @(posedge clk or negedge rst_n) begin @@ -70,6 +89,9 @@ module uart_ctrl_sysreg #( cmd_reg[63:32] <= uart_rx_data; state <= S_RX_CMD_L; end + else if(report_pending) begin + state <= S_REPORT; + end end S_RX_CMD_L : begin //1 if(uart_rx_done)begin @@ -109,15 +131,21 @@ module uart_ctrl_sysreg #( else begin state <= S_IDLE; end - + end + S_REPORT : begin //6 + // 构造上报数据包,例如:[8'hAA (帧头) + 24'bit温度数据] + uart_tx_data <= {8'hAA, report_data_latch}; + uart_tx_go <= 1'b1; + state <= S_IDLE; end - + default: state <= S_IDLE; endcase end end + diff --git a/tb/TB_top.sv b/tb/TB_top.sv index ebc03cb..0c1ab2f 100644 --- a/tb/TB_top.sv +++ b/tb/TB_top.sv @@ -30,72 +30,87 @@ module TB_top(); .sig_in (sig_in) ); - // ========================================== - // 任务:发送一个字节 (Serial TX) - // ========================================== - task automatic send_byte(input [7:0] data); - begin - uart_rx = 0; // 起始位 - #(BIT_TIME); - for (int i = 0; i < 8; i++) begin - uart_rx = data[i]; // LSB First - #(BIT_TIME); - end - uart_rx = 1; // 停止位 - #(BIT_TIME); - end - endtask - // 任务:发送 32/64 位数据 - task automatic send_data(input [63:0] data, input int len_bits); - int bytes = len_bits / 8; - for (int i = bytes - 1; i >= 0; i--) begin // 从最高字节往下发 - send_byte(data[i*8 +: 8]); - end - endtask - // ========================================== - // 流程控制:TX 驱动 (从 case.txt 读取) - // ========================================== + // // ========================================== + // // 流程控制:TX 驱动 (从 case.txt 读取) + // // ========================================== + // initial begin + // int file_h; + // int status; + // logic [63:0] val; + + // // 初始化信号 + // rst_n = 0; + // uart_rx = 1; + // #(CLK_PERIOD * 10); + // rst_n = 1; + // file_h = $fopen("case.txt", "r"); + // if (!file_h) begin + // $display("[TX ERROR] Cannot open case.txt"); + // $finish; + // end + + // $display("[TX] Starting transmission..."); + + // while (!$feof(file_h)) begin + // // 假设文件中每行是一个 hex 数据 + // status = $fscanf(file_h, "%h\n", val); + // if (status == 1) begin + // if (val > 64'hFFFF_FFFF) begin + // $display("[%t] TX CMD: %h", $time, val); + // send_data(val, 64); + // end else begin + // $display("[%t] TX DATA: %h", $time, val[31:0]); + // send_data(val[31:0], 32); + // end + // #(BIT_TIME * 5); // 帧间隙 + // end + // end + + // $fclose(file_h); + // $display("[TX] All cases sent."); + + // // 等待一段时间观察 RX 是否还有回传,然后结束 + // #(BIT_TIME * 500); + // $display("[SIM] Simulation finished."); + // $finish; + // end + initial begin - int file_h; - int status; - logic [63:0] val; - - // 初始化信号 - rst_n = 0; - uart_rx = 1; - #(CLK_PERIOD * 10); + // 1. 初始化 + rst_n = 0; uart_rx = 1; sig_in = 0; + #(CLK_PERIOD * 20); rst_n = 1; - file_h = $fopen("case.txt", "r"); - if (!file_h) begin - $display("[TX ERROR] Cannot open case.txt"); - $finish; - end + #(CLK_PERIOD * 100); - $display("[TX] Starting transmission..."); + $display("------- Step 1: Configure Thermometer Regs -------"); + send_data(64'h80000004_00000004,64); + send_data(64'h80000008_00000004,64); + send_data(64'h8000000c_00000004,64); + send_data(64'h80000010_00000004,64); + send_data(64'h80000014_00000004,64); - while (!$feof(file_h)) begin - // 假设文件中每行是一个 hex 数据 - status = $fscanf(file_h, "%h\n", val); - if (status == 1) begin - if (val > 64'hFFFF_FFFF) begin - $display("[%t] TX CMD: %h", $time, val); - send_data(val, 64); - end else begin - $display("[%t] TX DATA: %h", $time, val[31:0]); - send_data(val[31:0], 32); - end - #(BIT_TIME * 5); // 帧间隙 + + $display("------- Step 2: Running Concurrent Tasks -------"); + fork + // 进程 A: 模拟输入脉冲 (代表温度变化) + begin + gen_pulses(400, 10); // 100kHz 持续 10ms end - end - - $fclose(file_h); - $display("[TX] All cases sent."); - - // 等待一段时间观察 RX 是否还有回传,然后结束 + + // 进程 B: 在上报期间,强行插口读取指令 + begin + #(2_000000); // 等待第一个上报包可能发出 + $display("[%t] TX: Sending Read Request during active reporting...", $time); + send_data(64'h80000014_00000004,64); + send_data(64'h00000010_00000004,64);send_data(32'h8000_06e8,32); + send_data(64'h00000010_00000004,64);send_data(32'h8000_06e8,32); + end + join + #(BIT_TIME * 500); - $display("[SIM] Simulation finished."); + $display("Test Done."); $finish; end @@ -177,4 +192,28 @@ module TB_top(); end endtask + // ========================================== + // 任务:发送一个字节 (Serial TX) + // ========================================== + task automatic send_byte(input [7:0] data); + begin + uart_rx = 0; // 起始位 + #(BIT_TIME); + for (int i = 0; i < 8; i++) begin + uart_rx = data[i]; // LSB First + #(BIT_TIME); + end + uart_rx = 1; // 停止位 + #(BIT_TIME); + end + endtask + + // 任务:发送 32/64 位数据 + task automatic send_data(input [63:0] data, input int len_bits); + int bytes = len_bits / 8; + for (int i = bytes - 1; i >= 0; i--) begin // 从最高字节往下发 + send_byte(data[i*8 +: 8]); + end + endtask + endmodule \ No newline at end of file