module Lab5 ( parameter SCREEN_TOP = 10'd1, SCREEN_DOWN = 10'd238, SCREEN_LEFT = 10'd3, SCREEN_RIGHT = 10'd319, SCREEN_XHALF = 158, SCREEN_YHALF = 118; // LCD ON assign LCD_ON = 1'b0; assign LCD_BLON = 1'b0; // All inout port turn to tri-state assign DRAM_DQ = 16'hzzzz; assign FL_DQ = 8'hzz; assign SRAM_DQ = 16'hzzzz; assign OTG_DATA = 16'hzzzz; assign SD_DAT = 1'bz; assign ENET_DATA = 16'hzzzz; assign GPIO_0 = 36'hzzzzzzzzz; assign GPIO_1 = 36'hzzzzzzzzz; // VGA wires wire [9:0] mVGA_R, mVGA_G, mVGA_B; // wires to the VGA controller wire [19:0] mVGA_ADDR; // output from the VGA conntroller wire [9:0] coord_x, coord_y; // the requested coordinates from VGA controller // VGA wiring /////////////////////////////////////////// assign mVGA_R = { SRAM_DQ[15:12], 6'h0 }; assign mVGA_B = { SRAM_DQ[11:8], 6'h0 }; assign mVGA_G = { SRAM_DQ[7:4], 6'h0 }; wire VGA_CTRL_CLK; wire AUD_CTRL_CLK; wire DLY_RST; //Allow 27 MHz assign TD_RESET = 1'b1; wire reset_all; assign reset_all = ~KEY[3]; wire pause_all; assign pause_all = ~KEY[2]; VGA_Audio_PLL v0(.areset(~DLY_RST), .inclk0(CLOCK_27), .c0(VGA_CTRL_CLK), .c1(AUD_CTRL_CLK), .c2(VGA_CLK)); Reset_Delay r0( .iCLK(CLOCK_50), .oRESET(DLY_RST)); VGA_Controller c0(.iCursor_RGB_EN(4'b0111), .oAddress(mVGA_ADDR), .oCoord_X(coord_x), .oCoord_Y(coord_y), .iRed(mVGA_R), .iGreen(mVGA_G), .iBlue(mVGA_B), .oVGA_R(VGA_R), .oVGA_G(VGA_G), .oVGA_B(VGA_B), .oVGA_H_SYNC(VGA_HS), .oVGA_V_SYNC(VGA_VS), .oVGA_SYNC(VGA_SYNC), .oVGA_BLANK(VGA_BLANK), .iCLK(VGA_CTRL_CLK), .iRST_N(DLY_RST)); // vga lock reg lock; // SRAM data goes to NIOS data in line reg we; reg [17:0] addr_reg; reg [15:0] data_reg; assign SRAM_ADDR[17:0] = addr_reg[17:0]; assign SRAM_DQ[15:0] = (we) ? data_reg[15:0] : 16'hzzzz; // SRAM CONTROL ///////////////////////////////////////// assign SRAM_UB_N = 0; // hi byte select enabled assign SRAM_LB_N = 0; // lo byte select enable assign SRAM_OE_N = 0; // output enable overriden by WE assign SRAM_WE_N = ~we; // write enable assign SRAM_CE_N = 0; // chip enable assign LEDR[15:12] = object_state[3:0]; assign LEDR[11:08] = comp_state[3:0]; assign LEDR[07:04] = raster_state[3:0]; assign LEDR[03:00] = 4'd0; assign LEDG[3:0] = ~KEY[3:0]; // state counters reg [3:0] object_state; reg [3:0] comp_state; reg [3:0] raster_state; // edge list reg signed [15:0] edge_Ax[0:255], edge_Ay[0:255], edge_Az[0:255], edge_Bx[0:255], edge_By[0:255], edge_Bz[0:255]; reg [7:0] edge_count; reg [7:0] edge_iterator; // computed edges reg signed [15:0] comp_Ax[0:255], comp_Ay[0:255], comp_Az[0:255], comp_Bx[0:255], comp_By[0:255], comp_Bz[0:255]; reg [7:0] comp_count; reg [7:0] comp_iterator; // bresenhem wires reg bresenhem_init; reg [9:0] bre_Ax, bre_Ay, bre_Bx, bre_By; wire bresenhem_busy, bresenhem_done; wire bresenhem_we; wire [8:0] bresenhem_addr_reg_x, bresenhem_addr_reg_y; wire [1:0] bresenhem_data_reg; bresenhem bresenhem_instance(.CLK(VGA_CTRL_CLK), .reset(reset_all), .init(bresenhem_init), .lock((~VGA_VS | ~VGA_HS) & ~pause_all), .busy(bresenhem_busy), .done(bresenhem_done), .Ax_in(bre_Ax), .Ay_in(bre_Ay), .Bx_in(bre_Bx), .By_in(bre_By), .we(bresenhem_we), .addr_reg_x(bresenhem_addr_reg_x), .addr_reg_y(bresenhem_addr_reg_y), .data_reg(bresenhem_data_reg)); // circle wires reg circle_init; wire circle_busy, circle_done; wire [15:0] circle_Ax, circle_Ay, circle_Az, circle_Bx, circle_By, circle_Bz; reg [15:0] circle_stepsize; circle_gen circle_generator(.CLK(VGA_CTRL_CLK), .reset(reset_all), .init(circle_init), .lock(1'b1), .busy(circle_busy), .done(circle_done), .Ax(circle_Ax), .Ay(circle_Ay), .Az(circle_Az), .Bx(circle_Bx), .By(circle_By), .Bz(circle_Bz), .stepsize(circle_stepsize)); // cube wires reg cube_init; wire cube_busy, cube_done; wire [15:0] cube_Ax, cube_Ay, cube_Az, cube_Bx, cube_By, cube_Bz; cube_gen cube_generator(.CLK(VGA_CTRL_CLK), .reset(reset_all), .init(cube_init), .lock(1'b1), .busy(cube_busy), .done(cube_done), .Ax(cube_Ax), .Ay(cube_Ay), .Az(cube_Az), .Bx(cube_Bx), .By(cube_By), .Bz(cube_Bz)); // transformation wires reg [55:0] graphic_word; reg translater_init, scaler_init, rotater_init; wire [4:0] knob_addr; reg [15:0] knob_val; // obvious wire [15:0] transarg_x, transarg_y, transarg_z; // non-knob-multiplied wire [17:0] knobmult_x, knobmult_y, knobmult_z; // processed op (knob-multiplied or not) wire [15:0] transop_x, transop_y, transop_z; wire [1:0] rotate_axis; // status wires per module wire translater_busy_A, translater_done_A; wire translater_busy_B, translater_done_B; wire scaler_busy_A, scaler_done_A; wire scaler_busy_B, scaler_done_B; wire rotater_busy_A, rotater_done_A; wire rotater_busy_B, rotater_done_B; // all status wires wire translater_busy, translater_done; wire scaler_busy, scaler_done; wire rotater_busy, rotater_done; // if either are busy, don't advance assign translater_busy = translater_busy_A | translater_busy_B; assign scaler_busy = scaler_busy_A | scaler_busy_B; assign rotater_busy = rotater_busy_A | rotater_busy_B; // if both aren't done, not done assign translater_done = translater_done_A & translater_done_B; assign scaler_done = scaler_done_A & scaler_done_B; assign rotater_done = rotater_done_A & rotater_done_B; // temporary registers reg [15:0] transform_Ax, transform_Ay, transform_Az; reg [15:0] transform_Bx, transform_By, transform_Bz; wire [15:0] next_Ax, next_Ay, next_Az; wire [15:0] next_Bx, next_By, next_Bz; // transformation and rotation selection wire [2:0] transform_sel; assign rotate_axis[1:0] = transform_sel[1:0]; // transform ops reg [55:0] graphic_ops [0:4]; reg [4:0] graphic_ops_count; reg [4:0] graphic_ops_iterator; // 56-bit control word // opcode 3 bits wide // 3x16 transformation arguments // 5 bit knob handler `define G_OPCODE 55:53 `define G_KNOB 52:48 `define G_XARG 47:32 `define G_YARG 31:16 `define G_ZARG 15:0 assign transform_sel[2:0] = graphic_word[`G_OPCODE]; assign knob_addr[4:0] = graphic_word[`G_KNOB]; assign transarg_x[15:0] = graphic_word[`G_XARG]; assign transarg_y[15:0] = graphic_word[`G_YARG]; assign transarg_z[15:0] = graphic_word[`G_ZARG]; signed_mult transop_xer(knobmult_x[17:0], { transarg_x[15:0], 2'b00 }, { knob_val[15:0], 2'b00 }); signed_mult transop_yer(knobmult_y[17:0], { transarg_y[15:0], 2'b00 }, { knob_val[15:0], 2'b00 }); signed_mult transop_zer(knobmult_z[17:0], { transarg_z[15:0], 2'b00 }, { knob_val[15:0], 2'b00 }); assign transop_x[15:0] = (knob_addr == 0) ? transarg_x[15:0] : knobmult_x[17:2]; assign transop_y[15:0] = (knob_addr == 0) ? transarg_y[15:0] : knobmult_y[17:2]; assign transop_z[15:0] = (knob_addr == 0) ? transarg_z[15:0] : knobmult_z[17:2]; rotate rotaterA(.CLK(VGA_CTRL_CLK), .reset(reset_all), .lock(1'b1), .init(rotater_init), .busy(rotater_busy_A), .done(rotater_done_A), .Ax(transform_Ax), .Ay(transform_Ay), .Az(transform_Az), .theta(transop_x), .axis(rotate_axis), .Bx(next_Ax), .By(next_Ay), .Bz(next_Az)); translate translaterA(.CLK(VGA_CTRL_CLK), .reset(reset_all), .lock(1'b1), .init(translater_init), .busy(translater_busy_A), .done(translater_done_A), .Ax(transform_Ax), .Ay(transform_Ay), .Az(transform_Az), .Dx(transop_x), .Dy(transop_y), .Dz(transop_z), .Bx(next_Ax), .By(next_Ay), .Bz(next_Az)); scale scalerA(.CLK(VGA_CTRL_CLK), .reset(reset_all), .lock(1'b1), .init(scaler_init), .busy(scaler_busy_A), .done(scaler_done_A), .Ax(transform_Ax), .Ay(transform_Ay), .Az(transform_Az), .Sx(transop_x), .Sy(transop_y), .Sz(transop_z), .Bx(next_Ax), .By(next_Ay), .Bz(next_Az)); rotate rotaterB(.CLK(VGA_CTRL_CLK), .reset(reset_all), .lock(1'b1), .init(rotater_init), .busy(rotater_busy_B), .done(rotater_done_B), .Ax(transform_Bx), .Ay(transform_By), .Az(transform_Bz), .theta(transop_x), .axis(rotate_axis), .Bx(next_Bx), .By(next_By), .Bz(next_Bz)); translate translaterB(.CLK(VGA_CTRL_CLK), .reset(reset_all), .lock(1'b1), .init(translater_init), .busy(translater_busy_B), .done(translater_done_B), .Ax(transform_Bx), .Ay(transform_By), .Az(transform_Bz), .Dx(transop_x), .Dy(transop_y), .Dz(transop_z), .Bx(next_Bx), .By(next_By), .Bz(next_Bz)); scale scalerB(.CLK(VGA_CTRL_CLK), .reset(reset_all), .lock(1'b1), .init(scaler_init), .busy(scaler_busy_B), .done(scaler_done_B), .Ax(transform_Bx), .Ay(transform_By), .Az(transform_Bz), .Sx(transop_x), .Sy(transop_y), .Sz(transop_z), .Bx(next_Bx), .By(next_By), .Bz(next_Bz)); parameter draw_circle = 4'd0, wait_circle = 4'd1, draw_lines = 4'd2, wait_lines = 4'd3, keyok_lines = 4'd8, transform_prep = 4'd4, transform_exec = 4'd5, transform_wait = 4'd6, transform_save = 4'd7; parameter debug_transform = 1'b0; // consumer of objects, producer of edge list always @(posedge VGA_CTRL_CLK) begin if (reset_all) begin edge_count <= 8'd0; object_state <= draw_circle; end else if (object_state == draw_circle) begin //circle_stepsize <= 16'd100; //circle_stepsize <= 16'd32; //circle_stepsize <= 16'd8; circle_stepsize <= SW[9:0]; if (SW[17:16] == 2'b00) begin circle_init <= 1'b1; cube_init <= 1'b0; end else if (SW[17:16] == 2'b10) begin circle_init <= 1'b0; cube_init <= 1'b1; end object_state <= wait_circle; end else if (object_state == wait_circle) begin if (circle_busy | cube_busy) begin edge_Ax[edge_count] <= (SW[17:16] == 2'b00) ? circle_Ax : cube_Ax; edge_Ay[edge_count] <= (SW[17:16] == 2'b00) ? circle_Ay : cube_Ay; edge_Az[edge_count] <= (SW[17:16] == 2'b00) ? circle_Az : cube_Az; edge_Bx[edge_count] <= (SW[17:16] == 2'b00) ? circle_Bx : cube_Bx; edge_By[edge_count] <= (SW[17:16] == 2'b00) ? circle_By : cube_By; edge_Bz[edge_count] <= (SW[17:16] == 2'b00) ? circle_Bz : cube_Bz; edge_count <= edge_count + 8'd1; end // if (circle_busy) else if (circle_done | cube_done) begin circle_init <= 1'b0; end end // if (object_state == wait_circle) end // always @ (posedge VGA_CTRL_CLK) // consumer of edge list, producer of computed edges always @(posedge VGA_CTRL_CLK) begin if (reset_all) begin edge_iterator <= 8'd0; comp_count <= 8'd0; graphic_ops_iterator <= 0; // initialize the graphics ops here graphic_ops_count <= 4; graphic_ops[0] = { 3'b101, 5'd0, 16'd1 << 13, 16'd1 << 13, 16'd1 << 13}; //graphic_ops[0] = { 3'b101, 5'd0, 16'd1 << 12, 16'd1 << 12, 16'd1 << 12}; graphic_ops[1] = { 3'b100, 5'd0, 16'd20, 16'd20, 16'd20 }; // rotate about x-axis 45 degrees graphic_ops[2] = { 3'b000, 5'd0, 16'h0200, 16'd20, 16'd20 }; // rotate about y-axis 45 degrees graphic_ops[3] = { 3'b001, 5'd0, 16'h0010, 16'd20, 16'd20 }; // scale by 0.5 //graphic_ops[0] = { 3'b101, 5'd0, 16'd1 << 13, 16'd1 << 13, 16'd1 << 13}; // translate by +20 //graphic_ops[1] = { 3'b100, 5'd0, 16'd20, 16'd20, 16'd20 }; // translate +20, +20, +20. works perfectly // graphic_word[55:0] = { 3'b100, 5'd0, 16'd20, 16'd20, 16'd20 }; // for every unit of scale required, must right shift by 14 //graphic_word[55:0] = { 3'b101, 5'd0, 16'd2, 16'd2, 16'd2 }; // rotate 180 == 256 steps //graphic_word[55:0] = { 3'b010, 5'd0, 16'd256, 16'd2, 16'd2 }; //graphic_word[55:0] = { 3'b010, 5'd0, 16'd128, 16'd0, 16'd0 }; comp_state <= transform_prep; end // if (reset_all) // blocking on edge_count. else if (comp_state == transform_prep) begin if (edge_iterator < edge_count) begin if (debug_transform) begin $display("op dump: %b", graphic_ops[0]); $display("op dump: %b", graphic_ops[1]); end // load transform registers transform_Ax <= edge_Ax[edge_iterator] >>> 8; transform_Ay <= edge_Ay[edge_iterator] >>> 8; transform_Az <= edge_Az[edge_iterator] >>> 8; transform_Bx <= edge_Bx[edge_iterator] >>> 8; transform_By <= edge_By[edge_iterator] >>> 8; transform_Bz <= edge_Bz[edge_iterator] >>> 8; // select none rotater_init <= 1'b0; translater_init <= 1'b0; scaler_init <= 1'b0; // go to transform_exec comp_state <= transform_exec; // load graphics op word graphic_word <= graphic_ops[graphic_ops_iterator]; end // if (comp_state == transform_prep) else begin //$display("in transform_prep waiting for more edges"); end end else if (comp_state == transform_exec) begin if (graphic_ops_iterator < graphic_ops_count) begin if (transform_sel == 3'b000 | transform_sel == 3'b001 | transform_sel == 3'b010) begin // select rotation rotater_init <= 1'b1; translater_init <= 1'b0; scaler_init <= 1'b0; end else if (transform_sel == 3'b100) begin // select translation rotater_init <= 1'b0; translater_init <= 1'b1; scaler_init <= 1'b0; end else if (transform_sel == 3'b101) begin // select scaling rotater_init <= 1'b0; translater_init <= 1'b0; scaler_init <= 1'b1; end else begin $display("TRANSFORMATION DISPATCH: op %d of %d.", graphic_ops_iterator, graphic_ops_count, transop_x); $finish; end // wait for transformation to be finished //$display("going to transform_wait"); comp_state <= transform_wait; // increment to the next operation graphic_ops_iterator <= graphic_ops_iterator + 1; end // if (graphic_ops_iterator < graphic_ops_count) else begin $display("transform waiting on exec for more points"); $finish; end end // if (comp_state == transform_exec) else if (comp_state == transform_wait) begin if (rotater_done | translater_done | scaler_done) begin // save the intermediate values transform_Ax <= next_Ax; transform_Ay <= next_Ay; transform_Az <= next_Az; transform_Bx <= next_Bx; transform_By <= next_By; transform_Bz <= next_Bz; // deselect all the transformation units rotater_init <= 1'b0; translater_init <= 1'b0; scaler_init <= 1'b0; if (graphic_ops_iterator < graphic_ops_count) begin // load graphics op word graphic_word <= graphic_ops[graphic_ops_iterator]; // go back to transform_exec comp_state <= transform_exec; end else begin // done state comp_state <= transform_save; end end // if (rotater_done | translater_done | scaler_done) end // if (comp_state == transform_wait) else if (comp_state == transform_save) begin // writeback // save point into computed rf comp_Ax[edge_iterator] <= next_Ax; comp_Ay[edge_iterator] <= next_Ay; comp_Az[edge_iterator] <= next_Az; comp_Bx[edge_iterator] <= next_Bx; comp_By[edge_iterator] <= next_By; comp_Bz[edge_iterator] <= next_Bz; comp_count <= comp_count + 8'd1; // increment edge iterator edge_iterator <= edge_iterator + 8'd1; // reset graphics op iterator graphic_ops_iterator <= 8'd0; // go to transform_prep to wait for more edges //comp_state <= transform_prep; comp_state <= transform_prep; end // if (comp_state == transform_save) end // always @ (posedge VGA_CTRL_CLK) always @(posedge VGA_CTRL_CLK) begin if (reset_all) begin // wipe all screen lock <= 1'b1; addr_reg <= { coord_x[9:1], coord_y[9:1] }; if ({1'b0, coord_x[9:1]} <= SCREEN_LEFT | {1'b0, coord_x[9:1]} >= SCREEN_RIGHT | {1'b0, coord_y[9:1]} <= SCREEN_TOP | {1'b0, coord_y[9:1]} >= SCREEN_DOWN) begin data_reg <= 16'hffff; end else begin data_reg <= 16'h0000; end // active-hi save we <= 1'b1; // bresenhem vars comp_iterator <= 8'd0; raster_state <= draw_lines; bresenhem_init <= 1'b0; end else if ((~VGA_VS | ~VGA_HS) & ~pause_all & ~circle_busy) begin lock <= 1'b1; // set the output to the data reg addr_reg <= { bresenhem_addr_reg_x[8:0], bresenhem_addr_reg_y[8:0] }; data_reg <= (bresenhem_data_reg == 2'b01) ? 16'hffff : 16'h0000; we <= bresenhem_we; if (raster_state == draw_lines) begin if (comp_iterator < comp_count) begin bre_Ax <= comp_Ax[comp_iterator] + SCREEN_XHALF; bre_Ay <= comp_Ay[comp_iterator] + SCREEN_YHALF; bre_Bx <= comp_Bx[comp_iterator] + SCREEN_XHALF; bre_By <= comp_By[comp_iterator] + SCREEN_YHALF; bresenhem_init <= 1'b1; comp_iterator <= comp_iterator + 8'd1; raster_state <= wait_lines; end // if (comp_iterator < comp_count) end // if (raster_state <= draw_lines) else if (raster_state == wait_lines) begin if (bresenhem_busy) begin bresenhem_init <= 1'b0; end //else if (bresenhem_done & (1'b1 & ~KEY[0])) begin else if (bresenhem_done) begin bresenhem_init <= 1'b0; raster_state <= draw_lines; end end // if (raster_state == wait_lines) else if (raster_state == keyok_lines) begin if (KEY[0]) begin bresenhem_init <= 1'b0; raster_state <= draw_lines; end end end // if ((~VGA_VS | ~VGA_HS) & ~pause_all & ~circle_busy) else begin // drawing to the screen lock <= 1'b0; addr_reg <= { coord_x[9:1], coord_y[9:1] }; we <= 1'b0; end end // show the addressing being asserted using HEX[7:4] HexDigit Digit0(HEX0, bre_By[3:0]); HexDigit Digit1(HEX1, bre_By[7:4]); HexDigit Digit2(HEX2, bre_Bx[3:0]); HexDigit Digit3(HEX3, bre_Bx[7:4]); HexDigit Digit4(HEX4, bre_Ay[3:0]); HexDigit Digit5(HEX5, bre_Ay[7:4]); HexDigit Digit6(HEX6, bre_Ax[3:0]); HexDigit Digit7(HEX7, bre_Ax[7:4]); // show the contents of that address using HEX[3:0] endmodule