178 lines
5.9 KiB
Verilog
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_0010_0000, //CPLD3==1,version=1.2.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 |