pico-ice-video/ice/mandelbrot/source/impl_1/renderer.sv
2024-10-06 00:18:41 -04:00

82 lines
1.8 KiB
Systemverilog

module renderer
#(
parameter ITERATIONS = 7,
parameter OUTPUT_WIDTH = 3,
localparam ITERATION_WIDTH = $clog2(ITERATIONS + 1),
localparam SHIFT_AMOUNT = ITERATION_WIDTH - OUTPUT_WIDTH
)(
input wire clk,
input wire rst,
input wire start,
input wire signed [7:0] x,
input wire signed [7:0] y,
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 [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 [7:0] a_squared;
wire signed [7:0] b_squared;
wire signed [7: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
x_reg <= '0;
y_reg <= '0;
z_real <= '0;
z_imag <= '0;
iters <= current_iteration >> SHIFT_AMOUNT;
current_iteration <= '0;
done <= 1'b1;
end else if (current_iteration == 0) begin
// store c for later
x_reg <= x;
y_reg <= y;
// add c for first iteration.
// no need to include z as it is initially (0, 0)
z_real <= x;
z_imag <= y;
if (!start) begin
current_iteration <= '0;
end
end else begin
z_real <= a_squared + b_squared + x_reg;
z_imag <= (ab << 1'b1) + y_reg;
end
if (rst) begin
x_reg <= 8'h00;
y_reg <= 8'h00;
z_real <= 8'h00;
z_imag <= 8'h00;
current_iteration <= '0;
end
end
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];
endmodule