I am currently trying to implement a simple SPI Master module in Verilog using Quartus Prime Lite V15.1.0 Build 185 for compilation and Simulation Waveform Editor as my simulation tool. The module has been designed to ideally work in such a way that you load an 8-bit value onto a bus, toggle a 'transmit' bit telling the module to send out the value, and finally the module replies by toggling a 'done' bit to notify the host module that the byte was sent out. The SPI module doesn't control CS lines, as it is assumed these will be controlled by the master module.
//CPOL 0, CPHA 0 RIC60 SPI Master module module SPI ( output reg MOSI, // Map to external I/O pin that will act as MOSI for the spi interface output wire SCLK, // Map to external I/O pin that will act as SCLK for the spi interface output wire DATAEN, // Map to external I/O pin that will act as DATAEN for the spi interface input wire [7:0] inData,// Data to be sent over SPI input wire CLK, // System clock input wire datCLK, // Clock to be used for SPI input wire transmit, // Trigger for when to send out SPI command output reg done, // signal to trigger finished SPI comm input wire reset); // System reset input reg _moduleActive, _moduleActiveQue; reg [7:0] _inData_INT; reg [7:0] _countDown; wire _shiftData; reg _DCLK2, _DCLK3; wire _DCLK_FALL, _DCLK_RISE; reg _Transmit2, _Transmit3; wire _Transmit_FALL, _Transmit_RISE; //Initialize initial begin _moduleActive = 0; _moduleActiveQue = 0; //_countDown[7:0] = 8'b01001100; MOSI = 0; end //SPI Clock catch edges always@(posedge CLK) begin _DCLK2 <= datCLK; end assign _DCLK_FALL = (_DCLK2)&(~datCLK); assign _DCLK_RISE = (~_DCLK2)&(datCLK); //Transmit catch edges always@(posedge CLK) begin _Transmit2 <= transmit; end assign _Transmit_RISE = (!_Transmit2)&(transmit); //que module start at next rising edge of SPI clock always @ (posedge CLK) begin if (_Transmit_RISE) begin _moduleActiveQue = 1; end else if (_moduleActive) begin _moduleActiveQue = 0; end end //put module into 'active' state always @ (posedge CLK) begin if (_moduleActiveQue && _DCLK_FALL) begin _moduleActive = 1; end else if (_countDown == 0) begin _moduleActive = 0; end end //set SPI clock assign SCLK = datCLK && _moduleActive; //clock out data always @ (posedge CLK) begin if (_moduleActiveQue && _DCLK_FALL) begin _inData_INT = inData; _countDown = 8'b10101010; end else if (_moduleActive && _DCLK_RISE) begin MOSI <= _inData_INT; _inData_INT <= _inData_INT << 1; _countDown <= _countDown << 1; end end endmodule
The module works using a 'counter' comprised of a value stuffed with 1's, and bitshifts on each clock until it equates to 0. Currently this counter bus, denounced _countDown, is what is proving to provide the biggest headache. When the above code is simulates it produces the waveforms as seen in the waveform window below.
The least significant bit of _countDown seems to be stuck at high impedance and it does not count down as I would expect form the given code. Also as you may have noticed, in the 'initial begin' block the initialization of _countDown has been commented out. If this line of code is uncommented I find that _countDown always stays in a state of high impedance. I am relatively unexperienced with Verilog (which may show itself in the code) so any pointers would be highly appreciated.