Attached is an updated version of the arbiter from SVN, fixed a few syntax errors (missing declarations, assign statements for regs, etc).

I have a few questions about the load mode register part for now, can you explain what this part does in more detail, and i have a few specific questions about the code, which i ask below:

   // Config regs and load mode register (lmr)
   reg [14:0]              lmr_data;
   reg [3:0]               lmr_delay;
   reg                     lmr_addr;
   reg [10:0]              refresh_delay;
   reg                     refresh_enable;
   reg [1:0]               lmr_write; // missing, added
***is the lmr_write reg only 2 bits?***


   always @(posedge reg_clock or negedge reset_) begin
      if (!reset_) begin
         lmr_write[0] <= 0;
         lmr_write[1] <= 0;
         lmr_data <= 0;
      end else begin
         lmr_write[0] <= lmr_write[0] >> 1;
         lmr_write[1] <= lmr_write[1] >> 1;
***does the right shift do anything here? seems to me like it's just copying back the same value***


         if (reg_do_write) begin
            case (reg_addr[1:0])
              0: begin
                 lmr_data <= reg_data;
                 lmr_delay <= 4'b1110;
                 lmr_addr <= 0;
              end
              2: begin
                 lmr_addr <= 1;
                 lmr_delay <= 4'b1110;
              end
              3: {refresh_enable, refresh_delay} <= reg_data;
            endcase
         end
      end
   end


   reg last_lmr_delay;
   reg do_lmr;

   always @(posedge clock) begin
      last_lmr_delay <= lmr_delay[0];
      do_lmr <= !last_lmr_delay && lmr_delay[0];
   end
***the value of lmr_delay doesn't seem to change from 4'b1110, so do_lmr value doesn't change? is there a shift register missing?***


Timothy Normand Miller wrote:
Ok, maybe the arbiter itself hasn't changed that much.  In any case,
just work from the version in SVN.

Thanks.

On 12/29/07, Farhan Mohamed Ali <[EMAIL PROTECTED]> wrote:
I have looked in the SVN. Looks the same as the one in the "Draft of
arbiter" post on the mailing list. This is the latest version, correct?

Timothy Normand Miller wrote:
It has changed massively.  Please check out a copy from SVN.

Thank you for your help.  The arbiter is mostly done, so you just need
to make sense of it and make sure it makes sense.  :)


On 12/28/07, Farhan Mohamed Ali <[EMAIL PROTECTED]> wrote:
I've started looking at the arbiter. I have about 2 weeks to work on it,
so i'll be able to get some useful work done. Has it been changed or
updated since the very first version you posted on the mailing list?

-Farhan

Timothy Normand Miller wrote:
There are a handful of things left to code.  Some of these are the
sorts of things that Howard is best suited for.  Those include clock
managers and constraints files.  The XP10 top level is basically done,
and Howard will be sending me some code this week.

The S3 still needs work.  I've been trying to get some people to help
me check the connections, but no one's reported anything to me.
Wiring top levels (getting the wire instances right and stuff) are my
greatest weakness.  This is where I make the most mistakes.  This kind
of checking has to be done first.  Right now, I have one memory
controller and one video controller wired up.  After the checking, we
can wire up the remaining 3 memory controllers and 1 video controller
(along with the output blocks), and check it again.  Still, there will
be details that remain to be fixed.

Finally, we need to create a simulation wrapper that binds together
the two FPGA top levels, a PCI master that is in the repository, and
some test code that tries out various basic functions like accessing
memory and scanning out a video frame.  This too falls squarely into
where-I-suck territory and would be done much quicker and better by
someone with far greater talent with this kind of detail.

The break is nearing its end, and I need help with these things.  The
next step after that is synthesis and fixing things to meet timing.
Those are things I'm good at.  It would be best if we can get this
simulation stuff done before classes start before we work on
synthesis.






// There will be four instances of this arbiter, one for each memory 
// controller.


/*
Notes:
    It will become an issue later that there is no way to throttle
    the return data coming from the memory controller.  A variety
    of solutions exist, one of which is to count the outstanding
    requests for a given agent and never submit more than can be
    accepted by the return queue.
    
    This is not a problem for video, as its huge return queue will
    never fill.
    
Addresses:
    All addresses refer to 64-bit words

    
LMR:
    To load the mode register, first ensure that refresh is disabled.
    Check the spec for the DRAMs for required delays, which must be 
    enforced by software.
    A precharge command must be issued (reg 2).
    Then LMR or LMR-extended (reg 0) can be issued.
*/

