├── SimpleGPUonS7.srcs ├── sources_1 │ ├── new │ │ ├── testMatrixData.mem │ │ ├── sram_tte_example.v │ │ ├── staticRam.v │ │ ├── spi_slave.v │ │ ├── dualPortRam.v │ │ ├── ViewToScreenConverter.v │ │ ├── FiFO.v │ │ ├── vgaSignalGenerator.v │ │ ├── vert_projector.v │ │ ├── matrix4x4x1.v │ │ └── top.v │ └── imports │ │ └── Desktop │ │ ├── qadd.v │ │ ├── qmult.v │ │ ├── qmults.v │ │ └── qdiv.v ├── sim_1 │ └── new │ │ ├── FIFO_Test.v │ │ ├── test_matrixMult.v │ │ └── test_vert_projector.v └── constrs_1 │ └── new │ └── s7.xdc ├── docs ├── output.jpg ├── setup.png └── gpusimple-2.png ├── waveforms └── debugging counter.dwf3work ├── SimpleGPUonS7.ip_user_files └── README.txt ├── README.md ├── SimpleGPUonS7.sim └── sim_1 │ └── behav │ └── xsim │ └── glbl.v ├── .gitignore ├── SimpleGPUonS7.xpr └── LICENSE /SimpleGPUonS7.srcs/sources_1/new/testMatrixData.mem: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/output.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjkkirschner/simpleGPUCore/HEAD/docs/output.jpg -------------------------------------------------------------------------------- /docs/setup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjkkirschner/simpleGPUCore/HEAD/docs/setup.png -------------------------------------------------------------------------------- /docs/gpusimple-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjkkirschner/simpleGPUCore/HEAD/docs/gpusimple-2.png -------------------------------------------------------------------------------- /waveforms/debugging counter.dwf3work: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjkkirschner/simpleGPUCore/HEAD/waveforms/debugging counter.dwf3work -------------------------------------------------------------------------------- /SimpleGPUonS7.ip_user_files/README.txt: -------------------------------------------------------------------------------- 1 | The files in this directory structure are automatically generated and managed by Vivado. Editing these files is not recommended. 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # simpleGPUCore 2 | verilog/FPGA hardware description for very simple GPU 3 | 4 | diagram: 5 | ![](https://github.com/mjkkirschner/simpleGPUCore/blob/master/docs/gpusimple-2.png) 6 | sample output: 7 | ![](https://github.com/mjkkirschner/simpleGPUCore/blob/master/docs/output.jpg) 8 | 9 | references: 10 | 11 | * vga: https://github.com/WillGreen/timetoexplore 12 | * fixedpoint math: https://opencores.org/projects/verilog_fixed_point_math_library 13 | * spi: https://www.fpga4fun.com/SPI2.html 14 | -------------------------------------------------------------------------------- /SimpleGPUonS7.srcs/sources_1/new/sram_tte_example.v: -------------------------------------------------------------------------------- 1 | module sram #(parameter ADDR_WIDTH=8, DATA_WIDTH=8, DEPTH=256, MEMFILE="") ( 2 | input wire i_clk, 3 | input wire [ADDR_WIDTH-1:0] i_addr, 4 | input wire i_write, 5 | input wire [DATA_WIDTH-1:0] i_data, 6 | output reg [DATA_WIDTH-1:0] o_data 7 | ); 8 | 9 | reg [DATA_WIDTH-1:0] memory_array [0:DEPTH-1]; 10 | 11 | initial begin 12 | if (MEMFILE > 0) 13 | begin 14 | $display("Loading memory init file '" + MEMFILE + "' into array."); 15 | $readmemh(MEMFILE, memory_array); 16 | end 17 | end 18 | 19 | always @ (posedge i_clk) 20 | begin 21 | if(i_write) begin 22 | memory_array[i_addr] <= i_data; 23 | end 24 | else begin 25 | o_data <= memory_array[i_addr]; 26 | end 27 | end 28 | endmodule 29 | -------------------------------------------------------------------------------- /SimpleGPUonS7.srcs/sources_1/new/staticRam.v: -------------------------------------------------------------------------------- 1 | (* DONT_TOUCH = "yes" *) 2 | //----------------------------------------------------- 3 | module staticRamDiscretePorts ( 4 | address , // Address Input 5 | data , // Data input 6 | we_, 7 | clock, 8 | Q //output 9 | ); 10 | parameter ROMFILE = "noFile"; 11 | parameter DATA_WIDTH = 8 ; 12 | parameter ADDR_WIDTH = 8 ; 13 | parameter RAM_DEPTH = 1 << ADDR_WIDTH; 14 | 15 | 16 | //--------------Input Ports----------------------- 17 | input [ADDR_WIDTH-1:0] address ; 18 | input [DATA_WIDTH-1:0] data; 19 | input we_; 20 | input clock; 21 | 22 | //--------------Output Ports----------------------- 23 | output reg [DATA_WIDTH-1:0] Q; 24 | integer i; 25 | //--------------Internal variables---------------- 26 | reg [DATA_WIDTH-1:0] mem [RAM_DEPTH-1:0]; 27 | 28 | //--------------Code Starts Here------------------ 29 | initial begin 30 | $readmemb(ROMFILE, mem); 31 | for (i = 0; i < RAM_DEPTH; i = i + 1) begin 32 | //#1 $display("%d",mem[i]); 33 | end 34 | end 35 | 36 | always @(posedge clock) 37 | begin 38 | if (!we_) begin 39 | mem[address] <= data; 40 | end 41 | else begin 42 | Q <= mem[address]; 43 | end 44 | end 45 | 46 | endmodule 47 | -------------------------------------------------------------------------------- /SimpleGPUonS7.sim/sim_1/behav/xsim/glbl.v: -------------------------------------------------------------------------------- 1 | // $Header: /devl/xcs/repo/env/Databases/CAEInterfaces/verunilibs/data/glbl.v,v 1.14 2010/10/28 20:44:00 fphillip Exp $ 2 | `ifndef GLBL 3 | `define GLBL 4 | `timescale 1 ps / 1 ps 5 | 6 | module glbl (); 7 | 8 | parameter ROC_WIDTH = 100000; 9 | parameter TOC_WIDTH = 0; 10 | 11 | //-------- STARTUP Globals -------------- 12 | wire GSR; 13 | wire GTS; 14 | wire GWE; 15 | wire PRLD; 16 | tri1 p_up_tmp; 17 | tri (weak1, strong0) PLL_LOCKG = p_up_tmp; 18 | 19 | wire PROGB_GLBL; 20 | wire CCLKO_GLBL; 21 | wire FCSBO_GLBL; 22 | wire [3:0] DO_GLBL; 23 | wire [3:0] DI_GLBL; 24 | 25 | reg GSR_int; 26 | reg GTS_int; 27 | reg PRLD_int; 28 | 29 | //-------- JTAG Globals -------------- 30 | wire JTAG_TDO_GLBL; 31 | wire JTAG_TCK_GLBL; 32 | wire JTAG_TDI_GLBL; 33 | wire JTAG_TMS_GLBL; 34 | wire JTAG_TRST_GLBL; 35 | 36 | reg JTAG_CAPTURE_GLBL; 37 | reg JTAG_RESET_GLBL; 38 | reg JTAG_SHIFT_GLBL; 39 | reg JTAG_UPDATE_GLBL; 40 | reg JTAG_RUNTEST_GLBL; 41 | 42 | reg JTAG_SEL1_GLBL = 0; 43 | reg JTAG_SEL2_GLBL = 0 ; 44 | reg JTAG_SEL3_GLBL = 0; 45 | reg JTAG_SEL4_GLBL = 0; 46 | 47 | reg JTAG_USER_TDO1_GLBL = 1'bz; 48 | reg JTAG_USER_TDO2_GLBL = 1'bz; 49 | reg JTAG_USER_TDO3_GLBL = 1'bz; 50 | reg JTAG_USER_TDO4_GLBL = 1'bz; 51 | 52 | assign (strong1, weak0) GSR = GSR_int; 53 | assign (strong1, weak0) GTS = GTS_int; 54 | assign (weak1, weak0) PRLD = PRLD_int; 55 | 56 | initial begin 57 | GSR_int = 1'b1; 58 | PRLD_int = 1'b1; 59 | #(ROC_WIDTH) 60 | GSR_int = 1'b0; 61 | PRLD_int = 1'b0; 62 | end 63 | 64 | initial begin 65 | GTS_int = 1'b1; 66 | #(TOC_WIDTH) 67 | GTS_int = 1'b0; 68 | end 69 | 70 | endmodule 71 | `endif 72 | -------------------------------------------------------------------------------- /SimpleGPUonS7.srcs/sources_1/new/spi_slave.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | //inspired by https://www.fpga4fun.com/SPI2.html 4 | 5 | module SPI_slave(i_base_clock, i_SCK, i_MOSI, i_EN, o_WORDVALID,o_DATA,o_COUNTER); 6 | 7 | 8 | input i_base_clock; 9 | input i_SCK, i_EN,i_MOSI; 10 | parameter n = 32; 11 | 12 | output reg o_WORDVALID; 13 | output wire [n-1:0] o_DATA; 14 | output [7:0] o_COUNTER; 15 | 16 | assign o_COUNTER = counter; 17 | 18 | reg[2:0] sck_samples = 0; 19 | reg[2:0] en_samples = 0; 20 | reg[1:0] mosi_samples = 0; 21 | 22 | wire validInputData = mosi_samples[1]; 23 | wire enableActive = ~en_samples[1]; //active low 24 | 25 | always @(posedge i_base_clock) begin 26 | 27 | sck_samples <= {sck_samples[1:0],i_SCK}; 28 | en_samples <= {en_samples[1:0],i_EN}; 29 | mosi_samples <= {mosi_samples[0],i_MOSI}; 30 | 31 | end 32 | 33 | //recieve data from avr 34 | //parameterize this better... 35 | reg [7:0] counter = 0; 36 | reg [n-1:0] dataInputRegister = 0; 37 | assign o_DATA = dataInputRegister; 38 | 39 | 40 | always@(posedge i_base_clock) begin 41 | //if enable is true, and serial clock is rising 42 | //read data 43 | if(enableActive && sck_samples[2:1] == 2'b01) begin 44 | counter <= counter +1; 45 | //read a bit of the data into the register 46 | dataInputRegister <= {dataInputRegister[n-2:0],validInputData}; 47 | end //if 48 | else 49 | if (enableActive == 0) begin 50 | counter <= 0; 51 | end 52 | 53 | end 54 | 55 | //TODO does this need more constraints? 56 | always@(posedge i_base_clock) begin 57 | if( (counter == n-1) && enableActive && (sck_samples[2:1] == 2'b01) ) begin 58 | o_WORDVALID <= 1; 59 | end 60 | else begin 61 | o_WORDVALID <= 0; 62 | end 63 | end 64 | 65 | endmodule -------------------------------------------------------------------------------- /SimpleGPUonS7.srcs/sources_1/new/dualPortRam.v: -------------------------------------------------------------------------------- 1 | (* DONT_TOUCH = "yes" *) 2 | //----------------------------------------------------- 3 | module dualPortStaticRam ( 4 | address_1 , // Address Input 5 | address_2 , // Address Input 6 | data , // Data input 7 | we_, 8 | clock, 9 | clock2, 10 | Q_1, //output 11 | Q_2 //output 12 | ); 13 | parameter ROMFILE = "noFile"; 14 | parameter DATA_WIDTH = 8 ; 15 | parameter ADDR_WIDTH = 8 ; 16 | parameter RAM_DEPTH = 1 << ADDR_WIDTH; 17 | 18 | 19 | //--------------Input Ports----------------------- 20 | input [ADDR_WIDTH-1:0] address_1 ; 21 | input [ADDR_WIDTH-1:0] address_2 ; 22 | input [DATA_WIDTH-1:0] data; 23 | input we_; 24 | input clock; 25 | input clock2; 26 | 27 | //--------------Output Ports----------------------- 28 | output reg [DATA_WIDTH-1:0] Q_1; 29 | output reg [DATA_WIDTH-1:0] Q_2; 30 | integer i; 31 | //--------------Internal variables---------------- 32 | reg [DATA_WIDTH-1:0] mem [RAM_DEPTH-1:0]; 33 | 34 | //--------------Code Starts Here------------------ 35 | initial begin 36 | $readmemb(ROMFILE, mem); 37 | for (i = 0; i < RAM_DEPTH; i = i + 1) begin 38 | //#1 $display("%d: %d ",i,mem[i]); 39 | end 40 | end 41 | 42 | always @(posedge clock) 43 | begin 44 | if (!we_) begin 45 | mem[address_1] = data; 46 | end 47 | else begin 48 | Q_1 <= mem[address_1]; 49 | end 50 | end 51 | 52 | always@(posedge clock2) begin 53 | Q_2 = mem[address_2]; 54 | end 55 | 56 | endmodule -------------------------------------------------------------------------------- /SimpleGPUonS7.srcs/sim_1/new/FIFO_Test.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | module FIFO_Test; 4 | 5 | //inputs 6 | reg [15:0] inputData = 0; 7 | wire [15:0] outputData; 8 | 9 | reg clock = 0; 10 | wire reset = 0; 11 | reg readVertex = 0; 12 | reg writeVertex = 0; 13 | wire empty; 14 | wire full; 15 | 16 | FIFO#(.DATA_WIDTH(16),.RAM_DEPTH(3)) 17 | 18 | uut ( 19 | .clk_i(clock), 20 | .reset_i(reset), 21 | .data_i(inputData), 22 | .r_en_i(readVertex), 23 | .w_en_i(writeVertex), 24 | .data_o(outputData), 25 | .empty_o(empty), 26 | .full_o(full)); 27 | 28 | initial begin 29 | $monitor ("input: %b, output: %b, empty %b, full %b", inputData, outputData, empty, full); //Monitor the stuff we care about 30 | 31 | //first input data word 32 | #10 inputData = 16'b0000000000000001; 33 | 34 | //assert write 35 | #10 writeVertex = 1; 36 | 37 | //change data 38 | #10 inputData = 16'b0000000000000010; 39 | 40 | //change data 41 | #10 inputData = 16'b0000000000000011; 42 | 43 | //assert write off 44 | #10 writeVertex = 0; 45 | #100 readVertex = 1; 46 | 47 | end 48 | 49 | 50 | always begin 51 | #5 clock = ! clock; 52 | end 53 | 54 | endmodule 55 | -------------------------------------------------------------------------------- /SimpleGPUonS7.srcs/sim_1/new/test_matrixMult.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 12/23/2018 06:51:22 PM 7 | // Design Name: 8 | // Module Name: test_matrixMult 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | 22 | 23 | module test_matrixMult; 24 | 25 | //inputs 26 | reg [255:0] mvp_in; 27 | reg [63:0] vertex_in; 28 | 29 | //outputs 30 | wire [63:0] result; 31 | 32 | matrix4x4x1 33 | #( 34 | .Q(4), 35 | .N(16)) 36 | 37 | uut(.mvp_in( mvp_in), 38 | .vertex_in(vertex_in), 39 | .result( result) 40 | ); 41 | 42 | initial begin 43 | $monitor ("%b,%b,%b", mvp_in, vertex_in, result); // Monitor the stuff we care about 44 | 45 | //ident matrix 46 | #10 mvp_in = {{16'b0000000000010000},{16'b0000000000000000},{16'b0000000000000000},{16'b0000000000000000}, 47 | {16'b0000000000000000},{16'b0000000000010000},{16'b0000000000000000},{16'b0000000000000000}, 48 | {16'b0000000000000000},{16'b0000000000000000},{16'b0000000000010000},{16'b0000000000000000}, 49 | {16'b0000000000000000},{16'b0000000000000000},{16'b0000000000000000},{16'b0000000000010000} 50 | }; 51 | 52 | #10 vertex_in = {{16'd0},{16'd0},{16'd0},{16'd0}}; 53 | end 54 | 55 | always begin 56 | #10 vertex_in = {{16'b0000000001010000},{16'b0000000001010000},{16'b0000000001010000},{16'b0000000001010000}}; 57 | end 58 | endmodule 59 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ######################################################################################################### 2 | ## This is an example .gitignore file for Vivado, please treat it as an example as 3 | ## it might not be complete. In addition, XAPP 1165 should be followed. 4 | ######################################################################################################### 5 | ######### 6 | #Exclude all 7 | ######### 8 | * 9 | !*/ 10 | !.gitignore 11 | ########################################################################### 12 | ## VIVADO 13 | ########################################################################### 14 | ######### 15 | #Source files: 16 | ######### 17 | #Do NOT ignore VHDL, Verilog, block diagrams or EDIF files. 18 | !*.vhd 19 | !*.v 20 | !*.bd 21 | !*.edif 22 | ######### 23 | #IP files 24 | ######### 25 | #.xci: synthesis and implemented not possible - you need to return back to the previous version to generate output products 26 | #.xci + .dcp: implementation possible but not re-synthesis 27 | #*.xci(www.spiritconsortium.org) 28 | !*.xci 29 | #*.dcp(checkpoint files) 30 | !*.dcp 31 | !*.vds 32 | !*.pb 33 | #All bd comments and layout coordinates are stored within .ui 34 | !*.ui 35 | !*.ooc 36 | ######### 37 | #System Generator 38 | ######### 39 | !*.mdl 40 | !*.slx 41 | !*.bxml 42 | ######### 43 | #Simulation logic analyzer 44 | ######### 45 | !*.wcfg 46 | !*.coe 47 | ######### 48 | #MIG 49 | ######### 50 | !*.prj 51 | !*.mem 52 | ######### 53 | #Project files 54 | ######### 55 | #XPR + *.XML ? XPR (Files are merged into a single XPR file for 2014.1 version) 56 | #Do NOT ignore *.xpr files 57 | !*.xpr 58 | #Include *.xml files for 2013.4 or earlier version 59 | !*.xml 60 | ######### 61 | #Constraint files 62 | ######### 63 | #Do NOT ignore *.xdc files 64 | !*.xdc 65 | ######### 66 | #TCL - files 67 | ######### 68 | !*.tcl 69 | ######### 70 | #Journal - files 71 | ######### 72 | !*.jou 73 | ######### 74 | #Reports 75 | ######### 76 | !*.rpt 77 | !*.txt 78 | !*.vdi 79 | ######### 80 | #C-files 81 | ######### 82 | !*.c 83 | !*.h 84 | !*.elf 85 | !*.bmm 86 | !*.xmp -------------------------------------------------------------------------------- /SimpleGPUonS7.srcs/sim_1/new/test_vert_projector.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | module test_vert_projector( 4 | 5 | ); 6 | //inputs 7 | reg clk, inStart; 8 | reg [255:0] mvp_in; 9 | reg [63:0] vertex_in; 10 | 11 | //outputs 12 | wire [47:0] projected_vector; 13 | wire out_done; 14 | 15 | vert_projector #(.Q(4),.N(16)) 16 | uut(.i_clk(clk), 17 | .in_start(inStart), 18 | .mvp_in( mvp_in), 19 | .vertex_in(vertex_in), 20 | .out_vector( projected_vector), 21 | .out_done(out_done) 22 | ); 23 | 24 | 25 | initial 26 | begin 27 | $monitor ("matrix: %b \n, vertex: %b \n ,projectedVert: %b \n ,start: %b \n, done: %b \n", mvp_in, vertex_in, projected_vector, inStart , out_done); // Monitor the stuff we care about 28 | clk = 0; 29 | inStart = 0; 30 | mvp_in = {{16'b0000000000010000},{16'b0000000000000000},{16'b0000000000000000},{16'b0000000000000000}, 31 | {16'b0000000000000000},{16'b0000000000010000},{16'b0000000000000000},{16'b0000000000000000}, 32 | {16'b0000000000000000},{16'b0000000000000000},{16'b0000000000010000},{16'b0000000000000000}, 33 | {16'b0000000000000000},{16'b0000000000000000},{16'b0000000000000000},{16'b0000000000010000} 34 | }; 35 | vertex_in = {{16'b0000000001010000},{16'b0000000001010000},{16'b0000000001010000},{16'b0000000000010000}}; 36 | 37 | #100 inStart <= 1; 38 | 39 | 40 | end 41 | 42 | always 43 | #5 clk = ! clk; 44 | 45 | 46 | endmodule 47 | -------------------------------------------------------------------------------- /SimpleGPUonS7.srcs/sources_1/new/ViewToScreenConverter.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | module ViewToScreenConverter( 3 | 4 | 5 | input [11:0] width_in, 6 | input [11:0] height_in, 7 | //vector format(x,y,z) each component is [1signbit,N-1databits,Qbits] 8 | input [(N*3)-1:0] vector_in, 9 | 10 | //the final pixels - these should be unsigned integers I think...? 11 | output [11:0] xpix_out, 12 | output [11:0] ypix_out, 13 | output on_screen_out 14 | 15 | ); 16 | 17 | parameter Q = 8; 18 | parameter N = 16; 19 | 20 | wire [N-1:0] xResult1; 21 | wire [N-1:0] yResult1; 22 | wire [N-1:0] xResult2; 23 | wire [N-1:0] yResult2; 24 | 25 | wire [N-1:0] xInteger; 26 | wire [N-1:0] yInteger; 27 | 28 | wire [11:0] halfWidth = width_in >> 1; 29 | wire [11:0] halfHeight = height_in >> 1; 30 | 31 | // drop upper Q bits (max width is 2048... 2^11) not a problem for 640x480 vga output 32 | //TODO do we need to concat extra 0's in front here? 33 | wire [N-1:0] fixedPointHalfWidth = {{4{1'b0}},halfWidth, {Q{1'b0}}}; 34 | wire [N-1:0] fixedPointHalfHeight = {{4{1'b0}},halfHeight, {Q{1'b0}}}; 35 | 36 | 37 | qadd #( 38 | .Q(Q), 39 | .N(N)) addXandWidth(xInteger,fixedPointHalfWidth,xResult2); 40 | 41 | qadd #( 42 | .Q(Q), 43 | .N(N)) addYandHeight(yInteger,fixedPointHalfHeight,yResult2); 44 | 45 | // multiply x cord 46 | qmult #( 47 | .Q(Q), 48 | .N(N)) mult1x(fixedPointHalfWidth,vector_in[(N*3)-1:(N*2)],xResult1); 49 | //multiply by neg y coord to get correct scaling. (non mirrored) 50 | qmult #( 51 | .Q(Q), 52 | .N(N)) mult1y({1'b1,fixedPointHalfHeight[N-2:0]},vector_in[(N*2)-1:(N*1)],yResult1); 53 | 54 | 55 | //this converts the resulting normalized value to the screen integer as a Q number. 56 | assign xInteger = {xResult1[N-1:Q],{Q{1'b0}}}; 57 | assign yInteger = {yResult1[N-1:Q],{Q{1'b0}}}; 58 | // this converts the resulting Q addition to an unsigned integer, shifting down by Q bits 59 | assign xpix_out = xResult2[N-1:Q]; 60 | assign ypix_out = yResult2[N-1:Q]; 61 | 62 | //on_screen is high only when x and y values are between 0 and width/height. 63 | assign on_screen_out = (xpix_out < width_in) && (xpix_out >=0) && (ypix_out < height_in) && (ypix_out >= 0); 64 | 65 | 66 | endmodule 67 | -------------------------------------------------------------------------------- /SimpleGPUonS7.srcs/sources_1/imports/Desktop/qadd.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 09:28:18 08/24/2011 7 | // Design Name: 8 | // Module Name: q15_add 9 | // Project Name: 10 | // Target Devices: 11 | // Tool versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module qadd #( 22 | //Parameterized values 23 | parameter Q = 15, 24 | parameter N = 32 25 | ) 26 | ( 27 | input [N-1:0] a, 28 | input [N-1:0] b, 29 | output [N-1:0] c 30 | ); 31 | 32 | reg [N-1:0] res; 33 | 34 | assign c = res; 35 | 36 | always @(a,b) begin 37 | // both negative or both positive 38 | if(a[N-1] == b[N-1]) begin // Since they have the same sign, absolute magnitude increases 39 | res[N-2:0] = a[N-2:0] + b[N-2:0]; // So we just add the two numbers 40 | res[N-1] = a[N-1]; // and set the sign appropriately... Doesn't matter which one we use, 41 | // they both have the same sign 42 | // Do the sign last, on the off-chance there was an overflow... 43 | end // Not doing any error checking on this... 44 | // one of them is negative... 45 | else if(a[N-1] == 0 && b[N-1] == 1) begin // subtract a-b 46 | if( a[N-2:0] > b[N-2:0] ) begin // if a is greater than b, 47 | res[N-2:0] = a[N-2:0] - b[N-2:0]; // then just subtract b from a 48 | res[N-1] = 0; // and manually set the sign to positive 49 | end 50 | else begin // if a is less than b, 51 | res[N-2:0] = b[N-2:0] - a[N-2:0]; // we'll actually subtract a from b to avoid a 2's complement answer 52 | if (res[N-2:0] == 0) 53 | res[N-1] = 0; // I don't like negative zero.... 54 | else 55 | res[N-1] = 1; // and manually set the sign to negative 56 | end 57 | end 58 | else begin // subtract b-a (a negative, b positive) 59 | if( a[N-2:0] > b[N-2:0] ) begin // if a is greater than b, 60 | res[N-2:0] = a[N-2:0] - b[N-2:0]; // we'll actually subtract b from a to avoid a 2's complement answer 61 | if (res[N-2:0] == 0) 62 | res[N-1] = 0; // I don't like negative zero.... 63 | else 64 | res[N-1] = 1; // and manually set the sign to negative 65 | end 66 | else begin // if a is less than b, 67 | res[N-2:0] = b[N-2:0] - a[N-2:0]; // then just subtract a from b 68 | res[N-1] = 0; // and manually set the sign to positive 69 | end 70 | end 71 | end 72 | endmodule 73 | -------------------------------------------------------------------------------- /SimpleGPUonS7.srcs/sources_1/imports/Desktop/qmult.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 11:21:14 08/24/2011 7 | // Design Name: 8 | // Module Name: q15_mult 9 | // Project Name: 10 | // Target Devices: 11 | // Tool versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module qmult #( 22 | //Parameterized values 23 | parameter Q = 15, 24 | parameter N = 32 25 | ) 26 | ( 27 | input [N-1:0] i_multiplicand, 28 | input [N-1:0] i_multiplier, 29 | output [N-1:0] o_result, 30 | output reg ovr 31 | ); 32 | 33 | // The underlying assumption, here, is that both fixed-point values are of the same length (N,Q) 34 | // Because of this, the results will be of length N+N = 2N bits.... 35 | // This also simplifies the hand-back of results, as the binimal point 36 | // will always be in the same location... 37 | 38 | reg [2*N-1:0] r_result; // Multiplication by 2 values of N bits requires a 39 | // register that is N+N = 2N deep... 40 | reg [N-1:0] r_RetVal; 41 | 42 | //-------------------------------------------------------------------------------- 43 | assign o_result = r_RetVal; // Only handing back the same number of bits as we received... 44 | // with fixed point in same location... 45 | 46 | //--------------------------------------------------------------------------------- 47 | always @(i_multiplicand, i_multiplier) begin // Do the multiply any time the inputs change 48 | r_result <= i_multiplicand[N-2:0] * i_multiplier[N-2:0]; // Removing the sign bits from the multiply - that 49 | //#100 $display("multiplying %b, and %b, %b",i_multiplicand,i_multiplier, r_result); // would introduce *big* errors 50 | ovr <= 1'b0; // reset overflow flag to zero 51 | end 52 | 53 | // This always block will throw a warning, as it uses a & b, but only acts on changes in result... 54 | always @(r_result) begin // Any time the result changes, we need to recompute the sign bit, 55 | r_RetVal[N-1] <= i_multiplicand[N-1] ^ i_multiplier[N-1]; // which is the XOR of the input sign bits... (you do the truth table...) 56 | r_RetVal[N-2:0] <= r_result[N-2+Q:Q]; // And we also need to push the proper N bits of result up to 57 | //#100 $display("multiplying %b, and %b, %b",i_multiplicand,i_multiplier, r_RetVal); // the calling entity... 58 | if (r_result[2*N-2:N-1+Q] > 0) // And finally, we need to check for an overflow 59 | ovr <= 1'b1; 60 | end 61 | 62 | endmodule 63 | -------------------------------------------------------------------------------- /SimpleGPUonS7.srcs/sources_1/new/FiFO.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | module FIFO(clk_i, data_i, reset_i, r_en_i, w_en_i, data_o, empty_o, full_o, count_o ); 4 | input clk_i; 5 | input reset_i; 6 | input [DATA_WIDTH-1:0]data_i; 7 | input r_en_i; 8 | input w_en_i; 9 | 10 | output reg [DATA_WIDTH-1:0]data_o; 11 | output empty_o; 12 | output full_o; 13 | output count_o; 14 | 15 | parameter DATA_WIDTH = 8; 16 | parameter RAM_DEPTH = 8; 17 | 18 | reg [RAM_DEPTH:0]count; 19 | reg [DATA_WIDTH-1:0]memory[RAM_DEPTH-1:0]; 20 | reg [2:0]wr_pointer, rd_pointer; 21 | reg full, empty; 22 | reg [DATA_WIDTH-1:0]dataout; 23 | 24 | // reading data out from the FIFO 25 | always @( posedge clk_i or posedge reset_i) 26 | begin 27 | if( reset_i ) 28 | begin 29 | dataout <= 0; 30 | //memory <= {RAM_DEPTH{DATA_WIDTH{1'b0}}}; 31 | end 32 | else 33 | begin 34 | if( r_en_i && !empty_o ) 35 | dataout <= memory[rd_pointer]; 36 | 37 | else 38 | dataout <= dataout; 39 | 40 | end 41 | end 42 | 43 | //writing data in the FIFO 44 | always @(posedge clk_i) 45 | begin 46 | if( w_en_i && !full_o ) 47 | memory[wr_pointer] <= data_i; 48 | 49 | else 50 | memory[wr_pointer] <= memory[wr_pointer]; 51 | end 52 | 53 | 54 | 55 | //pointer increment system 56 | always @ (posedge clk_i or posedge reset_i) 57 | begin 58 | if(reset_i) 59 | begin 60 | //reset pointers 61 | wr_pointer <= 0; 62 | rd_pointer <= 0; 63 | end 64 | else 65 | begin 66 | //write data increment pointer 67 | if(!full_o && w_en_i) 68 | wr_pointer <= wr_pointer+1; 69 | //do nothing 70 | else 71 | wr_pointer <= wr_pointer; 72 | //read data, increment pointer 73 | if(!empty_o && r_en_i) 74 | rd_pointer <= rd_pointer+1; 75 | //do nothing 76 | else 77 | rd_pointer <= rd_pointer; 78 | end 79 | end 80 | 81 | //set states of full,empty flags 82 | always @(posedge clk_i or posedge reset_i) 83 | begin 84 | if( reset_i ) 85 | count <= 0; 86 | 87 | // trying to both read and write while fifo is in good state 88 | // count stays the same. - This is valid because there is only 89 | // one clock for this fifo. 90 | else if( (!full_o && w_en_i) && ( !empty_o && r_en_i ) ) 91 | count <= count; 92 | // writing not full, increment 93 | else if( !full_o && w_en_i ) 94 | count <= count + 1; 95 | //reading and not empty, decrement 96 | else if( !empty_o && r_en_i ) 97 | count <= count - 1; 98 | else 99 | count <= count; 100 | end 101 | 102 | //for full and empty 103 | //use blocking assigns for combinatoral logic 104 | always @(count) 105 | begin 106 | if(count==0) 107 | empty = 1 ; 108 | else 109 | empty = 0; 110 | 111 | if(count==RAM_DEPTH) 112 | full = 1; 113 | else 114 | full = 0; 115 | end 116 | 117 | endmodule 118 | -------------------------------------------------------------------------------- /SimpleGPUonS7.srcs/sources_1/new/vgaSignalGenerator.v: -------------------------------------------------------------------------------- 1 | (* DONT_TOUCH = "yes" *) 2 | module vgaSignalGenerator( 3 | input wire i_clk, // base clock 4 | input wire i_pix_stb, // pixel clock strobe 5 | output wire o_hs, // horizontal sync 6 | output wire o_vs, // vertical sync 7 | output wire o_blanking, // high during blanking interval 8 | output wire o_active, // high during active pixel drawing 9 | output wire o_screenend, // high for one tick at the end of screen 10 | output wire o_animate, // high for one tick at end of active drawing 11 | output wire [9:0] o_x, // current pixel x position 12 | output wire [8:0] o_y // current pixel y position 13 | ); 14 | 15 | // VGA timings https://timetoexplore.net/blog/video-timings-vga-720p-1080p 16 | localparam HS_STA = 16; // horizontal sync start 17 | localparam HS_END = 16 + 96; // horizontal sync end 18 | localparam HA_STA = 16 + 96 + 48; // horizontal active pixel start 19 | localparam VS_STA = 480 + 11; // vertical sync start 20 | localparam VS_END = 480 + 11 + 2; // vertical sync end 21 | localparam VA_END = 480; // vertical active pixel end 22 | localparam LINE = 800; // complete line (pixels) 23 | localparam SCREEN = 524; // complete screen (lines) 24 | 25 | reg [9:0] h_count = 0; // line position 26 | reg [9:0] v_count = 0; // screen position 27 | 28 | // generate sync signals (active low for 640x480) 29 | assign o_hs = ~((h_count >= HS_STA) & (h_count < HS_END)); 30 | assign o_vs = ~((v_count >= VS_STA) & (v_count < VS_END)); 31 | 32 | // keep x and y bound within the active pixels 33 | assign o_x = (h_count < HA_STA) ? 0 : (h_count - HA_STA); 34 | assign o_y = (v_count >= VA_END) ? (VA_END - 1) : (v_count); 35 | 36 | // blanking: high within the blanking period 37 | assign o_blanking = ((h_count < HA_STA) | (v_count > VA_END - 1)); 38 | 39 | // active: high during active pixel drawing 40 | assign o_active = ~((h_count < HA_STA) | (v_count > VA_END - 1)); 41 | 42 | // screenend: high for one tick at the end of the screen 43 | assign o_screenend = ((v_count == SCREEN - 1) & (h_count == LINE)); 44 | 45 | // animate: high for one tick at the end of the final active pixel line 46 | assign o_animate = ((v_count == VA_END - 1) & (h_count == LINE)); 47 | 48 | always @ (posedge i_clk) 49 | begin 50 | if (i_pix_stb) // once per pixel 51 | begin 52 | if (h_count == LINE) // end of line 53 | begin 54 | h_count <= 0; 55 | v_count <= v_count + 1; 56 | end 57 | else 58 | h_count <= h_count + 1; 59 | 60 | if (v_count == SCREEN) // end of screen 61 | begin 62 | v_count <= 0; 63 | end 64 | end 65 | end 66 | endmodule 67 | -------------------------------------------------------------------------------- /SimpleGPUonS7.srcs/sources_1/imports/Desktop/qmults.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 13:33:36 01/02/2014 7 | // Design Name: 8 | // Module Name: qmults 9 | // Project Name: 10 | // Target Devices: 11 | // Tool versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module qmults#( 22 | //Parameterized values 23 | parameter Q = 15, 24 | parameter N = 32 25 | ) 26 | ( 27 | input [N-1:0] i_multiplicand, 28 | input [N-1:0] i_multiplier, 29 | input i_start, 30 | input i_clk, 31 | output [N-1:0] o_result_out, 32 | output o_complete, 33 | output o_overflow 34 | ); 35 | 36 | reg [2*N-2:0] reg_working_result; // a place to accumulate our result 37 | reg [2*N-2:0] reg_multiplier_temp; // a working copy of the multiplier 38 | reg [N-1:0] reg_multiplicand_temp; // a working copy of the umultiplicand 39 | 40 | reg [N-1:0] reg_count; // This is obviously a lot bigger than it needs to be, as we only need 41 | // count to N, but computing that number of bits requires a 42 | // logarithm (base 2), and I don't know how to do that in a 43 | // way that will work for every possibility 44 | 45 | reg reg_done; // Computation completed flag 46 | reg reg_sign; // The result's sign bit 47 | reg reg_overflow; // Overflow flag 48 | 49 | initial reg_done = 1'b1; // Initial state is to not be doing anything 50 | initial reg_overflow = 1'b0; // And there should be no woverflow present 51 | initial reg_sign = 1'b0; // And the sign should be positive 52 | 53 | assign o_result_out[N-2:0] = reg_working_result[N-2+Q:Q]; // The multiplication results 54 | assign o_result_out[N-1] = reg_sign; // The sign of the result 55 | assign o_complete = reg_done; // "Done" flag 56 | assign o_overflow = reg_overflow; // Overflow flag 57 | 58 | always @( posedge i_clk ) begin 59 | if( reg_done && i_start ) begin // This is our startup condition 60 | reg_done <= 1'b0; // We're not done 61 | reg_count <= 0; // Reset the count 62 | reg_working_result <= 0; // Clear out the result register 63 | reg_multiplier_temp <= 0; // Clear out the multiplier register 64 | reg_multiplicand_temp <= 0; // Clear out the multiplicand register 65 | reg_overflow <= 1'b0; // Clear the overflow register 66 | 67 | reg_multiplicand_temp <= i_multiplicand[N-2:0]; // Load the multiplicand in its working register and lose the sign bit 68 | reg_multiplier_temp <= i_multiplier[N-2:0]; // Load the multiplier into its working register and lose the sign bit 69 | 70 | reg_sign <= i_multiplicand[N-1] ^ i_multiplier[N-1]; // Set the sign bit 71 | end 72 | 73 | else if (!reg_done) begin 74 | if (reg_multiplicand_temp[reg_count] == 1'b1) // if the appropriate multiplicand bit is 1 75 | reg_working_result <= reg_working_result + reg_multiplier_temp; // then add the temp multiplier 76 | 77 | reg_multiplier_temp <= reg_multiplier_temp << 1; // Do a left-shift on the multiplier 78 | reg_count <= reg_count + 1; // Increment the count 79 | 80 | //stop condition 81 | if(reg_count == N) begin 82 | reg_done <= 1'b1; // If we're done, it's time to tell the calling process 83 | if (reg_working_result[2*N-2:N-1+Q] > 0) // Check for an overflow 84 | reg_overflow <= 1'b1; 85 | // else 86 | // reg_count <= reg_count + 1; // Increment the count 87 | end 88 | end 89 | end 90 | endmodule 91 | -------------------------------------------------------------------------------- /SimpleGPUonS7.srcs/sources_1/imports/Desktop/qdiv.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: Burke 4 | // Engineer: Tom Burke 5 | // 6 | // Create Date: 19:39:14 08/24/2011 7 | // Design Name: 8 | // Module Name: qdiv.v 9 | // Project Name: Fixed-point Math Library (Verilog) 10 | // Target Devices: 11 | // Tool versions: Xilinx ISE WebPack v14.7 12 | // Description: Fixed-point division in (Q,N) format 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Revision 0.02 - 25 May 2014 19 | // Updated to fix an error 20 | // 21 | // Additional Comments: Based on my description on youtube: 22 | // http://youtu.be/TEnaPMYiuR8 23 | // 24 | ////////////////////////////////////////////////////////////////////////////////// 25 | 26 | module qdiv #( 27 | //Parameterized values 28 | parameter Q = 15, 29 | parameter N = 32 30 | ) 31 | ( 32 | input [N-1:0] i_dividend, 33 | input [N-1:0] i_divisor, 34 | input i_start, 35 | input i_clk, 36 | output [N-1:0] o_quotient_out, 37 | output o_complete, 38 | output o_overflow 39 | ); 40 | 41 | reg [2*N+Q-3:0] reg_working_quotient; // Our working copy of the quotient 42 | reg [N-1:0] reg_quotient; // Final quotient 43 | reg [N-2+Q:0] reg_working_dividend; // Working copy of the dividend 44 | reg [2*N+Q-3:0] reg_working_divisor; // Working copy of the divisor 45 | 46 | reg [N-1:0] reg_count; // This is obviously a lot bigger than it needs to be, as we only need 47 | // count to N-1+Q but, computing that number of bits requires a 48 | // logarithm (base 2), and I don't know how to do that in a 49 | // way that will work for everyone 50 | 51 | reg reg_done; // Computation completed flag 52 | reg reg_sign; // The quotient's sign bit 53 | reg reg_overflow; // Overflow flag 54 | 55 | initial reg_done = 1'b1; // Initial state is to not be doing anything 56 | initial reg_overflow = 1'b0; // And there should be no woverflow present 57 | initial reg_sign = 1'b0; // And the sign should be positive 58 | 59 | initial reg_working_quotient = 0; 60 | initial reg_quotient = 0; 61 | initial reg_working_dividend = 0; 62 | initial reg_working_divisor = 0; 63 | initial reg_count = 0; 64 | 65 | 66 | assign o_quotient_out[N-2:0] = reg_quotient[N-2:0]; // The division results 67 | assign o_quotient_out[N-1] = reg_sign; // The sign of the quotient 68 | assign o_complete = reg_done; 69 | assign o_overflow = reg_overflow; 70 | 71 | always @( posedge i_clk ) begin 72 | if( reg_done && i_start ) begin // This is our startup condition 73 | // Need to check for a divide by zero right here, I think.... 74 | reg_done <= 1'b0; // We're not done 75 | reg_count <= N+Q-1; // Set the count 76 | reg_working_quotient <= 0; // Clear out the quotient register 77 | reg_working_dividend <= 0; // Clear out the dividend register 78 | reg_working_divisor <= 0; // Clear out the divisor register 79 | reg_overflow <= 1'b0; // Clear the overflow register 80 | 81 | reg_working_dividend[N+Q-2:Q] <= i_dividend[N-2:0]; // Left-align the dividend in its working register 82 | reg_working_divisor[2*N+Q-3:N+Q-1] <= i_divisor[N-2:0]; // Left-align the divisor into its working register 83 | 84 | reg_sign <= i_dividend[N-1] ^ i_divisor[N-1]; // Set the sign bit 85 | end 86 | else if(!reg_done) begin 87 | reg_working_divisor <= reg_working_divisor >> 1; // Right shift the divisor (that is, divide it by two - aka reduce the divisor) 88 | reg_count <= reg_count - 1; // Decrement the count 89 | 90 | // If the dividend is greater than the divisor 91 | if(reg_working_dividend >= reg_working_divisor) begin 92 | reg_working_quotient[reg_count] <= 1'b1; // Set the quotient bit 93 | reg_working_dividend <= reg_working_dividend - reg_working_divisor; // and subtract the divisor from the dividend 94 | end 95 | 96 | //stop condition 97 | if(reg_count == 0) begin 98 | reg_done <= 1'b1; // If we're done, it's time to tell the calling process 99 | reg_quotient <= reg_working_quotient; // Move in our working copy to the outside world 100 | //#5 $display("divisionDone %b, and %b, %b",i_dividend,i_divisor, reg_working_quotient); 101 | if (reg_working_quotient[2*N+Q-3:N]>0) 102 | reg_overflow <= 1'b1; 103 | end 104 | else 105 | reg_count <= reg_count - 1; 106 | end 107 | end 108 | endmodule -------------------------------------------------------------------------------- /SimpleGPUonS7.srcs/sources_1/new/vert_projector.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | module vert_projector( 4 | input i_clk, 5 | input in_start, 6 | input [(N*16)-1:0] mvp_in, 7 | input [(N*4)-1:0] vertex_in, 8 | output out_done, 9 | output [(N*3)-1:0] out_vector 10 | ); 11 | 12 | parameter Q = 8; 13 | parameter N = 16; 14 | 15 | wire [(N*4)-1:0] result; 16 | reg in_start_1; 17 | 18 | wire x_division_done; 19 | wire y_division_done; 20 | wire z_division_done; 21 | 22 | reg inProgress = 0; 23 | reg [8:0] counter = 0; 24 | reg divide_start = 0; 25 | wire [N-1:0] xResult; 26 | wire [N-1:0] yResult; 27 | wire[N-1:0] zResult; 28 | 29 | reg out_done_reg = 0; 30 | reg [(N*3)-1:0] out_vector_reg = 0; 31 | reg internal_done = 0; 32 | 33 | wire [N-1:0] xcomp = vertex_in[(N*4)-1:(N*3)]; 34 | wire [N-1:0] ycomp = vertex_in[(N*3)-1:(N*2)]; 35 | wire [N-1:0] zcomp= vertex_in[(N*2)-1:(N*1)]; 36 | wire [N-1:0] wcomp = vertex_in[(N*1)-1:(N*0)]; 37 | 38 | assign out_done = out_done_reg; 39 | assign out_vector = out_vector_reg; 40 | 41 | localparam WAIT = 33; 42 | 43 | 44 | matrix4x4x1#( 45 | .Q(Q), 46 | .N(N) 47 | ) vertexMultipler 48 | ( 49 | .mvp_in( mvp_in), 50 | .vertex_in(vertex_in), 51 | .result( result) 52 | ); 53 | 54 | 55 | // we should instantiate 3 dividers - 56 | // one for each vector component. 57 | // we somehow need to wait to start dividing until the 58 | // result is valid... 59 | 60 | qdiv#( 61 | .Q(Q), 62 | .N(N)) 63 | xDivider( 64 | .i_dividend(result[(N*4)-1:(N*3)]), 65 | .i_divisor(result[N-1:0]), 66 | .i_start(divide_start), 67 | .i_clk(i_clk), 68 | .o_quotient_out(xResult), 69 | .o_complete(x_division_done) 70 | ); 71 | 72 | qdiv#( 73 | .Q(Q), 74 | .N(N)) 75 | yDivider( 76 | .i_dividend(result[(N*3)-1:(N*2)]), 77 | .i_divisor(result[N-1:0]), 78 | .i_start(divide_start), 79 | .i_clk(i_clk), 80 | .o_quotient_out(yResult), 81 | .o_complete(y_division_done) 82 | ); 83 | 84 | qdiv#( 85 | .Q(Q), 86 | .N(N)) 87 | zDivider( 88 | .i_dividend(result[(N*2)-1:(N*1)]), 89 | .i_divisor(result[N-1:0]), 90 | .i_start(divide_start), 91 | .i_clk(i_clk), 92 | .o_quotient_out(zResult), 93 | .o_complete(z_division_done) 94 | ); 95 | 96 | 97 | always@(posedge i_clk) begin 98 | 99 | if (inProgress == 1) begin 100 | //if we're in progress, we are not done. 101 | internal_done <= 0; 102 | //lets wait x count before starting division. 103 | counter <= counter + 1; 104 | if (counter > WAIT) begin 105 | // start dividing - then wait another 17 clocks to be safe. 106 | // or wait until the complete signal is raised. 107 | divide_start <= 1; 108 | if(z_division_done == 1 && counter > WAIT * 2) begin 109 | // we're done dividing 110 | internal_done <= 1; 111 | counter <= 0; 112 | divide_start <= 0; 113 | out_vector_reg <= {xResult,yResult,zResult}; 114 | #1 $display("x %b ,y %b ,z %b" , xResult,yResult,zResult); 115 | #1 $display("x %d,%f",xResult[N-2:Q],$itor(xResult[Q:0])*2.0**-16.0); 116 | #1 $display("y %d,%f",yResult[N-2:Q],$itor(yResult[Q:0])*2.0**-16.0); 117 | #1 $display("z %d,%f",zResult[N-2:Q],$itor(zResult[Q:0])*2.0**-16.0); 118 | end // if 119 | end // if 120 | end //start if 121 | end //end always 122 | 123 | //we need N clocks before the division result is ready. 124 | always @(posedge i_clk) begin 125 | in_start_1 <= in_start; 126 | //only do anything if we detect a start pulse. 127 | if(in_start && ~in_start_1) begin 128 | #1 $display("The original vertex"); 129 | #1 $display("x %b ,y %b ,z %b , w%b" , xcomp,ycomp,zcomp,wcomp); 130 | #1 $display("x %d,%f",xcomp[N-2:Q],$itor(xcomp[Q:0])*2.0**-16.0); 131 | #1 $display("y %d,%f",ycomp[N-2:Q],$itor(ycomp[Q:0])*2.0**-16.0); 132 | #1 $display("z %d,%f",zcomp[N-2:Q],$itor(zcomp[Q:0])*2.0**-16.0); 133 | #1 $display("w %d,%f",wcomp[N-2:Q],$itor(wcomp[Q:0])*2.0**-16.0); 134 | 135 | //we saw the pulse so we're now doing our work: 136 | inProgress <= 1; 137 | //reset the done flag. 138 | out_done_reg <= 0; 139 | end 140 | if(internal_done == 1) begin 141 | inProgress <= 0; 142 | out_done_reg =1; 143 | end 144 | end // always 145 | 146 | endmodule 147 | -------------------------------------------------------------------------------- /SimpleGPUonS7.srcs/sources_1/new/matrix4x4x1.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 12/16/2018 12:29:25 PM 7 | // Design Name: 8 | // Module Name: matrix4x4x1 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | 22 | 23 | module matrix4x4x1( 24 | input [(N*16)-1:0] mvp_in, 25 | input [(N*4)-1:0] vertex_in, 26 | output [(N*4)-1:0] result 27 | ); 28 | 29 | parameter Q = 8; 30 | parameter N = 16; 31 | 32 | //internal variables 33 | reg [N-1:0] mvp_inTemp[0:3][0:3]; 34 | reg [N-1:0] vertex_inTemp[0:3]; 35 | wire [N-1:0] res_TempOut [0:3]; 36 | wire [N-1:0] res_TempIntermediate [0:7]; 37 | 38 | reg [(N*4)-1:0] out_reg_result = 0; 39 | 40 | wire [N-1:0] tempx1; 41 | wire [N-1:0] tempx2; 42 | wire [N-1:0] tempx3; 43 | wire [N-1:0] tempx4; 44 | 45 | wire [N-1:0] tempy1; 46 | wire [N-1:0] tempy2; 47 | wire [N-1:0] tempy3; 48 | wire [N-1:0] tempy4; 49 | 50 | wire [N-1:0] tempz1; 51 | wire [N-1:0] tempz2; 52 | wire [N-1:0] tempz3; 53 | wire [N-1:0] tempz4; 54 | 55 | wire [N-1:0] tempw1; 56 | wire [N-1:0] tempw2; 57 | wire [N-1:0] tempw3; 58 | wire [N-1:0] tempw4; 59 | 60 | integer i,j = 0; 61 | 62 | 63 | assign result = out_reg_result; 64 | 65 | //TODO I think matrix[row][col] is correct. 66 | 67 | //calculate x component of result vector 68 | qmult #( 69 | .Q(Q), 70 | .N(N)) mult1x(mvp_inTemp[0][0],vertex_inTemp[0],tempx1); 71 | 72 | qmult #( 73 | .Q(Q), 74 | .N(N)) mult12x(mvp_inTemp[0][1],vertex_inTemp[1],tempx2); 75 | 76 | qadd #( 77 | .Q(Q), 78 | .N(N)) add2x(tempx2,tempx1,res_TempIntermediate[0]); 79 | 80 | qmult #( 81 | .Q(Q), 82 | .N(N)) mult3x(mvp_inTemp[0][2],vertex_inTemp[2],tempx3); 83 | 84 | qadd #( 85 | .Q(Q), 86 | .N(N)) add3x(res_TempIntermediate[0],tempx3,res_TempIntermediate[1]); 87 | 88 | qmult #( 89 | .Q(Q), 90 | .N(N)) mult4x(mvp_inTemp[0][3],vertex_inTemp[3],tempx4); 91 | 92 | qadd #( 93 | .Q(Q), 94 | .N(N)) add4x(res_TempIntermediate[1],tempx4,res_TempOut[0]); 95 | 96 | 97 | //calculate y component of result vector 98 | qmult #( 99 | .Q(Q), 100 | .N(N)) mult1y(mvp_inTemp[1][0],vertex_inTemp[0],tempy1); 101 | 102 | qmult #( 103 | .Q(Q), 104 | .N(N)) mult12y(mvp_inTemp[1][1],vertex_inTemp[1],tempy2); 105 | 106 | qadd #( 107 | .Q(Q), 108 | .N(N)) add2y(tempy2,tempy1,res_TempIntermediate[2]); 109 | 110 | qmult #( 111 | .Q(Q), 112 | .N(N)) mult3y(mvp_inTemp[1][2],vertex_inTemp[2],tempy3); 113 | 114 | qadd #( 115 | .Q(Q), 116 | .N(N)) add3y(res_TempIntermediate[2],tempy3,res_TempIntermediate[3]); 117 | 118 | qmult #( 119 | .Q(Q), 120 | .N(N)) mult4y(mvp_inTemp[1][3],vertex_inTemp[3],tempy4); 121 | 122 | qadd #( 123 | .Q(Q), 124 | .N(N)) add4y(res_TempIntermediate[3],tempy4,res_TempOut[1]); 125 | 126 | 127 | //calculate z component of result vector 128 | qmult #( 129 | .Q(Q), 130 | .N(N)) mult1z(mvp_inTemp[2][0],vertex_inTemp[0],tempz1); 131 | 132 | qmult #( 133 | .Q(Q), 134 | .N(N)) mult12z(mvp_inTemp[2][1],vertex_inTemp[1],tempz2); 135 | 136 | qadd #( 137 | .Q(Q), 138 | .N(N)) add2z(tempz2,tempz1,res_TempIntermediate[4]); 139 | 140 | qmult #( 141 | .Q(Q), 142 | .N(N)) mult3z(mvp_inTemp[2][2],vertex_inTemp[2],tempz3); 143 | 144 | qadd #( 145 | .Q(Q), 146 | .N(N)) add3z(res_TempIntermediate[4],tempz3,res_TempIntermediate[5]); 147 | 148 | qmult #( 149 | .Q(Q), 150 | .N(N)) mult4z(mvp_inTemp[2][3],vertex_inTemp[3],tempz4); 151 | 152 | qadd #( 153 | .Q(Q), 154 | .N(N)) add4z(res_TempIntermediate[5],tempz4,res_TempOut[2]); 155 | 156 | 157 | //calculate w component of result vector 158 | qmult #( 159 | .Q(Q), 160 | .N(N)) mult1w(mvp_inTemp[3][0],vertex_inTemp[0],tempw1); 161 | 162 | qmult #( 163 | .Q(Q), 164 | .N(N)) mult12w(mvp_inTemp[3][1],vertex_inTemp[1],tempw2); 165 | 166 | qadd #( 167 | .Q(Q), 168 | .N(N)) add2w(tempw2,tempw1,res_TempIntermediate[6]); 169 | 170 | qmult #( 171 | .Q(Q), 172 | .N(N)) mult3w(mvp_inTemp[3][2],vertex_inTemp[2],tempw3); 173 | 174 | qadd #( 175 | .Q(Q), 176 | .N(N)) add3w(res_TempIntermediate[6],tempw3,res_TempIntermediate[7]); 177 | 178 | qmult #( 179 | .Q(Q), 180 | .N(N)) mult4w(mvp_inTemp[3][3],vertex_inTemp[3],tempw4); 181 | 182 | qadd #( 183 | .Q(Q), 184 | .N(N)) add4w(res_TempIntermediate[7],tempw4,res_TempOut[3]); 185 | 186 | 187 | 188 | 189 | always@(mvp_in,vertex_in,res_TempOut) begin 190 | //convert 1d to 3d 191 | //TODO consider row v col. 192 | 193 | //(matrix[row][col] 194 | { mvp_inTemp[0][0],mvp_inTemp[0][1],mvp_inTemp[0][2],mvp_inTemp[0][3], 195 | mvp_inTemp[1][0],mvp_inTemp[1][1],mvp_inTemp[1][2],mvp_inTemp[1][3], 196 | mvp_inTemp[2][0],mvp_inTemp[2][1],mvp_inTemp[2][2],mvp_inTemp[2][3], 197 | mvp_inTemp[3][0],mvp_inTemp[3][1],mvp_inTemp[3][2],mvp_inTemp[3][3] } = mvp_in; 198 | 199 | {vertex_inTemp[0],vertex_inTemp[1],vertex_inTemp[2],vertex_inTemp[3]} = vertex_in; 200 | 201 | 202 | 203 | 204 | //TODO(could use a generate loop) 205 | //makes assumption i iterates column, j iterates rows 206 | // for(i = 0; i<4; i= i + 1) 207 | // for(j=0;j <4; j = j +1) 208 | /// 209 | // 210 | // 211 | // res_Temp[i] = res_Temp[i] + mvp_inTemp[i][j] * vertex_inTemp[j]; 212 | 213 | //flatten result back to 1d vector (4 * 16 bits) 214 | out_reg_result = {res_TempOut[0],res_TempOut[1],res_TempOut[2],res_TempOut[3]}; 215 | end 216 | 217 | 218 | endmodule 219 | -------------------------------------------------------------------------------- /SimpleGPUonS7.srcs/sources_1/new/top.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | module top( 4 | 5 | input [2:0] MODE_I, //(000) = vertexWriteMode 6 | input CLK100MHZ, 7 | input WRITE_IN, 8 | input MOSI,SERIALCLOCK,ENABLE, 9 | 10 | output VGA_HS_O, 11 | output VGA_VS_O, 12 | output VGA_R, 13 | output VGA_G, 14 | output VGA_B, 15 | output led, 16 | output VALIDWORD, 17 | output READVERTEX, 18 | output WRITEVERTEX, 19 | output CLOCK25, 20 | output FULL, 21 | output [4:0] COUNTER 22 | ); 23 | 24 | wire i_clk = CLK100MHZ; 25 | 26 | reg we_ = 1; 27 | 28 | reg [13:0] romAddressLines = 0; 29 | 30 | reg [Nbit-1:0] romDataLines = 0; 31 | 32 | wire [Nbit-1:0] vertDataOut; 33 | //single buffer xyz 34 | reg [(Nbit*3)-1:0] vertexBuffer = 0; 35 | reg[(Nbit*4)-1:0] vertex = 0; 36 | 37 | //TODO - maybe remove after vert data comes from external source 38 | reg [32:0] iterationCounter = 0; 39 | reg [15:0] vertCounter = 0; 40 | reg [8:0] stateCounter = 0; 41 | 42 | reg vertexReady = 0; 43 | //TODO this will be ready when matrix buffer is full. 44 | reg matrixReady = 1; 45 | 46 | //projection regs 47 | reg startProjection = 0; 48 | //16 x 16 matrix 49 | reg [(Nbit*16)-1:0] mvp_in = 512'b00000000000000001011010100000100000000000000000000000000000000001000000000000000101101010000010000000000000000000000000000000000100000000000000010001011010110010000000000000001000101101011001010000000000000001000101101011001000000000000000000000000000000001000000000000000101110001100000010000000000000001011100011000000100000000000000010111000110000000000000000001000010100110100100010000000000000001001001111001101100000000000000010010011110011011000000000000000100100111100110100000000000010001010100100000110; 50 | wire [(Nbit*3)-1:0] projected_vector; 51 | wire projection_done; 52 | 53 | //viewToScreen regs 54 | localparam SCREEN_WIDTH = 640; 55 | localparam Qbit = 16; 56 | localparam Nbit = 32; 57 | reg [11:0 ]width = 640; 58 | reg [11:0 ]height = 480; 59 | 60 | wire [11:0] xpixel; 61 | wire [11:0] ypixel; 62 | wire pixelOnScreen; 63 | 64 | //framebuffer regs 65 | reg [18:0] frameBufferAddressLines1 = 0; 66 | reg [18:0] frameBufferAddressLines2 = 0; 67 | reg frameBufferData = 1; 68 | reg frameBuffer_we_ = 1; 69 | wire frameBufferDataOut1; 70 | wire frameBufferDataOut2; 71 | 72 | //memory address regs 73 | reg [19:0] memoryAddress = 0; 74 | 75 | //vga data 76 | wire hs; 77 | wire vs; 78 | wire [9:0] xvga; 79 | wire [8:0] yvga; 80 | reg [15:0] cnt = 0; 81 | reg pix_stb = 0; 82 | assign CLOCK25 = cnt[15]; 83 | 84 | reg outputColorReg = 0; 85 | 86 | //fifo data 87 | wire reset_fifos; 88 | reg readVertexFromFifo = 0; 89 | reg writeVertexToFifo = 0; 90 | wire empty; 91 | wire full; 92 | 93 | assign reset_fifos = 0; 94 | 95 | 96 | //spi data 97 | wire [Nbit-1:0] serialData; 98 | wire validSerialData; 99 | assign led = validSerialData; 100 | assign VALIDWORD = validSerialData; 101 | 102 | 103 | 104 | //DEBUG 105 | 106 | assign READVERTEX = readVertexFromFifo; 107 | assign WRITEVERTEX = writeVertexToFifo; 108 | assign FULL = full; 109 | 110 | 111 | 112 | 113 | always@(posedge CLK100MHZ) begin 114 | if(pix_stb) begin 115 | if(MODE_I == 3'b000 && validSerialData) begin 116 | writeVertexToFifo <= 1; 117 | end 118 | else begin 119 | writeVertexToFifo <= 0; 120 | end 121 | end 122 | end 123 | 124 | 125 | wire [7:0] debugCounter; 126 | 127 | SPI_slave#(.n(Nbit)) 128 | serialInput (.i_base_clock(cnt[15]), 129 | .i_SCK(SERIALCLOCK), 130 | .i_MOSI(MOSI), 131 | .i_EN(ENABLE), 132 | .o_WORDVALID(validSerialData), 133 | .o_DATA(serialData), 134 | .o_COUNTER(debugCounter) 135 | ); 136 | 137 | assign COUNTER = debugCounter[4:0]; 138 | 139 | //FIFO for reading vertex data from external source 140 | FIFO#(.DATA_WIDTH(Nbit),.RAM_DEPTH(3)) 141 | 142 | vertexFifo (.clk_i(cnt[15]), 143 | .reset_i(reset_fifos), 144 | .data_i(serialData), 145 | .r_en_i(readVertexFromFifo), 146 | .w_en_i(writeVertexToFifo), 147 | .data_o(vertDataOut), 148 | .empty_o(empty), 149 | .full_o(full)); 150 | 151 | dualPortStaticRam #(.ROMFILE("framebuffer.mem"),.DATA_WIDTH(1),.ADDR_WIDTH(19)) frameBuffer ( 152 | .address_1(frameBufferAddressLines1), 153 | .address_2(frameBufferAddressLines2), 154 | .data(frameBufferData), 155 | .we_(frameBuffer_we_), 156 | .clock(i_clk), 157 | .clock2(i_clk), 158 | .Q_1(frameBufferDataOut1), 159 | .Q_2(frameBufferDataOut2)); 160 | 161 | 162 | 163 | vert_projector #(.Q(Qbit),.N(Nbit)) 164 | projector(.i_clk(i_clk), 165 | .in_start(startProjection), 166 | .mvp_in( mvp_in), 167 | .vertex_in(vertex), 168 | .out_vector( projected_vector), 169 | .out_done(projection_done) 170 | ); 171 | 172 | ViewToScreenConverter#(.Q(Qbit),.N(Nbit)) 173 | viewToScreen(.width_in(width), 174 | .height_in(height), 175 | .vector_in(projected_vector), 176 | .xpix_out(xpixel), 177 | .ypix_out(ypixel), 178 | .on_screen_out(pixelOnScreen)); 179 | 180 | vgaSignalGenerator vgaPart ( 181 | .i_clk(i_clk), 182 | .i_pix_stb(pix_stb), 183 | .o_hs(hs), 184 | .o_vs(vs), 185 | .o_x(xvga), 186 | .o_y(yvga) 187 | ); 188 | 189 | assign VGA_HS_O = hs; 190 | assign VGA_VS_O = vs; 191 | assign VGA_R = outputColorReg; 192 | assign VGA_G = outputColorReg; 193 | assign VGA_B = outputColorReg; 194 | 195 | 196 | //on each clock - increment the counter and grab more data from ram. 197 | //TODO a state machine would work well for this... 198 | always@(posedge i_clk) begin 199 | 200 | {pix_stb, cnt} <= cnt + 16'h4000; // divide by 4: (2^16)/4 = 0x4000 201 | iterationCounter <= iterationCounter + 1; 202 | frameBufferAddressLines2 <= (yvga * SCREEN_WIDTH) + xvga; 203 | outputColorReg <= frameBufferDataOut2; 204 | 205 | 206 | //~3mhz 207 | if(pix_stb) begin 208 | 209 | // Based on MODE - jump to various states... 210 | //mode control 211 | /// 000_ vertex write 212 | /// 001 213 | /// 010 214 | /// 011_blank frame buffer 215 | 216 | // if mode is set to write vertex, and we're outside of write vertex states 217 | // then start write vertex flow over from 0. 218 | if(MODE_I == 3'b000 && stateCounter >= 200 ) begin 219 | stateCounter <= 0; 220 | end 221 | 222 | if(MODE_I == 3'b011) begin 223 | // jump to state 200 - where we will blank the framebuffer 224 | // by incrementing address and writing over and over. 225 | // until we leave this mode. 226 | stateCounter <= 200; 227 | end 228 | 229 | 230 | // wait until the FIFO is full, (3) numbers- 231 | // then grab all three, do the projection 232 | // then return to a waiting state. 233 | 234 | //wait for FIFO state 235 | if(stateCounter == 0) begin 236 | //reset some values for writing pixels 237 | frameBufferData <= 1; 238 | frameBuffer_we_ <= 1; 239 | 240 | if(full == 1) begin 241 | stateCounter <= 1; 242 | end 243 | 244 | end 245 | 246 | // start read from FIFO state 247 | if(stateCounter == 1) begin 248 | readVertexFromFifo <= 1; 249 | stateCounter <= 2; 250 | end 251 | //build up the vertex buffer 252 | //GET X 253 | if(stateCounter == 2) begin 254 | //save data from FIFO shifted into the buffer. 255 | vertexBuffer <= {vertexBuffer[(Nbit*2)-1:0],vertDataOut}; 256 | stateCounter <= stateCounter + 1; 257 | end 258 | 259 | //GET Y 260 | if(stateCounter == 3) begin 261 | //save data from ram shifted into the buffer. 262 | vertexBuffer <= {vertexBuffer[(Nbit*2)-1:0],vertDataOut}; 263 | stateCounter <= stateCounter + 1; 264 | end 265 | 266 | //GET Z 267 | if(stateCounter == 4) begin 268 | //save data from ram shifted into the buffer. 269 | vertexBuffer <= {vertexBuffer[(Nbit*2)-1:0],vertDataOut}; 270 | readVertexFromFifo <= 0; 271 | stateCounter <= stateCounter + 1; 272 | end 273 | 274 | if(stateCounter == 5) begin 275 | stateCounter <= stateCounter + 1; 276 | end 277 | 278 | // append W - and set the states. 279 | if (stateCounter == 6) begin 280 | vertCounter <= vertCounter + 1; 281 | vertex <= {vertexBuffer,{Qbit-1{1'b0}},1'b1,{Qbit{1'b0}}}; 282 | vertexReady <= 1; 283 | stateCounter <= 7; 284 | end 285 | 286 | // in state 4 - we are done buffering and are starting to project. 287 | if(stateCounter ==7 && vertexReady ==1 && matrixReady == 1) begin 288 | startProjection <= 1; 289 | stateCounter <= 8; 290 | end 291 | 292 | // projection just finished, reset some state and 293 | // draw the vertex. 294 | if(stateCounter >7 && stateCounter <100 && projection_done == 1) begin 295 | //lets wait here for another 15 cycles 296 | //TODO make this more easily adjustable. 297 | stateCounter <= stateCounter+1; 298 | end 299 | 300 | //TODO lets assume pixel calculations are done 301 | //so now map to memory and write to the framebuffer. 302 | // 303 | if(stateCounter == 100) begin 304 | #5 $display("vertexcount %d, should display at coord x %d, y %d ",vertCounter,xpixel,ypixel ); 305 | memoryAddress <= xpixel + (ypixel * SCREEN_WIDTH); 306 | frameBufferAddressLines1 <= memoryAddress; 307 | stateCounter <= 101; 308 | end 309 | 310 | // actually write a one into memory if the pixel is 311 | // visible - else give do nothing. 312 | if(stateCounter == 101) begin 313 | //assert the write bit for a clock. 314 | if(pixelOnScreen ==1) begin 315 | frameBuffer_we_ = 0; 316 | end 317 | stateCounter <= 102; 318 | 319 | end 320 | 321 | //we're done - reset all state 322 | if(stateCounter == 102) begin 323 | frameBuffer_we_ <= 1; 324 | stateCounter <= 0; 325 | vertexReady <= 0; 326 | startProjection <= 0; 327 | 328 | end 329 | 330 | if(stateCounter == 200) begin 331 | //should not be projecting during screen blank. 332 | vertexReady <= 0; 333 | startProjection <= 0; 334 | 335 | //we want to write black pixels 336 | frameBufferData <= 0; 337 | // this will overflow and loop. 338 | memoryAddress <= memoryAddress +1; 339 | frameBufferAddressLines1 <= memoryAddress; 340 | //write 0 to framebuffer 341 | frameBuffer_we_ <= 0; 342 | 343 | end 344 | 345 | end 346 | end 347 | 348 | endmodule 349 | -------------------------------------------------------------------------------- /SimpleGPUonS7.xpr: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 249 | 250 | 251 | 252 | 253 | 256 | 257 | 259 | 260 | 262 | 263 | 265 | 266 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | -------------------------------------------------------------------------------- /SimpleGPUonS7.srcs/constrs_1/new/s7.xdc: -------------------------------------------------------------------------------- 1 | ## This file is a general .xdc for the Arty S7-50 Rev. E 2 | ## To use it in a project: 3 | ## - uncomment the lines corresponding to used pins 4 | ## - rename the used ports (in each line, after get_ports) according to the top level signal names in the project 5 | 6 | ## Clock Signals 7 | #set_property -dict { PACKAGE_PIN F14 IOSTANDARD LVCMOS33 } [get_ports { CLK12MHZ }]; #IO_L13P_T2_MRCC_15 Sch=uclk 8 | #create_clock -add -name sys_clk_pin -period 83.333 -waveform {0 41.667} [get_ports { CLK12MHZ }]; 9 | set_property -dict { PACKAGE_PIN R2 IOSTANDARD SSTL135 } [get_ports { CLK100MHZ }]; #IO_L12P_T1_MRCC_34 Sch=ddr3_clk[200] 10 | create_clock -add -name sys_clk_pin -period 10.000 -waveform {0 5.000} [get_ports { CLK100MHZ }]; 11 | 12 | ## Switches 13 | #set_property -dict { PACKAGE_PIN H14 IOSTANDARD LVCMOS33 } [get_ports { sw[0] }]; #IO_L20N_T3_A19_15 Sch=sw[0] 14 | #set_property -dict { PACKAGE_PIN H18 IOSTANDARD LVCMOS33 } [get_ports { sw[1] }]; #IO_L21P_T3_DQS_15 Sch=sw[1] 15 | #set_property -dict { PACKAGE_PIN G18 IOSTANDARD LVCMOS33 } [get_ports { sw[2] }]; #IO_L21N_T3_DQS_A18_15 Sch=sw[2] 16 | #set_property -dict { PACKAGE_PIN M5 IOSTANDARD SSTL135 } [get_ports { sw[3] }]; #IO_L6N_T0_VREF_34 Sch=sw[3] 17 | 18 | ## RGB LEDs 19 | #set_property -dict { PACKAGE_PIN J15 IOSTANDARD LVCMOS33 } [get_ports { led0_r }]; #IO_L23N_T3_FWE_B_15 Sch=led0_r 20 | #set_property -dict { PACKAGE_PIN G17 IOSTANDARD LVCMOS33 } [get_ports { led0_g }]; #IO_L14N_T2_SRCC_15 Sch=led0_g 21 | #set_property -dict { PACKAGE_PIN F15 IOSTANDARD LVCMOS33 } [get_ports { led0_b }]; #IO_L13N_T2_MRCC_15 Sch=led0_b 22 | #set_property -dict { PACKAGE_PIN E15 IOSTANDARD LVCMOS33 } [get_ports { led1_r }]; #IO_L15N_T2_DQS_ADV_B_15 Sch=led1_r 23 | #set_property -dict { PACKAGE_PIN F18 IOSTANDARD LVCMOS33 } [get_ports { led1_g }]; #IO_L16P_T2_A28_15 Sch=led1_g 24 | #set_property -dict { PACKAGE_PIN E14 IOSTANDARD LVCMOS33 } [get_ports { led1_b }]; #IO_L15P_T2_DQS_15 Sch=led1_b 25 | 26 | ## LEDs 27 | set_property -dict { PACKAGE_PIN E18 IOSTANDARD LVCMOS33 } [get_ports { led }]; #IO_L16N_T2_A27_15 Sch=led[2] 28 | #set_property -dict { PACKAGE_PIN F13 IOSTANDARD LVCMOS33 } [get_ports { led[1] }]; #IO_L17P_T2_A26_15 Sch=led[3] 29 | #set_property -dict { PACKAGE_PIN E13 IOSTANDARD LVCMOS33 } [get_ports { led[2] }]; #IO_L17N_T2_A25_15 Sch=led[4] 30 | #set_property -dict { PACKAGE_PIN H15 IOSTANDARD LVCMOS33 } [get_ports { led[3] }]; #IO_L18P_T2_A24_15 Sch=led[5] 31 | 32 | ## Buttons 33 | #set_property -dict { PACKAGE_PIN G15 IOSTANDARD LVCMOS33 } [get_ports { btn[0] }]; #IO_L18N_T2_A23_15 Sch=btn[0] 34 | #set_property -dict { PACKAGE_PIN K16 IOSTANDARD LVCMOS33 } [get_ports { btn[1] }]; #IO_L19P_T3_A22_15 Sch=btn[1] 35 | #set_property -dict { PACKAGE_PIN J16 IOSTANDARD LVCMOS33 } [get_ports { btn[2] }]; #IO_L19N_T3_A21_VREF_15 Sch=btn[2] 36 | #set_property -dict { PACKAGE_PIN H13 IOSTANDARD LVCMOS33 } [get_ports { btn[3] }]; #IO_L20P_T3_A20_15 Sch=btn[3] 37 | 38 | ## Pmod Header JA 39 | set_property -dict { PACKAGE_PIN L17 IOSTANDARD LVCMOS33 } [get_ports { COUNTER[0] }]; #IO_L4P_T0_D04_14 Sch=ja_p[1] 40 | set_property -dict { PACKAGE_PIN L18 IOSTANDARD LVCMOS33 } [get_ports { COUNTER[1] }]; #IO_L4N_T0_D05_14 Sch=ja_n[1] 41 | set_property -dict { PACKAGE_PIN M14 IOSTANDARD LVCMOS33 } [get_ports { COUNTER[2] }]; #IO_L5P_T0_D06_14 Sch=ja_p[2] 42 | set_property -dict { PACKAGE_PIN N14 IOSTANDARD LVCMOS33 } [get_ports { COUNTER[3] }]; #IO_L5N_T0_D07_14 Sch=ja_n[2] 43 | set_property -dict { PACKAGE_PIN M16 IOSTANDARD LVCMOS33 } [get_ports { COUNTER[4] }]; #IO_L7P_T1_D09_14 Sch=ja_p[3] 44 | #set_property -dict { PACKAGE_PIN M17 IOSTANDARD LVCMOS33 } [get_ports { INPUTDATA[5] }]; #IO_L7N_T1_D10_14 Sch=ja_n[3] 45 | #set_property -dict { PACKAGE_PIN M18 IOSTANDARD LVCMOS33 } [get_ports { INPUTDATA[6] }]; #IO_L8P_T1_D11_14 Sch=ja_p[4] 46 | #set_property -dict { PACKAGE_PIN N18 IOSTANDARD LVCMOS33 } [get_ports { INPUTDATA[7] }]; #IO_L8N_T1_D12_14 Sch=ja_n[4] 47 | 48 | ## Pmod Header JB 49 | #set_property -dict { PACKAGE_PIN P17 IOSTANDARD LVCMOS33 } [get_ports { INPUTDATA[8] }]; #IO_L9P_T1_DQS_14 Sch=jb_p[1] 50 | #set_property -dict { PACKAGE_PIN P18 IOSTANDARD LVCMOS33 } [get_ports { INPUTDATA[9] }]; #IO_L9N_T1_DQS_D13_14 Sch=jb_n[1] 51 | #set_property -dict { PACKAGE_PIN R18 IOSTANDARD LVCMOS33 } [get_ports { INPUTDATA[10] }]; #IO_L10P_T1_D14_14 Sch=jb_p[2] 52 | #set_property -dict { PACKAGE_PIN T18 IOSTANDARD LVCMOS33 } [get_ports { INPUTDATA[11] }]; #IO_L10N_T1_D15_14 Sch=jb_n[2] 53 | #set_property -dict { PACKAGE_PIN P14 IOSTANDARD LVCMOS33 } [get_ports { INPUTDATA[12] }]; #IO_L11P_T1_SRCC_14 Sch=jb_p[3] 54 | #set_property -dict { PACKAGE_PIN P15 IOSTANDARD LVCMOS33 } [get_ports { INPUTDATA[13] }]; #IO_L11N_T1_SRCC_14 Sch=jb_n[3] 55 | #set_property -dict { PACKAGE_PIN N15 IOSTANDARD LVCMOS33 } [get_ports { INPUTDATA[14] }]; #IO_L12P_T1_MRCC_14 Sch=jb_p[4] 56 | #set_property -dict { PACKAGE_PIN P16 IOSTANDARD LVCMOS33 } [get_ports { INPUTDATA[15] }]; #IO_L12N_T1_MRCC_14 Sch=jb_n[4] 57 | 58 | ## Pmod Header JC 59 | #set_property -dict { PACKAGE_PIN U15 IOSTANDARD LVCMOS33 } [get_ports { INPUTDATA[16] }]; #IO_L18P_T2_A12_D28_14 Sch=jc1/ck_io[41] 60 | #set_property -dict { PACKAGE_PIN V16 IOSTANDARD LVCMOS33 } [get_ports { INPUTDATA[17] }]; #IO_L18N_T2_A11_D27_14 Sch=jc2/ck_io[40] 61 | #set_property -dict { PACKAGE_PIN U17 IOSTANDARD LVCMOS33 } [get_ports { INPUTDATA[18] }]; #IO_L15P_T2_DQS_RDWR_B_14 Sch=jc3/ck_io[39] 62 | #set_property -dict { PACKAGE_PIN U18 IOSTANDARD LVCMOS33 } [get_ports { INPUTDATA[19] }]; #IO_L15N_T2_DQS_DOUT_CSO_B_14 Sch=jc4/ck_io[38] 63 | #set_property -dict { PACKAGE_PIN U16 IOSTANDARD LVCMOS33 } [get_ports { INPUTDATA[20] }]; #IO_L16P_T2_CSI_B_14 Sch=jc7/ck_io[37] 64 | #set_property -dict { PACKAGE_PIN P13 IOSTANDARD LVCMOS33 } [get_ports { INPUTDATA[21] }]; #IO_L19P_T3_A10_D26_14 Sch=jc8/ck_io[36] 65 | #set_property -dict { PACKAGE_PIN R13 IOSTANDARD LVCMOS33 } [get_ports { INPUTDATA[22] }]; #IO_L19N_T3_A09_D25_VREF_14 Sch=jc9/ck_io[35] 66 | #set_property -dict { PACKAGE_PIN V14 IOSTANDARD LVCMOS33 } [get_ports { INPUTDATA[23] }]; #IO_L20P_T3_A08_D24_14 Sch=jc10/ck_io[34] 67 | 68 | ## Pmod Header JD 69 | set_property -dict { PACKAGE_PIN V15 IOSTANDARD LVCMOS33 } [get_ports { ENABLE }]; #IO_L20N_T3_A07_D23_14 Sch=jd1/ck_io[33] 70 | set_property -dict { PACKAGE_PIN U12 IOSTANDARD LVCMOS33 } [get_ports { SERIALCLOCK }]; #IO_L21P_T3_DQS_14 Sch=jd2/ck_io[32] 71 | set_property -dict { PACKAGE_PIN V13 IOSTANDARD LVCMOS33 } [get_ports { MOSI }]; #IO_L21N_T3_DQS_A06_D22_14 Sch=jd3/ck_io[31] 72 | set_property -dict { PACKAGE_PIN T12 IOSTANDARD LVCMOS33 } [get_ports { WRITE_IN }]; #IO_L22P_T3_A05_D21_14 Sch=jd4/ck_io[30] 73 | set_property -dict { PACKAGE_PIN T13 IOSTANDARD LVCMOS33 } [get_ports { MODE_I[2] }]; #IO_L22N_T3_A04_D20_14 Sch=jd7/ck_io[29] 74 | set_property -dict { PACKAGE_PIN R11 IOSTANDARD LVCMOS33 } [get_ports { MODE_I[1] }]; #IO_L23P_T3_A03_D19_14 Sch=jd8/ck_io[28] 75 | set_property -dict { PACKAGE_PIN T11 IOSTANDARD LVCMOS33 } [get_ports { MODE_I[0] }]; #IO_L23N_T3_A02_D18_14 Sch=jd9/ck_io[27] 76 | #set_property -dict { PACKAGE_PIN U11 IOSTANDARD LVCMOS33 } [get_ports { }]; #IO_L24P_T3_A01_D17_14 Sch=jd10/ck_io[26] 77 | 78 | ## USB-UART Interface 79 | #set_property -dict { PACKAGE_PIN R12 IOSTANDARD LVCMOS33 } [get_ports { uart_rxd_out }]; #IO_25_14 Sch=uart_rxd_out 80 | #set_property -dict { PACKAGE_PIN V12 IOSTANDARD LVCMOS33 } [get_ports { uart_txd_in }]; #IO_L24N_T3_A00_D16_14 Sch=uart_txd_in 81 | 82 | ## ChipKit Outer Digital Header 83 | set_property -dict { PACKAGE_PIN L13 IOSTANDARD LVCMOS33 } [get_ports { VGA_HS_O }]; #IO_0_14 Sch=ck_io[0] 84 | set_property -dict { PACKAGE_PIN N13 IOSTANDARD LVCMOS33 } [get_ports { VGA_VS_O }]; #IO_L6N_T0_D08_VREF_14 Sch=ck_io[1] 85 | set_property -dict { PACKAGE_PIN L16 IOSTANDARD LVCMOS33 } [get_ports { VGA_R }]; #IO_L3N_T0_DQS_EMCCLK_14 Sch=ck_io[2] 86 | set_property -dict { PACKAGE_PIN R14 IOSTANDARD LVCMOS33 } [get_ports { VGA_G }]; #IO_L13P_T2_MRCC_14 Sch=ck_io[3] 87 | set_property -dict { PACKAGE_PIN T14 IOSTANDARD LVCMOS33 } [get_ports { VGA_B }]; #IO_L13N_T2_MRCC_14 Sch=ck_io[4] 88 | set_property -dict { PACKAGE_PIN R16 IOSTANDARD LVCMOS33 } [get_ports { VALIDWORD }]; #IO_L14P_T2_SRCC_14 Sch=ck_io[5] 89 | set_property -dict { PACKAGE_PIN R17 IOSTANDARD LVCMOS33 } [get_ports { CLOCK25 }]; #IO_L14N_T2_SRCC_14 Sch=ck_io[6] 90 | set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 } [get_ports { READVERTEX }]; #IO_L16N_T2_A15_D31_14 Sch=ck_io[7] 91 | set_property -dict { PACKAGE_PIN R15 IOSTANDARD LVCMOS33 } [get_ports { WRITEVERTEX }]; #IO_L17P_T2_A14_D30_14 Sch=ck_io[8] 92 | set_property -dict { PACKAGE_PIN T15 IOSTANDARD LVCMOS33 } [get_ports { FULL }]; #IO_L17N_T2_A13_D29_14 Sch=ck_io[9] 93 | 94 | ## ChipKit SPI Header 95 | ## NOTE: The ChipKit SPI header ports can also be used as digital I/O and share FPGA pins with ck_io10-13. Do not use both at the same time. 96 | #set_property -dict { PACKAGE_PIN H16 IOSTANDARD LVCMOS33 } [get_ports { ck_io10_ss }]; #IO_L22P_T3_A17_15 Sch=ck_io10_ss 97 | #set_property -dict { PACKAGE_PIN H17 IOSTANDARD LVCMOS33 } [get_ports { ck_io11_mosi }]; #IO_L22N_T3_A16_15 Sch=ck_io11_mosi 98 | #set_property -dict { PACKAGE_PIN K14 IOSTANDARD LVCMOS33 } [get_ports { ck_io12_miso }]; #IO_L23P_T3_FOE_B_15 Sch=ck_io12_miso 99 | #set_property -dict { PACKAGE_PIN G16 IOSTANDARD LVCMOS33 } [get_ports { ck_io13_sck }]; #IO_L14P_T2_SRCC_15 Sch=ck_io13_sck 100 | 101 | ## ChipKit Inner Digital Header 102 | ## Note: these pins are shared with PMOD Headers JC and JD and cannot be used at the same time as the applicable PMOD interface(s) 103 | #set_property -dict { PACKAGE_PIN U11 IOSTANDARD LVCMOS33 } [get_ports { ck_io26 }]; #IO_L24P_T3_A01_D17_14 Sch=jd10/ck_io[26] 104 | #set_property -dict { PACKAGE_PIN T11 IOSTANDARD LVCMOS33 } [get_ports { ck_io27 }]; #IO_L23N_T3_A02_D18_14 Sch=jd9/ck_io[27] 105 | #set_property -dict { PACKAGE_PIN R11 IOSTANDARD LVCMOS33 } [get_ports { ck_io28 }]; #IO_L23P_T3_A03_D19_14 Sch=jd8/ck_io[28] 106 | #set_property -dict { PACKAGE_PIN T13 IOSTANDARD LVCMOS33 } [get_ports { ck_io29 }]; #IO_L22N_T3_A04_D20_14 Sch=jd7/ck_io[29] 107 | #set_property -dict { PACKAGE_PIN T12 IOSTANDARD LVCMOS33 } [get_ports { ck_io30 }]; #IO_L22P_T3_A05_D21_14 Sch=jd4/ck_io[30] 108 | #set_property -dict { PACKAGE_PIN V13 IOSTANDARD LVCMOS33 } [get_ports { ck_io31 }]; #IO_L21N_T3_DQS_A06_D22_14 Sch=jd3/ck_io[31] 109 | #set_property -dict { PACKAGE_PIN U12 IOSTANDARD LVCMOS33 } [get_ports { ck_io32 }]; #IO_L21P_T3_DQS_14 Sch=jd2/ck_io[32] 110 | #set_property -dict { PACKAGE_PIN V15 IOSTANDARD LVCMOS33 } [get_ports { ck_io33 }]; #IO_L20N_T3_A07_D23_14 Sch=jd1/ck_io[33] 111 | #set_property -dict { PACKAGE_PIN V14 IOSTANDARD LVCMOS33 } [get_ports { ck_io34 }]; #IO_L20P_T3_A08_D24_14 Sch=jc10/ck_io[34] 112 | #set_property -dict { PACKAGE_PIN R13 IOSTANDARD LVCMOS33 } [get_ports { ck_io35 }]; #IO_L19N_T3_A09_D25_VREF_14 Sch=jc9/ck_io[35] 113 | #set_property -dict { PACKAGE_PIN P13 IOSTANDARD LVCMOS33 } [get_ports { ck_io36 }]; #IO_L19P_T3_A10_D26_14 Sch=jc8/ck_io[36] 114 | #set_property -dict { PACKAGE_PIN U16 IOSTANDARD LVCMOS33 } [get_ports { ck_io37 }]; #IO_L16P_T2_CSI_B_14 Sch=jc7/ck_io[37] 115 | #set_property -dict { PACKAGE_PIN U18 IOSTANDARD LVCMOS33 } [get_ports { ck_io38 }]; #IO_L15N_T2_DQS_DOUT_CSO_B_14 Sch=jc4/ck_io[38] 116 | #set_property -dict { PACKAGE_PIN U17 IOSTANDARD LVCMOS33 } [get_ports { ck_io39 }]; #IO_L15P_T2_DQS_RDWR_B_14 Sch=jc3/ck_io[39] 117 | #set_property -dict { PACKAGE_PIN V16 IOSTANDARD LVCMOS33 } [get_ports { ck_io40 }]; #IO_L18N_T2_A11_D27_14 Sch=jc2/ck_io[40] 118 | #set_property -dict { PACKAGE_PIN U15 IOSTANDARD LVCMOS33 } [get_ports { ck_io41 }]; #IO_L18P_T2_A12_D28_14 Sch=jc1/ck_io[41] 119 | 120 | ## Dedicated Analog Inputs 121 | #set_property -dict { PACKAGE_PIN J10 } [get_ports { vp_in }]; #IO_L1P_T0_AD4P_35 Sch=v_p 122 | #set_property -dict { PACKAGE_PIN K9 } [get_ports { vn_in }]; #IO_L1N_T0_AD4N_35 Sch=v_n 123 | 124 | ## ChipKit Outer Analog Header - as Single-Ended Analog Inputs 125 | ## NOTE: These ports can be used as single-ended analog inputs with voltages from 0-3.3V (ChipKit analog pins A0-A5) or as digital I/O. 126 | ## WARNING: Do not use both sets of constraints at the same time! 127 | ## NOTE: The following constraints should be used with the XADC IP core when using these ports as analog inputs. 128 | #set_property -dict { PACKAGE_PIN B13 IOSTANDARD LVCMOS33 } [get_ports { vaux0_p }]; #IO_L1P_T0_AD0P_15 Sch=ck_an_p[0] ChipKit pin=A0 129 | #set_property -dict { PACKAGE_PIN A13 IOSTANDARD LVCMOS33 } [get_ports { vaux0_n }]; #IO_L1N_T0_AD0N_15 Sch=ck_an_n[0] ChipKit pin=A0 130 | #set_property -dict { PACKAGE_PIN B15 IOSTANDARD LVCMOS33 } [get_ports { vaux1_p }]; #IO_L3P_T0_DQS_AD1P_15 Sch=ck_an_p[1] ChipKit pin=A1 131 | #set_property -dict { PACKAGE_PIN A15 IOSTANDARD LVCMOS33 } [get_ports { vaux1_n }]; #IO_L3N_T0_DQS_AD1N_15 Sch=ck_an_n[1] ChipKit pin=A1 132 | #set_property -dict { PACKAGE_PIN E12 IOSTANDARD LVCMOS33 } [get_ports { vaux9_p }]; #IO_L5P_T0_AD9P_15 Sch=ck_an_p[2] ChipKit pin=A2 133 | #set_property -dict { PACKAGE_PIN D12 IOSTANDARD LVCMOS33 } [get_ports { vaux9_n }]; #IO_L5N_T0_AD9N_15 Sch=ck_an_n[2] ChipKit pin=A2 134 | #set_property -dict { PACKAGE_PIN B17 IOSTANDARD LVCMOS33 } [get_ports { vaux2_p }]; #IO_L7P_T1_AD2P_15 Sch=ck_an_p[3] ChipKit pin=A3 135 | #set_property -dict { PACKAGE_PIN A17 IOSTANDARD LVCMOS33 } [get_ports { vaux2_n }]; #IO_L7N_T1_AD2N_15 Sch=ck_an_n[3] ChipKit pin=A3 136 | #set_property -dict { PACKAGE_PIN C17 IOSTANDARD LVCMOS33 } [get_ports { vaux10_p }]; #IO_L8P_T1_AD10P_15 Sch=ck_an_p[4] ChipKit pin=A4 137 | #set_property -dict { PACKAGE_PIN B18 IOSTANDARD LVCMOS33 } [get_ports { vaux10_n }]; #IO_L8N_T1_AD10N_15 Sch=ck_an_n[4] ChipKit pin=A4 138 | #set_property -dict { PACKAGE_PIN E16 IOSTANDARD LVCMOS33 } [get_ports { vaux11_p }]; #IO_L10P_T1_AD11P_15 Sch=ck_an_p[5] ChipKit pin=A5 139 | #set_property -dict { PACKAGE_PIN E17 IOSTANDARD LVCMOS33 } [get_ports { vaux11_n }]; #IO_L10N_T1_AD11N_15 Sch=ck_an_n[5] ChipKit pin=A5 140 | ## ChipKit Outer Analog Header - as Digital I/O 141 | ## NOTE: The following constraints should be used when using these ports as digital I/O. 142 | #set_property -dict { PACKAGE_PIN G13 IOSTANDARD LVCMOS33 } [get_ports { ck_a0 }]; #IO_0_15 Sch=ck_a[0] 143 | #set_property -dict { PACKAGE_PIN B16 IOSTANDARD LVCMOS33 } [get_ports { ck_a1 }]; #IO_L4P_T0_15 Sch=ck_a[1] 144 | #set_property -dict { PACKAGE_PIN A16 IOSTANDARD LVCMOS33 } [get_ports { ck_a2 }]; #IO_L4N_T0_15 Sch=ck_a[2] 145 | #set_property -dict { PACKAGE_PIN C13 IOSTANDARD LVCMOS33 } [get_ports { ck_a3 }]; #IO_L6P_T0_15 Sch=ck_a[3] 146 | #set_property -dict { PACKAGE_PIN C14 IOSTANDARD LVCMOS33 } [get_ports { ck_a4 }]; #IO_L6N_T0_VREF_15 Sch=ck_a[4] 147 | #set_property -dict { PACKAGE_PIN D18 IOSTANDARD LVCMOS33 } [get_ports { ck_a5 }]; #IO_L11P_T1_SRCC_15 Sch=ck_a[5] 148 | 149 | ## ChipKit Inner Analog Header - as Differential Analog Inputs 150 | ## NOTE: These ports can be used as differential analog inputs with voltages from 0-1.0V (ChipKit analog pins A6-A11) or as digital I/O. 151 | ## WARNING: Do not use both sets of constraints at the same time! 152 | ## NOTE: The following constraints should be used with the XADC core when using these ports as analog inputs. 153 | #set_property -dict { PACKAGE_PIN B14 IOSTANDARD LVCMOS33 } [get_ports { vaux8_p }]; #IO_L2P_T0_AD8P_15 Sch=ad_p[8] ChipKit pin=A6 154 | #set_property -dict { PACKAGE_PIN A14 IOSTANDARD LVCMOS33 } [get_ports { vaux8_n }]; #IO_L2N_T0_AD8N_15 Sch=ad_n[8] ChipKit pin=A7 155 | #set_property -dict { PACKAGE_PIN D16 IOSTANDARD LVCMOS33 } [get_ports { vaux3_p }]; #IO_L9P_T1_DQS_AD3P_15 Sch=ad_p[3] ChipKit pin=A8 156 | #set_property -dict { PACKAGE_PIN D17 IOSTANDARD LVCMOS33 } [get_ports { vaux3_n }]; #IO_L9N_T1_DQS_AD3N_15 Sch=ad_n[3] ChipKit pin=A9 157 | ## ChipKit Inner Analog Header - as Digital I/O 158 | ## NOTE: The following constraints should be used when using the inner analog header ports as digital I/O. 159 | #set_property -dict { PACKAGE_PIN B14 IOSTANDARD LVCMOS33 } [get_ports { ck_a6 }]; #IO_L2P_T0_AD8P_15 Sch=ad_p[8] 160 | #set_property -dict { PACKAGE_PIN A14 IOSTANDARD LVCMOS33 } [get_ports { ck_a7 }]; #IO_L2N_T0_AD8N_15 Sch=ad_n[8] 161 | #set_property -dict { PACKAGE_PIN D16 IOSTANDARD LVCMOS33 } [get_ports { ck_a8 }]; #IO_L9P_T1_DQS_AD3P_15 Sch=ad_p[3] 162 | #set_property -dict { PACKAGE_PIN D17 IOSTANDARD LVCMOS33 } [get_ports { ck_a9 }]; #IO_L9N_T1_DQS_AD3N_15 Sch=ad_n[3] 163 | #set_property -dict { PACKAGE_PIN D14 IOSTANDARD LVCMOS33 } [get_ports { ck_a10 }]; #IO_L12P_T1_MRCC_15 Sch=ck_a10_r (Cannot be used as an analog input) 164 | #set_property -dict { PACKAGE_PIN D15 IOSTANDARD LVCMOS33 } [get_ports { ck_a11 }]; #IO_L12N_T1_MRCC_15 Sch=ck_a11_r (Cannot be used as an analog input) 165 | 166 | ## ChipKit I2C 167 | #set_property -dict { PACKAGE_PIN J14 IOSTANDARD LVCMOS33 } [get_ports { ck_scl }]; #IO_L24N_T3_RS0_15 Sch=ck_scl 168 | #set_property -dict { PACKAGE_PIN J13 IOSTANDARD LVCMOS33 } [get_ports { ck_sda }]; #IO_L24P_T3_RS1_15 Sch=ck_sda 169 | 170 | ## Misc. ChipKit Ports 171 | #set_property -dict { PACKAGE_PIN K13 IOSTANDARD LVCMOS33 } [get_ports { ck_ioa }]; #IO_25_15 Sch=ck_ioa 172 | #set_property -dict { PACKAGE_PIN C18 IOSTANDARD LVCMOS33 } [get_ports { ck_rst }]; #IO_L11N_T1_SRCC_15 173 | 174 | ## Quad SPI Flash 175 | ## Note: the SCK clock signal can be driven using the STARTUPE2 primitive 176 | #set_property -dict { PACKAGE_PIN M13 IOSTANDARD LVCMOS33 } [get_ports { qspi_cs }]; #IO_L6P_T0_FCS_B_14 Sch=qspi_cs 177 | #set_property -dict { PACKAGE_PIN K17 IOSTANDARD LVCMOS33 } [get_ports { qspi_dq[0] }]; #IO_L1P_T0_D00_MOSI_14 Sch=qspi_dq[0] 178 | #set_property -dict { PACKAGE_PIN K18 IOSTANDARD LVCMOS33 } [get_ports { qspi_dq[1] }]; #IO_L1N_T0_D01_DIN_14 Sch=qspi_dq[1] 179 | #set_property -dict { PACKAGE_PIN L14 IOSTANDARD LVCMOS33 } [get_ports { qspi_dq[2] }]; #IO_L2P_T0_D02_14 Sch=qspi_dq[2] 180 | #set_property -dict { PACKAGE_PIN M15 IOSTANDARD LVCMOS33 } [get_ports { qspi_dq[3] }]; #IO_L2N_T0_D03_14 Sch=qspi_dq[3] 181 | 182 | ## Configuration options, can be used for all designs 183 | set_property BITSTREAM.CONFIG.CONFIGRATE 50 [current_design] 184 | set_property CONFIG_VOLTAGE 3.3 [current_design] 185 | set_property CFGBVS VCCO [current_design] 186 | set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design] 187 | set_property CONFIG_MODE SPIx4 [current_design] 188 | 189 | ## SW3 is assigned to a pin M5 in the 1.35v bank. This pin can also be used as 190 | ## the VREF for BANK 34. To ensure that SW3 does not define the reference voltage 191 | ## and to be able to use this pin as an ordinary I/O the following property must 192 | ## be set to enable an internal VREF for BANK 34. Since a 1.35v supply is being 193 | ## used the internal reference is set to half that value (i.e. 0.675v). Note that 194 | ## this property must be set even if SW3 is not used in the design. 195 | set_property INTERNAL_VREF 0.675 [get_iobanks 34] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 2.1, February 1999 3 | 4 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | [This is the first released version of the Lesser GPL. It also counts 10 | as the successor of the GNU Library Public License, version 2, hence 11 | the version number 2.1.] 12 | 13 | Preamble 14 | 15 | The licenses for most software are designed to take away your 16 | freedom to share and change it. By contrast, the GNU General Public 17 | Licenses are intended to guarantee your freedom to share and change 18 | free software--to make sure the software is free for all its users. 19 | 20 | This license, the Lesser General Public License, applies to some 21 | specially designated software packages--typically libraries--of the 22 | Free Software Foundation and other authors who decide to use it. You 23 | can use it too, but we suggest you first think carefully about whether 24 | this license or the ordinary General Public License is the better 25 | strategy to use in any particular case, based on the explanations below. 26 | 27 | When we speak of free software, we are referring to freedom of use, 28 | not price. Our General Public Licenses are designed to make sure that 29 | you have the freedom to distribute copies of free software (and charge 30 | for this service if you wish); that you receive source code or can get 31 | it if you want it; that you can change the software and use pieces of 32 | it in new free programs; and that you are informed that you can do 33 | these things. 34 | 35 | To protect your rights, we need to make restrictions that forbid 36 | distributors to deny you these rights or to ask you to surrender these 37 | rights. These restrictions translate to certain responsibilities for 38 | you if you distribute copies of the library or if you modify it. 39 | 40 | For example, if you distribute copies of the library, whether gratis 41 | or for a fee, you must give the recipients all the rights that we gave 42 | you. You must make sure that they, too, receive or can get the source 43 | code. If you link other code with the library, you must provide 44 | complete object files to the recipients, so that they can relink them 45 | with the library after making changes to the library and recompiling 46 | it. And you must show them these terms so they know their rights. 47 | 48 | We protect your rights with a two-step method: (1) we copyright the 49 | library, and (2) we offer you this license, which gives you legal 50 | permission to copy, distribute and/or modify the library. 51 | 52 | To protect each distributor, we want to make it very clear that 53 | there is no warranty for the free library. Also, if the library is 54 | modified by someone else and passed on, the recipients should know 55 | that what they have is not the original version, so that the original 56 | author's reputation will not be affected by problems that might be 57 | introduced by others. 58 | 59 | Finally, software patents pose a constant threat to the existence of 60 | any free program. We wish to make sure that a company cannot 61 | effectively restrict the users of a free program by obtaining a 62 | restrictive license from a patent holder. Therefore, we insist that 63 | any patent license obtained for a version of the library must be 64 | consistent with the full freedom of use specified in this license. 65 | 66 | Most GNU software, including some libraries, is covered by the 67 | ordinary GNU General Public License. This license, the GNU Lesser 68 | General Public License, applies to certain designated libraries, and 69 | is quite different from the ordinary General Public License. We use 70 | this license for certain libraries in order to permit linking those 71 | libraries into non-free programs. 72 | 73 | When a program is linked with a library, whether statically or using 74 | a shared library, the combination of the two is legally speaking a 75 | combined work, a derivative of the original library. The ordinary 76 | General Public License therefore permits such linking only if the 77 | entire combination fits its criteria of freedom. The Lesser General 78 | Public License permits more lax criteria for linking other code with 79 | the library. 80 | 81 | We call this license the "Lesser" General Public License because it 82 | does Less to protect the user's freedom than the ordinary General 83 | Public License. It also provides other free software developers Less 84 | of an advantage over competing non-free programs. These disadvantages 85 | are the reason we use the ordinary General Public License for many 86 | libraries. However, the Lesser license provides advantages in certain 87 | special circumstances. 88 | 89 | For example, on rare occasions, there may be a special need to 90 | encourage the widest possible use of a certain library, so that it becomes 91 | a de-facto standard. To achieve this, non-free programs must be 92 | allowed to use the library. A more frequent case is that a free 93 | library does the same job as widely used non-free libraries. In this 94 | case, there is little to gain by limiting the free library to free 95 | software only, so we use the Lesser General Public License. 96 | 97 | In other cases, permission to use a particular library in non-free 98 | programs enables a greater number of people to use a large body of 99 | free software. For example, permission to use the GNU C Library in 100 | non-free programs enables many more people to use the whole GNU 101 | operating system, as well as its variant, the GNU/Linux operating 102 | system. 103 | 104 | Although the Lesser General Public License is Less protective of the 105 | users' freedom, it does ensure that the user of a program that is 106 | linked with the Library has the freedom and the wherewithal to run 107 | that program using a modified version of the Library. 108 | 109 | The precise terms and conditions for copying, distribution and 110 | modification follow. Pay close attention to the difference between a 111 | "work based on the library" and a "work that uses the library". The 112 | former contains code derived from the library, whereas the latter must 113 | be combined with the library in order to run. 114 | 115 | GNU LESSER GENERAL PUBLIC LICENSE 116 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 117 | 118 | 0. This License Agreement applies to any software library or other 119 | program which contains a notice placed by the copyright holder or 120 | other authorized party saying it may be distributed under the terms of 121 | this Lesser General Public License (also called "this License"). 122 | Each licensee is addressed as "you". 123 | 124 | A "library" means a collection of software functions and/or data 125 | prepared so as to be conveniently linked with application programs 126 | (which use some of those functions and data) to form executables. 127 | 128 | The "Library", below, refers to any such software library or work 129 | which has been distributed under these terms. A "work based on the 130 | Library" means either the Library or any derivative work under 131 | copyright law: that is to say, a work containing the Library or a 132 | portion of it, either verbatim or with modifications and/or translated 133 | straightforwardly into another language. (Hereinafter, translation is 134 | included without limitation in the term "modification".) 135 | 136 | "Source code" for a work means the preferred form of the work for 137 | making modifications to it. For a library, complete source code means 138 | all the source code for all modules it contains, plus any associated 139 | interface definition files, plus the scripts used to control compilation 140 | and installation of the library. 141 | 142 | Activities other than copying, distribution and modification are not 143 | covered by this License; they are outside its scope. The act of 144 | running a program using the Library is not restricted, and output from 145 | such a program is covered only if its contents constitute a work based 146 | on the Library (independent of the use of the Library in a tool for 147 | writing it). Whether that is true depends on what the Library does 148 | and what the program that uses the Library does. 149 | 150 | 1. You may copy and distribute verbatim copies of the Library's 151 | complete source code as you receive it, in any medium, provided that 152 | you conspicuously and appropriately publish on each copy an 153 | appropriate copyright notice and disclaimer of warranty; keep intact 154 | all the notices that refer to this License and to the absence of any 155 | warranty; and distribute a copy of this License along with the 156 | Library. 157 | 158 | You may charge a fee for the physical act of transferring a copy, 159 | and you may at your option offer warranty protection in exchange for a 160 | fee. 161 | 162 | 2. You may modify your copy or copies of the Library or any portion 163 | of it, thus forming a work based on the Library, and copy and 164 | distribute such modifications or work under the terms of Section 1 165 | above, provided that you also meet all of these conditions: 166 | 167 | a) The modified work must itself be a software library. 168 | 169 | b) You must cause the files modified to carry prominent notices 170 | stating that you changed the files and the date of any change. 171 | 172 | c) You must cause the whole of the work to be licensed at no 173 | charge to all third parties under the terms of this License. 174 | 175 | d) If a facility in the modified Library refers to a function or a 176 | table of data to be supplied by an application program that uses 177 | the facility, other than as an argument passed when the facility 178 | is invoked, then you must make a good faith effort to ensure that, 179 | in the event an application does not supply such function or 180 | table, the facility still operates, and performs whatever part of 181 | its purpose remains meaningful. 182 | 183 | (For example, a function in a library to compute square roots has 184 | a purpose that is entirely well-defined independent of the 185 | application. Therefore, Subsection 2d requires that any 186 | application-supplied function or table used by this function must 187 | be optional: if the application does not supply it, the square 188 | root function must still compute square roots.) 189 | 190 | These requirements apply to the modified work as a whole. If 191 | identifiable sections of that work are not derived from the Library, 192 | and can be reasonably considered independent and separate works in 193 | themselves, then this License, and its terms, do not apply to those 194 | sections when you distribute them as separate works. But when you 195 | distribute the same sections as part of a whole which is a work based 196 | on the Library, the distribution of the whole must be on the terms of 197 | this License, whose permissions for other licensees extend to the 198 | entire whole, and thus to each and every part regardless of who wrote 199 | it. 200 | 201 | Thus, it is not the intent of this section to claim rights or contest 202 | your rights to work written entirely by you; rather, the intent is to 203 | exercise the right to control the distribution of derivative or 204 | collective works based on the Library. 205 | 206 | In addition, mere aggregation of another work not based on the Library 207 | with the Library (or with a work based on the Library) on a volume of 208 | a storage or distribution medium does not bring the other work under 209 | the scope of this License. 210 | 211 | 3. You may opt to apply the terms of the ordinary GNU General Public 212 | License instead of this License to a given copy of the Library. To do 213 | this, you must alter all the notices that refer to this License, so 214 | that they refer to the ordinary GNU General Public License, version 2, 215 | instead of to this License. (If a newer version than version 2 of the 216 | ordinary GNU General Public License has appeared, then you can specify 217 | that version instead if you wish.) Do not make any other change in 218 | these notices. 219 | 220 | Once this change is made in a given copy, it is irreversible for 221 | that copy, so the ordinary GNU General Public License applies to all 222 | subsequent copies and derivative works made from that copy. 223 | 224 | This option is useful when you wish to copy part of the code of 225 | the Library into a program that is not a library. 226 | 227 | 4. You may copy and distribute the Library (or a portion or 228 | derivative of it, under Section 2) in object code or executable form 229 | under the terms of Sections 1 and 2 above provided that you accompany 230 | it with the complete corresponding machine-readable source code, which 231 | must be distributed under the terms of Sections 1 and 2 above on a 232 | medium customarily used for software interchange. 233 | 234 | If distribution of object code is made by offering access to copy 235 | from a designated place, then offering equivalent access to copy the 236 | source code from the same place satisfies the requirement to 237 | distribute the source code, even though third parties are not 238 | compelled to copy the source along with the object code. 239 | 240 | 5. A program that contains no derivative of any portion of the 241 | Library, but is designed to work with the Library by being compiled or 242 | linked with it, is called a "work that uses the Library". Such a 243 | work, in isolation, is not a derivative work of the Library, and 244 | therefore falls outside the scope of this License. 245 | 246 | However, linking a "work that uses the Library" with the Library 247 | creates an executable that is a derivative of the Library (because it 248 | contains portions of the Library), rather than a "work that uses the 249 | library". The executable is therefore covered by this License. 250 | Section 6 states terms for distribution of such executables. 251 | 252 | When a "work that uses the Library" uses material from a header file 253 | that is part of the Library, the object code for the work may be a 254 | derivative work of the Library even though the source code is not. 255 | Whether this is true is especially significant if the work can be 256 | linked without the Library, or if the work is itself a library. The 257 | threshold for this to be true is not precisely defined by law. 258 | 259 | If such an object file uses only numerical parameters, data 260 | structure layouts and accessors, and small macros and small inline 261 | functions (ten lines or less in length), then the use of the object 262 | file is unrestricted, regardless of whether it is legally a derivative 263 | work. (Executables containing this object code plus portions of the 264 | Library will still fall under Section 6.) 265 | 266 | Otherwise, if the work is a derivative of the Library, you may 267 | distribute the object code for the work under the terms of Section 6. 268 | Any executables containing that work also fall under Section 6, 269 | whether or not they are linked directly with the Library itself. 270 | 271 | 6. As an exception to the Sections above, you may also combine or 272 | link a "work that uses the Library" with the Library to produce a 273 | work containing portions of the Library, and distribute that work 274 | under terms of your choice, provided that the terms permit 275 | modification of the work for the customer's own use and reverse 276 | engineering for debugging such modifications. 277 | 278 | You must give prominent notice with each copy of the work that the 279 | Library is used in it and that the Library and its use are covered by 280 | this License. You must supply a copy of this License. If the work 281 | during execution displays copyright notices, you must include the 282 | copyright notice for the Library among them, as well as a reference 283 | directing the user to the copy of this License. Also, you must do one 284 | of these things: 285 | 286 | a) Accompany the work with the complete corresponding 287 | machine-readable source code for the Library including whatever 288 | changes were used in the work (which must be distributed under 289 | Sections 1 and 2 above); and, if the work is an executable linked 290 | with the Library, with the complete machine-readable "work that 291 | uses the Library", as object code and/or source code, so that the 292 | user can modify the Library and then relink to produce a modified 293 | executable containing the modified Library. (It is understood 294 | that the user who changes the contents of definitions files in the 295 | Library will not necessarily be able to recompile the application 296 | to use the modified definitions.) 297 | 298 | b) Use a suitable shared library mechanism for linking with the 299 | Library. A suitable mechanism is one that (1) uses at run time a 300 | copy of the library already present on the user's computer system, 301 | rather than copying library functions into the executable, and (2) 302 | will operate properly with a modified version of the library, if 303 | the user installs one, as long as the modified version is 304 | interface-compatible with the version that the work was made with. 305 | 306 | c) Accompany the work with a written offer, valid for at 307 | least three years, to give the same user the materials 308 | specified in Subsection 6a, above, for a charge no more 309 | than the cost of performing this distribution. 310 | 311 | d) If distribution of the work is made by offering access to copy 312 | from a designated place, offer equivalent access to copy the above 313 | specified materials from the same place. 314 | 315 | e) Verify that the user has already received a copy of these 316 | materials or that you have already sent this user a copy. 317 | 318 | For an executable, the required form of the "work that uses the 319 | Library" must include any data and utility programs needed for 320 | reproducing the executable from it. However, as a special exception, 321 | the materials to be distributed need not include anything that is 322 | normally distributed (in either source or binary form) with the major 323 | components (compiler, kernel, and so on) of the operating system on 324 | which the executable runs, unless that component itself accompanies 325 | the executable. 326 | 327 | It may happen that this requirement contradicts the license 328 | restrictions of other proprietary libraries that do not normally 329 | accompany the operating system. Such a contradiction means you cannot 330 | use both them and the Library together in an executable that you 331 | distribute. 332 | 333 | 7. You may place library facilities that are a work based on the 334 | Library side-by-side in a single library together with other library 335 | facilities not covered by this License, and distribute such a combined 336 | library, provided that the separate distribution of the work based on 337 | the Library and of the other library facilities is otherwise 338 | permitted, and provided that you do these two things: 339 | 340 | a) Accompany the combined library with a copy of the same work 341 | based on the Library, uncombined with any other library 342 | facilities. This must be distributed under the terms of the 343 | Sections above. 344 | 345 | b) Give prominent notice with the combined library of the fact 346 | that part of it is a work based on the Library, and explaining 347 | where to find the accompanying uncombined form of the same work. 348 | 349 | 8. You may not copy, modify, sublicense, link with, or distribute 350 | the Library except as expressly provided under this License. Any 351 | attempt otherwise to copy, modify, sublicense, link with, or 352 | distribute the Library is void, and will automatically terminate your 353 | rights under this License. However, parties who have received copies, 354 | or rights, from you under this License will not have their licenses 355 | terminated so long as such parties remain in full compliance. 356 | 357 | 9. You are not required to accept this License, since you have not 358 | signed it. However, nothing else grants you permission to modify or 359 | distribute the Library or its derivative works. These actions are 360 | prohibited by law if you do not accept this License. Therefore, by 361 | modifying or distributing the Library (or any work based on the 362 | Library), you indicate your acceptance of this License to do so, and 363 | all its terms and conditions for copying, distributing or modifying 364 | the Library or works based on it. 365 | 366 | 10. Each time you redistribute the Library (or any work based on the 367 | Library), the recipient automatically receives a license from the 368 | original licensor to copy, distribute, link with or modify the Library 369 | subject to these terms and conditions. You may not impose any further 370 | restrictions on the recipients' exercise of the rights granted herein. 371 | You are not responsible for enforcing compliance by third parties with 372 | this License. 373 | 374 | 11. If, as a consequence of a court judgment or allegation of patent 375 | infringement or for any other reason (not limited to patent issues), 376 | conditions are imposed on you (whether by court order, agreement or 377 | otherwise) that contradict the conditions of this License, they do not 378 | excuse you from the conditions of this License. If you cannot 379 | distribute so as to satisfy simultaneously your obligations under this 380 | License and any other pertinent obligations, then as a consequence you 381 | may not distribute the Library at all. For example, if a patent 382 | license would not permit royalty-free redistribution of the Library by 383 | all those who receive copies directly or indirectly through you, then 384 | the only way you could satisfy both it and this License would be to 385 | refrain entirely from distribution of the Library. 386 | 387 | If any portion of this section is held invalid or unenforceable under any 388 | particular circumstance, the balance of the section is intended to apply, 389 | and the section as a whole is intended to apply in other circumstances. 390 | 391 | It is not the purpose of this section to induce you to infringe any 392 | patents or other property right claims or to contest validity of any 393 | such claims; this section has the sole purpose of protecting the 394 | integrity of the free software distribution system which is 395 | implemented by public license practices. Many people have made 396 | generous contributions to the wide range of software distributed 397 | through that system in reliance on consistent application of that 398 | system; it is up to the author/donor to decide if he or she is willing 399 | to distribute software through any other system and a licensee cannot 400 | impose that choice. 401 | 402 | This section is intended to make thoroughly clear what is believed to 403 | be a consequence of the rest of this License. 404 | 405 | 12. If the distribution and/or use of the Library is restricted in 406 | certain countries either by patents or by copyrighted interfaces, the 407 | original copyright holder who places the Library under this License may add 408 | an explicit geographical distribution limitation excluding those countries, 409 | so that distribution is permitted only in or among countries not thus 410 | excluded. In such case, this License incorporates the limitation as if 411 | written in the body of this License. 412 | 413 | 13. The Free Software Foundation may publish revised and/or new 414 | versions of the Lesser General Public License from time to time. 415 | Such new versions will be similar in spirit to the present version, 416 | but may differ in detail to address new problems or concerns. 417 | 418 | Each version is given a distinguishing version number. If the Library 419 | specifies a version number of this License which applies to it and 420 | "any later version", you have the option of following the terms and 421 | conditions either of that version or of any later version published by 422 | the Free Software Foundation. If the Library does not specify a 423 | license version number, you may choose any version ever published by 424 | the Free Software Foundation. 425 | 426 | 14. If you wish to incorporate parts of the Library into other free 427 | programs whose distribution conditions are incompatible with these, 428 | write to the author to ask for permission. For software which is 429 | copyrighted by the Free Software Foundation, write to the Free 430 | Software Foundation; we sometimes make exceptions for this. Our 431 | decision will be guided by the two goals of preserving the free status 432 | of all derivatives of our free software and of promoting the sharing 433 | and reuse of software generally. 434 | 435 | NO WARRANTY 436 | 437 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 438 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 439 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 440 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 441 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 442 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 443 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 444 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 445 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 446 | 447 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 448 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 449 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 450 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 451 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 452 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 453 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 454 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 455 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 456 | DAMAGES. 457 | 458 | END OF TERMS AND CONDITIONS 459 | 460 | How to Apply These Terms to Your New Libraries 461 | 462 | If you develop a new library, and you want it to be of the greatest 463 | possible use to the public, we recommend making it free software that 464 | everyone can redistribute and change. You can do so by permitting 465 | redistribution under these terms (or, alternatively, under the terms of the 466 | ordinary General Public License). 467 | 468 | To apply these terms, attach the following notices to the library. It is 469 | safest to attach them to the start of each source file to most effectively 470 | convey the exclusion of warranty; and each file should have at least the 471 | "copyright" line and a pointer to where the full notice is found. 472 | 473 | 474 | Copyright (C) 475 | 476 | This library is free software; you can redistribute it and/or 477 | modify it under the terms of the GNU Lesser General Public 478 | License as published by the Free Software Foundation; either 479 | version 2.1 of the License, or (at your option) any later version. 480 | 481 | This library is distributed in the hope that it will be useful, 482 | but WITHOUT ANY WARRANTY; without even the implied warranty of 483 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 484 | Lesser General Public License for more details. 485 | 486 | You should have received a copy of the GNU Lesser General Public 487 | License along with this library; if not, write to the Free Software 488 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 489 | USA 490 | 491 | Also add information on how to contact you by electronic and paper mail. 492 | 493 | You should also get your employer (if you work as a programmer) or your 494 | school, if any, to sign a "copyright disclaimer" for the library, if 495 | necessary. Here is a sample; alter the names: 496 | 497 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 498 | library `Frob' (a library for tweaking knobs) written by James Random 499 | Hacker. 500 | 501 | , 1 April 1990 502 | Ty Coon, President of Vice 503 | 504 | That's all there is to it! 505 | --------------------------------------------------------------------------------