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[7];
_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.