From: Joshua Wise Date: Sat, 15 Mar 2008 22:17:46 +0000 (-0400) Subject: Initial revision -- unknown as to whether it works, post-precision increment. X-Git-Tag: PRE_ROLLBACK~19 X-Git-Url: http://git.joshuawise.com/mandelfpga.git/commitdiff_plain/05c0805be5682a94d874a89f05f01d1830941a70 Initial revision -- unknown as to whether it works, post-precision increment. --- 05c0805be5682a94d874a89f05f01d1830941a70 diff --git a/FPGA.pal b/FPGA.pal new file mode 100644 index 0000000..fa8bb6f --- /dev/null +++ b/FPGA.pal @@ -0,0 +1,258 @@ +GIMP Palette +Name: FPGA +0 0 0 +0 0 85 +0 0 170 +0 0 255 +0 36 0 +0 36 85 +0 36 170 +0 36 255 +0 72 0 +0 72 85 +0 72 170 +0 72 255 +0 109 0 +0 109 85 +0 109 170 +0 109 255 +0 145 0 +0 145 85 +0 145 170 +0 145 255 +0 182 0 +0 182 85 +0 182 170 +0 182 255 +0 218 0 +0 218 85 +0 218 170 +0 218 255 +0 255 0 +0 255 85 +0 255 170 +0 255 255 +36 0 0 +36 0 85 +36 0 170 +36 0 255 +36 36 0 +36 36 85 +36 36 170 +36 36 255 +36 72 0 +36 72 85 +36 72 170 +36 72 255 +36 109 0 +36 109 85 +36 109 170 +36 109 255 +36 145 0 +36 145 85 +36 145 170 +36 145 255 +36 182 0 +36 182 85 +36 182 170 +36 182 255 +36 218 0 +36 218 85 +36 218 170 +36 218 255 +36 255 0 +36 255 85 +36 255 170 +36 255 255 +72 0 0 +72 0 85 +72 0 170 +72 0 255 +72 36 0 +72 36 85 +72 36 170 +72 36 255 +72 72 0 +72 72 85 +72 72 170 +72 72 255 +72 109 0 +72 109 85 +72 109 170 +72 109 255 +72 145 0 +72 145 85 +72 145 170 +72 145 255 +72 182 0 +72 182 85 +72 182 170 +72 182 255 +72 218 0 +72 218 85 +72 218 170 +72 218 255 +72 255 0 +72 255 85 +72 255 170 +72 255 255 +109 0 0 +109 0 85 +109 0 170 +109 0 255 +109 36 0 +109 36 85 +109 36 170 +109 36 255 +109 72 0 +109 72 85 +109 72 170 +109 72 255 +109 109 0 +109 109 85 +109 109 170 +109 109 255 +109 145 0 +109 145 85 +109 145 170 +109 145 255 +109 182 0 +109 182 85 +109 182 170 +109 182 255 +109 218 0 +109 218 85 +109 218 170 +109 218 255 +109 255 0 +109 255 85 +109 255 170 +109 255 255 +145 0 0 +145 0 85 +145 0 170 +145 0 255 +145 36 0 +145 36 85 +145 36 170 +145 36 255 +145 72 0 +145 72 85 +145 72 170 +145 72 255 +145 109 0 +145 109 85 +145 109 170 +145 109 255 +145 145 0 +145 145 85 +145 145 170 +145 145 255 +145 182 0 +145 182 85 +145 182 170 +145 182 255 +145 218 0 +145 218 85 +145 218 170 +145 218 255 +145 255 0 +145 255 85 +145 255 170 +145 255 255 +182 0 0 +182 0 85 +182 0 170 +182 0 255 +182 36 0 +182 36 85 +182 36 170 +182 36 255 +182 72 0 +182 72 85 +182 72 170 +182 72 255 +182 109 0 +182 109 85 +182 109 170 +182 109 255 +182 145 0 +182 145 85 +182 145 170 +182 145 255 +182 182 0 +182 182 85 +182 182 170 +182 182 255 +182 218 0 +182 218 85 +182 218 170 +182 218 255 +182 255 0 +182 255 85 +182 255 170 +182 255 255 +218 0 0 +218 0 85 +218 0 170 +218 0 255 +218 36 0 +218 36 85 +218 36 170 +218 36 255 +218 72 0 +218 72 85 +218 72 170 +218 72 255 +218 109 0 +218 109 85 +218 109 170 +218 109 255 +218 145 0 +218 145 85 +218 145 170 +218 145 255 +218 182 0 +218 182 85 +218 182 170 +218 182 255 +218 218 0 +218 218 85 +218 218 170 +218 218 255 +218 255 0 +218 255 85 +218 255 170 +218 255 255 +255 0 0 +255 0 85 +255 0 170 +255 0 255 +255 36 0 +255 36 85 +255 36 170 +255 36 255 +255 72 0 +255 72 85 +255 72 170 +255 72 255 +255 109 0 +255 109 85 +255 109 170 +255 109 255 +255 145 0 +255 145 85 +255 145 170 +255 145 255 +255 182 0 +255 182 85 +255 182 170 +255 182 255 +255 218 0 +255 218 85 +255 218 170 +255 218 255 +255 255 0 +255 255 85 +255 255 170 +255 255 255 diff --git a/Main.v b/Main.v new file mode 100644 index 0000000..2dd4764 --- /dev/null +++ b/Main.v @@ -0,0 +1,386 @@ +/* + * MandelFPGA + * by Joshua Wise and Chris Lu + * + * An implementation of a pipelined algorithm to calculate the Mandelbrot set + * in real time on an FPGA. + */ + +`define XRES 640 +`define YRES 480 +`define WHIRRRRR 21 + +module SyncGen( + input pixclk, + output reg vs, hs, + output reg [11:0] xout = `WHIRRRRR, yout = 0, + output wire [11:0] xoutreal, youtreal, + output reg border); + + reg [11:0] x = 0, y = 0; // Used for generating border and timing. + assign xoutreal = x; + assign youtreal = y; + + parameter XFPORCH = 16; + parameter XSYNC = 96; + parameter XBPORCH = 48; + + parameter YFPORCH = 10; + parameter YSYNC = 2; + parameter YBPORCH = 29; + + always @(posedge pixclk) + begin + if (x >= (`XRES + XFPORCH + XSYNC + XBPORCH)) + begin + if (y >= (`YRES + YFPORCH + YSYNC + YBPORCH)) + y <= 0; + else + y <= y + 1; + x <= 0; + end else + x <= x + 1; + + if (xout >= (`XRES + XFPORCH + XSYNC + XBPORCH)) + begin + if (yout >= (`YRES + YFPORCH + YSYNC + YBPORCH)) + yout <= 0; + else + yout <= yout + 1; + xout <= 0; + end else + xout <= xout + 1; + hs <= (x >= (`XRES + XFPORCH)) && (x < (`XRES + XFPORCH + XSYNC)); + vs <= (y >= (`YRES + YFPORCH)) && (y < (`YRES + YFPORCH + YSYNC)); + border <= (x > `XRES) || (y > `YRES); + end +endmodule + +// bits: 1.12 + +module NaiveMultiplier( + input clk, + input [12:0] x, y, + input xsign, ysign, + output reg [12:0] out, + output reg sign, + output reg [1:0] ovf); + + always @(posedge clk) + begin + {ovf,out} <= + (((y[12] ? (x ) : 0) + + (y[11] ? (x >> 1) : 0) + + (y[10] ? (x >> 2) : 0) + + (y[9] ? (x >> 3) : 0)) + + ((y[8] ? (x >> 4) : 0) + + (y[7] ? (x >> 5) : 0) + + (y[6] ? (x >> 6) : 0)))+ + (((y[5] ? (x >> 7) : 0) + + (y[4] ? (x >> 8) : 0) + + (y[3] ? (x >> 9) : 0)) + + ((y[2] ? (x >> 10): 0) + + (y[1] ? (x >> 11): 0) + + (y[0] ? (x >> 12): 0))); + sign <= xsign ^ ysign; + end + +endmodule + +module Multiplier( + input clk, + input [11:0] x, y, + input xsign, ysign, + output wire [11:0] out, + output wire sign, + output wire [1:0] overflow); + + NaiveMultiplier nm(clk, x, y, xsign, ysign, out, sign, overflow); + +endmodule + +module MandelUnit( + input clk, + input [12:0] x, y, + input xsign, ysign, + input [13:0] r, i, + input rsign, isign, + input [7:0] ibail, icuriter, + output reg [12:0] xout, yout, + output reg xsout, ysout, + output reg [13:0] rout, iout, + output reg rsout, isout, + output reg [7:0] obail, ocuriter); + + wire [13:0] r2, i2, ri, diff; + wire r2sign, i2sign, risign, dsign; + wire [16:0] bigsum; + wire bigsum_ovf, rin_ovf, iin_ovf, throwaway; + + reg [12:0] xd, yd; + reg rd, id; + reg xsd, ysd; + reg [7:0] ibaild, curiterd; + + assign ri[0] = 0; + + Multiplier r2m(clk, r[12:0], r[12:0], rsign, rsign, r2[12:0], r2sign, r2[13]); + Multiplier i2m(clk, i[12:0], i[12:0], isign, isign, i2[12:0], i2sign, i2[13]); + Multiplier rim(clk, r[12:0], i[12:0], rsign, isign, ri[13:1], risign, throwaway); + + assign bigsum = r2 + i2; + assign bigsum_ovf = bigsum[16] | bigsum[15] | bigsum[14]; + assign rin_ovf = rd; + assign iin_ovf = id; + assign diff = (r2 > i2) ? r2 - i2 : i2 - r2; + assign dsign = (r2 > i2) ? 0 : 1; + + always @ (posedge clk) + begin + xd <= x; + yd <= y; + xsd <= xsign; + ysd <= ysign; + xout <= xd; + yout <= yd; + xsout <= xsd; + ysout <= ysd; + ibaild <= ibail; + curiterd <= icuriter; + rd <= r[13]; + id <= i[13]; + + if (xsd ^ dsign) begin + if (diff > xd) begin + rout <= diff - xd; + rsout <= dsign; + end else begin + rout <= xd - diff; + rsout <= xsd; + end + end else begin + rout <= diff + xd; + rsout <= xsd; + end + + if (ysd ^ risign) begin + if (ri > yd) begin + iout <= ri - yd; + isout <= risign; + end else begin + iout <= yd - ri; + isout <= ysd; + end + end else begin + iout <= ri + yd; + isout <= ysd; + end + + // If we haven't bailed out, and we meet any of the bailout conditions, + // bail out now. Otherwise, leave the bailout at whatever it was before. + if ((ibaild == 255) && (bigsum_ovf | rin_ovf | iin_ovf)) + obail <= curiterd; + else + obail <= ibaild; + ocuriter <= curiterd + 8'b1; + end + +endmodule + +module Mandelbrot( + input mclk, + input pixclk, + input [11:0] x, y, + input [12:0] xofs, yofs, + input [7:0] colorofs, + input [2:0] scale, + output reg [2:0] red, green, output reg [1:0] blue); + + wire [12:0] rx, ry; + wire [13:0] nx, ny; + wire rxsign, rysign; + + assign nx = x + xofs; + assign ny = y + yofs; + assign rx = (nx[13] ? -nx[12:0] : nx[12:0]) << scale; + assign rxsign = nx[13]; + assign ry = (ny[13] ? -ny[12:0] : ny[12:0]) << scale; + assign rysign = ny[13]; + + + wire [13:0] mr[9:0], mi[9:0]; + wire mrs[9:0], mis[9:0]; + wire [7:0] mb[9:0]; + wire [12:0] xprop[9:0], yprop[9:0]; + wire xsprop[9:0], ysprop[9:0]; + wire [7:0] curiter[9:0]; + + wire [13:0] initx, inity, initr, initi; + wire [7:0] initci, initb; + wire initxs, initys, initrs, initis; + + reg [13:0] loopx, loopy, loopr, loopi; + reg [7:0] loopci, loopb; + reg loopxs, loopys, looprs, loopis; + + reg state = 0; + + // On pixclk = 1, + // A new value to be loaded comes in, and a value in need of loopback comes out. + // On pixclk = 0, + // A new value in need of loopback comes in, and a completed value comes out. + + assign initx = state ? rx : loopx; + assign inity = state ? ry : loopy; + assign initr = state ? rx : loopr; + assign initi = state ? ry : loopi; + assign initxs = state ? rxsign : loopxs; + assign initys = state ? rysign : loopys; + assign initrs = state ? rxsign : looprs; + assign initis = state ? rysign : loopis; + assign initb = state ? 8'b11111111 : loopb; + assign initci = state ? 8'b00000000 : loopci; + + reg [7:0] out; + reg pixclksync; + always @(negedge mclk) + pixclksync <= ~pixclk; + + always @(posedge mclk) + begin + if (!state) begin + out <= ~mb[9] + colorofs; + end else begin + {red, green, blue} <= {out[0],out[3],out[6],out[1],out[4],out[7],out[2],out[5]}; + loopx <= xprop[9]; + loopy <= yprop[9]; + loopr <= mr[9]; + loopi <= mi[9]; + loopxs <= xsprop[9]; + loopys <= ysprop[9]; + looprs <= mrs[9]; + loopis <= mis[9]; + loopb <= mb[9]; + loopci <= curiter[9]; + end + state <= ~pixclksync; + end + + MandelUnit mu0( + mclk, + initx, inity, initxs, initys, + initr, initi, initrs, initis, + initb, initci, + xprop[0], yprop[0], xsprop[0], ysprop[0], + mr[0], mi[0], mrs[0], mis[0], + mb[0], curiter[0]); + + MandelUnit mu1(mclk, + xprop[0], yprop[0], xsprop[0], ysprop[0], mr[0], mi[0], mrs[0], mis[0], mb[0], curiter[0], + xprop[1], yprop[1], xsprop[1], ysprop[1], mr[1], mi[1], mrs[1], mis[1], mb[1], curiter[1]); + MandelUnit mu2(mclk, + xprop[1], yprop[1], xsprop[1], ysprop[1], mr[1], mi[1], mrs[1], mis[1], mb[1], curiter[1], + xprop[2], yprop[2], xsprop[2], ysprop[2], mr[2], mi[2], mrs[2], mis[2], mb[2], curiter[2]); + MandelUnit mu3(mclk, + xprop[2], yprop[2], xsprop[2], ysprop[2], mr[2], mi[2], mrs[2], mis[2], mb[2], curiter[2], + xprop[3], yprop[3], xsprop[3], ysprop[3], mr[3], mi[3], mrs[3], mis[3], mb[3], curiter[3]); + MandelUnit mu4(mclk, + xprop[3], yprop[3], xsprop[3], ysprop[3], mr[3], mi[3], mrs[3], mis[3], mb[3], curiter[3], + xprop[4], yprop[4], xsprop[4], ysprop[4], mr[4], mi[4], mrs[4], mis[4], mb[4], curiter[4]); + MandelUnit mu5(mclk, + xprop[4], yprop[4], xsprop[4], ysprop[4], mr[4], mi[4], mrs[4], mis[4], mb[4], curiter[4], + xprop[5], yprop[5], xsprop[5], ysprop[5], mr[5], mi[5], mrs[5], mis[5], mb[5], curiter[5]); + MandelUnit mu6(mclk, + xprop[5], yprop[5], xsprop[5], ysprop[5], mr[5], mi[5], mrs[5], mis[5], mb[5], curiter[5], + xprop[6], yprop[6], xsprop[6], ysprop[6], mr[6], mi[6], mrs[6], mis[6], mb[6], curiter[6]); + MandelUnit mu7(mclk, + xprop[6], yprop[6], xsprop[6], ysprop[6], mr[6], mi[6], mrs[6], mis[6], mb[6], curiter[6], + xprop[7], yprop[7], xsprop[7], ysprop[7], mr[7], mi[7], mrs[7], mis[7], mb[7], curiter[7]); + MandelUnit mu8(mclk, + xprop[7], yprop[7], xsprop[7], ysprop[7], mr[7], mi[7], mrs[7], mis[7], mb[7], curiter[7], + xprop[8], yprop[8], xsprop[8], ysprop[8], mr[8], mi[8], mrs[8], mis[8], mb[8], curiter[8]); + MandelUnit mu9(mclk, + xprop[8], yprop[8], xsprop[8], ysprop[8], mr[8], mi[8], mrs[8], mis[8], mb[8], curiter[8], + xprop[9], yprop[9], xsprop[9], ysprop[9], mr[9], mi[9], mrs[9], mis[9], mb[9], curiter[9]); + +endmodule + +module Logo( + input pixclk, + input [11:0] x, y, + output wire enb, + output wire [2:0] red, green, output wire [1:0] blue); + + reg [1:0] logo[8191:0]; + initial $readmemb("logo.readmemb", logo); + + assign enb = (x < 96) && (y < 64); + wire [12:0] addr = {y[5:0], x[6:0]}; + wire [1:0] data = logo[addr]; + assign {red, green, blue} = + (data == 2'b00) ? 8'b00000000 : + ((data == 2'b01) ? 8'b00011100 : + ((data == 2'b10) ? 8'b11100000 : + 8'b11111111)); +endmodule + +module MandelTop( + input gclk, output wire dcmok, + output wire vs, hs, + output wire [2:0] red, green, output [1:0] blue, + input left, right, up, down, rst, cycle, logooff, + input [2:0] scale); + + wire border; + wire pixclk; + wire [7:0] zero = 8'b0; + wire clk; + wire [11:0] x, y; + reg [12:0] xofs = -`XRES/2, yofs = -`YRES/2; + reg [5:0] slowctr = 0; + reg [7:0] colorcycle = 0; + wire [11:0] realx, realy; + + wire logoenb; + wire [2:0] mandelr, mandelg, logor, logog; + wire [1:0] mandelb, logob; + + pixDCM dcm( // CLKIN is 50MHz xtal, CLKFX_OUT is 25MHz + .CLKIN_IN(gclk), + .CLKFX_OUT(pixclk), + .CLKIN_IBUFG_OUT(clk), + .LOCKED_OUT(dcmok) + ); + + SyncGen sync(pixclk, vs, hs, x, y, realx, realy, border); + Mandelbrot mandel(clk, pixclk, x, y, xofs, yofs, cycle ? colorcycle : 0, scale, mandelr, mandelg, mandelb); + Logo logo(pixclk, realx, realy, logoenb, logor, logog, logob); + + assign {red,green,blue} = + border ? 8'b00000000 : + (!logooff && logoenb) ? {logor, logog, logob} : {mandelr, mandelg, mandelb}; + + always @(posedge vs) + begin + if (rst) + begin + xofs <= -`XRES/2; + yofs <= -`YRES/2; + colorcycle <= 0; + end else begin + if (up) yofs <= yofs + 1; + else if (down) yofs <= yofs - 1; + + if (left) xofs <= xofs + 1; + else if (right) xofs <= xofs - 1; + + if (slowctr == 0) + colorcycle <= colorcycle + 1; + end + + if (slowctr == 12) + slowctr <= 0; + else + slowctr <= slowctr + 1; + end +endmodule diff --git a/ctoreadmemb.c b/ctoreadmemb.c new file mode 100644 index 0000000..330cb6d --- /dev/null +++ b/ctoreadmemb.c @@ -0,0 +1,29 @@ +#include "mandelfpga.c" +#include + +// w t f, the data is inverted somehow :psyduck: +void main() +{ + int y,x; + + for (y=MANDELFPGA_HEIGHT-1; y >= 0; y--) + { + for (x = MANDELFPGA_WIDTH; x < 128; x++) + printf("00\n"); // XST can't take don't cares there. sad face + for (x=MANDELFPGA_WIDTH-1; x >= 0; x--) + { + unsigned char *p = &MANDELFPGA_PIXEL_DATA[MANDELFPGA_BYTES_PER_PIXEL*(MANDELFPGA_WIDTH*y+x)]; + if (p[0] == 0 && p[1] == 0 && p[2] == 0) + printf("00\n"); + else if (p[0] == 255 && p[1] == 0 && p[2] == 0) + printf("10\n"); + else if (p[0] == 0 && p[1] == 255 && ((p[2] == 0) || (p[2] == 36))) + printf("01\n"); + else if (p[0] == 255 && p[1] == 255 && p[2] == 255) + printf("11\n"); + else + fprintf(stderr, "o shi, what is %d %d %d\n", p[0], p[1], p[2]); + } + + } +} \ No newline at end of file diff --git a/makepal.c b/makepal.c new file mode 100644 index 0000000..915e15b --- /dev/null +++ b/makepal.c @@ -0,0 +1,14 @@ +void main() +{ + unsigned char c = 0; + printf("GIMP Palette\n"); + printf("Name: FPGA\n"); + do + { + printf("%d %d %d\n", + (int)(255 * ((float)(c >> 5)) / 7.0), + (int)(255 * ((float)((c >> 2) & 0x7) / 7.0)), + (int)(255 * ((float)(c & 0x3) / 3.0))); + c++; + } while (c != 0); +} \ No newline at end of file diff --git a/mandelfpga.xcf b/mandelfpga.xcf new file mode 100644 index 0000000..e1a1419 Binary files /dev/null and b/mandelfpga.xcf differ diff --git a/shnasto.cmd b/shnasto.cmd new file mode 100644 index 0000000..cda4be7 --- /dev/null +++ b/shnasto.cmd @@ -0,0 +1,7 @@ +setMode -bs +setCable -port svf -file "/home/joshua/projects/fpga/MandelFPGA/test.svf" +addDevice -p 1 -file "/home/joshua/projects/fpga/MandelFPGA/MandelTop.bit" +addDevice -p 2 -part xcf04s +Program -p 1 -defaultVersion 0 +quit +