Subversion Repositories ngs

Rev

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

  1. // part of NeoGS project (c) 2008-2013 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 [21:0] addr0,
  37.         input wire [21:0] addr1,
  38.         input wire [21:0] addr2,
  39.         input wire [21: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. //      dma controller connection
  63.         output wire        dma_req,
  64.         output wire [21:0] dma_addr,
  65.         output wire        dma_rnw,
  66.         output wire  [7:0] dma_wd,
  67.  
  68.         input  wire        dma_ack,
  69.         input  wire        dma_end
  70. );
  71.         localparam DEVNUM = 4;
  72.  
  73.  
  74.  
  75.         wire [DEVNUM-1:0] reqs;
  76.         wire       [21:0] addrs [0:DEVNUM-1];
  77.         wire [DEVNUM-1:0] rnws;
  78.         wire        [7:0] wds   [0:DEVNUM-1];
  79.         wire [DEVNUM-1:0] acks;
  80.         wire [DEVNUM-1:0] ends;
  81.  
  82.  
  83.         // aggregate signals for brewity
  84.         assign reqs[DEVNUM-1:0] = {req3,req2,req1,req0};
  85.         assign addrs[0] = addr0;
  86.         assign addrs[1] = addr1;
  87.         assign addrs[2] = addr2;
  88.         assign addrs[3] = addr3;
  89.         assign rnws[DEVNUM-1:0] = {rnw3,rnw2,rnw1,rnw0};
  90.         assign wds[0] = wd0;
  91.         assign wds[1] = wd1;
  92.         assign wds[2] = wd2;
  93.         assign wds[3] = wd3;
  94.         assign {ack3,ack2,ack1,ack0} = acks[DEVNUM-1:0];
  95.         assign {end3,end2,end1,end0} = ends[DEVNUM-1:0];
  96.  
  97.  
  98.  
  99.  
  100.  
  101.         reg  [DEVNUM-1:0] cur_input_mux;  // which current input is muxed to the DMA  (input=req,ack,addr,wd)
  102.         reg  [DEVNUM-1:0] cur_output_mux; // which current output is muxed to the DMA (output=end)
  103.  
  104.         wire [DEVNUM-1:0] next_input_mux;
  105.  
  106.         reg busy;
  107.  
  108.  
  109.         always @(posedge clk, negedge rst_n)
  110.         begin
  111.                 if( !rst_n )
  112.                         busy = 1'b0;
  113.                 else // posedge clk
  114.                 begin
  115.                         if( !busy )
  116.                                 busy <= |reqs;
  117.                         else // busy
  118.                                 busy <= dma_req;
  119.                 end
  120.         end
  121.  
  122.  
  123.         always @(posedge clk, negedge rst_n)
  124.         begin
  125.                 if( !rst_n )
  126.                 begin
  127.                         cur_input_mux  = {DEVNUM{1'b0}}; // to remove static priority selection after idle -- have here 'd1!
  128.                 end
  129.                 else // posedge clk
  130.                 begin
  131.                         if( (!busy) || dma_ack ) // idle or dma acknoledges data receive
  132.                         begin
  133.                                 cur_input_mux <= next_input_mux;
  134.                         end
  135.                 end
  136.         end
  137.  
  138.         rr_arbiter #( .DEVNUM(DEVNUM) ) rr_arbiter(
  139.                 .reqs(reqs),
  140.                 .prev( cur_input_mux),
  141.                 .next(next_input_mux)
  142.         );
  143.  
  144.  
  145.  
  146.         // output mux should follow input after dma_ack
  147.         //
  148.         always @(posedge clk, negedge rst_n)
  149.         begin
  150.                 if( !rst_n )
  151.                 begin
  152.                         cur_output_mux = {DEVNUM{1'b0}};
  153.                 end
  154.                 else // posedge clk
  155.                 begin
  156.                         if( dma_ack )
  157.                                 cur_output_mux <= cur_input_mux;
  158.                 end
  159.         end
  160.  
  161.  
  162.  
  163.  
  164.  
  165.         // actual muxing of input data
  166.         //
  167.         wor         int_dma_req;  // wor is to do easily decoded AND-OR muxes
  168.         wor  [20:0] int_dma_addr; //
  169.         wand        int_dma_rnw;  // this is WAND to have it 1 in idle
  170.         wor   [7:0] int_dma_wd;   //
  171.         //
  172.         genvar i;
  173.         generate
  174.                 for(i=0;i<DEVNUM;i=i+1)
  175.                 begin : mux_dma_inputs
  176.  
  177.                         assign int_dma_req  =     cur_input_mux[i]   &  reqs[i]; // wired OR happens!
  178.                         assign int_dma_addr = {21{cur_input_mux[i]}} & addrs[i]; //
  179.                         assign int_dma_rnw  =   (~cur_input_mux[i])  |  rnws[i]; // wired AND...
  180.                         assign int_dma_wd   =  {8{cur_input_mux[i]}} &   wds[i]; //
  181.                 end
  182.         endgenerate
  183.         //
  184.         // output data to dma controller
  185.         //
  186.         assign dma_req  = int_dma_req;
  187.         assign dma_addr = int_dma_addr;
  188.         assign dma_rnw  = int_dma_rnw;
  189.         assign dma_wd   = int_dma_wd;
  190.  
  191.         // actual de-muxing of output data from dma controller
  192.         //
  193.         assign acks = cur_input_mux  & {DEVNUM{dma_ack}};
  194.         assign ends = cur_output_mux & {DEVNUM{dma_end}};
  195.  
  196. endmodule
  197.  
  198.  
  199.  
  200.  
  201.  
  202.  
  203. // round-robin arbiter
  204. module rr_arbiter(
  205.         /*input  wire [DEVNUM-1:0]*/ reqs,
  206.         /*input  wire [DEVNUM-1:0]*/ prev,
  207.  
  208.         /*output wire [DEVNUM-1:0]*/ next
  209. );
  210.         parameter DEVNUM=4;
  211.  
  212.  
  213.         input  wire [DEVNUM-1:0] reqs;
  214.         input  wire [DEVNUM-1:0] prev;
  215.  
  216.         output wire [DEVNUM-1:0] next;
  217.  
  218.  
  219.  
  220.         genvar i;
  221.  
  222.  
  223.  
  224.         // arbitration if there was previous actives
  225.         //
  226.         wire [DEVNUM-1:0] loop;
  227.         wire [DEVNUM-1:0] next_arb;
  228.  
  229.         generate
  230.                 for(i=0;i<DEVNUM;i=i+1)
  231.                 begin : gen_forwarders
  232.  
  233.                         if( i==0 )
  234.                                 rr_fwd forwarder( .prev(prev[i]),
  235.                                                   .req(reqs[i]),
  236.                                                   .next(next_arb[i]),
  237.                                                   .loop_in(loop[DEVNUM-1]),
  238.                                                   .loop_out(loop[i]) );
  239.                         else
  240.                                 rr_fwd forwarder( .prev(prev[i]),
  241.                                                   .req(reqs[i]),
  242.                                                   .next(next_arb[i]),
  243.                                                   .loop_in(loop[i-1]),
  244.                                                   .loop_out(loop[i]) );
  245.                 end
  246.         endgenerate
  247.  
  248.  
  249.         // arbitration if there was no actives prior to requests
  250.         //
  251.         wire  [DEVNUM-1:0] next_empty;
  252.  
  253.         generate
  254.                 for(i=0;i<DEVNUM;i=i+1)
  255.                 begin : pri_enc
  256.                         if( i==0 )
  257.                         begin : pri_zero
  258.                                 assign next_empty[0] = reqs[0];
  259.                         end
  260.                         else
  261.                         begin : pri_nonzero
  262.                                 assign next_empty[i] = reqs[i] & ( ~|reqs[i-1:0] );
  263.                         end
  264.                 end
  265.         endgenerate
  266.  
  267.  
  268.         // select between prev-busy and prev-free cases
  269.         assign next = ( prev ) ? next_arb : next_empty;
  270.  
  271. endmodule
  272.  
  273.  
  274. // round-robin request forwarder (1 bit)
  275. module rr_fwd(
  276.         input  wire prev,  // who was arbitrated last time (one-hot)
  277.         input  wire req,   // who are requesting
  278.         output reg  next, // who will be next
  279.  
  280.         input  wire loop_in, // for internal arbitration
  281.         output reg  loop_out //
  282. );
  283.  
  284.         always @*
  285.         begin
  286.                 if( prev )
  287.                 begin
  288.                         loop_out = 1'b1;
  289.                 end
  290.                 else //!prev
  291.                 begin
  292.                         loop_out = req ? 1'b0 : loop_in;
  293.                 end
  294.         end
  295.  
  296.         always @*
  297.         begin
  298.                 next = req ? loop_in : 1'b0;
  299.         end
  300.  
  301. endmodule
  302.