SOFA/BENCHMARK/i2c_master_top/rtl/StateMachine.v

590 lines
16 KiB
Verilog

// -----------------------------------------------------------------------------
// title : Sensor Manager Statemachine
// project : ULP Sensor Hub
// -----------------------------------------------------------------------------
// file : StateMachine.v
// author : Glen Gomes
// company : QuickLogic Corp
// created : 2013/12/06
// last update : 2013/12/06
// platform : PolarPro III
// standard : Verilog 2001
// -----------------------------------------------------------------------------
// description: The Sensor Manger Statemachine is responsible for controlling the
// operations of the Sensor Manager. These include performing
// transfers between Sensor Memory and various registers.
// -----------------------------------------------------------------------------
// copyright (c) 2013
// -----------------------------------------------------------------------------
// revisions :
// date version author description
// 2013/12/06 1.0 Glen Gomes created
// -----------------------------------------------------------------------------
// Comments: This solution is specifically for use with the QuickLogic
// PolarPro III device.
// -----------------------------------------------------------------------------
`timescale 1ns/10ps
module StateMachine (
CLK_IN,
RESET_IN,
RUNTIME_ADDRESS,
CONTROL_JUMP_REG_DCD,
SAVE_REG_2_MEM,
WB_ACK_I,
WB_BUSY_I,
WB_BUSY_POLL_I,
WB_WE_O,
WB_STB_O,
WB_CYC_O,
SM_CNTL_REG_RUN,
SM_CNTL_INIT_SEQ,
SM_READ_DATA,
SM_INSTR_PTR,
SM_READ_SELECT,
SM_WRITE_SELECT,
SM_BUSY
);
//-----Port Signals--------------------
//
input CLK_IN;
input RESET_IN;
input [7:0] RUNTIME_ADDRESS;
input CONTROL_JUMP_REG_DCD;
input SAVE_REG_2_MEM;
input WB_ACK_I;
input WB_BUSY_I;
input WB_BUSY_POLL_I;
output WB_WE_O;
output WB_STB_O;
output WB_CYC_O;
input SM_CNTL_REG_RUN;
input SM_CNTL_INIT_SEQ;
input [7:0] SM_READ_DATA;
output [7:0] SM_INSTR_PTR;
output SM_READ_SELECT;
output SM_WRITE_SELECT;
output SM_BUSY;
wire CLK_IN;
wire RESET_IN;
wire [7:0] RUNTIME_ADDRESS;
wire CONTROL_JUMP_REG_DCD;
wire SAVE_REG_2_MEM;
wire WB_ACK_I;
wire WB_BUSY_I;
wire WB_BUSY_POLL_I;
reg WB_WE_O;
reg wb_we_o_nxt;
reg WB_STB_O;
reg wb_stb_o_nxt;
reg WB_CYC_O;
reg wb_cyc_o_nxt;
wire SM_CNTL_REG_RUN;
wire SM_CNTL_INIT_SEQ;
wire [7:0] SM_READ_DATA;
reg [7:0] SM_INSTR_PTR;
reg [7:0] sm_instr_ptr_nxt;
reg SM_READ_SELECT;
reg sm_read_select_nxt;
reg SM_WRITE_SELECT;
reg sm_write_select_nxt;
reg SM_BUSY;
reg sm_busy_nxt;
//-----Internal Signals--------------------
//
//
// Define the Statemachine registers
//
reg [3:0] sensor_manager_sm;
reg [3:0] sensor_manager_sm_nxt;
//
// Define the Instruction Pointer variables
//
reg sm_instr_ptr_ce;
reg sm_instr_ptr_ce_nxt;
reg sm_instr_ptr_ld;
reg sm_instr_ptr_ld_nxt;
reg sm_instr_ptr_sel;
reg sm_instr_ptr_sel_nxt;
//------Define Parameters---------
//
//
// Define the Sensor Manager Statemachine States
//
// Note: These states are chosen to allow for overlap of various signals
// during operation. This overlap should help reduce timing
// dependancies.
//
parameter SM_IDLE = 4'h0;
parameter SM_INC_PTR = 4'h1;
parameter SM_INST_RD = 4'h2;
//parameter SM_INST_DCD = 4'h3; // Note: Will be used for TimeStamp Support in a future design
parameter SM_REG_WR = 4'h4;
parameter SM_REG_RD = 4'h5;
parameter SM_WAIT_BUSY_ON = 4'h6;
parameter SM_WAIT_BUSY_OFF = 4'h7;
//
// Sensor Manager Initialization Start Address
//
// Note: The previous IP used the reset of the "RuntimeAddress" register to
// select the sensor initialization code. This value explicity selects
// the value for the start (or re-start) of initialization.
//
parameter SM_INIT_INSTR_ADR = 8'h0; // Address for the start in initialization instructions
//------Logic Operations----------
//
//
// Define the Instruction Pointer
//
// Note: This pointer can start at either the sensor initialization code start
// address or the run-time code start address.
//
always @( SM_INSTR_PTR or
sm_instr_ptr_ld or
sm_instr_ptr_ce or
sm_instr_ptr_sel or
SM_READ_DATA or
CONTROL_JUMP_REG_DCD or
RUNTIME_ADDRESS
)
begin
case({sm_instr_ptr_ld, sm_instr_ptr_ce})
2'b00: sm_instr_ptr_nxt <= SM_INSTR_PTR; // Hold Current Value
2'b01: sm_instr_ptr_nxt <= SM_INSTR_PTR + 1'b1; // Increment to the next address
2'b10:
begin
case({CONTROL_JUMP_REG_DCD, sm_instr_ptr_sel})
2'b00: sm_instr_ptr_nxt <= SM_INIT_INSTR_ADR; // Initialization Code Address
2'b01: sm_instr_ptr_nxt <= RUNTIME_ADDRESS; // Run-time Code Address
2'b10: sm_instr_ptr_nxt <= SM_READ_DATA[7:0]; // Jump Address
2'b11: sm_instr_ptr_nxt <= SM_READ_DATA[7:0]; // Jump Address
endcase
end
2'b11: sm_instr_ptr_nxt <= SM_INSTR_PTR; // Hold Current Value
endcase
end
// Define the registers associated with the Sensor Manager Statemachine
//
always @(posedge CLK_IN or posedge RESET_IN)
begin
if (RESET_IN)
begin
sensor_manager_sm <= SM_IDLE;
SM_INSTR_PTR <= 8'h0;
sm_instr_ptr_ce <= 1'b0;
sm_instr_ptr_ld <= 1'b0;
sm_instr_ptr_sel <= 1'b0;
WB_WE_O <= 1'b0;
WB_STB_O <= 1'b0;
WB_CYC_O <= 1'b0;
SM_READ_SELECT <= 1'b0;
SM_WRITE_SELECT <= 1'b0;
SM_BUSY <= 1'b0;
end
else
begin
sensor_manager_sm <= sensor_manager_sm_nxt;
SM_INSTR_PTR <= sm_instr_ptr_nxt;
sm_instr_ptr_ce <= sm_instr_ptr_ce_nxt;
sm_instr_ptr_ld <= sm_instr_ptr_ld_nxt;
sm_instr_ptr_sel <= sm_instr_ptr_sel_nxt;
WB_WE_O <= wb_we_o_nxt;
WB_STB_O <= wb_stb_o_nxt;
WB_CYC_O <= wb_cyc_o_nxt;
SM_READ_SELECT <= sm_read_select_nxt;
SM_WRITE_SELECT <= sm_write_select_nxt;
SM_BUSY <= sm_busy_nxt;
end
end
// Define the Sensor Manager Statemachine
//
always @( sensor_manager_sm or
SM_CNTL_INIT_SEQ or
SM_CNTL_REG_RUN or
CONTROL_JUMP_REG_DCD or
SAVE_REG_2_MEM or
WB_BUSY_I or
WB_BUSY_POLL_I or
WB_ACK_I
)
begin
case(sensor_manager_sm)
SM_IDLE:
begin
case({SM_CNTL_INIT_SEQ, SM_CNTL_REG_RUN})
2'b00: // No Activity
begin
sensor_manager_sm_nxt <= SM_IDLE;
sm_busy_nxt <= 1'b0;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_sel_nxt <= 1'b0;
end
2'b01: // Start at the Sensor Run-Time Code
begin
sensor_manager_sm_nxt <= SM_INC_PTR;
sm_busy_nxt <= 1'b1;
sm_instr_ptr_ld_nxt <= 1'b1;
sm_instr_ptr_sel_nxt <= 1'b1;
end
2'b10: // No Activity
begin
sensor_manager_sm_nxt <= SM_IDLE;
sm_busy_nxt <= 1'b0;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_sel_nxt <= 1'b0;
end
2'b11: // Start at the Sensor Initialization Code
begin
sensor_manager_sm_nxt <= SM_INC_PTR;
sm_busy_nxt <= 1'b1;
sm_instr_ptr_ld_nxt <= 1'b1;
sm_instr_ptr_sel_nxt <= 1'b0;
end
endcase
sm_instr_ptr_ce_nxt <= 1'b0;
sm_read_select_nxt <= 1'b0;
sm_write_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
end
SM_INC_PTR:
begin
sensor_manager_sm_nxt <= SM_INST_RD;
sm_busy_nxt <= 1'b1;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_instr_ptr_sel_nxt <= 1'b0;
sm_read_select_nxt <= 1'b1;
sm_write_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
end
SM_INST_RD:
begin
sensor_manager_sm_nxt <= SM_REG_WR;
sm_busy_nxt <= 1'b1;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_instr_ptr_sel_nxt <= 1'b0;
sm_read_select_nxt <= 1'b0;
sm_write_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b1;
wb_stb_o_nxt <= 1'b1;
wb_cyc_o_nxt <= 1'b1;
end
SM_REG_WR:
begin
sm_instr_ptr_sel_nxt <= 1'b0;
sm_read_select_nxt <= 1'b0;
case(SM_CNTL_REG_RUN)
1'b0: // A write of "0" to bit "0" of the Command register at address "0" turns off
// the Sensor Manager's Statemachine
begin
sensor_manager_sm_nxt <= SM_IDLE;
sm_busy_nxt <= 1'b0;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_write_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
end
1'b1: // Sensor Manager Statemachine is not stopped; continue processing
begin
sm_busy_nxt <= 1'b1;
case({WB_BUSY_POLL_I, WB_ACK_I})
2'b00: // Wait for Wish Bone Acknowledge and no need to wait for transfer complete
begin
sensor_manager_sm_nxt <= SM_REG_WR;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_write_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b1;
wb_stb_o_nxt <= 1'b1;
wb_cyc_o_nxt <= 1'b1;
end
2'b01: // Wish Bone Acknowledge Received and no need to wait for transfer complete
begin
case(SAVE_REG_2_MEM)
1'b0:
begin
sensor_manager_sm_nxt <= SM_INC_PTR;
sm_instr_ptr_ld_nxt <= CONTROL_JUMP_REG_DCD;
sm_instr_ptr_ce_nxt <= ~CONTROL_JUMP_REG_DCD;
sm_write_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
end
1'b1:
begin
sensor_manager_sm_nxt <= SM_REG_RD;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_write_select_nxt <= 1'b1;
wb_we_o_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b1;
wb_cyc_o_nxt <= 1'b1;
end
endcase
end
2'b10: // Wait for Wish Bone Acknowledge and will need to wait for transfer complete
begin
sensor_manager_sm_nxt <= SM_REG_WR;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_write_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b1;
wb_stb_o_nxt <= 1'b1;
wb_cyc_o_nxt <= 1'b1;
end
2'b11: // Acknowledge received but need to wait for transfer complete
begin
sensor_manager_sm_nxt <= SM_WAIT_BUSY_ON;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_write_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
end
endcase
end
endcase
end
SM_REG_RD:
begin
sm_busy_nxt <= 1'b1;
sm_instr_ptr_sel_nxt <= 1'b0;
sm_read_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b0;
case(WB_ACK_I)
1'b0: // Waiting for Wish Bone Acknowledge
begin
sensor_manager_sm_nxt <= SM_REG_RD;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_write_select_nxt <= 1'b1;
wb_stb_o_nxt <= 1'b1;
wb_cyc_o_nxt <= 1'b1;
end
1'b1: // Got Wish Bone Acknowledge
begin
sensor_manager_sm_nxt <= SM_INC_PTR;
sm_instr_ptr_ld_nxt <= CONTROL_JUMP_REG_DCD;
sm_instr_ptr_ce_nxt <= ~CONTROL_JUMP_REG_DCD;
sm_write_select_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
end
endcase
end
SM_WAIT_BUSY_ON:
begin
sm_busy_nxt <= 1'b1;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_instr_ptr_sel_nxt <= 1'b0;
sm_read_select_nxt <= 1'b0;
sm_write_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
case(WB_BUSY_I)
1'b0: sensor_manager_sm_nxt <= SM_WAIT_BUSY_ON; // Wait for Busy from I/F
1'b1: sensor_manager_sm_nxt <= SM_WAIT_BUSY_OFF; // Got Busy from I/F
endcase
end
SM_WAIT_BUSY_OFF:
begin
sm_busy_nxt <= 1'b1;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_sel_nxt <= 1'b0;
sm_read_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b0;
case({SAVE_REG_2_MEM, WB_BUSY_I})
2'b00: // Wishbone transfer complete; no need to write anything to Sensor Manager Memory
//
// Note: Writes to the command register do not enter this state.
// Therefore, there is no need to check for the end of processing.
begin
sensor_manager_sm_nxt <= SM_INC_PTR;
sm_instr_ptr_ce_nxt <= 1'b1;
sm_write_select_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
end
2'b01: // Wait for Wishbone transfer to complete
begin
sensor_manager_sm_nxt <= SM_WAIT_BUSY_OFF;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_write_select_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
end
2'b10: // Wishbone transfer complete; Write resulting register value to Sensor Manager Memory
begin
sensor_manager_sm_nxt <= SM_REG_RD;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_write_select_nxt <= 1'b1;
wb_stb_o_nxt <= 1'b1;
wb_cyc_o_nxt <= 1'b1;
end
2'b11: // Wait for Wishbone transfer to complete
begin
sensor_manager_sm_nxt <= SM_WAIT_BUSY_OFF;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_write_select_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
end
endcase
end
default:
begin
sensor_manager_sm_nxt <= SM_IDLE;
sm_busy_nxt <= 1'b0;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_instr_ptr_sel_nxt <= 1'b0;
sm_read_select_nxt <= 1'b0;
sm_write_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
end
endcase
end
endmodule