Archive

Archive for December, 2015

Is Spartixed the lowest cost board for FPGA / Verilog / VHDL learners ?

December 19th, 2015

Vikas Shukla
-------------

The idea to create Spartixed was rooted in two things - one, we already had a Verilog Tutorial that is very popular among students as well as casual learners. Rodney Schaerer, Lecturer in University of California took interest into the tutorial and his students were using this tutorial ( Thanks Rodney for pointing out the typos in the tutorial). My Google Analytics tells that the Verilog tutorial page has a really very low bounce rate, a measure of how many people get out of your site after visiting that page. That brings us to the second point - the tutorial is good for theoretical understanding but lacks to really show how the things work in real life.

In my graduation class, I vividly remember our ECE lab where we actually made a small RAM using bread board and components. There is no magic into it, but the interest generated, greatly added the interest to learn more about electronics.

With the Spartixed, we expect to achieve the same for learners. And it is designed in a way that it will be most suitable for new engineer looking at polishing their digital hardware design skill using Verilog / VHDL. The undergraduate students of Electrical, Electronics and Computer Science streams will find it useful for learning as well as for their projects. But more importantly, this board will can also be used by 12 year olds to start learning hardware programming. I will encourage parents take a serious look at this board for their kids.

The board is not going to generate any profit but is not designed for it. However, this is not a philanthropist project. The cost engineering involved, ensures that the BOM cost is kept under control. I am still struggling to find and inexpensive way to ship to international buyers. With typical shipping cost at $20, it will hurt the enthusiasts not living in US. May be, we will ship in bulk to a specific country in bulk and the distributors will take care of regional sale.

The initial response to kickstarter has been lukewarm. I expect it to pick up in coming days. In the meantime take a look at the tutorials presented using the Spartixed. You will learn a lot about Verilog and FPGA programming even if you are not buying this board.

123 passport photo

Uncategorized

Clock Divider in Spartixed using Verilog

December 15th, 2015

The Spartixed board has 50 MHz Clock and you need to slow it down to work on slower Bus, like I2C. The following section of code will generate a code that will divide the 50 MHz clock by 1024

module i2c(input clk, output scl );
reg clk_track;
reg [9:0] counter; 
always @(posedge clk )
  begin
  counter <= counter +1;
  clk_track <= counter[9]; // Division by 1024
  end 
assign scl = ~clk_track; 
endmodule

The Output was sent to Pin P78 of the Spartixed board.

and observed on a USB Oscilloscope and here is the result.

divideby1024

Uncategorized

I2C on Spartixed FPGA Learner board

December 13th, 2015

By Vikas Shukla

Update 12/28/2015
It turned out that the start condition was not properly generated. There was a small fix and the updated program is posted here .

Update 12/27/2015

Today I finally tried to download the working code into Spartixed. We attempted to glow an LED when we get an Acknowledgement from an I2C IC. First the code

module i2c
(input clk, reset, button_sw3 , output scl, led2,i2c_wp , inout sda );

reg start;
reg [7:0] data;

reg led_output;

reg clk_track;
// For simulation use below
//reg [2:0] counter; 
// Actual for  division by 1024
reg [9:0] counter; 

always @(posedge clk, negedge reset )
//always @(posedge clk )
begin

  if (~reset)
     begin
        counter <= 0;
     end
 
  else
  begin
  
  counter <= counter +1;
  // Use this for simulation
  // clk_track<= counter[2]; // Division by 8
  clk_track <= counter[9]; // Division by 1024
  end 

end  

  
 //wire serclock = clk_track;
 wire serclock = (counter ==0);
 
 // Use this for simulation	
 // wire sernegclock =(counter ==5);
 wire sernegclock =(counter ==512);
 
 assign scl = ~clk_track; 
 assign i2c_wp= 1'b0; 
 
reg [3:0] state;

always @(posedge clk)
begin
   case (state)
	
        4'b0000: if (start)  state <= 4'b0001;
		  4'b0001: if (serclock) state <= 4'b0010;    // Start bit
		  
        4'b0010: if (sernegclock) state <= 4'b0011;    // Bit 0
        4'b0011: if (sernegclock) state <= 4'b0100;    // Bit 1
        4'b0100: if (sernegclock) state <= 4'b0101;    // Bit 2
        4'b0101: if (sernegclock) state <= 4'b0110;    // Bit 3
        4'b0110: if (sernegclock) state <= 4'b0111;    // Bit 4
        4'b0111: if (sernegclock) state <= 4'b1000;    // Bit 5
        4'b1000: if (sernegclock) state <= 4'b1001;    // Bit 6
         4'b1001: if (sernegclock) state <= 4'b1010;   // Bit 7
        4'b1010: if (serclock) state <= 4'b1011;    // Release Bus
		4'b1011: if (sernegclock) state <= 4'b0000;    // Read Acknowledgement
		
        default: state <= 4'b0000;                  // Undefined, skip to stop
		  
		  
		  
    endcase
