Vikas Shukla -November 28, 2015
Two months ago the Spartan 6 Learner's board PCB was released for prototype manufacturing. It was supposed to be released in October. But few things came up in between and after a delay of a month, the first prototype is up and running. And this is the subject of this post.
We are able to power up the board and are able to program it using Xilinx ISE tool. We started with a simple code that will take in the Switch SW3 and will display the LED2 when the switch is pressed. A simple verilog code is here
module LED_Button ( input button_sw3, output led2 ); assign led2 = ~button_sw3; endmodule
It also required the ucf file for the two pins used in the code
NET "led2" LOC = P131; NET "button_sw3" LOC = P126;
Here is a video of board running the above code.
This code will verify both the Switches and both the LEDs
module LED_Buttom ( input button_sw2, button_sw3, output led1,led2 ); assign led1 = button_sw2; assign led2 = button_sw3; endmodule
The associated ucf file is
NET "led2" LOC = P131; NET "button_sw3" LOC = P126; NET "led1" LOC = P127; NET "button_sw2" LOC = P124;
The board can be powered either by USB or by a Wall mount power supply that can take in wide range of input from 4.5V to 18V. The power supply from USB comes handy when you wish to debug your board while being connected with your laptop.
The board was built manually, obviously there was some scope of error. For example here is an example program that I tried to test the three seven segment display.
module LED_Buttom ( input button_sw3, output select_7seg3, sega,segb,segc,segd,sege,segf,segg,segdot ); assign select_7seg3 = button_sw3; assign sega = button_sw3; assign segb = button_sw3; assign segc = button_sw3; assign segd = button_sw3; assign sege = button_sw3; assign segf = button_sw3; assign segg = button_sw3; assign segdot = button_sw3; endmodule 1 With the following section of ucf file 1 NET "button_sw3" LOC = P126; NET "sega" LOC = P5; NET "segb" LOC = P141; NET "segc" LOC = P16; NET "segd" LOC = P21; NET "sege" LOC = P22; NET "segf" LOC = P2; NET "segg" LOC = P15; NET "segdot" LOC = P17; //NET "select_7seg1" LOC = P12; //NET "select_7seg2" LOC = P144; NET "select_7seg3" LOC = P142;
It did work, however, the segments c and d did not work as ( corresponding to resistors R10 and R12 in the schematics) you can see in the picture below ( likely a manual assembly error).
The DIP switches were verified by making each segment of the 7 segment LED turn on and off based upon which switch is turned on or off. The following is the section of the ucf file for the 8 pins of the DIP switch.
NET "dip1" LOC = P23; NET "dip2" LOC = P24; NET "dip3" LOC = P26; NET "dip4" LOC = P27; NET "dip5" LOC = P29; NET "dip6" LOC = P30; NET "dip7" LOC = P32; NET "dip8" LOC = P33;
The following code will test the 50 MHz oscillator on the board by blinking and LED.
module clk_div ( input clk, output led2 ); reg [32:0] counter; reg state; assign led2 = state; always @ (posedge clk) begin counter <= counter + 1; state <= counter; // Changes when MSB changes end endmodule
Of course you will need to assign 50 MHz clock input to Pin 55 as in the following ucf file.
NET "LED2" LOC = P131; //LED2 NET "clk" LOC = P55; // clk
The video of the LED blinking example
After touching up the 7 Segment area on the board, it was confirmed that the assembly was the issue.
A nice feature of the learner's board is its ability to communicate with the your computer on UART made possible by the in built USB to UART chip PL2303. You need putty and a USB port on your computer to test the Serial Port. The following code will send an ascii letter on the Serial Port every time switch SW3 is pressed. The switch edge level detection is imported from this post . The serial port code is borrowed from the stackexchange post here ( of course we corrected the stop bit thing mentioned in the post).
module uart_on_spartan6(input clk, reset, button_sw3 , output ser); reg start; reg [7:0] data; reg [14:0] clockdiv; // 9600 baud generator always @(posedge clk) begin if (clockdiv == 5207) clockdiv <= 0; else clockdiv <= clockdiv + 1; end wire serclock = (clockdiv == 0); 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 (serclock) state <= 4'b0011; // Bit 0 4'b0011: if (serclock) state <= 4'b0100; // Bit 1 4'b0100: if (serclock) state <= 4'b0101; // Bit 2 4'b0101: if (serclock) state <= 4'b0110; // Bit 3 4'b0110: if (serclock) state <= 4'b0111; // Bit 4 4'b0111: if (serclock) state <= 4'b1000; // Bit 5 4'b1000: if (serclock) state <= 4'b1001; // Bit 6 4'b1001: if (serclock) state <= 4'b1010; // Bit 7 4'b1010: if (serclock) state <= 4'b0000; // Stop bit default: state <= 4'b0000; // Undefined, skip to stop endcase end reg outbit; always @(posedge clk) begin case (state) 4'b0000: outbit <= 1; // idle 4'b0001: outbit <= 0; // Start bit 4'b0010: outbit <= data; // Bit 0 4'b0011: outbit <= data; // Bit 1 4'b0100: outbit <= data; // Bit 2 4'b0101: outbit <= data; // Bit 3 4'b0110: outbit <= data; // Bit 4 4'b0111: outbit <= data; // Bit 5 4'b1000: outbit <= data; // Bit 6 4'b1001: outbit <= data; // Bit 7 4'b1010: outbit <= 1; // Stop bit default: outbit <= 1; // Bad state output idle endcase end // Output register to pin assign ser = outbit; /////////////////////////////////////////////////////////////////////////////// // Test by outputting a letter 'd' reg delay_reg ; always @(posedge clk, negedge reset) if ( reset == 0) begin data <= 100; // corressponds to letter d delay_reg <= 0; start <=0; end else begin delay_reg <= button_sw3 ; start <= (delay_reg) & (~button_sw3); end endmodule
Of course, we also used the switch SW2 for reset. The ucf file used for this project is here
NET "clk" LOC = P55; // clk NET "ser" LOC = P80; // Data Transmission from FPGA to PL2303 NET "button_sw3" LOC = P126; NET "reset" LOC = P124;
Booting from the Flash
Once you have tested the board with your code, you may want to program the flash, so the board can boot from it when powered on. We verified that it did work. It will be the subject of another separate post.
The leaves us with the following things still to be verified.
1. I2C EEPROM
2. SPI Bus EEPROM
3. SPI Bus A/D Converter
There are open source code for I2C Bus, but we may be writing a deprecated I2C code, which will possible write a defined byte on a given address on the I2C EEPROM. And then possibly a read code which will read read from the I2C and display on the 7 segment display.