Subversion Repositories ngs

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed | ?url?

  1. // part of NeoGS project (c) 2008-2009 NedoPC
  2.  
  3. // dma sequencer
  4.  
  5. /*
  6.  
  7. input interface of every DMA end-user
  8.  
  9. clocks: ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^
  10. reqN    _______/```````````\______________/`````````````````\______________/``````````````````
  11. ackN    ________________/``\_____________________________/``\____________________/``\__/``\__/
  12. doneN   _________________________/``\_____________________________/``\______________/``\__/``\
  13. rnwN    -------/```````````\--------------\_________________/--------------/````````\_____/```
  14. adrwdN  -------< read addr >--------------< write addr&data >--------------< rdaddr X wra X rd
  15. rdN     -------------------------<dd>-----------------------------------------------<dd>------
  16.  
  17.  
  18. sequencing algorithm is round-robin with fixed initial prioritizing when multiple requests appear simultaneously while
  19. everything was idle
  20.  
  21. */
  22.  
  23.  
  24. module dma_sequencer(
  25.  
  26.         input wire clk,
  27.         input wire rst_n,
  28.  
  29.         // dma requests connection
  30.         //
  31.         input wire req0,
  32.         input wire req1,
  33.         input wire req2,
  34.         input wire req3,
  35.  
  36.         input wire [20:0] addr0,
  37.         input wire [20:0] addr1,
  38.         input wire [20:0] addr2,
  39.         input wire [20:0] addr3,
  40.  
  41.         input wire rnw0,
  42.         input wire rnw1,
  43.         input wire rnw2,
  44.         input wire rnw3,
  45.  
  46.         input wire [7:0] wd0,
  47.         input wire [7:0] wd1,
  48.         input wire [7:0] wd2,
  49.         input wire [7:0] wd3,
  50.  
  51.  
  52.         output wire ack0,
  53.         output wire ack1,
  54.         output wire ack2,
  55.         output wire ack3,
  56.  
  57.         output wire end0,
  58.         output wire end1,
  59.         output wire end2,
  60.         output wire end3,
  61.  
  62.         output wire [7:0] rd,
  63.  
  64.  
  65. //      dma controller connection
  66.         output wire        dma_req,
  67.         output wire [20:0] dma_addr,
  68.         output wire        dma_rnw,
  69.         output wire  [7:0] dma_wd,
  70.  
  71.         input  wire  [7:0] dma_rd,
  72.         input  wire        dma_ack,
  73.         input  wire        dma_end
  74. );
  75.         localparam DEVNUM = 4;
  76.  
  77.  
  78.  
  79.         wire [DEVNUM-1:0] reqs;
  80.         wire       [20:0] addrs [0:DEVNUM-1];
  81.         wire [DEVNUM-1:0] rnws;
  82.         wire        [7:0] wds   [0:DEVNUM-1];
  83.         wire [DEVNUM-1:0] acks;
  84.         wire [DEVNUM-1:0] ends;
  85.  
  86.  
  87.         // aggregate signals for brewity
  88.         assign reqs[DEVNUM-1:0] = {req3,req2,req1,req0};
  89.         assign addrs[0] = addr0;
  90.         assign addrs[1] = addr1;
  91.         assign addrs[2] = addr2;
  92.         assign addrs[3] = addr3;
  93.         assign rnws[DEVNUM-1:0] = {rnw3,rnw2,rnw1,rnw0};
  94.         assign wds[0] = wd0;
  95.         assign wds[1] = wd1;
  96.         assign wds[2] = wd2;
  97.         assign wds[3] = wd3;
  98.         assign {ack3,ack2,ack1,ack0} = acks[DEVNUM-1:0];
  99.         assign {end3,end2,end1,end0} = ends[DEVNUM-1:0];
  100.  
  101.  
  102.  
  103.  
  104.  
  105.         reg  [DEVNUM-1:0] cur_input_mux;  // which current input is muxed to the DMA  (input=req,ack,addr,wd)
  106.         reg  [DEVNUM-1:0] cur_output_mux; // which current output is muxed to the DMA (output=end)
  107.  
  108.         wire [DEVNUM-1:0] next_input_mux;
  109.  
  110.         reg busy;
  111.  
  112.  
  113.         always @(posedge clk, negedge rst_n)
  114.         begin
  115.                 if( !rst_n )
  116.                         busy = 1'b0;
  117.                 else // posedge clk
  118.                 begin
  119.                         if( !busy )
  120.                                 busy <= |reqs;
  121.                         else // busy
  122.                                 busy <= dma_req;
  123.                 end
  124.         end
  125.  
  126.  
  127.         always @(posedge clk, negedge rst_n)
  128.         begin
  129.                 if( !rst_n )
  130.                 begin
  131.                         cur_input_mux  = {DEVNUM{1'b0}};
  132.                 end
  133.                 else // posedge clk
  134.                 begin
  135.                         if( (!busy) || dma_ack ) // idle or dma acknoledges data receive
  136.                         begin
  137.                                 cur_input_mux <= next_input_mux;
  138.                         end
  139.                 end
  140.         end
  141.  
  142.         rr_arbiter #( .DEVNUM(DEVNUM) ) rr_arbiter(
  143.                 .reqs(reqs),
  144.                 .prev( cur_input_mux),
  145.                 .next(next_input_mux)
  146.         );
  147.  
  148.  
  149.  
  150.         // output mux should follow input after dma_ack
  151.         //
  152.         always @(posedge clk, negedge rst_n)
  153.         begin
  154.                 if( !rst_n )
  155.                 begin
  156.                         cur_output_mux = {DEVNUM{1'b0}};
  157.                 end
  158.                 else // posedge clk
  159.                 begin
  160.                         if( dma_ack )
  161.                                 cur_output_mux <= cur_input_mux;
  162.                 end
  163.         end
  164.  
  165.  
  166.  
  167.  
  168.  
  169.         // actual muxing of input data
  170.         //
  171.         wor         int_dma_req;  // wor is to do easily decoded AND-OR muxes
  172.         wor  [20:0] int_dma_addr; //
  173.         wand        int_dma_rnw;  // this is WAND to have it 1 in idle
  174.         wor   [7:0] int_dma_wd;   //
  175.         //
  176.         genvar i;
  177.         generate
  178.                 for(i=0;i<DEVNUM;i=i+1)
  179.                 begin : mux_dma_inputs
  180.  
  181.                         assign int_dma_req  =     cur_input_mux[i]   &  reqs[i]; // wired OR happens!
  182.                         assign int_dma_addr = {21{cur_input_mux[i]}} & addrs[i]; //
  183.                         assign int_dma_rnw  =   (~cur_input_mux[i])  |  rnws[i]; // wired AND...
  184.                         assign int_dma_wd   =  {8{cur_input_mux[i]}} &   wds[i]; //
  185.                 end
  186.         endgenerate
  187.         //
  188.         // output data to dma controller
  189.         //
  190.         assign dma_req  = int_dma_req;
  191.         assign dma_addr = int_dma_addr;
  192.         assign dma_rnw  = int_dma_rnw;
  193.         assign dma_wd   = int_dma_wd;
  194.  
  195.         // actual de-muxing of output data from dma controller
  196.         //
  197.         assign acks = cur_input_mux  & {DEVNUM{dma_ack}};
  198.         assign ends = cur_output_mux & {DEVNUM{dma_end}};
  199.         //
  200.         assign   rd = dma_rd; // read data does not need (de)muxing
  201.  
  202. endmodule
  203.  
  204.  
  205.  
  206.  
  207.  
  208.  
  209. // round-robin arbiter
  210. module rr_arbiter(
  211.         /*input  wire [DEVNUM-1:0]*/ reqs,
  212.         /*input  wire [DEVNUM-1:0]*/ prev,
  213.  
  214.         /*output wire [DEVNUM-1:0]*/ next
  215. );
  216.         parameter DEVNUM=4;
  217.  
  218.  
  219.         input  wire [DEVNUM-1:0] reqs;
  220.         input  wire [DEVNUM-1:0] prev;
  221.  
  222.         output wire [DEVNUM-1:0] next;
  223.  
  224.  
  225.  
  226.         genvar i;
  227.  
  228.  
  229.  
  230.         // arbitration if there was previous actives
  231.         //
  232.         wire [DEVNUM-1:0] loop;
  233.         wire [DEVNUM-1:0] next_arb;
  234.  
  235.         generate
  236.                 for(i=0;i<DEVNUM;i=i+1)
  237.                 begin : gen_forwarders
  238.  
  239.                         if( i==0 )
  240.                                 rr_fwd forwarder( .prev(prev[i]),
  241.                                                   .req(reqs[i]),
  242.                                                   .next(next_arb[i]),
  243.                                                   .loop_in(loop[DEVNUM-1]),
  244.                                                   .loop_out(loop[i]) );
  245.                         else
  246.                                 rr_fwd forwarder( .prev(prev[i]),
  247.                                                   .req(reqs[i]),
  248.                                                   .next(next_arb[i]),
  249.                                                   .loop_in(loop[i-1]),
  250.                                                   .loop_out(loop[i]) );
  251.                 end
  252.         endgenerate
  253.  
  254.  
  255.         // arbitration if there was no actives prior to requests
  256.         //
  257.         wire  [DEVNUM-1:0] next_empty;
  258.  
  259.         generate
  260.                 for(i=0;i<DEVNUM;i=i+1)
  261.                 begin : pri_enc
  262.                         if( i==0 )
  263.                         begin : pri_zero
  264.                                 assign next_empty[0] = reqs[0];
  265.                         end
  266.                         else
  267.                         begin : pri_nonzero
  268.                                 assign next_empty[i] = reqs[i] & ( ~|reqs[i-1:0] );
  269.                         end
  270.                 end
  271.         endgenerate
  272.  
  273.  
  274.         // select between prev-busy and prev-free cases
  275.         assign next = ( prev ) ? next_arb : next_empty;
  276.  
  277. endmodule
  278.  
  279.  
  280. // round-robin request forwarder (1 bit)
  281. module rr_fwd(
  282.         input  wire prev,  // who was arbitrated last time (one-hot)
  283.         input  wire req,   // who are requesting
  284.         output reg  next, // who will be next
  285.  
  286.         input  wire loop_in, // for internal arbitration
  287.         output reg  loop_out //
  288. );
  289.  
  290.         always @*
  291.         begin
  292.                 if( prev )
  293.                 begin
  294.                         loop_out = 1'b1;
  295.                 end
  296.                 else //!prev
  297.                 begin
  298.                         loop_out = req ? 1'b0 : loop_in;
  299.                 end
  300.         end
  301.  
  302.         always @*
  303.         begin
  304.                 next = req ? loop_in : 1'b0;
  305.         end
  306.  
  307. endmodule
  308.