Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //##################################################################################################
- // module: gcController.sv
- // desc: driver for one wire interface used by gamecube controllers
- // params: p_clkFreq : input clock frequency, default is 100 MHz
- // p_controllerClock : controller interface clock frequency, default is 250 KHz
- // p_updateRate : controller data refresh rate, default is 100
- // io: clk : clock
- // rst_n : asynchronus active low reset
- // data : controller bidirectional data pin
- // jStickX : analog joystick 8-bit x value
- // jStickY : analog joystick 8 bit y value
- // cStickX : analog cstick 8 bit x
- // faceButtons : current face button values, a/b/x/y/start
- // dPad : current d pad values
- // shoulderButtons : current shoulder button values, l/r/z
- // newDataAvaliable : new controller data is ready
- // controllerPresent : controller is present, active high
- //##################################################################################################
- module gcController
- (
- input wire clk,
- input wire rst_n,
- inout wire data,
- output wire [4:0] faceButtons,
- output wire [3:0] dPad,
- output wire [2:0] shoulderButtons,
- output wire [7:0] jStickX,
- output wire [7:0] jStickY,
- output wire [7:0] cStickX,
- output wire [7:0] cStickY,
- output wire [7:0] lAnalog,
- output wire [7:0] rAnalog,
- output wire newDataAvaliable,
- output wire controllerPresent
- );
- `default_nettype none
- // input clock frequency, controller update rate, controller interface frequency
- parameter p_clkFreq = 100000000;
- parameter p_updateRate = 100;
- parameter p_controllerClock = 250000;
- // number of clock ticks per sub bit pattern, number of clock ticks per update period, and
- // number of clock ticks for read timeout
- localparam c_subBitClkTicks = (p_clkFreq / p_controllerClock) / 4;
- localparam c_timeoutClkTicks = (p_clkFreq / p_controllerClock);
- localparam c_updateRateClkTicks = (p_clkFreq / p_updateRate);
- // data and probe packets including stop bits
- localparam c_probeSequence = 9'b100000000;
- localparam c_dataRequestSequence = 25'b1010000001100000000000010;
- // reponse packet (stadard oem controller) to probe sequence, needs work to determine what bits
- // mean what from different controller types
- localparam c_probeResponseSequence = 24'b000010010000000000100000;
- localparam c_stopBit = 1'b1;
- // controller data
- typedef struct packed
- {
- reg [2:0] zeros;
- reg [4:0] faceButtons;
- reg one;
- reg [3:0] dPad;
- reg [2:0] shoulderButtons;
- reg [7:0] jStickX;
- reg [7:0] jStickY;
- reg [7:0] cStickX;
- reg [7:0] cStickY;
- reg [7:0] lAnalog;
- reg [7:0] rAnalog;
- reg stop;
- } sGcData;
- typedef union packed
- {
- sGcData bits;
- reg [64:0] buffer;
- } uGcData;
- // one hot state indices
- enum
- {
- IDLE = 0,
- SEND_CONTROLLER_PACKET = 1,
- TIMEOUT = 2,
- GET_CONTROLLER_RESPONSE = 3
- } gcStates;
- // open drain states
- enum
- {
- WRITE = 0,
- READ = 1
- } openDrainStates;
- // current state of bus protocol
- enum
- {
- PROBE_REQ_SENT = 0,
- DATA_REQ_SENT = 1
- } masterBusAction;
- // counters
- reg [($clog2(c_updateRateClkTicks) - 1):0] updateCount;
- reg [($clog2(c_subBitClkTicks) - 1):0] subBitCount;
- reg [($clog2(c_timeoutClkTicks) - 1):0] timeoutCount;
- reg [2:0] subPatternCount;
- reg [6:0] bitCount;
- // counter resets
- logic resetTimeoutCount;
- logic resetUpdateCount;
- logic resetSubBitCount;
- // counter gating/done signals
- logic updateCountDone;
- logic subBitCountDone;
- logic subPatternDone;
- logic timeoutCountDone;
- logic subBitCountEnable;
- // state vectors
- reg [3:0] state, nState;
- // control signals
- logic controllerIsThere;
- logic haveValidData;
- logic readWrite;
- logic halfBitWait;
- logic shiftDone;
- logic readDone;
- logic sentProbe;
- logic sentData;
- logic probeOrData;
- // sub pattern shift register control signals
- logic newSubBit;
- logic subBitShiftDone;
- // data shift register control signals
- logic dataShiftDone;
- logic finishShift;
- // data and probe packets, including stop bits
- reg [8:0] probeSequence;
- reg [24:0] dataRequestSequence;
- // data
- uGcData gcData;
- reg [3:0] subPattern;
- // startup values
- initial begin
- gcData.buffer = 64'd0;
- probeSequence = c_probeSequence;
- dataRequestSequence = c_dataRequestSequence;
- end
- // next state assigment
- always_ff @ (posedge clk) begin
- if (!rst_n) begin
- state[3:1] <= 'd0;
- state[IDLE] <= 1'b1;
- end
- else
- state <= nState;
- end
- // next state and output logic
- always_comb begin
- nState = 5'b0;
- readWrite = READ;
- haveValidData = 1'b0;
- sentProbe = 0;
- sentData = 0;
- subBitCountEnable = 1'b0;
- resetUpdateCount = 1'b0;
- resetSubBitCount = 1'b0;
- resetTimeoutCount = 1'b0;
- unique case (1'b1)
- state[IDLE]: begin
- // open drain read, off the bus
- readWrite = READ;
- // enable update rate counter, send probe/data when it expires
- if (updateCountDone) begin
- resetUpdateCount = 1'b1;
- nState[SEND_CONTROLLER_PACKET] = 1'b1;
- end
- else begin
- nState[IDLE] = 1'b1;
- resetUpdateCount = 1'b0;
- end
- end
- state[SEND_CONTROLLER_PACKET]: begin
- // open drain write, on the bus
- readWrite = WRITE;
- // latch current protocol state for read/check logic
- sentProbe = controllerIsThere ? 0 : 1;
- sentData = controllerIsThere ? 1 : 0;
- // enable write logic and wait for controller response
- if (subBitCountDone) begin
- resetSubBitCount = 1'b1;
- subBitCountEnable = 1'b0;
- nState[TIMEOUT] = 1'b1;
- resetTimeoutCount = 1'b1;
- end
- else begin
- subBitCountEnable = 1'b1;
- resetSubBitCount = 1'b0;
- resetTimeoutCount = 1'b0;
- nState[SEND_CONTROLLER_PACKET] = 1'b1;
- end
- end
- state[TIMEOUT]: begin
- // open drain read, off the bus
- readWrite = READ;
- // enable timeout counter, if slave pulls bus low read response else go back to idle
- if (timeoutCountDone)
- nState[IDLE] = 1'b1;
- else if (!data)
- nState[GET_CONTROLLER_RESPONSE] = 1'b1;
- else
- nState[TIMEOUT] = 1'b1;
- end
- state[GET_CONTROLLER_RESPONSE]: begin
- // open drain read, off the bus
- readWrite = READ;
- // enable read logic and wait for done
- if (readDone) begin
- resetSubBitCount = 1;
- subBitCountEnable = 0;
- haveValidData = (probeOrData == DATA_REQ_SENT) ? 1 : 0;
- nState[IDLE] = 1'b1;
- end
- else begin
- subBitCountEnable = 1;
- resetSubBitCount = 0;
- haveValidData = 0;
- nState[GET_CONTROLLER_RESPONSE] = 1;
- end
- end
- endcase
- end
- // previous master bus action
- always_ff @ (posedge clk) begin
- if (!rst_n)
- probeOrData <= PROBE_REQ_SENT;
- else if (sentProbe && !sentData)
- probeOrData <= PROBE_REQ_SENT;
- else if (sentData && !sentProbe)
- probeOrData <= DATA_REQ_SENT;
- else
- probeOrData <= probeOrData;
- end
- // counter for update rate
- always_ff @ (posedge clk) begin
- if (!rst_n || resetUpdateCount) begin
- updateCount <= {$clog2(c_updateRateClkTicks){1'b0}};
- updateCountDone <= 1'b0;
- end
- else if (updateCount == c_updateRateClkTicks - 1) begin
- updateCount <= {$clog2(c_updateRateClkTicks){1'b0}};
- updateCountDone <= 1'b1;
- end
- else begin
- updateCount <= updateCount + 1;
- updateCountDone <= 1'b0;
- end
- end
- // counter for read timeout
- always_ff @ (posedge clk) begin
- if (!rst_n || resetTimeoutCount) begin
- timeoutCount <= 0;
- timeoutCountDone <= 0;
- end
- else if (timeoutCount == (c_timeoutClkTicks - 1)) begin
- timeoutCount <= 0;
- timeoutCountDone <= 1;
- end
- else begin
- timeoutCount <= timeoutCount + 1;
- timeoutCountDone <= 0;
- end
- end
- // counter for sub-bits and bits
- always_ff @ (posedge clk) begin
- halfBitWait <= halfBitWait;
- bitCount <= bitCount;
- subBitCountDone <= 0;
- subPatternDone <= 0;
- newSubBit <= 0;
- if (!rst_n || resetSubBitCount) begin
- halfBitWait <= 0;
- subPatternDone <= 0;
- subBitCount <= 'd0;
- subPatternCount <= 'd0;
- bitCount <= 'd0;
- newSubBit <= 0;
- end
- else if (readWrite == READ && !halfBitWait && subBitCount == ((c_subBitClkTicks / 2) - 1)) begin
- subBitCount <= 0;
- subPatternDone <= 0;
- bitCount <= bitCount;
- halfBitWait <= 1;
- subPatternCount <= subPatternCount + 1;
- newSubBit <= 1;
- end
- else if (subBitCount == c_subBitClkTicks - 1) begin
- newSubBit <= 1;
- subBitCount <= 'd0;
- if (readWrite == WRITE && (bitCount == (controllerIsThere ? 'd24 : 'd8)) && subPatternCount == 2) begin
- subBitCountDone <= 1;
- bitCount <= 'd0;
- end
- else if (readWrite == READ && bitCount == (controllerIsThere ? 'd64 : 'd24) && subPatternCount == 3) begin
- subBitCountDone <= 1;
- bitCount <= 'd0;
- subPatternDone <= 1;
- end
- else if (subPatternCount == 3) begin
- subPatternCount <= 'd0;
- subPatternDone <= 1;
- bitCount <= bitCount + 1;
- end
- else begin
- subPatternCount <= subPatternCount + 1;
- subPatternDone <= 0;
- end
- end
- else begin
- subBitCount <= (subBitCountEnable) ? (subBitCount + 1) : subBitCount;
- subPatternCount <= subPatternCount;
- bitCount <= bitCount;
- subPatternDone <= 0;
- newSubBit <= 0;
- end
- end
- // latch sub-bit count done for data shift done
- always_ff @ (posedge clk) begin
- if (!rst_n || resetSubBitCount)
- finishShift <= 0;
- else if (subBitCountDone)
- finishShift <= 1;
- else
- finishShift <= finishShift;
- end
- // 4 bit sub pattern shift register
- always_ff @ (posedge clk) begin
- subBitShiftDone <= 0;
- if (!rst_n)
- subPattern <= 'd0;
- else if (readWrite == READ && newSubBit) begin
- subPattern <= {subPattern[2:0], data};
- if (subPatternDone)
- subBitShiftDone <= 1;
- else
- subBitShiftDone <= 0;
- end
- else
- subPattern <= subPattern;
- end
- // data buffer shift register
- always_ff @ (posedge clk) begin
- shiftDone <= 0;
- if (!rst_n)
- gcData.buffer = 'd0;
- else if (readWrite == READ && subBitShiftDone) begin
- gcData.buffer <= {gcData.buffer[63:0], (~subPattern[3] & (&subPattern[2:0]))};
- if (finishShift)
- shiftDone <= 1;
- else
- shiftDone <= 0;
- end
- else
- gcData.buffer <= gcData.buffer;
- end
- // data check logic
- always_ff @ (posedge clk) begin
- if (!rst_n) begin
- readDone <= 0;
- controllerIsThere <= 0;
- end
- else if (shiftDone && readWrite == READ) begin
- readDone <= 1;
- if (probeOrData == PROBE_REQ_SENT) begin
- if (gcData.buffer[24:1] == c_probeResponseSequence /*&& gcData.buffer[0] == c_stopBit*/)
- controllerIsThere <= 1;
- else
- controllerIsThere <= 0;
- end
- if (probeOrData == DATA_REQ_SENT) begin
- if (gcData.bits.zeros != 'd0 && gcData.bits.one != 'd1)
- controllerIsThere <= 0;
- else
- controllerIsThere <= 1;
- end
- end
- else begin
- readDone <= 0;
- controllerIsThere <= controllerIsThere;
- end
- end
- // data input/output logic
- assign data = (readWrite == READ) ? 1'bZ :
- (probeOrData == PROBE_REQ_SENT) ?
- (probeSequence[bitCount[3:0]] ?
- ((subPatternCount < 1 && subBitCountEnable) ? 1'b0 : 1'bZ) :
- ((subPatternCount < 3 && subBitCountEnable) ? 1'b0 : 1'bZ)) :
- (probeOrData == DATA_REQ_SENT) ?
- (dataRequestSequence[bitCount[4:0]] ?
- ((subPatternCount < 1 && subBitCountEnable) ? 1'b0 : 1'bZ) :
- ((subPatternCount < 3 && subBitCountEnable) ? 1'b0 : 1'bZ)) :
- 1'bZ;
- // controller presence
- assign controllerPresent = controllerIsThere ? 1'b1 : 1'b0;
- // controller data ready
- assign newDataAvaliable = haveValidData ? 1'b1 : 1'b0;
- // controller data fields
- assign faceButtons = gcData.bits.faceButtons;
- assign dPad = gcData.bits.dPad;
- assign shoulderButtons = gcData.bits.shoulderButtons;
- assign jStickX = gcData.bits.jStickX;
- assign jStickY = gcData.bits.jStickY;
- assign cStickX = gcData.bits.cStickX;
- assign cStickY = gcData.bits.cStickY;
- assign lAnalog = gcData.bits.lAnalog;
- assign rAnalog = gcData.bits.rAnalog;
- endmodule
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement