Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

SPI sample code using FPGA

Status
Not open for further replies.

myjoe1026

Junior Member level 3
Joined
Jan 7, 2016
Messages
26
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
198
Hi all,

I'd like to use FPGA, Lattice broad LCMXO2, as a mater to implement SPI command to control other ICs.

I only need pins: SS(set low while transmitting), MOSI(send data transmit) and CLK (clock for trigger)

Is there any sample code for me to start with it?
 

There are plenty of SPI examples if you search the web....
 

Anything wrong here?

Code:
module SPI(clkin,clkout,SS,MOSI);
input clkin;
output reg clkout = 1'b0;
output reg SS;
output reg MOSI;
reg [0:79] register = 80'h9E8280E700010060000;
reg [0:6] count = 7'd0;


always @(posedge clkin)
	begin
		if(count == 7'd80)
			begin
			count = 7'd0;
			SS = 1'b1;
			//MOSI = register[count];
			end
		else
			begin
			SS = 1'b0;	
			MOSI = register[count];
		    count = count + 1'b1;	
			end
		clkout = 1'b1;
		clkout = 1'b0;
	end
endmodule
 

Why not testbench it and find out if it works as you expected?
 

Hi,

Give useful informations:

* what clkout signal (waveform, voltages, frequency, duty cycle...) do you expect?
* and what do you see instead?
* show how you tried to achieve the desired result
* show what you have done to debug the problem, and the results.

Klaus
 

Follow what is said in #6.

Yes, I've complied it, but the clkout seems worng
Where are you toggling your clock? Do you know how to toggle a signal using verilog?

The following seems to make little sense:
clkout = 1'b1;
clkout = 1'b0;


If you are a beginner start with something simpler!
 

Hi,

What I expect is when SS=0,
the MOSI will output a bit of data in register, an then the clkout will output a 1'b1 and 1b0 as SPI rules.
Both MOSI and register pins output are as required, but nothing at clkout pin. Any wrong in the codes?

Thanks.

- - - Updated - - -

Follow what is said in #6.


Where are you toggling your clock? Do you know how to toggle a signal using verilog?

The following seems to make little sense:
clkout = 1'b1;
clkout = 1'b0;


If you are a beginner start with something simpler!

In every positive edge, I want to toggle the clkout by
clkout = 1'b1;
clkout = 1'b0;

Any suggestion to fix it?

Thanks!
 

Anything wrong here?

Code:
MOSI = register[count];
count = count + 1'b1;

What is wrong? How about using what amounts to a mux instead of a shift register for a serial protocol.

In an FPGA a shift register is much more efficiently implemented than a mux.

Also using mixed tabs and spaces...get a better text editor.

- - - Updated - - -

Oh and that clkout problem...

Your writing in Verilog which is a Hardware Description Language. It is not software so doing things like this...

Code Verilog - [expand]
1
2
3
4
always @(posedge clk) begin
  clkout <= 1'b1;
  clkout <= 1'b0;
end


does absolutely nothing except assign clkout <= 1'b0 as a clock always block updates all the right hand sides of the assignments first and then after that is done applies the assignments to the left hand side. So in this case clkout only gets assigned with 1'b0, the clkout <= 1'b1 gets ignored.

- - - Updated - - -

Please don't try using blocking assignments and # delays to make it work (more software thinking bias).
 

does absolutely nothing except assign clkout <= 1'b0 as a clock always block updates all the right hand sides of the assignments first and then after that is done applies the assignments to the left hand side. So in this case clkout only gets assigned with 1'b0, the clkout <= 1'b1 gets ignored.

- - - Updated - - -

Please don't try using blocking assignments and # delays to make it work (more software thinking bias).

Thanks! I understand that the clkout <= 1'b1 gets ignored, so the output always 0.
But, I still can't fix it. How can I generate a high-then-low pulse after every output of the register[count],
so the SPI rules can be followed?

Thanks again.
 

Hi,

I´m not familiar with Verilog.

therefore some pseudo-code:
Code:
always @(posedge clk) begin
  clkout <= !clkout;
end

***
but you need a counter to count from 0 to 7 for the bits to transmit... then use a 4 bit counter (at least) and use bit0 of the counter as clkout.
Because bit 0 toggles with every rising edge of the counter_clock.

Klaus
 

! is a logical operator, the correct operator to invert the signal is actually ~. In this particular case they do the exact same thing, but I've seen people use the wrong operator on a bus and then they wonder why their code doesn't work correctly.
 

Code:
always @(posedge clk) begin
  clkout <= !clkout;
end

***
but you need a counter to count from 0 to 7 for the bits to transmit... then use a 4 bit counter (at least) and use bit0 of the counter as clkout.
Because bit 0 toggles with every rising edge of the counter_clock.

Klaus

Hi Klaus,

Thanks for your suggestion. The thing is, I'd like to output clkout like b010 transition while transmitting the data in register in order to follow the SPI protocol. But, using bit0 of the counter as clkout only outputs a high or low not b010.
And a loop of posedge seems can only output one bit to clkout.
How can I modified my code?
 

Do you know how to do logic design? If you have any notes from any class on the subject you should reefer back to them.
You can create that sequence by making a truth table.
A better method would be to use an FSM to generate the entire transfer sequence.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top