module bresenhem (CLK, reset, init, Ax_in, Ay_in, Bx_in, By_in, lock, busy, done, we, addr_reg_x, addr_reg_y, data_reg); input CLK; wire CLK; // active-high reset input reset; wire reset; // external signal to start. ax, ay, bx, by are set input init; wire init; input signed [9:0] Ax_in, Ay_in, Bx_in, By_in; wire signed [9:0] Ax_in, Ay_in, Bx_in, By_in; // did we lose the lock? input lock; wire lock; // SRAM (or data-store) control output we; output [8:0] addr_reg_x, addr_reg_y; output [1:0] data_reg; reg we; // write enable reg [8:0] addr_reg_x, addr_reg_y; reg [1:0] data_reg; //reg [17:0] addr_reg; //reg [15:0] data_reg; reg signed [9:0] Ax, Ay, Bx, By; // signal raised to show that the algo. isn't done // only high if init is high. // is never high when done is high. output busy; reg busy = 1'b0; // signal raised to show that the ax,ay,bx,by line is drawn. // only high for as long as init is not going posedge. output done; reg done = 1'b0; reg signed [9:0] Ax_last, Ay_last, Bx_last, By_last; reg signed [9:0] dX, dY, Xincr, Yincr; reg signed [9:0] dPr, dPru, P, loop_end; wire signed [9:0] Ax_incr, Ay_incr; assign Ax_incr = Ax + Xincr; assign Ay_incr = Ay + Yincr; reg [3:0] state; // state machine variable for current state //reg lock; // the hardware lock parameter init_line = 4'd0, lineDX = 4'd1, lineDY = 4'd2, done_line = 4'd3, SCREEN_TOP = 10'd1, SCREEN_DOWN = 10'd238, SCREEN_LEFT = 10'd3, SCREEN_RIGHT = 10'd319, debug_drawing = 1'b1, debug_bresenhem = 1'b1; always @(posedge CLK) begin if (reset) begin // last lines? Ax_last <= 10'd0; Ay_last <= 10'd0; Bx_last <= 10'd0; By_last <= 10'd0; busy <= 1'b0; done <= 1'b0; state <= done_line; we <= 1'b0; end else if (lock) begin case (state) done_line: begin // progress only if there is new input if (init == 1'b1) begin // this may hang if the requester asks the module // to draw the same points twice! // requester must de-asserted init line for at least // one cycle in order to reset if (Ax_in != Ax_last & Ay_in != Ay_last & Bx_in != Bx_last & By_in != By_last) begin // a new and different line was just requested thru ax,ay,bx,by // saving to compare Ax_last <= Ax_in; Ay_last <= Ay_in; Bx_last <= Bx_in; By_last <= By_in; // saving as state variables Ax <= Ax_in; Ay <= Ay_in; Bx <= Bx_in; By <= By_in; // setting some differential variables // dX gets abs (Bx - Ax) // Xincr gets (Ax < Bx) or (Bx > Ax) if (Bx_in > Ax_in) begin dX <= Bx_in - Ax_in; Xincr <= 10'd1; end else begin dX <= Ax_in - Bx_in; Xincr <= -10'd1; end // dY gets abs (By - Ay) // Yincr gets (Ay < By) or (By > Ay) if (By_in > Ay_in) begin dY <= By_in - Ay_in; Yincr <= 10'd1; end else begin dY <= Ay_in - By_in; Yincr <= -10'd1; end // start drawing this line state <= init_line; // not done drawing line. busy. busy <= 1'b1; done <= 1'b0; end else begin // done drawing the line. finished. busy <= 1'b0; done <= 1'b1; end end else begin // communicate to software that we are reset and ready. // here: nothing busy <= 1'b0; done <= 1'b0; Ax_last <= 10'd0; Ay_last <= 10'd0; Bx_last <= 10'd0; By_last <= 10'd0; end end // case: done_line init_line: begin if (dX >= dY) begin dPr <= (dY << 10'b1); dPru <= (dY << 10'b1) - (dX << 10'b1); P <= (dY << 10'b1) - dX; loop_end <= dX; state <= lineDX; end else begin dPr <= (dX << 10'b1); dPru <= (dX << 10'b1) - (dY << 10'b1); P <= (dX << 10'b1) - dY; loop_end <= dY; state <= lineDY; end // else: !if(dX >= dY) // draw the initial point? if (Ax_incr >= SCREEN_LEFT & Ax_incr < SCREEN_RIGHT & Ay_incr >= SCREEN_TOP & Ay_incr < SCREEN_DOWN) begin // plot the thing //lock <= 1'b1; addr_reg_x <= Ax[8:0]; addr_reg_y <= Ay[8:0]; //data_reg <= 16'hffff; data_reg <= 2'b01; // white dot we <= 1'b1; if (debug_drawing) begin $display("Drawing (%d, %d).", Ax[8:0], Ay[8:0]); end end else begin we <= 1'b0; end // else: !if(Ax >= SCREEN_LEFT & Ax < SCREEN_RIGHT &... end // case: init_line lineDX: begin // for the case when dX >= dY if (loop_end > 0) begin if (P > 0) begin Ax <= Ax_incr; Ay <= Ay_incr; P <= P + dPru; end else begin Ax <= Ax_incr; P <= P + dPr; end // else: !if(P > 0) // draw? if (Ax_incr >= SCREEN_LEFT & Ax_incr < SCREEN_RIGHT & Ay_incr >= SCREEN_TOP & Ay_incr < SCREEN_DOWN) begin // plot the thing //lock <= 1'b1; //addr_reg <= { Ax_incr[8:0], (P > 0) ? Ay_incr[8:0] : Ay[8:0] }; addr_reg_x <= Ax_incr[8:0]; addr_reg_y <= (P > 0) ? Ay_incr[8:0] : Ay[8:0]; //data_reg <= 16'hffff; data_reg <= 2'b01; we <= 1'b1; end else begin we <= 1'b0; end // else: !if(Ax >= SCREEN_LEFT & Ax < SCREEN_RIGHT &... loop_end <= loop_end - 1; end // if (loop_end > 0) else begin state <= done_line; busy <= 1'b0; done <= 1'b1; end // else: !if(loop_end > 0) end // case: lineDX lineDY: begin // for the case when dX < dY if (loop_end > 0) begin if (P > 0) begin if (debug_bresenhem) begin $display("lineDY_a: Ax = %d, Xincr = %d, Ax + Xincr = %d", Ax, Xincr, Ax_incr); end Ax <= Ax_incr; Ay <= Ay_incr; P <= P + dPru; end else begin if (debug_bresenhem) begin $display("lineDY_b: Ax = %d, Xincr = %d, Ax + Xincr = %d", Ax, Xincr, Ax_incr); end Ay <= Ay_incr; P <= P + dPr; end // draw? if (Ax_incr >= SCREEN_LEFT & Ax_incr < SCREEN_RIGHT & Ay_incr >= SCREEN_TOP & Ay_incr < SCREEN_DOWN) begin // plot the thing //lock <= 1'b1; //addr_reg <= { (P > 0) ? Ax_incr[8:0] : Ax[8:0], Ay_incr[8:0] }; addr_reg_x <= (P > 0) ? Ax_incr[8:0] : Ax[8:0]; addr_reg_y <= Ay_incr[8:0]; //data_reg <= 16'hffff; data_reg <= 2'b01; // white dot we <= 1'b1; end else begin we <= 1'b0; end // else: !if(Ax >= SCREEN_LEFT & Ax < SCREEN_RIGHT &... loop_end <= loop_end - 1; end else begin // if (loop_end > 0) state <= done_line; busy <= 1'b0; done <= 1'b1; end // else: !if(loop_end > 0) end // case: lineDY endcase // case (state) end end // always @ (posedge CLK) endmodule