end
 
 
reg outbit;
 
always @(posedge clk)
begin
    case (state)
	   
	
	 
         4'b0000: outbit <= 1'bz;              // idle - May be assign like this outbit <= 1'bz; 
			
         4'b0001: outbit <= 0;              // Start bit
         4'b0010: outbit <= data[7];        // Bit 7 , MAB
         4'b0011: outbit <= data[6];        // Bit 6
         4'b0100: outbit <= data[5];        // Bit 5
         4'b0101: outbit <= data[4];        // Bit 4
         4'b0110: outbit <= data[3];        // Bit 3
         4'b0111: outbit <= data[2];        // Bit 2
         4'b1000: outbit <= data[1];        // Bit 1
         4'b1001: outbit <= data[0];        // Bit 0
         4'b1010: outbit <= 1'bz;          // Release Bus// May be assign like outbit <= 1'bz; 
		 4'b1011:  led_output<= sda;              // Read the SDA line 
		 
		 
             default: outbit <= 1'bz;          // Bad state output idle better outbit <= 1'bz;
				 
				 
    endcase
end
 
// Output register to pin
assign sda = outbit;
assign led2 = ~led_output;
 
 
    reg  delay_reg  ;
     
     always @(posedge  clk,  negedge  reset)
	  //always @(posedge  clk_track,  negedge  reset)
    if  ( reset == 0)
     begin
    // Correct Address for the I2C EEPROM
	 data <= 8'b10100001; // 1010 is device address, last is 0 means write operation, 1 means read operation
   
	
	// Wrong Address to test 
  // data <= 8'b10101101; // 1010 is device address, last is 0 means write operation, 1 means read operation

	delay_reg  <=  0;
     //start <=0;
	  start <=1;
     end
      
		
    else
     begin
	 
    delay_reg  <=  button_sw3 ;
     start  <=  (delay_reg)  &  (~button_sw3);
	  
	  //start <= ~button_sw3;
     end
	  
	  
	 
endmodule

[verlog]
NET "scl" LOC = P78;
NET "sda" LOC = P79;
NET "led2" LOC = P131;
NET "reset" LOC = P88; // Moved to new Pin as the original not working
NET "clk" LOC = P55;
NET "button_sw3" LOC = P126;
NET "i2c_wp" LOC = P75;
[/verilog]

Basically we are trying to communicate with the I2C EEPROM CAT24C08YI-GT3. Everytime, I press the SW3 button the LED glows indicating the presence of the Acknowdgement signal. If I Change the device address

data <= 8'b10100001; to something like data <= 8'b10101001; the LED does not glow, indicating that the program is functioning as expected. A typical Data and Clock line is observed as follows. However, not everytime the program functioned as expected. A typical screen shot when it did not work will look like this i2c

When it does not work, it has to do with the start signal. It looks like, it is related to the push button ( may be key debounce or something we do not know about).

Stay tuned for more updates.
=============================

The last week I was trying to get some code for I2C working for the FPGA Learner's board, that I have nicknamed Spartixed. The name is derived from Spartan Six Educational - and indicates and Spartan 6 board for Education and learning.

The following is a section of the Schematics governing the I2C Section that uses CAT24C08YI-GT3 EEPROM.

I2C_Bus

It turned out that the Write protect is active high and therefore the WP pin needs to be driven low by the FPGA.

The first thing that I wished to do was to check if we the acknowledgement, or not ( and glow the LED based upon that). This is a first attempt to do verilog.

module i2c
(input clk, reset, button_sw3 , output scl, led2,i2c_wp , inout sda );

reg start;
reg [7:0] data;

reg led_output;

reg clk_track;
reg [2:0] counter; 
// Actual for  division by 1024
//reg [9:0] counter; 
always @(posedge clk )
 
begin
  if (reset == 0)
     begin
        counter <= 0;
     end
 
  else
  begin
  counter <= counter +1;
   clk_track<= counter[2]; // Division by 8
 //  state <= counter[9]; // Division by 1024
  end 
  
 

  
  
 end 
  
 //wire serclock = clk_track;
 wire serclock = (counter ==0);
 wire sernegclock =(counter ==5);
 
 assign scl = ~clk_track; 
 assign i2c_wp= 1'b0; 
 
