Files
2026-05-25 18:13:03 +08:00

178 lines
5.9 KiB
Verilog

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,
//DC Regs
output [23:0] o_DC1,
output [23:0] o_DC2,
output [23:0] o_DC3,
output [23:0] o_DC4
);
// --- Parameters ---
localparam REG_COUNT = 16;
localparam [23:0]
IDENT = 24'h800000 | 12'b0001_0000_0000, //CPLD3==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];
assign o_DC1 = regtable[6];
assign o_DC2 = regtable[7];
assign o_DC3 = regtable[8];
assign o_DC4 = regtable[9];
endmodule