I'll check this into SVN later, but some people may want to look at it
and discuss it for educational purposes. The following is a prototype
of the OGA video controller block, which will also be supplied with
OGD1. This is being issued under Traversal's dual license. I say
it's a prototype because it isn't tested (which I'm hoping some of you
will help with), and there are major flaws in the cursor overlay block
(which I expect you to find!) that I just haven't gotten around to
fixing. There's also a potential metastability issue with the
interrupt reset that I have to address. Note that the wrapper is
there primarily as a way to isolate the other blocks from the I/O
buffers when synthesizing so I can tell how the block will perform.
Also, I need to add lots of comments and clean up the sloppiness.
Let's see if anyone can figure out how this is supposed to work. :)
Without further ado, here it is:
module vid_wrapper(
vid_clock,
pci_clock,
reset,
reg_write_data,
reg_write_addr,
reg_write,
req_addr,
req_enq,
req_busy,
in_fifo_data,
deq_in_fifo,
out_pixels,
out_signals,
interrupt
);
input vid_clock, pci_clock, reset;
input [31:0] reg_write_data;
input [10:0] reg_write_addr;
input reg_write;
input req_busy;
output [27:0] req_addr;
output req_enq;
reg [27:0] req_addr;
reg req_enq;
input [0:255] in_fifo_data;
output deq_in_fifo;
reg deq_in_fifo;
output [0:127] out_pixels;
output [2:0] out_signals;
reg [0:127] out_pixels;
reg [2:0] out_signals;
output interrupt;
reg interrupt;
reg [31:0] reg_write_data_r;
reg [10:0] reg_write_addr_r;
reg reg_write_r;
always @(posedge pci_clock) begin
{reg_write_data_r, reg_write_addr_r, reg_write_r} <=
{reg_write_data, reg_write_addr, reg_write};
end
wire [27:0] req_addr_i;
wire req_enq_i;
wire [11:0] cursor_x_i, cursor_y_i;
wire [127:0] out_pixels_i;
wire [2:0] out_signals_i;
wire [127:0] out_pixels_j;
wire [2:0] out_signals_j;
wire interrupt_i;
reg req_busy_r;
reg [0:255] in_fifo_data_r;
wire deq_in_fifo_i;
always @(posedge vid_clock) begin
req_addr <= req_addr_i;
req_enq <= req_enq_i;
req_busy_r <= req_busy;
{out_pixels, out_signals} <= {out_pixels_i, out_signals_i};
interrupt <= interrupt_i;
in_fifo_data_r <= in_fifo_data;
deq_in_fifo <= deq_in_fifo_i;
end
vid_control vc (
.vid_clock (vid_clock),
.pci_clock (pci_clock),
.reset (reset),
.reg_write_data (reg_write_data_r),
.reg_write_addr (reg_write_addr_r[9:0]),
.reg_write (reg_write_r && !reg_write_addr_r[10]),
.req_addr (req_addr_i),
.req_enq (req_enq_i),
.req_busy (req_busy_r),
.in_fifo_data (in_fifo_data_r),
.deq_in_fifo (deq_in_fifo_i),
.out_pixels (out_pixels_j),
.out_signals (out_signals_j),
.cursor_x (cursor_x_i),
.cursor_y (cursor_y_i),
.interrupt (interrupt_i)
);
cursor_overlay co (
.vid_clock (vid_clock),
.pci_clock (pci_clock),
.reset (reset),
.reg_write_data (reg_write_data_r),
.reg_write_addr (reg_write_addr_r[9:0]),
.reg_write (reg_write_r && reg_write_addr_r[10]),
.cursor_x (cursor_x_i),
.cursor_y (cursor_y_i),
.in_pixels (out_pixels_j),
.in_signals (out_signals_j),
.out_pixels (out_pixels_i),
.out_signals (out_signals_i)
);
endmodule
module vid_control(
vid_clock,
pci_clock,
reset,
reg_write_data,
reg_write_addr,
reg_write,
req_addr,
req_enq,
req_busy,
in_fifo_data,
deq_in_fifo,
out_pixels,
out_signals,
cursor_x,
cursor_y,
interrupt
);
input vid_clock, pci_clock, reset;
input [31:0] reg_write_data;
input [9:0] reg_write_addr;
input reg_write;
input req_busy;
output [27:0] req_addr;
output req_enq;
input [0:255] in_fifo_data;
output deq_in_fifo;
output [0:127] out_pixels;
output [2:0] out_signals;
reg [0:127] out_pixels;
reg [2:0] out_signals;
output [11:0] cursor_x, cursor_y;
reg [11:0] cursor_x, cursor_y;
output interrupt;
reg interrupt;
reg [8:0] ins_addr;
wire [31:0] ins;
RAMB16_S36_S36 dlist_ram (
.DOA(ins), .DOPA(),
.DOB(), .DOPB(),
.ADDRA(ins_addr), .CLKA(vid_clock),
.DIA(32'b0), .DIPA(4'b0),
.DIB(reg_write_data), .DIPB(4'b0),
.ADDRB(reg_write_addr[8:0]), .CLKB(pci_clock),
.ENA(1'b1), .SSRA(1'b0),
.ENB(1'b1), .SSRB(1'b0),
.WEA(1'b0), .WEB(reg_write && !reg_write_addr[9]));
reg [11:0] cursor_x_start, cursor_y_start;
reg [7:0] clear_int;
reg [2:0] depth;
always @(posedge pci_clock) begin
clear_int <= {clear_int[6:0], 1'b0};
if (reg_write && reg_write_addr[9]) begin
case (reg_write_addr[1:0])
0: cursor_x_start <= reg_write_data;
1: cursor_y_start <= reg_write_data;
2: clear_int <= 8'hff;
3: depth <= reg_write_data;
endcase
end
end
reg [8:0] pc, npc, retpc, retnpc;
reg [11:0] counter0, counter1;
reg [1:0] counting;
wire jump_ins = ins[23:22]==0;
//wire [11:0] next_counter = counting[0] ? counter[0] : ins[20:9];
wire no_loop = counting[0] ? counter0[11] : ins[20];
always @(ins or jump_ins or no_loop or pc or npc or retpc or retnpc) begin
if (jump_ins) begin
ins_addr = ins[8:0];
end else if (!no_loop) begin
ins_addr = ins[26] ? retpc : pc;
end else begin
ins_addr = ins[26] ? retnpc : npc;
end
end
reg [7:0] req_count;
reg [27:0] req_addr;
reg req_enq;
reg [1:0] inc_carry;
reg [3:0] deq_count;
reg [2:0] shift_count;
reg send_pixel;
assign deq_in_fifo = send_pixel && deq_count[3];
reg [0:255] shifted_pixels;
reg [0:127] pixels16, pixels8;
reg [0:127] muxed_pixels;
reg [7:0] i;
always @(shifted_pixels or depth) begin
//shifted_pixels = in_fifo_data << {shift_count, 5'b0};
for (i=0; i<128; i=i+1) begin
pixels16[i] = shifted_pixels[{i[6:5], i[3:0]}];
end
for (i=0; i<128; i=i+1) begin
pixels8[i] = shifted_pixels[{i[6:5], i[2:0]}];
end
muxed_pixels = shifted_pixels[0:127] & {128{depth[2]}};
muxed_pixels = muxed_pixels | (pixels16 & {128{depth[1]}});
muxed_pixels = muxed_pixels | (pixels8 & {128{depth[0]}});
end
always @(posedge vid_clock) begin
out_pixels <= muxed_pixels;
end
//wire [31:0] const_pixel = {8'b0, ins[20:14], ins[20],
// ins[13:7], ins[13], ins[6:0], ins[6]};
reg [2:0] out_signals_a, out_signals_b;
reg [20:0] addr_val;
reg addr_add, addr_set;
always @(posedge vid_clock or negedge reset) begin
if (!reset) begin
pc <= 0;
npc <= 1;
{retpc, retnpc} <= 0;
counter0 <= 0;
counter1 <= 0;
counting <= 0;
req_addr <= 0;
req_count <= 0;
req_enq <= 0;
//out_pixels <= 0;
out_signals <= 0;
out_signals_a <= 0;
{cursor_x, cursor_y} <= 0;
inc_carry <= 0;
deq_count <= 0;
send_pixel <= 0;
out_signals_b <= 0;
{addr_val, addr_add, addr_set} <= 0;
end else begin
out_signals_b <= ins[31:29];
out_signals_a <= out_signals_b;
out_signals <= out_signals_a;
inc_carry <= 0;
{inc_carry[1], req_addr[17:9]} <= req_addr[17:9] + inc_carry[0];
req_addr[27:18] <= req_addr[27:18] + inc_carry[1];
/*case (1'b1) // synthesis parallel_case
req_enq: begin
if (!req_busy) begin
if (!inc_carry) begin
{inc_carry[0], req_addr[8:0]} <= req_addr[8:0] + 1;
end
if (req_addr[8:0] == 9'h1ff ||
(inc_carry[0] && req_addr[17:9] == 9'h1ff)) begin
req_enq <= 0;
end else begin
req_count <= req_count - 1;
req_enq <= req_count > 1;
end
end
end
addr_set: begin
req_addr <= {addr_val, 7'b0};
end
addr_add: begin
{inc_carry[0], req_addr[8:0]} <= req_addr[8:0] + addr_val[8:0];
{inc_carry[1], req_addr[17:9]} <= req_addr[17:9] +
addr_val[17:9];
req_addr[27:18] <= req_addr[27:18] + addr_val[20:18];
end
endcase*/
if (req_enq && !req_busy) begin
if (!inc_carry) begin
{inc_carry[0], req_addr[8:0]} <= req_addr[8:0] + 1;
end
if (req_addr[8:0] == 9'h1ff ||
(inc_carry[0] && req_addr[17:9] == 9'h1ff)) begin
req_enq <= 0;
end else begin
req_count <= req_count - 1;
req_enq <= req_count > 1;
end
end
if (addr_set) begin
req_addr <= {addr_val, 7'b0};
end
if (addr_add) begin
{inc_carry[0], req_addr[8:0]} <= req_addr[8:0] + addr_val[8:0];
{inc_carry[1], req_addr[17:9]} <= req_addr[17:9] + addr_val[17:9];
req_addr[27:18] <= req_addr[27:18] + addr_val[20:18];
end
pc <= ins_addr;
npc <= ins_addr + 1;
if (ins[27]) begin
cursor_x <= cursor_x_start;
deq_count <= depth[2:0];
shift_count <= 0;
end
case (ins[28:27])
0: ;
1: cursor_y <= cursor_y - 1;
2, 3: cursor_y <= cursor_y_start;
endcase
/* if (ins[28]) begin
cursor_y <= cursor_y_start;
end
if (ins[28:27] == 1) begin
cursor_y <= cursor_y - 1;
end*/
{addr_add, addr_set} <= 0;
case (ins[23:21])
0: ;
1: begin
if (counting) begin
counter1 <= counter0 - 1;
counting[1] <= counter0 > 0;
end else begin
counter1 <= ins[20:9];
counting[1] <= ins[20:9] > 0;
end
retpc <= pc;
retnpc <= npc;
end
2, 3: begin
if (counting) begin
counter0 <= counter0 - 1;
counting[0] <= !counter0[11];
end else begin
counter0 <= ins[20:9];
counting[0] <= !ins[20];
end
end
5: begin
req_count <= ins[20:9];
req_enq <= 1;
end
/*7: begin
//shifted_pixels[0:127] <= {4{const_pixel}};
end*/
6, 7: begin
addr_val <= ins[20:0];
addr_set <= !ins[21];
addr_add <= ins[21];
end
endcase
send_pixel <= (ins[23:21] == 3);
if (send_pixel) begin
shifted_pixels <= in_fifo_data << {shift_count, 5'b0};
cursor_x <= cursor_x - 4;
shift_count <= deq_count;
deq_count <= deq_count + depth[2:0];
end
if (ins[25]) begin
interrupt <= 1;
end
if (clear_int[7]) begin
interrupt <= 0;
end
if (ins[26] && no_loop) begin
counter0 <= counter1;
counting[0] <= counting[1];
end
end
end
endmodule
module cursor_overlay(
vid_clock,
pci_clock,
reset,
reg_write_data,
reg_write_addr,
reg_write,
cursor_x,
cursor_y,
in_pixels,
in_signals,
out_pixels,
out_signals
);
input vid_clock, pci_clock, reset;
input [31:0] reg_write_data;
input [9:0] reg_write_addr;
input reg_write;
output [0:127] out_pixels;
output [2:0] out_signals;
reg [0:127] out_pixels;
reg [2:0] out_signals;
input [0:127] in_pixels;
input [2:0] in_signals;
input [11:0] cursor_x, cursor_y;
wire in_range = !cursor_y[11:5] && !cursor_x[11:5];
wire [7:0] cursor_addr = ~{cursor_y[4:0], cursor_x[4:2]};
wire [0:127] cram_bits;
RAMB16_S36_S36 cram0 (
.DOA(cram_bits[0:31]), .DOPA(),
.DOB(cram_bits[32:63]), .DOPB(),
.ADDRA({1'b0, cursor_addr}), .CLKA(vid_clock),
.DIA(32'b0), .DIPA(4'b0),
.DIB(reg_write_data), .DIPB(4'b0),
.ADDRB(reg_write ? reg_write_addr[8:0] : {1'b1, cursor_addr}),
.CLKB(pci_clock),
.ENA(1'b1), .SSRA(1'b0),
.ENB(1'b1), .SSRB(1'b0),
.WEA(1'b0), .WEB(reg_write && !reg_write_addr[9]));
RAMB16_S36_S36 cram1 (
.DOA(cram_bits[64:95]), .DOPA(),
.DOB(cram_bits[96:127]), .DOPB(),
.ADDRA({1'b0, cursor_addr}), .CLKA(vid_clock),
.DIA(32'b0), .DIPA(4'b0),
.DIB(reg_write_data), .DIPB(4'b0),
.ADDRB(reg_write ? reg_write_addr[8:0] : {1'b1, cursor_addr}),
.CLKB(pci_clock),
.ENA(1'b1), .SSRA(1'b0),
.ENB(1'b1), .SSRB(1'b0),
.WEA(1'b0), .WEB(reg_write && reg_write_addr[9]));
reg last_mask, mask;
reg [0:127] last_word;
always @(posedge vid_clock) begin
last_word <= cram_bits;
mask <= in_range;
last_mask <= mask;
end
reg [0:127] cursor_bits;
reg [0:3] mask_bits;
always @(posedge vid_clock) begin
case (cursor_x[1:0])
0: cursor_bits <= cram_bits;
1: cursor_bits <= {last_word[96:127], cram_bits[0:95]};
2: cursor_bits <= {last_word[64:127], cram_bits[0:63]};
3: cursor_bits <= {last_word[32:127], cram_bits[0:31]};
endcase
end
always @(posedge vid_clock) begin
case (cursor_x[1:0])
0: mask_bits <= {4{mask}};
1: mask_bits <= {last_mask, {3{mask}}};
2: mask_bits <= {{2{last_mask}}, {2{mask}}};
3: mask_bits <= {{3{last_mask}}, mask};
endcase
end
always @(posedge vid_clock) begin
out_pixels[0:31] <= mask_bits[0] ? cursor_bits[0:31] : in_pixels[0:31];
out_pixels[32:63] <= mask_bits[1] ? cursor_bits[32:63] : in_pixels[32:63];
out_pixels[64:95] <= mask_bits[2] ? cursor_bits[64:95] : in_pixels[64:95];
out_pixels[96:127] <=
mask_bits[3] ? cursor_bits[96:127] : in_pixels[96:127];
out_signals <= in_signals;
end
endmodule
_______________________________________________
Open-graphics mailing list
[email protected]
http://lists.duskglow.com/mailman/listinfo/open-graphics
List service provided by Duskglow Consulting, LLC (www.duskglow.com)