reg [3:0] state;
 
always @(posedge clk)
begin
   case (state)
        4'b0000: if (start) state <= 4'b0001;
        4'b0001: if (sernegclock) state <= 4'b0010;    // Start bit
        4'b0010: if (sernegclock) state <= 4'b0011;    // Bit 0
        4'b0011: if (sernegclock) state <= 4'b0100;    // Bit 1
        4'b0100: if (sernegclock) state <= 4'b0101;    // Bit 2
        4'b0101: if (sernegclock) state <= 4'b0110;    // Bit 3
        4'b0110: if (sernegclock) state <= 4'b0111;    // Bit 4
        4'b0111: if (sernegclock) state <= 4'b1000;    // Bit 5
        4'b1000: if (sernegclock) state <= 4'b1001;    // Bit 6
         4'b1001: if (sernegclock) state <= 4'b1010;   // Bit 7
        4'b1010: if (sernegclock) state <= 4'b1011;    // Release Bus
		4'b1011: if (sernegclock) state <= 4'b0000;    // Read Acknowledgement
		
        default: state <= 4'b0000;                  // Undefined, skip to stop
    endcase
end
 
 
reg outbit;
 
always @(posedge clk)
begin
    case (state)
         4'b0000: outbit <= 1'bz;              // idle - May be assign like this outbit <= 1'bz; 
         4'b0001: outbit <= 0;              // Start bit
         4'b0010: outbit <= data[7];        // Bit 7 , MAB
         4'b0011: outbit <= data[6];        // Bit 6
         4'b0100: outbit <= data[5];        // Bit 5
         4'b0101: outbit <= data[4];        // Bit 4
         4'b0110: outbit <= data[3];        // Bit 3
         4'b0111: outbit <= data[2];        // Bit 2
         4'b1000: outbit <= data[1];        // Bit 1
         4'b1001: outbit <= data[0];        // Bit 0
         4'b1010: outbit <= 1'bz;          // Release Bus// May be assign like outbit <= 1'bz; 
		 4'b1011:  led_output<= sda;              // Read the SDA line 
		 
             default: outbit <= 1'bz;          // Bad state output idle better outbit <= 1'bz;
    endcase
end
 
// Output register to pin
assign sda = outbit;
assign led2 = ~led_output;
 

    reg  delay_reg  ;
     
     always @(posedge  clk,  negedge  reset)
    if  ( reset == 0)
     begin
     data <= 8'b10100001; // 1010 is device address, last is 0 means write operation, 1 means read operation
    delay_reg  <=  0;
     start <=0;
     end
      
    else
     begin
    delay_reg  <=  button_sw3 ;
     start  <=  (delay_reg)  &  (~button_sw3);
     end
	 
endmodule
  

And a testbench for this ( remove the i2c_wp in the code above for it to work)

`timescale 1 us / 1 us
 
 
module i2c_tb();
    reg clk;
    reg reset;
    reg button_sw3;
    wire out;
    wire sda;	
		
	
 
    i2c UUT (
        .clk(clk), 
        .reset(reset),
		.button_sw3(button_sw3), 	
        .scl(scl),
		.sda(sda)
		
        );
 
 reg OE =0;
 reg SDA_reg;
 
 assign sda = (OE == 1) ? SDA_reg : 1'bz;
 
    initial begin
            clk = 1'b0;
			OE = 0;
			reset = 1'b0;
			#15 reset = 1'b1;
			button_sw3 = 1'b1;
			#150 button_sw3 = 1'b0;
			#1450 SDA_reg = 1'b0; 
			OE =1;
			 
			#1700 OE = 0;
			 #1000
			            $finish;
    end
    always
            #10 clk = ~clk;  // 20 mirco seconds = 50 KHz Clock cycle   
 
initial
      begin
      $dumpfile ("i2c.vcd");
      $dumpvars (0,i2c_tb);
      end
endmodule

This is the simulation result

I2C_sim

This is the ucf file used.

NET "scl" LOC = P78;
NET "sda" LOC = P79;
NET "led2" LOC = P131;
NET "reset" LOC = P124;
NET "clk" LOC = P55;
NET "button_sw3" LOC = P126;
NET "i2c_wp" LOC = P75;

I have still not downloaded the code in the Spartixed. Something for the next week. I do expect some errors, but should be debuggable with a scope.

Uncategorized