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)

Reply via email to