module arbiter(
               input clock,
               input reset_,
    
               // Config interface
               input reg_clock,
               input [2:0] reg_addr,
               input [31:0] reg_data,
               input reg_do_write,
               
               // Read end of request queue from bridge
               // This is only a 32-bit interface
               input [24:0] br_addr,
               input [63:0] br_wdata,
               input [7:0] br_bytes,
               input br_do_read,
               input br_do_write,
               input br_valid,
               output br_deq,
               
               // Write end of read return queue to bridge
               output [63:0] br_rdata,
               output br_rdata_enq,
               // input [3:0] br_rdata_free,
    
               // Read end of video request queue (head0)
               input [24:0] vid0_addr,
               input vid0_valid,
               output vid0_deq,

               // Read end of video request queue (head1)
               input [24:0] vid1_addr,
               input vid1_valid,
               output vid1_deq,
    
               // Write end of read return queue to video
               output [63:0] vid0_rdata,
               output vid0_rdata_enq,
               
               // Write end of read return queue to video
               output [63:0] vid1_rdata,
               output vid1_rdata_enq,
               
               // Memory controller
               output reg [2:0] cmd_mem,
               output reg [1:0] bank_mem,
               output reg [12:0] row_mem, 
               output reg [12:0] col_mem,
               output reg [63:0] wdata_mem,
               output reg [7:0] wbytes_mem,
               output reg [2:0] rtag_mem,
               input busy_mem,
               
               input [63:0] rdata_mem, 
               input rdata_valid_mem, 
               input [2:0] rtag_return 
               );
   
   
   
   // Config regs and load mode register (lmr)
   reg [14:0]              lmr_data;
   reg [3:0]               lmr_delay;
   reg                     lmr_addr;
   reg [10:0]              refresh_delay;
   reg                     refresh_enable;
   reg [1:0]               lmr_write;
   
   
   always @(posedge reg_clock or negedge reset_) begin
      if (!reset_) begin
         lmr_write[0] <= 0;
         lmr_write[1] <= 0;
         lmr_data <= 0;
      end else begin
         lmr_write[0] <= lmr_write[0] >> 1;
         lmr_write[1] <= lmr_write[1] >> 1;
         if (reg_do_write) begin
            case (reg_addr[1:0])
              0: begin
                 lmr_data <= reg_data;
                 lmr_delay <= 4'b1110;
                 lmr_addr <= 0;
              end
              2: begin
                 lmr_addr <= 1;
                 lmr_delay <= 4'b1110;
              end
              3: {refresh_enable, refresh_delay} <= reg_data;
            endcase
         end
      end
   end
   
   
   reg last_lmr_delay;
   reg do_lmr;
   
   always @(posedge clock) begin
      last_lmr_delay <= lmr_delay[0];
      do_lmr <= !last_lmr_delay && lmr_delay[0];
   end
   
   
   
   
   // Refresh counter
   integer i;
   reg [10:0] refresh_counter;
   reg [11:0] borrow, zero;
   always @(posedge clock or negedge reset_) begin
      if (!reset_) begin
         borrow <= 1;
         zero <= 1;
         refresh_counter <= 0;
      end else begin
         if (zero[11]) begin
            refresh_counter <= refresh_delay;
            zero <= 1;
            borrow <= 1;
         end else begin
            for (i=0; i<11; i=i+1) begin
               zero[i+1] <= zero[i] && !refresh_counter[i];
               borrow[i+1] <= !refresh_counter[i] && borrow[i];
               refresh_counter[i] <= refresh_counter[i] ^ borrow[i];
            end
         end
      end
   end
   
   reg refresh_pending;
   wire refresh_deq;
   always @(posedge clock or negedge reset_) begin
      if (!reset_) begin
         refresh_pending <= 0;
      end else begin
         if (zero[11] && refresh_enable) refresh_pending <= 1;
         if (refresh_deq) refresh_pending <= 0;
      end
   end
   
   
   
   parameter mem_read = 3'd1;
   parameter mem_write = 3'd2;
   parameter mem_precharge = 3'd3;
   parameter mem_refresh = 3'd4;
   parameter mem_lmr = 3'd5;
   
   
   
   wire      pci_access = br_valid;
   wire vid0_access = vid0_valid;
   wire vid1_access = vid1_valid;
   wire refresh_access = refresh_pending;
   
   // Scheduler
   reg  allow_pci, allow_vid0, allow_vid1, allow_refresh;
   always @(posedge clock or negedge reset_) begin
      if (!reset_) begin
         allow_pci <= 0;
         allow_vid0 <= 0;
         allow_vid1 <= 0;
         allow_refresh <= 0;
      end else begin
         if (refresh_access) begin
            allow_refresh <= 1;
            allow_pci <= 0;
            allow_vid0 <= 0;
            allow_vid1 <= 0;
         end else if (vid0_access) begin
            allow_vid0 <= 1;
            allow_pci <= 0;
            allow_refresh <= 0;
            allow_vid1 <= 0;
         end else if (vid1_access) begin
            allow_vid0 <= 1;
            allow_pci <= 0;
            allow_refresh <= 0;
            allow_vid1 <= 1;
         end else if (pci_access) begin
            allow_pci <= 1;
            allow_vid0 <= 0;
            allow_refresh <= 0;
            allow_vid1 <= 0;
         end
      end
   end
   
   wire vid_deq;
   assign br_deq = allow_pci && !memctl_busy;
   assign vid_deq = allow_video && !memctl_busy;
   assign refresh_deq = allow_refresh && !memctl_busy;
   
   
   // We will definitely need a stage of pipelining added here
   
   wire   lmr_cmd = do_lmr && !lmr_addr;
   wire   precharge_cmd = do_lmr && lmr_addr;
   wire   refresh_cmd = allow_refresh;
   wire   pci_read_cmd = allow_pci && br_do_read && br_valid;
   wire   pci_write_cmd = allow_pci && br_do_write && br_valid;
   wire   vid0_cmd = allow_vid0 && vid0_valid;
   wire   vid1_cmd = allow_vid1 && vid1_valid;

   always@(*) begin
      cmd_mem = 
                ({3{lmr_cmd}} & mem_lmr) |
                ({3{precharge_cmd}} & mem_precharge) |
                ({3{refresh_cmd}} & mem_refresh) |
                ({3{pci_read_cmd}} & mem_read) |
                ({3{pci_write_cmd}} & mem_write) |
                ({3{vid0_cmd}} & mem_read) |
                ({3{vid1_cmd}} & mem_read);
      
      bank_mem = 
                 ({2{lmr_cmd}} & lmr_data[14:13]) |
                 ({2{pci_read_cmd}} & br_addr[22:21]) |
                 ({2{pci_write_cmd}} & br_addr[22:21]) |
                 ({2{vid0_cmd}} & vid0_addr[22:21]) |
                 ({2{vid1_cmd}} & vid1_addr[22:21]);
      
      // 13-bit row
      row_mem = 
                ({13{pci_read_cmd}} & br_addr[20:8]) |
                ({13{pci_write_cmd}} & br_addr[20:8]) |
                ({13{vid0_cmd}} & vid0_addr[20:8]) |
                ({13{vid1_cmd}} & vid1_addr[20:8]);
      
      // 16-bit 256Mb chips have 9-bit column; we use only even numbers
      // Must make these configurable for ASIC
      col_mem[8:1] = 
                     ({8{lmr_cmd}} & lmr_data[8:1]) |
                     ({8{pci_read_cmd}} & br_addr[7:0]) |
                     ({8{pci_write_cmd}} & br_addr[7:0]) |
                     ({8{vid0_cmd}} & vid0_addr[7:0]) |
                     ({8{vid1_cmd}} & vid1_addr[7:0]);
      col_mem[0] = lmr_cmd & lmr_data[0];
      
      wdata_mem = br_wdata;
      wbytes_mem = br_bytes;
      
      rtag_mem = {pci_read_cmd, vid0_cmd, vid1_cmd};
   end // always@ (*)
   
   // Return path for read data
   assign br_rdata = rdata_mem;
   assign vid0_rdata = rdata_mem;
   assign vid1_rdata = rdata_mem;
   assign br_rdata_enq = rdata_valid_mem & rtag_return[2];
   assign vid0_rdata_enq = rdata_valid_mem & rtag_return[1];
   assign vid1_rdata_enq = rdata_valid_mem & rtag_return[0];
   
   
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