1
0
mirror of https://github.com/sehugg/8bitworkshop.git synced 2024-11-30 21:52:07 +00:00
8bitworkshop/fpga/examples/sprite_renderer.v

98 lines
2.8 KiB
Verilog

`ifndef SPRITE_RENDERER_H
`define SPRITE_RENDERER_H
`include "hvsync_generator.v"
`include "sprite_bitmap.v"
/*
Displays a 16x16 sprite (8 bits mirrored left/right).
*/
module sprite_renderer(clk, reset,
vstart, load, hstart, rom_addr, rom_bits,
gfx, in_progress);
input clk;
input reset;
input vstart; // start drawing (top border)
input load; // ok to load sprite data?
input hstart; // start drawing scanline (left border)
output reg [3:0] rom_addr; // select ROM address
input [7:0] rom_bits; // input bits from ROM
output reg gfx; // output pixel
output in_progress; // 0 if waiting for vstart
reg [2:0] state; // current state #
reg [3:0] ycount; // number of scanlines drawn so far
reg [3:0] xcount; // number of horiz. pixels in this line
reg [7:0] outbits; // register to store bits from ROM
// states for state machine
localparam WAIT_FOR_VSTART = 0;
localparam WAIT_FOR_LOAD = 1;
localparam LOAD1_SETUP = 2;
localparam LOAD1_FETCH = 3;
localparam WAIT_FOR_HSTART = 4;
localparam DRAW = 5;
// assign in_progress output bit
assign in_progress = state != WAIT_FOR_VSTART;
always @(posedge clk or posedge reset)
if (reset) begin
state <= WAIT_FOR_VSTART;
end else begin
case (state)
WAIT_FOR_VSTART: begin
ycount <= 0; // initialize vertical count
gfx <= 0; // default pixel value (off)
// wait for vstart, then next state
if (vstart)
state <= WAIT_FOR_LOAD;
end
WAIT_FOR_LOAD: begin
xcount <= 0; // initialize horiz. count
gfx <= 0;
// wait for load, then next state
if (load)
state <= LOAD1_SETUP;
end
LOAD1_SETUP: begin
rom_addr <= ycount; // load ROM address
state <= LOAD1_FETCH;
end
LOAD1_FETCH: begin
outbits <= rom_bits; // latch bits from ROM
state <= WAIT_FOR_HSTART;
end
WAIT_FOR_HSTART: begin
// wait for hstart, then start drawing
if (hstart)
state <= DRAW;
end
DRAW: begin
// get pixel, mirroring graphics left/right
gfx <= outbits[xcount<8 ? xcount[2:0] : ~xcount[2:0]];
xcount <= xcount + 1;
// finished drawing horizontal slice?
if (xcount == 15) begin // pre-increment value
ycount <= ycount + 1;
// finished drawing sprite?
if (ycount == 15) // pre-increment value
state <= WAIT_FOR_VSTART; // done drawing sprite
else
state <= WAIT_FOR_LOAD; // done drawing this scanline
end
end
// unknown state -- reset
default: begin
state <= WAIT_FOR_VSTART;
end
endcase
end
endmodule