Close

Code for the FPGA

A project log for A first FPGA project - SPI

How to create a SPI bus on an FPGA, and send data back and forth between a microcontroller and a FPGA

sciencedude1990sciencedude1990 10/30/2020 at 18:010 Comments

Here is the code for the FPGA.  I noted the pin numbers in at the top...

// Main module - monitor the ports from the microcontroller
module spi_micro_test(
	input wire clk, // 50 MHz clock, pin 27
	input wire bar_ss, // SPI chip select, pin 93
	input wire mosi, // SPI master output, pin 92
	input wire sck, // SPI clock, pin 99
	output wire miso, // SPI sidekick output, pin 101
	output wire led1, // LED1 pin 132
	output wire led2, // LED2 pin 134
	output wire led3, // LED3 pin 135
	output wire led4, // LED4 pin 140
	output wire led5); // LED5 pin 141

//////	
// Observe the serial clock
reg [2:0] sck_r;
initial begin
	sck_r <= 3'b000;
end
always @ (posedge clk) begin
	sck_r <= {sck_r[1:0], sck};
end

// Detect the rising edge
wire sck_risingedge = (sck_r[2:1]==2'b01);
// Detect the falling edge
wire sck_fallingedge = (sck_r[2:1]==2'b10);

//////
// Observe the mosi wire
reg [1:0] mosi_r;

always @ (posedge clk) begin
	mosi_r <= {mosi_r[0], mosi};
end
// The mosi data
wire mosi_data = mosi_r[1];

//////
// Observe bar_ss
reg[2:0] bar_ss_r;
initial begin
	bar_ss_r <= 3'b111;
end

always @ (posedge clk) begin
	bar_ss_r <= {bar_ss_r[1:0], bar_ss};
end

// Detect the rising edge
// wire bar_ss_risingedge = (bar_ss_r[2:1]==2'b01);
// Detect the falling edge
wire bar_ss_fallingedge = (bar_ss_r[2:1]==2'b10);
// Observation of bar_ss
wire bar_ss_observe = bar_ss_r[1];

//////
// Place to store input data
// reg data_ready;
reg [2:0] bit_count;
reg [7:0] data_rx;

//////
// Place to store the output data
reg [7:0] data_tx;

initial begin
	data_tx <= 8'b01100101;
end

// Output is tristate, until bar_ss_observe becomes 0
assign miso = (!bar_ss_observe) ? data_tx[7] : 1'bz;

// Capture the value of the bar_ss input from the microcontroller
always @(posedge clk) begin
	if (bar_ss_fallingedge == 1'b1) begin
		// On the falling edge of bar_ss, clear data ready 
		// data_ready <= 1'b0;
		bit_count <= 3'b000;
	end else if ((bar_ss_observe == 1'b0) && (sck_risingedge == 1'b1)) begin
		// If bar_ss is low and on the rising edge, bring in a bit
		bit_count <= bit_count + 3'b001;
		data_rx <= {data_rx[6:0], mosi_data};
	end else if ((bar_ss_observe == 1'b0) && (sck_fallingedge == 1'b1)) begin
		data_tx <= {data_tx[6:0], data_tx[7]};
	end
	
end

// Set the LED outputs
assign led1 = data_rx[0];
assign led2 = data_rx[1];
assign led3 = data_rx[2];
assign led4 = data_rx[3];
assign led5 = bar_ss_observe;

endmodule

Discussions