Subversion Repositories ngs

Rev

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

  1. // part of NeoGS project
  2. //
  3. // (c) NedoPC 2007-2019
  4.  
  5. module chan_ctrl
  6. (
  7.         input  wire clk, // 24.0 MHz
  8.         input  wire rst_n,
  9.  
  10.         // memory interface
  11.         output reg  [ 6:0] rd_addr,
  12.         input  wire [31:0] rd_data,
  13.         //
  14.         output reg  [ 6:0] wr_addr,
  15.         output wire [31:0] wr_data,
  16.         output reg         wr_stb,
  17.  
  18.         // 37500 Hz period strobe (1-cycle strobe)
  19.         input  wire        sync_stb,
  20.  
  21.         // channel enables
  22.         input  wire [31:0] ch_enas,
  23.  
  24.         // output data
  25.         output reg  [ 7:0] out_data,
  26.         output reg         out_stb_addr, // strobes address sequence (addrhi/mid/lo)
  27.         output reg         out_stb_mix   // strobes mix sequence (frac/vl/vr)
  28.         // sequence: addrhi, addrmid, addrlo; frac, vl, vr (6 bytes)
  29. );
  30.  
  31.         reg [ 5:0] curr_ch; // current channel number
  32.         wire       stop = curr_ch[5];
  33.  
  34.         // channel fetch state machine
  35.         reg [3:0] st;
  36.         reg [3:0] next_st;
  37.  
  38.         // channel enable
  39.         wire ch_ena = ch_enas[curr_ch[4:0]];
  40.  
  41.         // offset storage
  42.         reg [31:0] offset;
  43.         reg        off_cy; // extra carry [32th bit]
  44.  
  45.         // offset>=size flag
  46.         reg oversize;
  47.  
  48.         // volumes storage
  49.         reg [5:0] vol_left;
  50.         reg [5:0] vol_right;
  51.         // miscellaneous
  52.         reg loopena;
  53.         reg surround;
  54.        
  55.         // base address
  56.         reg [21:0] base;
  57.  
  58.  
  59.         // emit control
  60.         reg [1:0] addr_emit;
  61.  
  62.        
  63.         ///////////////////////
  64.         // states definition //
  65.         ///////////////////////
  66.         localparam ST_BEGIN     = 4'd0;
  67.         localparam ST_GETOFFS   = 4'd1; // when offset value arrives
  68.         localparam ST_GETADDVOL = 4'd2; // whed add and volumes arrive
  69.         localparam ST_GETSIZE   = 4'd3; // size and part of base address arrive
  70.         localparam ST_GETLOOP   = 4'd4; // when loop and last part of base address arrive
  71.         localparam ST_SAVEOFFS  = 4'd5;
  72.         //localparam ST_ = 4'd;
  73.         //localparam ST_ = 4'd;
  74.         //localparam ST_ = 4'd;
  75.         //localparam ST_ = 4'd;
  76.         //localparam ST_ = 4'd;
  77.         localparam ST_NEXT = 4'd14;
  78.         localparam ST_WAIT = 4'd15;
  79.        
  80.        
  81.        
  82.        
  83.        
  84.         always @(posedge clk)
  85.              if( st==ST_WAIT )
  86.                 curr_ch[5:0] <= 6'd0;
  87.         else if( st==ST_NEXT )
  88.                 curr_ch[5:0] <= curr_ch[5:0] + 6'd1;
  89.  
  90.  
  91.  
  92.  
  93.  
  94.  
  95.         always @(posedge clk, negedge rst_n)
  96.         if( !rst_n )
  97.                 st <= ST_WAIT;
  98.         else
  99.                 st <= next_st;
  100.         //
  101.         always @*
  102.         case( st )
  103.         //////////////////////////////////////////////////////////////////////
  104.         ST_BEGIN:
  105.         if( stop )
  106.                 next_st = ST_WAIT;
  107.         else if( !ch_ena )
  108.                 next_st = ST_NEXT;
  109.         else
  110.                 next_st = ST_GETOFFS;
  111.         ///////////////////////////////////////////////////////////////////////
  112.         ST_GETOFFS:
  113.                 next_st = ST_GETADDVOL;
  114.         ///////////////////////////////////////////////////////////////////////
  115.         ST_GETADDVOL:
  116.                 next_st = ST_GETSIZE;
  117.         ///////////////////////////////////////////////////////////////////////
  118.         ST_GETSIZE:
  119.                 next_st = ST_GETLOOP;
  120.         ///////////////////////////////////////////////////////////////////////
  121.         ST_GETLOOP:
  122.                 next_st = ST_SAVEOFFS;
  123.         ///////////////////////////////////////////////////////////////////////
  124.         ST_SAVEOFFS:
  125.                 next_st = ST_NEXT;
  126.         ///////////////////////////////////////////////////////////////////////
  127.         ///////////////////////////////////////////////////////////////////////
  128.         ///////////////////////////////////////////////////////////////////////
  129.         ///////////////////////////////////////////////////////////////////////
  130.         ST_NEXT:
  131.                 next_st = ST_BEGIN;
  132.         ///////////////////////////////////////////////////////////////////////
  133.         ST_WAIT:
  134.         if( sync_stb )
  135.                 next_st = ST_BEGIN;
  136.         else
  137.                 next_st = ST_WAIT;
  138.         ////////////////////////////////////////////////
  139.         ///////////////////////
  140.         default: next_st = ST_WAIT;
  141.         ///////////////////////////////////////////////////////////////////////
  142.         endcase
  143.  
  144.  
  145.         // state memory address control
  146.         always @*
  147.                 rd_addr[6:2] <= curr_ch[4:0];
  148.         always @*
  149.                 wr_addr[6:2] <= curr_ch[4:0];
  150.         always @(posedge clk)
  151.                 wr_addr[1:0] <= 2'd0;
  152.         //
  153.         always @(posedge clk)
  154.         if( st==ST_NEXT || st==ST_WAIT )
  155.         begin
  156.                 rd_addr[1:0] <= 2'd0;
  157.         end
  158.         else if( st==ST_BEGIN || st==ST_GETOFFS || st==ST_GETADDVOL )
  159.         begin
  160.                 rd_addr[1:0] <= rd_addr[1:0] + 2'd1;
  161.         end
  162.  
  163.  
  164.         // offset register control
  165.         always @(posedge clk)
  166.         if( st==ST_GETOFFS )
  167.                 offset <= rd_data;
  168.         else if( st==ST_GETADDVOL )
  169.                 {off_cy, offset} <= {1'b0, offset} + {1'b0, 14'd0, rd_data[31:14]};
  170.         else if( st==ST_GETLOOP )
  171.                 offset[31:12] <= oversize ? (offset[31:12]+rd_data[27:8]) : offset[31:12]; // TODO: or maybe rd_data & {20{oversize}} ?
  172.  
  173.         // offset overflow control
  174.         always @(posedge clk)
  175.         if( st==ST_GETSIZE )
  176.                 oversize <= ( {off_cy,offset[31:12]} >= {1'b0, rd_data[27:8]} );
  177.  
  178.         // offset writeback
  179.         always @(posedge clk)
  180.                 wr_stb <= st==ST_SAVEOFFS;
  181.         //
  182.         assign wr_data = offset;
  183.  
  184.  
  185.         // volumes and miscellaneous
  186.         always @(posedge clk)
  187.         if( st==ST_GETADDVOL )
  188.         begin
  189.                 vol_left  <= rd_data[11:6];
  190.                 vol_right <= rd_data[ 5:0];
  191.  
  192.                 loopena  <= rd_data[13];
  193.                 surround <= rd_data[12];
  194.         end
  195.  
  196.  
  197.  
  198.         // base address calc
  199.         always @(posedge clk)
  200.         if( st==ST_GETSIZE )
  201.                 base[15:8] <= rd_data[7:0];
  202.         else if( st==ST_GETLOOP )
  203.                 base[21:16] <= rd_data[5:0];
  204.         else if( st==ST_SAVEOFFS )
  205.         begin
  206.                 base[7:0] <= offset[19:12];
  207.                 base[21:8] <= base[21:8] + {2'd0,offset[31:20]};
  208.         end
  209.  
  210.  
  211.  
  212.  
  213.  
  214.         // emitting data to fifos
  215.         always @(posedge clk, negedge rst_n)
  216.         if( !rst_n )
  217.                 addr_emit <= 2'd0;
  218.         else
  219.                 addr_emit[1:0] <= {addr_emit[0], st==ST_NEXT};
  220.         //
  221.         always @(posedge clk)
  222.              if( st==ST_GETSIZE )
  223.                 out_data <= offset[11:4];
  224.         else if( st==ST_GETLOOP )
  225.                 out_data <= {2'd0, vol_left[5:0]};
  226.         else if( st==ST_SAVEOFFS )
  227.                 out_data <= {2'd0, vol_right[5:0] ^ {6{surround}}};
  228.         else if( st==ST_NEXT )
  229.                 out_data <= {2'd0, base[21:16]};
  230.         else if( addr_emit[0] )
  231.                 out_data <= base[15:8];
  232.         else
  233.                 out_data <= base[7:0];
  234.         //
  235.         always @(posedge clk, negedge rst_n)
  236.         if( !rst_n )
  237.                 out_stb_mix <= 1'b0;
  238.         else
  239.                 out_stb_mix <= (st==ST_GETSIZE)  ||
  240.                                (st==ST_GETLOOP)  ||
  241.                                (st==ST_SAVEOFFS) ;
  242.         //
  243.         always @(posedge clk, negedge rst_n)
  244.         if( !rst_n )
  245.                 out_stb_addr <= 1'b0;
  246.         else
  247.                 out_stb_addr <= (st==ST_NEXT) || addr_emit;
  248.  
  249.  
  250.  
  251. endmodule
  252.  
  253.