Created
August 25, 2013 11:04
-
-
Save ejrh/6333264 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module fpgafrac( | |
input wire mclk, | |
input wire [7:0] sw, | |
input wire [3:0] btn, | |
/*output wire [7:0] led, | |
output wire [3:0] an, | |
output wire dp, | |
output wire [6:0] seg,*/ | |
output reg vs, | |
output reg hs, | |
output reg [2:0] red, | |
output reg [2:0] green, | |
output reg [1:0] blue | |
); | |
/* | |
Active Video Front Porch Sync Pulse Back Porch Active Video Front Porch Sync Pulse Back Porch | |
800x600, 72Hz 50.000 800 56 120 64 600 37 6 23 | |
*/ | |
parameter CLK = 50000000; | |
parameter PAL = 640; | |
parameter HFP = 16; | |
parameter HPW = 96; | |
parameter HBP = 48; | |
parameter LAF = 480; | |
parameter VFP = 11; | |
parameter VPW = 2; | |
parameter VBP = 31; | |
/*parameter PAL = 800; | |
parameter HFP = 56; | |
parameter HPW = 120; | |
parameter HBP = 64; | |
parameter LAF = 600; | |
parameter VFP = 37; | |
parameter VPW = 6; | |
parameter VBP = 23;*/ | |
parameter PLD = PAL+HFP+HPW+HBP; | |
parameter LFD = LAF+VFP+VPW+VBP; | |
reg vga_clk; | |
reg [15:0] vga_x; | |
reg [15:0] vga_y; | |
/*wire red_colour; | |
defparam red_ball.VEL_X = 5; | |
defparam red_ball.VEL_Y = 3; | |
ball red_ball(mclk, PAL, LAF, 32, vga_x, vga_y, red_colour); | |
wire green_colour; | |
defparam green_ball.VEL_X = 4; | |
defparam green_ball.VEL_Y = 4; | |
ball green_ball(mclk, PAL, LAF, 32, vga_x, vga_y, green_colour); | |
wire blue_colour; | |
defparam blue_ball.VEL_X = 3; | |
defparam blue_ball.VEL_Y = 6; | |
ball blue_ball(mclk, PAL, LAF, 32, vga_x, vga_y, blue_colour);*/ | |
wire [7:0] mandelbrot_colour; | |
mandelbrot mandelbrot(sw[0], btn, mclk, PAL, LAF, vga_x, vga_y, mandelbrot_colour); | |
wire on_screen; | |
assign on_screen = (vga_x < PAL) && (vga_y < LAF); | |
//wire [1:0] tile_colour; | |
//assign tile_colour = vga_x[7:6] ^ vga_y[7:6]; | |
//assign tile_colour = mandelbrot_colour[7:6] ^ mandelbrot_colour[5:4] ^ mandelbrot_colour[3:2] ^ mandelbrot_colour[1:0]; | |
wire [2:0] red_component, green_component; | |
wire [1:0] blue_component; | |
errdiff errdiff_r(mclk, vga_clk, mandelbrot_colour, red_component); | |
errdiff errdiff_g(mclk, vga_clk, mandelbrot_colour, green_component); | |
defparam errdiff_b.OUT_WIDTH = 2; | |
defparam errdiff_b.ERR_WIDTH = 6; | |
errdiff errdiff_b(mclk, vga_clk, mandelbrot_colour, blue_component); | |
always @(posedge mclk) begin | |
vga_clk <= !vga_clk; | |
if (vga_clk) begin | |
/* Update Pixel and Line positions. */ | |
if (vga_x == PLD-1) begin | |
vga_x <= 0; | |
if (vga_y == LFD-1) begin | |
vga_y <= 0; | |
end else begin | |
vga_y <= vga_y + 1; | |
end | |
end else begin | |
vga_x <= vga_x + 1; | |
end | |
/* Horizontal sync. */ | |
if (vga_x == PAL-1+HFP) begin | |
hs <= 0; | |
end else if (vga_x == PAL-1+HFP+HPW) begin | |
hs <= 1; | |
end | |
/* Vertical sync. */ | |
if (vga_y == LAF-1+VFP) begin | |
vs <= 0; | |
end else if (vga_y == LAF-1+VFP+VPW) begin | |
vs <= 1; | |
end | |
if (on_screen) begin | |
/*red <= { red_colour, tile_colour }; | |
green <= { green_colour, tile_colour }; | |
blue <= { blue_colour, tile_colour[1] };*/ | |
//{ red, green, blue } <= mandelbrot_colour; | |
{ red, green, blue } <= { red_component, green_component, blue_component }; | |
end else begin | |
red <= 0; | |
green <= 0; | |
blue <= 0; | |
end | |
end | |
end | |
endmodule | |
module ball( | |
input wire mclk, | |
input wire [15:0] max_x, | |
input wire [15:0] max_y, | |
input wire [15:0] radius, | |
input wire [15:0] scan_x, | |
input wire [15:0] scan_y, | |
output wire in_circle | |
); | |
parameter POS_X = 0; | |
parameter POS_Y = 0; | |
parameter VEL_X = 1; | |
parameter VEL_Y = 2; | |
reg [31:0] pos_x = POS_X; | |
reg [31:0] pos_y = POS_Y; | |
reg signed [31:0] vel_x = VEL_X; | |
reg signed [31:0] vel_y = VEL_Y; | |
wire [15:0] circle_x; | |
assign circle_x = pos_x[31:21]; | |
wire [15:0] circle_y; | |
assign circle_y = pos_y[31:21]; | |
wire [15:0] xdiff, ydiff; | |
absdiff absdiff1(scan_x, circle_x, xdiff); | |
absdiff absdiff2(scan_y, circle_y, ydiff); | |
assign in_circle = xdiff*xdiff + ydiff*ydiff <= radius*radius; | |
always @(posedge mclk) begin | |
pos_x <= pos_x + vel_x; | |
pos_y <= pos_y + vel_y; | |
if (circle_x >= max_x - radius && vel_x > 0) begin | |
vel_x <= -vel_x; | |
end else if (circle_x < radius && vel_x < 0) begin | |
vel_x <= -vel_x; | |
end | |
if (circle_y >= max_y - radius && vel_y > 0) begin | |
vel_y <= -vel_y; | |
end else if (circle_y < radius && vel_y < 0) begin | |
vel_y <= -vel_y; | |
end | |
end | |
endmodule | |
module absdiff( | |
input wire [15:0] in1, | |
input wire [15:0] in2, | |
output wire [15:0] out | |
); | |
assign out = (in1 > in2) ? in1 - in2 : in2 - in1; | |
endmodule | |
module mandelbrot( | |
input wire control_mode, | |
input wire [3:0] button, | |
input wire mclk, | |
input wire [15:0] max_x, | |
input wire [15:0] max_y, | |
input wire [15:0] scan_x, | |
input wire [15:0] scan_y, | |
output wire [7:0] colour | |
); | |
parameter WIDTH = 80; | |
parameter HEIGHT = 60; | |
reg [12:0] store_addr; | |
reg [7:0] store_data; | |
reg store_enable = 0; | |
wire [12:0] read_addr; | |
wire [7:0] read_data; | |
videomem videomem(mclk, store_addr, store_data, store_enable, read_addr, read_data); | |
reg [7:0] iteration = 0; | |
reg [7:0] pos_x = WIDTH-1; | |
reg [7:0] pos_y = -1; | |
wire [12:0] pos = pos_y*WIDTH + pos_x; | |
reg signed [15:0] z_r = 0, z_i = 0; | |
reg signed [15:0] c_r = 0, c_i = 0; | |
wire [7:0] scan_pos_x, scan_pos_y; | |
assign scan_pos_x = scan_x >> 3; | |
assign scan_pos_y = scan_y >> 3; | |
wire [12:0] scan_pos; | |
assign scan_pos = scan_pos_y * WIDTH + scan_pos_x; | |
assign read_addr = (scan_pos < WIDTH*HEIGHT) ? scan_pos : 0; | |
wire in_fractal = (scan_pos_x < WIDTH) & (scan_pos_y < HEIGHT); | |
wire [7:0] pixel_val = read_data; | |
wire [5:0] pixel_colour; | |
colour_map map(pixel_val, pixel_colour); | |
//assign colour = in_fractal ? { pixel_colour, (scan_pos == pos) ? iteration[7:6] : 2'b00 } : 0; | |
assign colour = pixel_val; | |
wire [15:0] res_r, res_i, escaped; | |
mfunc mfunc(z_r, z_i, c_r, c_i, res_r, res_i, escaped); | |
wire new_pixel; | |
assign new_pixel = (iteration == 0) | escaped; | |
reg [1:0] slow_cnt; | |
reg [23:0] slow_cnt2; | |
wire signed [15:0] spos_x = pos_x; | |
wire signed [15:0] spos_y = pos_y; | |
parameter FIXPTS = 12; | |
reg [15:0] zoom = 192; | |
reg signed [15:0] centre_x = 0; //-(7 << (FIXPTS-2)); | |
reg signed [15:0] centre_y = 0; | |
always @(posedge mclk) begin | |
slow_cnt <= slow_cnt + 1; | |
if (slow_cnt == 0) begin | |
if (iteration == 0) begin | |
store_data <= 0; | |
store_addr <= pos; | |
store_enable <= 1; | |
end else if (escaped) begin | |
store_data <= iteration; | |
store_addr <= pos; | |
store_enable <= 1; | |
end | |
if (new_pixel) begin | |
if (pos_x == WIDTH-1) begin | |
pos_x <= 0; | |
if (pos_y == HEIGHT-1) begin | |
pos_y <= 0; | |
end else begin | |
pos_y <= pos_y + 1; | |
end | |
end else begin | |
pos_x <= pos_x + 1; | |
end | |
z_r <= 0; | |
z_i <= 0; | |
iteration <= 1; | |
c_r <= ((spos_x - (WIDTH/2)) * zoom) + centre_x; | |
c_i <= ((spos_y - (HEIGHT/2)) * zoom) + centre_y; | |
end else begin | |
z_r <= res_r; | |
z_i <= res_i; | |
iteration <= iteration + 1; | |
end | |
end | |
slow_cnt2 <= slow_cnt2 + 1; | |
if (slow_cnt2 == 0) begin | |
zoom <= zoom - 1; | |
end | |
/*if (control_mode) begin | |
if (button[0]) begin | |
zoom <= zoom + 1; | |
end else if (button[1]) begin | |
zoom <= zoom - 1; | |
end | |
end else begin | |
end*/ | |
if (store_enable) begin | |
store_enable <= 0; | |
end | |
end | |
endmodule | |
module mfunc( | |
input wire signed [15:0] in_r, | |
input wire signed [15:0] in_i, | |
input wire signed [15:0] c_r, | |
input wire signed [15:0] c_i, | |
output wire signed [15:0] out_r, | |
output wire signed [15:0] out_i, | |
output wire escaped | |
); | |
parameter FIXPTS = 12; | |
parameter BOUNDARY = 4 << FIXPTS; | |
wire signed [15:0] rsqr, isqr, riprod; | |
fixmul fixmul1(in_r, in_r, rsqr); | |
fixmul fixmul2(in_i, in_i, isqr); | |
fixmul fixmul3(in_r, in_i, riprod); | |
assign out_r = rsqr - isqr + c_r; | |
assign out_i = 2 * riprod + c_i; | |
assign escaped = rsqr + isqr > BOUNDARY; | |
endmodule | |
module fixmul( | |
input wire signed [15:0] a, | |
input wire signed [15:0] b, | |
output wire signed [15:0] result | |
); | |
parameter FIXPTS = 12; | |
wire signed [31:0] product; | |
assign product = a*b; | |
assign result = product[31:FIXPTS]; | |
endmodule | |
module colour_map(input wire [7:0] val, output wire [5:0] col); | |
assign col = val[7] ? { 3'b111, val[6:4] } : { val[6:4], 3'b000 }; | |
endmodule | |
module videomem( | |
input wire mclk, | |
input wire [12:0] store_addr, | |
input wire [7:0] store_data, | |
input wire store_enable, | |
input wire [12:0] read_addr, | |
output wire [7:0] read_data | |
); | |
wire enable00 = store_addr[12:11] == 2'b00; | |
wire enable01 = store_addr[12:11] == 2'b01; | |
wire enable10 = store_addr[12:11] == 2'b10; | |
wire enable11 = store_addr[12:11] == 2'b11; | |
wire [7:0] read_data00; | |
wire [7:0] read_data01; | |
wire [7:0] read_data10; | |
wire [7:0] read_data11; | |
videomem_module mod00(mclk, store_addr[10:0], store_data, store_enable & enable00, read_addr[10:0], read_data00); | |
videomem_module mod01(mclk, store_addr[10:0], store_data, store_enable & enable01, read_addr[10:0], read_data01); | |
videomem_module mod10(mclk, store_addr[10:0], store_data, store_enable & enable10, read_addr[10:0], read_data10); | |
videomem_module mod11(mclk, store_addr[10:0], store_data, store_enable & enable11, read_addr[10:0], read_data11); | |
wire read_enable00 = read_addr[12:11] == 2'b00; | |
wire read_enable01 = read_addr[12:11] == 2'b01; | |
wire read_enable10 = read_addr[12:11] == 2'b10; | |
wire read_enable11 = read_addr[12:11] == 2'b11; | |
assign read_data = read_enable00 ? read_data00 : | |
read_enable01 ? read_data01 : | |
read_enable10 ? read_data10 : read_data11; | |
endmodule | |
module videomem_module( | |
input wire mclk, | |
input wire [10:0] store_addr, | |
input wire [7:0] store_data, | |
input wire store_enable, | |
input wire [10:0] read_addr, | |
output wire [7:0] read_data | |
); | |
// RAMB16_S9_S9 : In order to incorporate this function into the design, | |
// Verilog : the forllowing instance declaration needs to be placed | |
// instance : in the body of the design code. The instance name | |
// declaration : (RAMB16_S9_S9_inst) and/or the port declarations within the | |
// code : parenthesis may be changed to properly reference and | |
// : connect this function to the design. All inputs | |
// : and outputs must be connected. | |
// <-----Cut code below this line----> | |
// RAMB16_S9_S9: 2k x 8 + 1 Parity bit Dual-Port RAM | |
// Spartan-3E | |
// Xilinx HDL Language Template, version 14.4 | |
RAMB16_S9_S9 #( | |
.WRITE_MODE_A("READ_FIRST"), // WRITE_FIRST, READ_FIRST or NO_CHANGE | |
.WRITE_MODE_B("READ_FIRST"), // WRITE_FIRST, READ_FIRST or NO_CHANGE | |
.SIM_COLLISION_CHECK("ALL") // "NONE", "WARNING_ONLY", "GENERATE_X_ONLY", "ALL" | |
) RAMB16_S9_S9_inst ( | |
.DOB(read_data), // Port B 8-bit Data Output | |
.ADDRA(store_addr), // Port A 11-bit Address Input | |
.ADDRB(read_addr), // Port B 11-bit Address Input | |
.CLKA(mclk), // Port A Clock | |
.CLKB(mclk), // Port B Clock | |
.DIA(store_data), // Port A 8-bit Data Input | |
.DIB(8'b11111111), // Port B 8-bit Data Input (not used) | |
.DIPA(1), // Port A 1-bit parity Input (not used) | |
.DIPB(1), // Port-B 1-bit parity Input (not used) | |
.ENA(store_enable), // Port A RAM Enable Input | |
.ENB(1), // Port B RAM Enable Input | |
.WEA(store_enable), // Port A Write Enable Input | |
.WEB(0) // Port B Write Enable Input | |
); | |
/*reg [7:0] data [0:299]; | |
always @(posedge mclk) begin | |
if (store_enable) | |
data[store_addr] <= store_data; | |
end | |
assign read_data = data[read_addr];*/ | |
endmodule | |
module errdiff(clk, enable, val, out); | |
parameter OUT_WIDTH = 3; | |
parameter ERR_WIDTH = 5; | |
input wire clk; | |
input wire enable; | |
input wire [OUT_WIDTH+ERR_WIDTH-1:0] val; | |
output wire [OUT_WIDTH-1:0] out; | |
reg [OUT_WIDTH+ERR_WIDTH-1:0] error = 0; | |
wire [OUT_WIDTH+ERR_WIDTH:0] adjval = val + error; | |
wire [ERR_WIDTH-1:0] newerr; | |
assign { out, newerr } = adjval; | |
always @(posedge clk) begin | |
if (enable) | |
error <= newerr; | |
end | |
endmodule |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment