mirror of https://github.com/lnis-uofu/SOFA.git
590 lines
16 KiB
Verilog
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
|