mirror of
https://github.com/UzixLS/TSConf_MiST.git
synced 2025-07-18 23:01:37 +03:00
151 lines
4.3 KiB
Verilog
151 lines
4.3 KiB
Verilog
`include "tune.v"
|
|
|
|
// This module renders pixels into TS-line for tiles/sprites
|
|
// Task execution is initiated by 'tsr_go' (one 'clk' period strobe).
|
|
// Inputs (only valid by 'tsr_go'):
|
|
// - DRAM address of graphics data (including page, line, word)
|
|
// - number of cycles to render (one cycle is 2 words = 8 pixels; 8 cycles = 64 pixels max)
|
|
// - X coordinate
|
|
// - X flip bit
|
|
// - palette selector
|
|
// Address in TS-line is calculated from X coordinate respecting the X flip.
|
|
// Inc/dec direction is set automatically.
|
|
// At the 'c2' of last DRAM cycle 'mem_rdy' is asserted.
|
|
// It should be used in comb to generate next cycle 'tsr_go' strobe for continuous renderer operation.
|
|
// First 'tsr_go' may be issued at any DRAM cycle, but the operation starts only
|
|
// after TS request recognized and processed by DRAM controller.
|
|
// It is recommended to assert 'tsr_go' at 'c2'.
|
|
|
|
module video_ts_render
|
|
(
|
|
// clocks
|
|
input wire clk,
|
|
|
|
// controls
|
|
input wire reset, // line start strobe, inits the machine
|
|
|
|
input wire [ 8:0] x_coord, // address in TS-line where render to, auto-flipped to match 'flip' times 'x_size'
|
|
input wire [ 2:0] x_size, // number of rendering cycles (each cycle is 8 pixels, 0 = 1 cycle)
|
|
input wire flip, // indicates that sprite is X-flipped
|
|
|
|
input wire tsr_go, // 1 clk 28MHz strobe for render start. Should be issued along with 'mem_rdy' for continuous process
|
|
input wire [ 5:0] addr, // address of dword within the line (dword = 8 pix)
|
|
input wire [ 8:0] line, // line of bitmap
|
|
input wire [ 7:0] page, // 1st page of bitmap (TxGpage or SGpage)
|
|
input wire [ 3:0] pal, // palette selector, bits[7:4] of CRAM address
|
|
output wire mem_rdy, // ready to receive new task
|
|
|
|
// TS-Line interface
|
|
output reg [ 8:0] ts_waddr,
|
|
output wire [ 7:0] ts_wdata,
|
|
output wire ts_we,
|
|
|
|
// DRAM interface
|
|
output wire [20:0] dram_addr,
|
|
output wire dram_req,
|
|
input wire [15:0] dram_rdata,
|
|
input wire dram_pre_next,
|
|
input wire dram_next
|
|
);
|
|
|
|
// renderer mux
|
|
reg [15:0] data;
|
|
reg [3:0] pal_r;
|
|
reg [2:0] pix_cnt;
|
|
|
|
wire [3:0] pix_m[0:3];
|
|
wire [3:0] pix = pix_m[pix_cnt[1:0]];
|
|
assign ts_wdata = {pal_r, pix};
|
|
|
|
assign pix_m[0] = data[7:4];
|
|
assign pix_m[1] = data[3:0];
|
|
assign pix_m[2] = data[15:12];
|
|
assign pix_m[3] = data[11:8];
|
|
|
|
// DRAM request
|
|
assign dram_req = tsr_go || !mem_rdy;
|
|
|
|
// DRAM addressing
|
|
reg [20:0] addr_reg;
|
|
|
|
wire [13:0] addr_offset = {page[7:3], line};
|
|
wire [20:0] addr_in = {addr_offset, addr, 1'b0};
|
|
wire [20:0] addr_next = {addr_reg[20:7], addr_reg[6:0] + dram_next};
|
|
assign dram_addr = tsr_go ? addr_in : addr_next;
|
|
|
|
always @(posedge clk)
|
|
addr_reg <= dram_addr;
|
|
|
|
// DRAM cycles counter
|
|
reg [4:0] cyc;
|
|
|
|
assign mem_rdy = cyc[4];
|
|
|
|
always @(posedge clk or posedge reset)
|
|
if (reset)
|
|
cyc <= 5'b10000;
|
|
else if (tsr_go)
|
|
cyc <= {1'b0, x_size, 1'b1};
|
|
else if (dram_pre_next)
|
|
cyc <= cyc - 5'd1;
|
|
|
|
// DRAM data fetching
|
|
always @(posedge clk)
|
|
if (dram_next)
|
|
data <= dram_rdata;
|
|
|
|
// pixel render counter
|
|
wire render_on = !pix_cnt[2];
|
|
assign ts_we = render_on && |pix; // write signal for TS-line
|
|
|
|
always @(posedge clk or posedge reset)
|
|
if (reset)
|
|
pix_cnt <= 3'b100;
|
|
else if (dram_next)
|
|
pix_cnt <= 3'b000;
|
|
else if (render_on)
|
|
pix_cnt <= pix_cnt + 3'd1;
|
|
|
|
// renderer reload
|
|
reg tsr_rld;
|
|
always @(posedge clk or posedge reset)
|
|
if (reset)
|
|
tsr_rld <= 1'b0;
|
|
else if (tsr_go)
|
|
tsr_rld <= 1'b1;
|
|
else if (dram_next)
|
|
tsr_rld <= 1'b0;
|
|
|
|
// delayed values
|
|
reg [8:0] x_coord_d;
|
|
reg [3:0] pal_d;
|
|
reg flip_d;
|
|
|
|
always @(posedge clk)
|
|
if (tsr_go)
|
|
begin
|
|
x_coord_d <= x_coord + (flip ? {x_size, 3'b111} : 6'd0);
|
|
pal_d <= pal;
|
|
flip_d <= flip;
|
|
end
|
|
|
|
|
|
// TS-line address
|
|
reg flip_r;
|
|
|
|
wire [8:0] x_next = ts_waddr + {{8{flip_r}}, 1'b1};
|
|
wire tsr_rld_stb = tsr_rld && dram_next;
|
|
wire [8:0] ts_waddr_mx = tsr_rld_stb ? x_coord_d : (render_on ? x_next : ts_waddr);
|
|
|
|
always @(posedge clk)
|
|
ts_waddr <= ts_waddr_mx;
|
|
|
|
always @(posedge clk)
|
|
if (tsr_rld_stb)
|
|
begin
|
|
pal_r <= pal_d;
|
|
flip_r <= flip_d;
|
|
end
|
|
|
|
endmodule
|