I rewrote nearly all the line drawing code, see
github for sources. It's still a work in progress, and right now it can't even draw diagonal lines. Instead, the code draws filled in rectangles. This is just for testing purposes to allow me to focus on the state machine and pipeline, without having to deal with Bresenham at the same time. The code works as follows:
The line module now has an interface to retrieve the vectors from the outside, through a new interface:
Code:
output reg [9:0] vector = 0, // vector number
output read_vector, // read vector enable
input [9:0] x0, // top x coordinate
input [9:0] y0, // top y coordinate
input [9:0] x1, // vector delta y (abs)
input [9:0] y1, // vector delta x (abs)
input [15:0] col, // vector color
input last_vector, // last vector
It outputs the number of the vector it wants, and a read enable signal. When the main module sees the read_vector enable, it writes the coordinates of the vector to (x0,y0) (x1,y1) and col. It also indicates if this was the last valid vector by setting the last_vector bit. For each scanline, the line module cycles through all the vectors, figures out which ones cross the current scanline, and draws them. Except instead of drawing a diagonal line, it paints the entire range between x0 and x1.
The idea is that the main code can choose how to generate the vectors. They could be read from a BRAM, or generated on the fly. Also, the interface could be extended with a 'wait' signal so that the main code could take some extra time to generate the vectors. This could allow a read from external SRAM, for instance. Of course, we're still racing the beam, so you can't afford to waste too many cycles.
The next step is to combine this with the Bresenham code, so that instead of rectangles, it draws diagonal lines. Below is the demo output of the current code. Each of the green horizontal and vertical lines are 1-pixel wide rectangles. Of course, the red square is also a rectangle.