From a7382d001c458127da8f311f70a8b77f61a4d6c1 Mon Sep 17 00:00:00 2001 From: shylie Date: Wed, 9 Oct 2024 15:18:36 -0400 Subject: [PATCH] mandelbrot fractal. --- fpga.pio | 4 +- ice/coords.sv | 18 +- ice/mandelbrot/.ng_run_manager.ini | 2 +- ice/mandelbrot/.recovery | 3 + ice/mandelbrot/mandelbrot.rdf | 2 +- ice/mandelbrot/mandelbrot_tcl.html | 27 +++ .../mandelbrot_tcr.dir/pn241008133909.tcr | 22 +++ ice/mandelbrot/promote.xml | 2 +- ice/mandelbrot/source/impl_1/makefile | 16 +- ice/mandelbrot/source/impl_1/multiplier.sv | 19 +- ice/mandelbrot/source/impl_1/renderer.sv | 81 ++++---- ice/mandelbrot/source/impl_1/tb_top.cpp | 176 ++++++++++++++++-- ice/mandelbrot/source/impl_1/top.sv | 70 ++++--- ice/spram.sv | 34 ++++ main.cpp | 14 +- tusb_config.h | 4 +- 16 files changed, 379 insertions(+), 115 deletions(-) create mode 100644 ice/mandelbrot/mandelbrot_tcr.dir/pn241008133909.tcr create mode 100644 ice/spram.sv diff --git a/fpga.pio b/fpga.pio index cc57075..00b8adf 100644 --- a/fpga.pio +++ b/fpga.pio @@ -44,11 +44,11 @@ set pindirs, 0b01 ; ... wait 1 gpio REQ_PIN ; wait for data to be ready, indicated by req signal high .wrap_target -wait 1 gpio CLK_PIN ; synchronize -wait 0 gpio CLK_PIN ; synchronize in pins, 8 ; read data from pins push noblock ; write data to memory +wait 0 gpio CLK_PIN ; synchronize jmp pin start ; stop receiving data if FPGA is done +wait 1 gpio CLK_PIN ; synchronize .wrap ; otherwise keep receiving data % c-sdk { diff --git a/ice/coords.sv b/ice/coords.sv index 9dc49e9..e817bae 100644 --- a/ice/coords.sv +++ b/ice/coords.sv @@ -1,34 +1,36 @@ module coords #( - parameter WIDTH = 128, - parameter HEIGHT = 128, + parameter WIDTH = 256, + parameter HEIGHT = 256, parameter POS_COUNT = 4, localparam WIDTH_BITS = $clog2(WIDTH), localparam HEIGHT_BITS = $clog2(HEIGHT) )( input wire clk, input wire rst, + input wire inc, output reg [WIDTH_BITS-1:0] x[POS_COUNT], - output reg [WIDTH_BITS-1:0] y[POS_COUNT], + output reg [HEIGHT_BITS-1:0] y[POS_COUNT], output wire finished ); reg [POS_COUNT-1:0] finished_r; always_ff @(posedge clk) begin - integer i; if (rst) begin + integer i; for (i = 0; i < POS_COUNT; i = i + 1) begin x[i] <= WIDTH_BITS'(i); y[i] <= 0; end finished_r <= '1; - end else begin + end else if (inc) begin + integer i; for (i = 0; i < POS_COUNT; i = i + 1) begin - x[i] <= WIDTH_BITS'((32'(x[i]) + POS_COUNT) % WIDTH); - if (x[i] > WIDTH_BITS'((32'(x[i]) + POS_COUNT) % WIDTH)) begin + x[i] <= x[i] + POS_COUNT; + if (32'(x[i]) > (32'(x[i]) + POS_COUNT) % WIDTH) begin y[i] <= y[i] + 1; - if (y[i] > HEIGHT_BITS'((32'(y[i]) + 1) % HEIGHT)) begin + if (32'(y[i]) > (32'(y[i]) + 1) % HEIGHT) begin finished_r[i] <= 0; end end diff --git a/ice/mandelbrot/.ng_run_manager.ini b/ice/mandelbrot/.ng_run_manager.ini index 593d2b6..ce3d9d0 100644 --- a/ice/mandelbrot/.ng_run_manager.ini +++ b/ice/mandelbrot/.ng_run_manager.ini @@ -1,6 +1,6 @@ [Runmanager] Geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\0\0\0\0\0\x14\0\0\x1\xca\0\0\0\xb9\0\0\0\0\0\0\0\x14\0\0\x1\xca\0\0\0\xb9\0\0\0\0\0\0\0\0\n\0\0\0\0\0\0\0\0\x14\0\0\x1\xca\0\0\0\xb9) -headerState=@ByteArray(\0\0\0\xff\0\0\0\0\0\0\0\x1\0\0\0\x1\0\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\x15\0\xf0\x1f\0\0\0\t\0\0\0\x13\0\0\0\x64\0\0\0\x12\0\0\0\x64\0\0\0\x14\0\0\0\x64\0\0\0\r\0\0\0\x64\0\0\0\f\0\0\0\x64\0\0\0\xf\0\0\0\x64\0\0\0\xe\0\0\0\x64\0\0\0\x11\0\0\0\x64\0\0\0\x10\0\0\0\x64\0\0\x5\xf\0\0\0\x15\x1\x1\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\x64\xff\xff\xff\xff\0\0\0\x84\0\0\0\0\0\0\0\x15\0\0\0\xc3\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\x3\xe8\0\0\0\0\x64) +headerState=@ByteArray(\0\0\0\xff\0\0\0\0\0\0\0\x1\0\0\0\x1\0\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\x15\0\xf0\x1f\0\0\0\t\0\0\0\xe\0\0\0\x64\0\0\0\xf\0\0\0\x64\0\0\0\f\0\0\0\x64\0\0\0\r\0\0\0\x64\0\0\0\x12\0\0\0\x64\0\0\0\x13\0\0\0\x64\0\0\0\x10\0\0\0\x64\0\0\0\x11\0\0\0\x64\0\0\0\x14\0\0\0\x64\0\0\x5\xf\0\0\0\x15\x1\x1\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\x64\xff\xff\xff\xff\0\0\0\x84\0\0\0\0\0\0\0\x15\0\0\0\xc3\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\x3\xe8\0\0\0\0\x64) [impl_1%3CStrategy1%3E] isChecked=false diff --git a/ice/mandelbrot/.recovery b/ice/mandelbrot/.recovery index 112931f..49b4ff7 100644 --- a/ice/mandelbrot/.recovery +++ b/ice/mandelbrot/.recovery @@ -18,6 +18,9 @@ + + + diff --git a/ice/mandelbrot/mandelbrot.rdf b/ice/mandelbrot/mandelbrot.rdf index 7c87ea9..112931f 100644 --- a/ice/mandelbrot/mandelbrot.rdf +++ b/ice/mandelbrot/mandelbrot.rdf @@ -2,7 +2,7 @@ - + diff --git a/ice/mandelbrot/mandelbrot_tcl.html b/ice/mandelbrot/mandelbrot_tcl.html index 4934044..3534011 100644 --- a/ice/mandelbrot/mandelbrot_tcl.html +++ b/ice/mandelbrot/mandelbrot_tcl.html @@ -275,6 +275,32 @@ prj_add_source "C:/Users/fuzzc/Documents/Hardware/pico-ice/pico-ice-video/ice/ma +pn241008133909 +#Start recording tcl command: 10/7/2024 10:43:02 +#Project Location: C:/Users/fuzzc/Documents/Hardware/pico-ice/pico-ice-video/ice/mandelbrot; Project name: mandelbrot +prj_open "C:/Users/fuzzc/Documents/Hardware/pico-ice/pico-ice-video/ice/mandelbrot/mandelbrot.rdf" +prj_run PAR -impl impl_1 +prj_run Export -impl impl_1 +prj_run PAR -impl impl_1 +prj_run Export -impl impl_1 +prj_run PAR -impl impl_1 +prj_run Export -impl impl_1 +prj_run PAR -impl impl_1 +prj_run Export -impl impl_1 +prj_run PAR -impl impl_1 +prj_run Export -impl impl_1 +prj_run PAR -impl impl_1 +prj_run Export -impl impl_1 +prj_run PAR -impl impl_1 +prj_run Export -impl impl_1 +prj_run PAR -impl impl_1 +prj_run Export -impl impl_1 +prj_run PAR -impl impl_1 +prj_run Export -impl impl_1 +#Stop recording: 10/8/2024 13:39:09 + + +
Contents @@ -284,6 +310,7 @@ prj_add_source "C:/Users/fuzzc/Documents/Hardware/pico-ice/pico-ice-video/ice/ma
  • pn241003133906
  • pn241004114221
  • pn241004151504
  • +
  • pn241008133909
  • diff --git a/ice/mandelbrot/mandelbrot_tcr.dir/pn241008133909.tcr b/ice/mandelbrot/mandelbrot_tcr.dir/pn241008133909.tcr new file mode 100644 index 0000000..ad40fd2 --- /dev/null +++ b/ice/mandelbrot/mandelbrot_tcr.dir/pn241008133909.tcr @@ -0,0 +1,22 @@ +#Start recording tcl command: 10/7/2024 10:43:02 +#Project Location: C:/Users/fuzzc/Documents/Hardware/pico-ice/pico-ice-video/ice/mandelbrot; Project name: mandelbrot +prj_open "C:/Users/fuzzc/Documents/Hardware/pico-ice/pico-ice-video/ice/mandelbrot/mandelbrot.rdf" +prj_run PAR -impl impl_1 +prj_run Export -impl impl_1 +prj_run PAR -impl impl_1 +prj_run Export -impl impl_1 +prj_run PAR -impl impl_1 +prj_run Export -impl impl_1 +prj_run PAR -impl impl_1 +prj_run Export -impl impl_1 +prj_run PAR -impl impl_1 +prj_run Export -impl impl_1 +prj_run PAR -impl impl_1 +prj_run Export -impl impl_1 +prj_run PAR -impl impl_1 +prj_run Export -impl impl_1 +prj_run PAR -impl impl_1 +prj_run Export -impl impl_1 +prj_run PAR -impl impl_1 +prj_run Export -impl impl_1 +#Stop recording: 10/8/2024 13:39:09 diff --git a/ice/mandelbrot/promote.xml b/ice/mandelbrot/promote.xml index 730cffd..afad920 100644 --- a/ice/mandelbrot/promote.xml +++ b/ice/mandelbrot/promote.xml @@ -1,3 +1,3 @@ - + diff --git a/ice/mandelbrot/source/impl_1/makefile b/ice/mandelbrot/source/impl_1/makefile index 63c42b6..6dde587 100644 --- a/ice/mandelbrot/source/impl_1/makefile +++ b/ice/mandelbrot/source/impl_1/makefile @@ -1,6 +1,18 @@ +VFLAGS = -O3 -x-assign fasta --x-initial fast --noassert +SDL_CFLAGS = `sdl2-config --cflags` +SDL_LDFLAGS = `sdl2-config --libs` + run: build - cd obj_dir && ./Vtop && gtkwave waveform.vcd + cd obj_dir && ./Vtop + +wave: run + gtkwave obj_dir/waveform.vcd build: - verilator --trace --cc top.sv --exe tb_top.cpp -I../../.. + verilator --cc top.sv --trace --exe tb_top.cpp -I../../.. -CFLAGS "${SDL_CFLAGS}" -LDFLAGS "${SDL_LDFLAGS}" make -C obj_dir -f Vtop.mk Vtop + +clean: + rm -rf ./obj_dir + +.PHONY: run wave build clean diff --git a/ice/mandelbrot/source/impl_1/multiplier.sv b/ice/mandelbrot/source/impl_1/multiplier.sv index 4eaff0f..9ec4466 100644 --- a/ice/mandelbrot/source/impl_1/multiplier.sv +++ b/ice/mandelbrot/source/impl_1/multiplier.sv @@ -1,22 +1,11 @@ module multiplier ( input wire clk, - input wire signed [7:0] a, - input wire signed [7:0] b, - output reg signed [15:0] product + input wire signed [15:0] a, + input wire signed [15:0] b, + output wire signed [31:0] product ); -reg signed [7:0] a_reg; -reg signed [7:0] b_reg; - -wire [15:0] product_out; - -always_ff @(posedge clk) begin - a_reg <= a; - b_reg <= b; - product <= product_out; -end - -assign product_out = a_reg * b_reg; +assign product = a * b; endmodule \ No newline at end of file diff --git a/ice/mandelbrot/source/impl_1/renderer.sv b/ice/mandelbrot/source/impl_1/renderer.sv index 1fb9d65..54fd8fa 100644 --- a/ice/mandelbrot/source/impl_1/renderer.sv +++ b/ice/mandelbrot/source/impl_1/renderer.sv @@ -1,72 +1,89 @@ module renderer #( - parameter ITERATIONS = 7, - parameter OUTPUT_WIDTH = 3, + parameter ITERATIONS = 127, + parameter OUTPUT_WIDTH = 7, localparam ITERATION_WIDTH = $clog2(ITERATIONS + 1), - localparam SHIFT_AMOUNT = ITERATION_WIDTH - OUTPUT_WIDTH + localparam SHIFT_AMOUNT = ITERATION_WIDTH - OUTPUT_WIDTH, + localparam FRACTION_BITS = 13 )( input wire clk, input wire rst, input wire start, - input wire signed [7:0] x, - input wire signed [7:0] y, + input wire [7:0] x, + input wire [7:0] y, + input wire signed [14:0] cx, + input wire signed [14:0] cy, + input wire [2:0] zoom, output reg done, output reg [OUTPUT_WIDTH-1:0] iters ); -reg signed [7:0] x_reg; -reg signed [7:0] y_reg; -reg signed [7:0] z_real; -reg signed [7:0] z_imag; +reg signed [15:0] x_reg; +reg signed [15:0] y_reg; +reg signed [15:0] z_real; +reg signed [15:0] z_imag; reg [ITERATION_WIDTH-1:0] current_iteration; -wire signed [15:0] a_squared_p; -wire signed [15:0] b_squared_p; -wire signed [15:0] ab_p; +wire signed [31:0] a_squared_p; +wire signed [31:0] b_squared_p; +wire signed [31:0] ab_p; -wire signed [7:0] a_squared; -wire signed [7:0] b_squared; -wire signed [7:0] ab; +wire signed [31:0] apb_squared; +wire signed [31:0] asb_squared; + +wire signed [31:0] ab; always_ff @(posedge clk) begin - current_iteration <= current_iteration + 1'b1; done <= 1'b0; - // 128 = 4 << FRACTION_BITS (4) - if (current_iteration == ITERATIONS || a_squared + b_squared >= 32) begin + if (current_iteration == ITERATIONS) begin x_reg <= '0; y_reg <= '0; z_real <= '0; z_imag <= '0; - iters <= current_iteration >> SHIFT_AMOUNT; current_iteration <= '0; + iters <= '0; + + done <= 1'b1; + end else if (apb_squared >= 32'h4 << (2 * FRACTION_BITS)) begin + x_reg <= '0; + y_reg <= '0; + + z_real <= '0; + z_imag <= '0; + + current_iteration <= '0; + iters <= OUTPUT_WIDTH'(current_iteration >> SHIFT_AMOUNT); done <= 1'b1; end else if (current_iteration == 0) begin // store c for later - x_reg <= x; - y_reg <= y; + x_reg <= cx + (16'(x) << zoom) + 16'hC000; + y_reg <= cy + (16'(y) << zoom) + 16'hC000; // add c for first iteration. // no need to include z as it is initially (0, 0) - z_real <= x; - z_imag <= y; + z_real <= cx + (16'(x) << zoom) + 16'hC000; + z_imag <= cy + (16'(y) << zoom) + 16'hC000; if (!start) begin current_iteration <= '0; + end else begin + current_iteration <= current_iteration + 1'b1; end end else begin - z_real <= a_squared + b_squared + x_reg; - z_imag <= (ab << 1'b1) + y_reg; + z_real <= asb_squared[15+FRACTION_BITS:FRACTION_BITS] + x_reg; + z_imag <= ab[15+FRACTION_BITS:FRACTION_BITS] + y_reg; + current_iteration <= current_iteration + 1'b1; end if (rst) begin - x_reg <= 8'h00; - y_reg <= 8'h00; - z_real <= 8'h00; - z_imag <= 8'h00; + x_reg <= '0; + y_reg <= '0; + z_real <= '0; + z_imag <= '0; current_iteration <= '0; end end @@ -75,8 +92,8 @@ multiplier m1(.clk(clk), .a(z_real), .b(z_real), .product(a_squared_p)); multiplier m2(.clk(clk), .a(z_imag), .b(z_imag), .product(b_squared_p)); multiplier m3(.clk(clk), .a(z_real), .b(z_imag), .product(ab_p)); -assign a_squared = a_squared_p[11:4]; -assign b_squared = b_squared_p[11:4]; -assign ab = ab_p[11:4]; +assign apb_squared = a_squared_p + b_squared_p; +assign asb_squared = a_squared_p - b_squared_p; +assign ab = ab_p << 1'b1; endmodule \ No newline at end of file diff --git a/ice/mandelbrot/source/impl_1/tb_top.cpp b/ice/mandelbrot/source/impl_1/tb_top.cpp index 2f655e3..0fa5694 100644 --- a/ice/mandelbrot/source/impl_1/tb_top.cpp +++ b/ice/mandelbrot/source/impl_1/tb_top.cpp @@ -1,32 +1,172 @@ #include +#include #include +#include #include #include #include "Vtop.h" -constexpr vluint64_t MAX_SIM_TIME = 100000; -vluint64_t sim_time = 0; +constexpr int H_RES = 256; +constexpr int V_RES = 256; + +constexpr int S_SCALE = 3; int main(int argc, char** argv, char** env) { - Vtop* dut = new Vtop; - - Verilated::traceEverOn(true); - VerilatedVcdC* m_trace = new VerilatedVcdC; - dut->trace(m_trace, 5); - m_trace->open("waveform.vcd"); - - while (sim_time < MAX_SIM_TIME) + if (SDL_Init(SDL_INIT_VIDEO) < 0) { - dut->clk ^= 1; - dut->eval(); - m_trace->dump(sim_time); - - sim_time++; + std::cout << "SDL init failed." << std::endl; + return 1; } - m_trace->close(); - delete m_trace; + uint8_t framebuffer[H_RES * V_RES * 2]; + unsigned int current = 0; + + SDL_Window* sdl_window = nullptr; + SDL_Renderer* sdl_renderer = nullptr; + SDL_Texture* sdl_texture = nullptr; + + sdl_window = SDL_CreateWindow("mandelbrot", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + H_RES * S_SCALE, V_RES * S_SCALE, SDL_WINDOW_SHOWN); + if (!sdl_window) + { + std::cout << "Window creation failed: " << SDL_GetError() << std::endl; + return 1; + } + + sdl_renderer = SDL_CreateRenderer(sdl_window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); + if (!sdl_renderer) + { + std::cout << "Renderer creation failed: " << SDL_GetError() << std::endl; + return 1; + } + SDL_RenderSetLogicalSize(sdl_renderer, V_RES, H_RES); + + sdl_texture = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_YUY2, SDL_TEXTUREACCESS_TARGET, H_RES, V_RES); + if (!sdl_texture) + { + std::cout << "Texture creation failed: " << SDL_GetError() << std::endl; + return 1; + } + + const Uint8* keyb_state = SDL_GetKeyboardState(nullptr); + + Vtop* dut = new Vtop; + + bool done = false; + + vluint64_t sim_time = 0; + + Verilated::traceEverOn(true); + VerilatedVcdC* trace = new VerilatedVcdC; + dut->trace(trace, 5); + trace->open("waveform.vcd"); + + dut->dir = 1; + dut->clk = 1; + dut->eval(); + trace->dump(sim_time++); + dut->clk = 0; + dut->eval(); + trace->dump(sim_time++); + for (int i = 0; i < 5; i++) + { + dut->clk = 1; + dut->eval(); + trace->dump(sim_time++); + dut->clk = 0; + dut->eval(); + trace->dump(sim_time++); + } + dut->clk = 1; + dut->eval(); + trace->dump(sim_time++); + dut->dir = 0; + dut->clk = 0; + dut->eval(); + trace->dump(sim_time++); + + bool swapped = false; + bool last = false; + + while (true) + { + SDL_Event e; + if (SDL_PollEvent(&e)) { if (e.type == SDL_QUIT) { break; } } + + if (keyb_state[SDL_SCANCODE_Q]) { break; } + + if (!done || !dut->fin) + { + dut->clk = 1; + dut->eval(); + trace->dump(sim_time++); + dut->clk = 0; + dut->eval(); + trace->dump(sim_time++); + + if (!dut->req || done) { continue; } + + framebuffer[current] = dut->data; + + if (++current == H_RES * V_RES * 2) + { + current = 0; + SDL_UpdateTexture(sdl_texture, nullptr, framebuffer, H_RES * 2); + SDL_RenderClear(sdl_renderer); + SDL_RenderCopy(sdl_renderer, sdl_texture, nullptr, nullptr); + SDL_RenderPresent(sdl_renderer); + + done = true; + } + } + else if (keyb_state[SDL_SCANCODE_N] && !last) + { + if (swapped) + { + SDL_UpdateTexture(sdl_texture, nullptr, framebuffer, H_RES * 2); + SDL_RenderClear(sdl_renderer); + SDL_RenderCopy(sdl_renderer, sdl_texture, nullptr, nullptr); + SDL_RenderPresent(sdl_renderer); + swapped = false; + } + else + { + uint8_t fb2[V_RES * H_RES * 2]; + for (int i = 0; i < V_RES * H_RES * 2; i += 2) + { + float zr = 0, zi = 0; + const float cr = (i % (H_RES * 2)) / 192.0f - 2.1f; + const float ci = (i / (H_RES * 2)) / 96.0f - 1.5f; + + fb2[i] = 62; + fb2[i + 1] = 128; + + for (int iter = 0; iter < 64; iter++) + { + if (zr * zr + zi * zi >= 4) + { + fb2[i] = 16.0f * sqrt(iter) + 62; + break; + } + float tzr = zr * zr - zi * zi + cr; + zi = 2 * zr * zi + ci; + zr = tzr; + } + } + SDL_UpdateTexture(sdl_texture, nullptr, fb2, H_RES * 2); + SDL_RenderClear(sdl_renderer); + SDL_RenderCopy(sdl_renderer, sdl_texture, nullptr, nullptr); + SDL_RenderPresent(sdl_renderer); + + swapped = true; + } + } + last = keyb_state[SDL_SCANCODE_N]; + } + + trace->close(); + delete trace; delete dut; - return EXIT_SUCCESS; + return 0; } diff --git a/ice/mandelbrot/source/impl_1/top.sv b/ice/mandelbrot/source/impl_1/top.sv index f4319ce..fdb7353 100644 --- a/ice/mandelbrot/source/impl_1/top.sv +++ b/ice/mandelbrot/source/impl_1/top.sv @@ -7,14 +7,8 @@ module top inout wire [7:0] data ); -reg [3:0] clk_div_8_counter; -wire clk_div_8; - -reg dir_last; reg req_last; -reg req_r; - reg [7:0] waddr; reg [7:0] raddr; @@ -22,48 +16,66 @@ wire [7:0] command; ram command_buffer(.wclk(clk), .rclk(clk), .waddr(waddr), .raddr(raddr), .data_in(data), .write_en(dir && req), .data_out(command)); -wire [6:0] x[4]; -wire [6:0] y[4]; +wire [6:0] iters; -coords #(.POS_COUNT(4)) coords_inst(.clk(clk_div_8), .rst(!req_r), .x(x), .y(y), .finished(fin)); +wire [7:0] x[1]; +wire [7:0] y[1]; -wire [2:0] iters[4]; +wire coords_fin; +wire coords_inc; -wire [7:0] data_out; +reg coords_inc_last; +reg coords_fin_last; -genvar i; -generate - for (i = 0; i < 4; i = i + 1) begin - renderer r(.clk(clk), .rst(dir), .start(clk_div_8_counter[2:0] >> 1 == i), .x({x[i], 1'b0}), .y({y[i], 1'b0}), .done(), .iters(iters[i])); - end -endgenerate +renderer r(.clk(clk), .rst(dir), .start(!dir && !coords_fin), .x(x[0]), .y(y[0]), .cx(16'h1000), .cy(16'h2000), .zoom(3'd6), .done(coords_inc), .iters(iters)); +coords #(.POS_COUNT(1)) coords_inst(.clk(clk), .rst(dir), .inc(coords_inc), .x(x), .y(y), .finished(coords_fin)); + +wire fb_clk; +reg [15:0] fb_addr; +wire [7:0] fb_data_in; +wire fb_we; + +wire [15:0] fb_data_out; + +reg fb_half_out; + +spram_big fb(.clk(fb_clk), .we({ fb_we, fb_we, fb_we, fb_we }), .addr(fb_addr), .data_in({ 8'd128, 8'(iters) + 8'd62 }), .data_out(fb_data_out)); always_ff @(posedge clk) begin - dir_last <= dir; req_last <= req; - req_r <= !fin && !dir_last; + coords_fin_last <= coords_fin && !dir; + coords_inc_last <= coords_inc && !dir; if (dir) begin - clk_div_8_counter <= 0; raddr <= 0; + fb_addr <= 0; + fb_half_out <= 0; if (req && req_last) begin waddr <= waddr + 1; end else begin waddr <= 0; end - end - - if (!dir && !dir_last) begin - clk_div_8_counter <= clk_div_8_counter + 1; + end else if (coords_fin) begin + if (!coords_fin_last) begin + fb_addr <= 0; + fb_half_out <= 0; + end else begin + fb_half_out <= !fb_half_out; + if (fb_half_out) begin + fb_addr <= fb_addr + 1; + end + end + end else if (coords_inc_last) begin + fb_addr <= fb_addr + 1; end end -assign clk_div_8 = clk_div_8_counter[3]; +assign fb_clk = clk; +assign fb_we = coords_inc; +assign fin = !dir && coords_fin && coords_fin_last && fb_addr >= 65531; -assign data_out = clk_div_8_counter[0] ? 128 : ((8'(iters[clk_div_8_counter[2:1]]) << 4) + 8'd62); - -assign req = dir ? 'Z : req_r; -assign data = dir ? 'Z : data_out; +assign req = dir ? 'Z : coords_fin_last; +assign data = dir ? 'Z : (fb_half_out ? fb_data_out[15:8] : fb_data_out[7:0]); endmodule \ No newline at end of file diff --git a/ice/spram.sv b/ice/spram.sv new file mode 100644 index 0000000..cfdcbce --- /dev/null +++ b/ice/spram.sv @@ -0,0 +1,34 @@ +module spram +( + input wire clk, + input wire [3:0] we, + input wire [13:0] addr, + input wire [15:0] data_in, + output wire [15:0] data_out +); + +SP256K bb_spram_inst(.AD(addr), .DI(data_in), .MASKWE(we), .WE(|we), .CS('1), .CK(clk), .STDBY('0), .SLEEP('0), .PWROFF_N('1), .DO(data_out)); + +endmodule + +module spram_big +( + input wire clk, + input wire [3:0] we, + input wire [15:0] addr, + input wire [15:0] data_in, + output wire [15:0] data_out +); + +wire [15:0] datas_out[4]; + +genvar i; +generate + for (i = 0; i < 4; i = i + 1) begin + spram spram_inst(.clk(clk), .we(addr[15:14] == i ? we : '0), .addr(addr[13:0]), .data_in(data_in), .data_out(datas_out[i])); + end +endgenerate + +assign data_out = datas_out[addr[15:14]]; + +endmodule \ No newline at end of file diff --git a/main.cpp b/main.cpp index 947c2a3..032f98e 100644 --- a/main.cpp +++ b/main.cpp @@ -50,12 +50,18 @@ int main() board_init_after_tusb(); } - start_next_frame(); - while (true) { - printf("%d %d |", command_buffer[0], command_buffer[1]); - for (int i = 0; i < 8; i++) { printf(" %d", gpio_get(i)); } + uint8_t val = 0; + for (int i = 0; i < 8; i++) + { + val |= gpio_get(i) << i; + } + printf("%d %d %d | %3d |", gpio_get(DIR_PIN), gpio_get(REQ_PIN), gpio_get(FIN_PIN), val); + for (int i = 0; i < 12; i++) + { + printf(" %3d", frame_buffer[i]); + } printf("\n"); tud_task(); video_task(); diff --git a/tusb_config.h b/tusb_config.h index 15e25e1..ed1ac54 100644 --- a/tusb_config.h +++ b/tusb_config.h @@ -72,8 +72,8 @@ #define CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE 1023 #define CFG_TUD_VIDEO_STREAMING_BULK 0 -#define FRAME_WIDTH 128 -#define FRAME_HEIGHT 128 +#define FRAME_WIDTH 256 +#define FRAME_HEIGHT 256 #define FRAME_RATE 60 // Temporarily here until ice_usb.h has necessary info