module Reg_file ( input i_sys_clk, input i_rst_n, // Bus Interface input i_wr_req, input i_wr, input [6:0] i_addr, input [23:0] i_wdata, output [23:0] o_rdata, output o_rvalid, output o_busy, output o_err, // Controller Interface input i_con_done, // 1=IDLE/DONE, 0=BUSY output o_exec, // Direct Register Outputs output [23:0] o_freq1, output [23:0] o_freq2, output [23:0] o_freq3, output [23:0] o_freq4 ); // --- Parameters --- localparam REG_COUNT = 16; localparam [23:0] IDENT = 24'h400000 | 12'b0001_0000_0000, //CPLD2==1,version=1.0.0 STATE_INIT = 24'h800000; // State Machine Definition localparam IDLE = 4'd0; localparam BUSY = 4'd1; localparam EXEC_ACK = 4'd2; // Wait for controller to go BUSY (Done=0) localparam EXEC_WAIT = 4'd3; // Wait for controller to go DONE (Done=1) // --- Internal Signals --- reg [3:0] state; reg [23:0] regtable [0:REG_COUNT - 1]; reg [23:0] rdata_reg; reg busy_flag; reg err_flag; reg rvalid_flag; integer i; // Mapping Control Bits wire exec_bit = regtable[1][0]; always @(posedge i_sys_clk or negedge i_rst_n) begin if (!i_rst_n) begin for (i = 0; i < REG_COUNT; i = i + 1) begin regtable[i] <= 24'h0; end regtable[0] <= IDENT; regtable[1] <= STATE_INIT; rvalid_flag <= 1'b0; busy_flag <= 1'b0; err_flag <= 1'b0; state <= IDLE; end else begin case (state) IDLE: begin rvalid_flag <= 1'b0; err_flag <= 1'b0; // Priority Check: Did we crash/reset while EXEC bit was still 1? if (exec_bit == 1'b1) begin state <= EXEC_ACK; busy_flag <= 1'b1; end else if (i_wr_req == 1'b1) begin busy_flag <= 1'b1; state <= BUSY; // Addr Sanity Check if ((i_wr && (i_addr == 'd0 || i_addr >= REG_COUNT)) || (!i_wr && (i_addr >= REG_COUNT))) begin err_flag <= 1'b1; end end else begin busy_flag <= 1'b0; end end BUSY: begin if (err_flag) begin state <= IDLE; end else begin if (i_wr == 1'b1) begin // --- WRITE --- if (exec_bit == 1'b1) begin // Cannot write if Controller is already running err_flag <= 1'b1; state <= IDLE; end else begin regtable[i_addr] <= i_wdata; // Check if this write is a "Start Command" if (i_addr == 7'd1 && i_wdata[0] == 1'b1) begin // Go to Handshake Start state <= EXEC_ACK; end else begin state <= IDLE; end end end else begin // --- READ --- rdata_reg <= regtable[i_addr]; rvalid_flag <= 1'b1; state <= IDLE; end end end // --- EXEC PHASE 1: ACK --- // Wait for Controller to register the command and pull 'done' LOW (Busy) EXEC_ACK: begin busy_flag <= 1'b1; if (i_con_done == 1'b0) begin state <= EXEC_WAIT; end // Optional: Timeout counter here to prevent hanging if Controller is dead end // --- EXEC PHASE 2: WAIT --- // Now wait for Controller to finish and pull 'done' HIGH (Idle/Ready) EXEC_WAIT: begin busy_flag <= 1'b1; if (i_con_done == 1'b1) begin // 1. Clear the Exec bit (Auto-Clear) // 2. Set the Ready bit (Bit 23) if you wish regtable[1] <= {1'b1, regtable[1][22:1], 1'b0}; busy_flag <= 1'b0; state <= IDLE; end end default: state <= IDLE; endcase end end assign o_rvalid = rvalid_flag; assign o_rdata = rdata_reg; assign o_busy = busy_flag; assign o_err = err_flag; // Output the control bit to the controller // This stays HIGH during both EXEC_ACK and EXEC_WAIT assign o_exec = exec_bit; assign o_freq1 = regtable[2]; assign o_freq2 = regtable[3]; assign o_freq3 = regtable[4]; assign o_freq4 = regtable[5]; endmodule