mandelbrot fractal.
This commit is contained in:
parent
d9b7fd7aa4
commit
a7382d001c
4
fpga.pio
4
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
|
wait 1 gpio REQ_PIN ; wait for data to be ready, indicated by req signal high
|
||||||
|
|
||||||
.wrap_target
|
.wrap_target
|
||||||
wait 1 gpio CLK_PIN ; synchronize
|
|
||||||
wait 0 gpio CLK_PIN ; synchronize
|
|
||||||
in pins, 8 ; read data from pins
|
in pins, 8 ; read data from pins
|
||||||
push noblock ; write data to memory
|
push noblock ; write data to memory
|
||||||
|
wait 0 gpio CLK_PIN ; synchronize
|
||||||
jmp pin start ; stop receiving data if FPGA is done
|
jmp pin start ; stop receiving data if FPGA is done
|
||||||
|
wait 1 gpio CLK_PIN ; synchronize
|
||||||
.wrap ; otherwise keep receiving data
|
.wrap ; otherwise keep receiving data
|
||||||
|
|
||||||
% c-sdk {
|
% c-sdk {
|
||||||
|
@ -1,34 +1,36 @@
|
|||||||
module coords
|
module coords
|
||||||
#(
|
#(
|
||||||
parameter WIDTH = 128,
|
parameter WIDTH = 256,
|
||||||
parameter HEIGHT = 128,
|
parameter HEIGHT = 256,
|
||||||
parameter POS_COUNT = 4,
|
parameter POS_COUNT = 4,
|
||||||
localparam WIDTH_BITS = $clog2(WIDTH),
|
localparam WIDTH_BITS = $clog2(WIDTH),
|
||||||
localparam HEIGHT_BITS = $clog2(HEIGHT)
|
localparam HEIGHT_BITS = $clog2(HEIGHT)
|
||||||
)(
|
)(
|
||||||
input wire clk,
|
input wire clk,
|
||||||
input wire rst,
|
input wire rst,
|
||||||
|
input wire inc,
|
||||||
output reg [WIDTH_BITS-1:0] x[POS_COUNT],
|
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
|
output wire finished
|
||||||
);
|
);
|
||||||
|
|
||||||
reg [POS_COUNT-1:0] finished_r;
|
reg [POS_COUNT-1:0] finished_r;
|
||||||
|
|
||||||
always_ff @(posedge clk) begin
|
always_ff @(posedge clk) begin
|
||||||
integer i;
|
|
||||||
if (rst) begin
|
if (rst) begin
|
||||||
|
integer i;
|
||||||
for (i = 0; i < POS_COUNT; i = i + 1) begin
|
for (i = 0; i < POS_COUNT; i = i + 1) begin
|
||||||
x[i] <= WIDTH_BITS'(i);
|
x[i] <= WIDTH_BITS'(i);
|
||||||
y[i] <= 0;
|
y[i] <= 0;
|
||||||
end
|
end
|
||||||
finished_r <= '1;
|
finished_r <= '1;
|
||||||
end else begin
|
end else if (inc) begin
|
||||||
|
integer i;
|
||||||
for (i = 0; i < POS_COUNT; i = i + 1) begin
|
for (i = 0; i < POS_COUNT; i = i + 1) begin
|
||||||
x[i] <= WIDTH_BITS'((32'(x[i]) + POS_COUNT) % WIDTH);
|
x[i] <= x[i] + POS_COUNT;
|
||||||
if (x[i] > WIDTH_BITS'((32'(x[i]) + POS_COUNT) % WIDTH)) begin
|
if (32'(x[i]) > (32'(x[i]) + POS_COUNT) % WIDTH) begin
|
||||||
y[i] <= y[i] + 1;
|
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;
|
finished_r[i] <= 0;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[Runmanager]
|
[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)
|
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]
|
[impl_1%3CStrategy1%3E]
|
||||||
isChecked=false
|
isChecked=false
|
||||||
|
@ -18,6 +18,9 @@
|
|||||||
<Source name="source/impl_1/multiplier.sv" type="Verilog" type_short="Verilog">
|
<Source name="source/impl_1/multiplier.sv" type="Verilog" type_short="Verilog">
|
||||||
<Options VerilogStandard="System Verilog"/>
|
<Options VerilogStandard="System Verilog"/>
|
||||||
</Source>
|
</Source>
|
||||||
|
<Source name="../spram.sv" type="Verilog" type_short="Verilog">
|
||||||
|
<Options VerilogStandard="System Verilog"/>
|
||||||
|
</Source>
|
||||||
<Source name="../constraints.pdc" type="Physical Constraints File" type_short="PDC">
|
<Source name="../constraints.pdc" type="Physical Constraints File" type_short="PDC">
|
||||||
<Options/>
|
<Options/>
|
||||||
</Source>
|
</Source>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<RadiantProject version="4.2" radiant="2024.1.0.34.2" title="mandelbrot" device="iCE40UP5K-SG48I" performance_grade="High-Performance_1.2V" family_int="ice40tp" device_int="itpa08" package_int="SG48" operation_int="IND" speed_int="6" default_implementation="impl_1">
|
<RadiantProject version="4.2" radiant="2024.1.0.34.2" title="mandelbrot" device="iCE40UP5K-SG48I" performance_grade="High-Performance_1.2V" family_int="ice40tp" device_int="itpa08" package_int="SG48" operation_int="IND" speed_int="6" default_implementation="impl_1">
|
||||||
<Options/>
|
<Options/>
|
||||||
<Implementation title="impl_1" dir="impl_1" description="impl_1" synthesis="synplify" default_strategy="Strategy1">
|
<Implementation title="impl_1" dir="impl_1" description="impl_1" synthesis="synplify" default_strategy="Strategy1">
|
||||||
<Options def_top="renderer" top="top"/>
|
<Options def_top="top" top="top"/>
|
||||||
<Source name="source/impl_1/top.sv" type="Verilog" type_short="Verilog">
|
<Source name="source/impl_1/top.sv" type="Verilog" type_short="Verilog">
|
||||||
<Options VerilogStandard="System Verilog" top_module="top"/>
|
<Options VerilogStandard="System Verilog" top_module="top"/>
|
||||||
</Source>
|
</Source>
|
||||||
|
@ -275,6 +275,32 @@ prj_add_source "C:/Users/fuzzc/Documents/Hardware/pico-ice/pico-ice-video/ice/ma
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<A name="pn241008133909"></A><B><U><big>pn241008133909</big></U></B>
|
||||||
|
#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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</PRE></DIV>
|
</PRE></DIV>
|
||||||
|
|
||||||
<DIV id="toc" class="radiant"><span onmousemove="showTocList()">Contents</span>
|
<DIV id="toc" class="radiant"><span onmousemove="showTocList()">Contents</span>
|
||||||
@ -284,6 +310,7 @@ prj_add_source "C:/Users/fuzzc/Documents/Hardware/pico-ice/pico-ice-video/ice/ma
|
|||||||
<LI><A href=#pn241003133906>pn241003133906</A></LI>
|
<LI><A href=#pn241003133906>pn241003133906</A></LI>
|
||||||
<LI><A href=#pn241004114221>pn241004114221</A></LI>
|
<LI><A href=#pn241004114221>pn241004114221</A></LI>
|
||||||
<LI><A href=#pn241004151504>pn241004151504</A></LI>
|
<LI><A href=#pn241004151504>pn241004151504</A></LI>
|
||||||
|
<LI><A href=#pn241008133909>pn241008133909</A></LI>
|
||||||
</UL>
|
</UL>
|
||||||
</DIV>
|
</DIV>
|
||||||
|
|
||||||
|
22
ice/mandelbrot/mandelbrot_tcr.dir/pn241008133909.tcr
Normal file
22
ice/mandelbrot/mandelbrot_tcr.dir/pn241008133909.tcr
Normal file
@ -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
|
@ -1,3 +1,3 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<userSetting name="C:/Users/fuzzc/Documents/Hardware/pico-ice/pico-ice-video/ice/mandelbrot/promote.xml" version="Diamond (64-bit) 2024.1.0.34.2" date="Sun Oct 06 00:16:13 2024" vendor="Lattice Semiconductor Corporation" >
|
<userSetting name="C:/Users/fuzzc/Documents/Hardware/pico-ice/pico-ice-video/ice/mandelbrot/promote.xml" version="Diamond (64-bit) 2024.1.0.34.2" date="Wed Oct 09 15:10:53 2024" vendor="Lattice Semiconductor Corporation" >
|
||||||
</userSetting>
|
</userSetting>
|
||||||
|
@ -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
|
run: build
|
||||||
cd obj_dir && ./Vtop && gtkwave waveform.vcd
|
cd obj_dir && ./Vtop
|
||||||
|
|
||||||
|
wave: run
|
||||||
|
gtkwave obj_dir/waveform.vcd
|
||||||
|
|
||||||
build:
|
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
|
make -C obj_dir -f Vtop.mk Vtop
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf ./obj_dir
|
||||||
|
|
||||||
|
.PHONY: run wave build clean
|
||||||
|
@ -1,22 +1,11 @@
|
|||||||
module multiplier
|
module multiplier
|
||||||
(
|
(
|
||||||
input wire clk,
|
input wire clk,
|
||||||
input wire signed [7:0] a,
|
input wire signed [15:0] a,
|
||||||
input wire signed [7:0] b,
|
input wire signed [15:0] b,
|
||||||
output reg signed [15:0] product
|
output wire signed [31:0] product
|
||||||
);
|
);
|
||||||
|
|
||||||
reg signed [7:0] a_reg;
|
assign product = a * b;
|
||||||
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;
|
|
||||||
|
|
||||||
endmodule
|
endmodule
|
@ -1,72 +1,89 @@
|
|||||||
module renderer
|
module renderer
|
||||||
#(
|
#(
|
||||||
parameter ITERATIONS = 7,
|
parameter ITERATIONS = 127,
|
||||||
parameter OUTPUT_WIDTH = 3,
|
parameter OUTPUT_WIDTH = 7,
|
||||||
localparam ITERATION_WIDTH = $clog2(ITERATIONS + 1),
|
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 clk,
|
||||||
input wire rst,
|
input wire rst,
|
||||||
input wire start,
|
input wire start,
|
||||||
input wire signed [7:0] x,
|
input wire [7:0] x,
|
||||||
input wire signed [7:0] y,
|
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 done,
|
||||||
output reg [OUTPUT_WIDTH-1:0] iters
|
output reg [OUTPUT_WIDTH-1:0] iters
|
||||||
);
|
);
|
||||||
|
|
||||||
reg signed [7:0] x_reg;
|
reg signed [15:0] x_reg;
|
||||||
reg signed [7:0] y_reg;
|
reg signed [15:0] y_reg;
|
||||||
reg signed [7:0] z_real;
|
reg signed [15:0] z_real;
|
||||||
reg signed [7:0] z_imag;
|
reg signed [15:0] z_imag;
|
||||||
reg [ITERATION_WIDTH-1:0] current_iteration;
|
reg [ITERATION_WIDTH-1:0] current_iteration;
|
||||||
|
|
||||||
wire signed [15:0] a_squared_p;
|
wire signed [31:0] a_squared_p;
|
||||||
wire signed [15:0] b_squared_p;
|
wire signed [31:0] b_squared_p;
|
||||||
wire signed [15:0] ab_p;
|
wire signed [31:0] ab_p;
|
||||||
|
|
||||||
wire signed [7:0] a_squared;
|
wire signed [31:0] apb_squared;
|
||||||
wire signed [7:0] b_squared;
|
wire signed [31:0] asb_squared;
|
||||||
wire signed [7:0] ab;
|
|
||||||
|
wire signed [31:0] ab;
|
||||||
|
|
||||||
always_ff @(posedge clk) begin
|
always_ff @(posedge clk) begin
|
||||||
current_iteration <= current_iteration + 1'b1;
|
|
||||||
done <= 1'b0;
|
done <= 1'b0;
|
||||||
|
|
||||||
// 128 = 4 << FRACTION_BITS (4)
|
if (current_iteration == ITERATIONS) begin
|
||||||
if (current_iteration == ITERATIONS || a_squared + b_squared >= 32) begin
|
|
||||||
x_reg <= '0;
|
x_reg <= '0;
|
||||||
y_reg <= '0;
|
y_reg <= '0;
|
||||||
|
|
||||||
z_real <= '0;
|
z_real <= '0;
|
||||||
z_imag <= '0;
|
z_imag <= '0;
|
||||||
|
|
||||||
iters <= current_iteration >> SHIFT_AMOUNT;
|
|
||||||
current_iteration <= '0;
|
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;
|
done <= 1'b1;
|
||||||
end else if (current_iteration == 0) begin
|
end else if (current_iteration == 0) begin
|
||||||
// store c for later
|
// store c for later
|
||||||
x_reg <= x;
|
x_reg <= cx + (16'(x) << zoom) + 16'hC000;
|
||||||
y_reg <= y;
|
y_reg <= cy + (16'(y) << zoom) + 16'hC000;
|
||||||
|
|
||||||
// add c for first iteration.
|
// add c for first iteration.
|
||||||
// no need to include z as it is initially (0, 0)
|
// no need to include z as it is initially (0, 0)
|
||||||
z_real <= x;
|
z_real <= cx + (16'(x) << zoom) + 16'hC000;
|
||||||
z_imag <= y;
|
z_imag <= cy + (16'(y) << zoom) + 16'hC000;
|
||||||
|
|
||||||
if (!start) begin
|
if (!start) begin
|
||||||
current_iteration <= '0;
|
current_iteration <= '0;
|
||||||
|
end else begin
|
||||||
|
current_iteration <= current_iteration + 1'b1;
|
||||||
end
|
end
|
||||||
end else begin
|
end else begin
|
||||||
z_real <= a_squared + b_squared + x_reg;
|
z_real <= asb_squared[15+FRACTION_BITS:FRACTION_BITS] + x_reg;
|
||||||
z_imag <= (ab << 1'b1) + y_reg;
|
z_imag <= ab[15+FRACTION_BITS:FRACTION_BITS] + y_reg;
|
||||||
|
current_iteration <= current_iteration + 1'b1;
|
||||||
end
|
end
|
||||||
|
|
||||||
if (rst) begin
|
if (rst) begin
|
||||||
x_reg <= 8'h00;
|
x_reg <= '0;
|
||||||
y_reg <= 8'h00;
|
y_reg <= '0;
|
||||||
z_real <= 8'h00;
|
z_real <= '0;
|
||||||
z_imag <= 8'h00;
|
z_imag <= '0;
|
||||||
current_iteration <= '0;
|
current_iteration <= '0;
|
||||||
end
|
end
|
||||||
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 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));
|
multiplier m3(.clk(clk), .a(z_real), .b(z_imag), .product(ab_p));
|
||||||
|
|
||||||
assign a_squared = a_squared_p[11:4];
|
assign apb_squared = a_squared_p + b_squared_p;
|
||||||
assign b_squared = b_squared_p[11:4];
|
assign asb_squared = a_squared_p - b_squared_p;
|
||||||
assign ab = ab_p[11:4];
|
assign ab = ab_p << 1'b1;
|
||||||
|
|
||||||
endmodule
|
endmodule
|
@ -1,32 +1,172 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <cmath>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <SDL.h>
|
||||||
#include <verilated.h>
|
#include <verilated.h>
|
||||||
#include <verilated_vcd_c.h>
|
#include <verilated_vcd_c.h>
|
||||||
#include "Vtop.h"
|
#include "Vtop.h"
|
||||||
|
|
||||||
constexpr vluint64_t MAX_SIM_TIME = 100000;
|
constexpr int H_RES = 256;
|
||||||
vluint64_t sim_time = 0;
|
constexpr int V_RES = 256;
|
||||||
|
|
||||||
|
constexpr int S_SCALE = 3;
|
||||||
|
|
||||||
int main(int argc, char** argv, char** env)
|
int main(int argc, char** argv, char** env)
|
||||||
{
|
{
|
||||||
Vtop* dut = new Vtop;
|
if (SDL_Init(SDL_INIT_VIDEO) < 0)
|
||||||
|
|
||||||
Verilated::traceEverOn(true);
|
|
||||||
VerilatedVcdC* m_trace = new VerilatedVcdC;
|
|
||||||
dut->trace(m_trace, 5);
|
|
||||||
m_trace->open("waveform.vcd");
|
|
||||||
|
|
||||||
while (sim_time < MAX_SIM_TIME)
|
|
||||||
{
|
{
|
||||||
dut->clk ^= 1;
|
std::cout << "SDL init failed." << std::endl;
|
||||||
dut->eval();
|
return 1;
|
||||||
m_trace->dump(sim_time);
|
|
||||||
|
|
||||||
sim_time++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_trace->close();
|
uint8_t framebuffer[H_RES * V_RES * 2];
|
||||||
delete m_trace;
|
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;
|
delete dut;
|
||||||
return EXIT_SUCCESS;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -7,14 +7,8 @@ module top
|
|||||||
inout wire [7:0] data
|
inout wire [7:0] data
|
||||||
);
|
);
|
||||||
|
|
||||||
reg [3:0] clk_div_8_counter;
|
|
||||||
wire clk_div_8;
|
|
||||||
|
|
||||||
reg dir_last;
|
|
||||||
reg req_last;
|
reg req_last;
|
||||||
|
|
||||||
reg req_r;
|
|
||||||
|
|
||||||
reg [7:0] waddr;
|
reg [7:0] waddr;
|
||||||
reg [7:0] raddr;
|
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));
|
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] iters;
|
||||||
wire [6:0] y[4];
|
|
||||||
|
|
||||||
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;
|
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));
|
||||||
generate
|
coords #(.POS_COUNT(1)) coords_inst(.clk(clk), .rst(dir), .inc(coords_inc), .x(x), .y(y), .finished(coords_fin));
|
||||||
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]));
|
wire fb_clk;
|
||||||
end
|
reg [15:0] fb_addr;
|
||||||
endgenerate
|
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
|
always_ff @(posedge clk) begin
|
||||||
dir_last <= dir;
|
|
||||||
req_last <= req;
|
req_last <= req;
|
||||||
req_r <= !fin && !dir_last;
|
coords_fin_last <= coords_fin && !dir;
|
||||||
|
coords_inc_last <= coords_inc && !dir;
|
||||||
|
|
||||||
if (dir) begin
|
if (dir) begin
|
||||||
clk_div_8_counter <= 0;
|
|
||||||
raddr <= 0;
|
raddr <= 0;
|
||||||
|
fb_addr <= 0;
|
||||||
|
fb_half_out <= 0;
|
||||||
|
|
||||||
if (req && req_last) begin
|
if (req && req_last) begin
|
||||||
waddr <= waddr + 1;
|
waddr <= waddr + 1;
|
||||||
end else begin
|
end else begin
|
||||||
waddr <= 0;
|
waddr <= 0;
|
||||||
end
|
end
|
||||||
end
|
end else if (coords_fin) begin
|
||||||
|
if (!coords_fin_last) begin
|
||||||
if (!dir && !dir_last) begin
|
fb_addr <= 0;
|
||||||
clk_div_8_counter <= clk_div_8_counter + 1;
|
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
|
||||||
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 : coords_fin_last;
|
||||||
|
assign data = dir ? 'Z : (fb_half_out ? fb_data_out[15:8] : fb_data_out[7:0]);
|
||||||
assign req = dir ? 'Z : req_r;
|
|
||||||
assign data = dir ? 'Z : data_out;
|
|
||||||
|
|
||||||
endmodule
|
endmodule
|
34
ice/spram.sv
Normal file
34
ice/spram.sv
Normal file
@ -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
|
14
main.cpp
14
main.cpp
@ -50,12 +50,18 @@ int main()
|
|||||||
board_init_after_tusb();
|
board_init_after_tusb();
|
||||||
}
|
}
|
||||||
|
|
||||||
start_next_frame();
|
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
printf("%d %d |", command_buffer[0], command_buffer[1]);
|
uint8_t val = 0;
|
||||||
for (int i = 0; i < 8; i++) { printf(" %d", gpio_get(i)); }
|
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");
|
printf("\n");
|
||||||
tud_task();
|
tud_task();
|
||||||
video_task();
|
video_task();
|
||||||
|
@ -72,8 +72,8 @@
|
|||||||
#define CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE 1023
|
#define CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE 1023
|
||||||
#define CFG_TUD_VIDEO_STREAMING_BULK 0
|
#define CFG_TUD_VIDEO_STREAMING_BULK 0
|
||||||
|
|
||||||
#define FRAME_WIDTH 128
|
#define FRAME_WIDTH 256
|
||||||
#define FRAME_HEIGHT 128
|
#define FRAME_HEIGHT 256
|
||||||
#define FRAME_RATE 60
|
#define FRAME_RATE 60
|
||||||
|
|
||||||
// Temporarily here until ice_usb.h has necessary info
|
// Temporarily here until ice_usb.h has necessary info
|
||||||
|
Loading…
Reference in New Issue
Block a user