Subversion Repositories ngs

Rev

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

  1. // part of NeoGS project (c) 2007-2008 NedoPC
  2. //
  3. // sound_main is the main sound module: it incorporates data storage (512b memory), from which
  4. //  it reads data, prepares it through sound_mulacc and sends to sound_dac. It incorporates in itself
  5. //  sound_dac, so it has outs to the DAC.
  6. // clock is ordinary 24 MHz clock, mode_8chans is asynchronous input signal controlling mode of operation,
  7. //  either 4 or 8 channels.
  8. //
  9. // channels in 4 channel mode (mode_8chans=0,mode_pan4ch=0)
  10. // 1,2 -> left
  11. // 3,4 -> right
  12. // channels in 8 channel mode (mode_8chans=1,mode_pan4ch=0)
  13. // 1,2,5,6 -> left
  14. // 3,4,7,8 -> right
  15. // channels in panning 4 channel mode (mode_8chans=0,mode_pan4ch=1)
  16. // 1,2,3,4 (vols 1,2,5,6) -> left
  17. // 1,2,3,4 (vols 3,4,7,8) -> right
  18. // channels in mem are at addressed 0-7 (corresponding to channels 1-8, respectively).
  19. // mem contains volumes (lower 6 bits, 0-zero volume, 63-max volume) and sound data (signed value with sign inverted:
  20. // -data in mem---+----value--
  21. //          $FF   |     +$7F
  22. //          $81   |     +$01
  23. //          $80   |     +$00
  24. //          $7F   |     -$01 (or $FF)
  25. //          $01   |     -$7F (or $81)
  26. //          $00   |     -$80 (or $80)
  27. // alternatively, it could be treated as unsigned positive samples with middle point of $7F-$80.
  28. //
  29. // clock      ``\__/``\__/``\__/``\__/``\__/``\__/``\__/``\__
  30. // mem_read   ______/`````\__________________________________
  31. // mem_wraddr       |  no |     |addr |
  32. // mem_di           |write|     |data |
  33. // mem_***_we ______|here!|_____/`````\______________________
  34. //                                   ^-- data written here!
  35.  
  36. module sound_main(
  37.  
  38.         clock,         // system clock (24 MHz)
  39.  
  40.         mode_8chans,   // =1 - 8 channels, =0 - 4 channels
  41.         mode_pan4ch,   // =1 - 4 channels with panning
  42.  
  43.  
  44.         in_wrtoggle,   // from ports.v module (async to clock)
  45.         in_datnvol,    //
  46.         in_wraddr,     //
  47.         in_data,       //
  48.  
  49.  
  50.         dac_clock,     // output to DAC
  51.         dac_leftright, // output to DAC
  52.         dac_data       // output to DAC
  53. );
  54.  
  55.     // input-output description
  56.  
  57.         input clock;
  58.  
  59.         input mode_8chans;
  60.         input mode_pan4ch;
  61.  
  62.         input in_wrtoggle;
  63.         input in_datnvol;
  64.         input [2:0] in_wraddr;
  65.         input [7:0] in_data;
  66.  
  67.         output dac_clock;
  68.  
  69.         output dac_leftright;
  70.  
  71.         output dac_data;
  72.  
  73.  
  74.         // internal regs/wires
  75.  
  76.         reg mem_read; // write to mem is forbidden while mem_read=1
  77.  
  78.         reg datnvol;
  79.  
  80.         reg [5:0] vol; // temporary storage for volume
  81.  
  82.         reg mem_we; // write strobe
  83.  
  84.         reg wrtgl1, wrtgl2, wrtgl3; // sync in and edge detect of in_wrtoggle
  85.  
  86.         reg do_write; // indicates that write should be performed
  87.  
  88.         reg [2:0] bf_wraddr;
  89.         reg [7:0] bf_data;
  90.         reg       bf_datnvol;
  91.  
  92.  
  93.  
  94.         wire dac_load; // signal from sound_dac module (when it loads new data)
  95.  
  96.         wire [15:0] dac_pardata; // parallel data from sound_mulacc to sound_dac
  97.  
  98.         reg mulacc_load;   // load to sound_mulacc
  99.         reg mulacc_clrsum; // clr_sum to sound_mulacc
  100.         wire mulacc_ready; // ready from sound_mulacc
  101.  
  102.         wire [7:0] mem_do; // data output of DAT or VOL
  103.  
  104.         reg [8:0] mem_rdaddr;  // read address for both memory blocks
  105.  
  106.         reg int_mode_8chans;  // internal and sync-in mode_8chans signals
  107.         reg sync_mode_8chans; //
  108.  
  109.         reg int_mode_pan4ch,sync_mode_pan4ch; // same for pan4ch signal
  110.  
  111.         reg [1:0] chanptr; // pointer to channels (4 channels total: 0,1,4,5 or 2,3,6,7 depending on lrptr state)
  112.         reg lrptr;         // left-right pointer (selects either left (0) or right (1) channels)
  113.  
  114.  
  115.  
  116.  
  117.         reg [2:0] cur_st,nxt_st;
  118.  
  119.  
  120.  
  121.  
  122.  
  123.  
  124.         // for simulation purposes
  125.         initial
  126.         begin
  127.                 bf_wraddr <= 0;
  128.                 bf_datnvol <= 0;
  129.                 bf_data <= 0;
  130.                 do_write <= 0;
  131.                 cur_st <= START;
  132.         end
  133.  
  134.  
  135.  
  136.         // instantiating modules
  137.  
  138.         sound_dac my_dac( .clock(clock),
  139.                           .dac_clock(dac_clock),
  140.                           .dac_leftright(dac_leftright),
  141.                           .dac_data(dac_data),
  142.                           .load(dac_load),
  143.                           .datain(dac_pardata) );
  144.  
  145.         sound_mulacc my_mulacc( .clock(clock),
  146.                                 .vol_in(vol),
  147.                                 .dat_in(mem_do),
  148.                                 .load(mulacc_load),
  149.                                 .clr_sum(mulacc_clrsum),
  150.                                 .ready(mulacc_ready),
  151.                                 .sum_out(dac_pardata) );
  152.  
  153.         // DAT-VOL memory block
  154.         mem512b my_mem( .clk(clock),
  155.                         .rdaddr(mem_rdaddr),
  156.                         .dataout(mem_do),
  157.                         .wraddr({5'b0,bf_datnvol,bf_wraddr}),
  158.                         .datain(bf_data),
  159.                         .we(mem_we) );
  160.  
  161.  
  162.  
  163.  
  164.  
  165.         // syncing in asynchronous control signals
  166.         always @(posedge clock)
  167.         begin
  168.                 { int_mode_8chans,sync_mode_8chans } <= { sync_mode_8chans, mode_8chans };
  169.                 { int_mode_pan4ch,sync_mode_pan4ch } <= { sync_mode_pan4ch, mode_pan4ch };
  170.         end
  171.  
  172.  
  173.         // load lrptr (left-right pointer) on dac_load pulse
  174.         always @(posedge clock)
  175.         begin
  176.                 if( dac_load )
  177.                         lrptr <= ~dac_leftright;
  178.         end
  179.  
  180.         // make memory read address from chanptr and lrptr
  181.         always @*
  182.         begin
  183. /*              mem_rdaddr[8:4] <= 5'd0;
  184.                 mem_rdaddr[3]   <= datnvol;
  185.                 mem_rdaddr[2]   <= int_mode_8chans ? chanptr[1] : 1'b0;
  186.                 mem_rdaddr[1]   <= lrptr;
  187.                 mem_rdaddr[0]   <= chanptr[0];*/
  188.  
  189.                 mem_rdaddr[8:4] <= 5'd0;
  190.  
  191.                 if( int_mode_8chans )
  192.                 begin
  193.                         mem_rdaddr[3]   <= datnvol;
  194.                         mem_rdaddr[2]   <= chanptr[1];
  195.                         mem_rdaddr[1]   <= lrptr;
  196.                         mem_rdaddr[0]   <= chanptr[0];
  197.                 end
  198.                 else if( int_mode_pan4ch )
  199.                 begin
  200.                         mem_rdaddr[3] <= datnvol;
  201.  
  202.                         if( datnvol ) // sample data
  203.                         begin
  204.                                 mem_rdaddr[2] <= 1'b0;
  205.                                 mem_rdaddr[1] <= chanptr[1];
  206.                                 mem_rdaddr[0] <= chanptr[0];
  207.                         end
  208.                         else // !datnvol: volumes
  209.                         begin
  210.                                 mem_rdaddr[2]   <= chanptr[1]; // same as in 8 channel
  211.                                 mem_rdaddr[1]   <= lrptr;
  212.                                 mem_rdaddr[0]   <= chanptr[0];
  213.                         end
  214.                 end
  215.                 else //normal 4 channel mode
  216.                 begin
  217.                         mem_rdaddr[3]   <= datnvol;
  218.                         mem_rdaddr[2]   <= 1'b0;
  219.                         mem_rdaddr[1]   <= lrptr;
  220.                         mem_rdaddr[0]   <= chanptr[0];
  221.                 end
  222.         end
  223.  
  224.         // handle mulacc_clrsum signal
  225.         always @(posedge clock)
  226.         begin
  227.                 if( dac_load )
  228.                         mulacc_clrsum <= 1'b1;     // set on dac_load pulse
  229.                 else if( mulacc_load )
  230.                         mulacc_clrsum <= 1'b0;     // clear on mulacc_load pulse, so only first mulacc cycle will read clrsum high
  231.         end
  232.  
  233.  
  234.  
  235.  
  236.  
  237.         localparam START      = 0;
  238.         localparam LOAD_VOL   = 1;
  239.         localparam LOAD_VOL2  = 2;
  240.         localparam LOAD_DAT   = 3;
  241.         localparam LOAD_DAT2  = 4;
  242.         localparam START_MUL  = 5;
  243.         localparam WAIT_STOP  = 6;
  244.         localparam LOOP       = 7;
  245.  
  246.         // FSM!
  247.         always @(posedge clock)
  248.         begin
  249.                 if( dac_load )
  250.                         cur_st <= START;
  251.                 else
  252.                         cur_st <= nxt_st;
  253.         end
  254.  
  255.         always @*
  256.         begin
  257.                 case( cur_st )
  258. /////////////////////////////////////////////////////////////////////
  259.                 START:
  260.                         nxt_st <= LOAD_VOL;
  261. /////////////////////////////////////////////////////////////////////
  262.                 LOAD_VOL:
  263.                         nxt_st <= LOAD_VOL2;
  264. /////////////////////////////////////////////////////////////////////
  265.                 LOAD_VOL2:
  266.                         nxt_st <= LOAD_DAT;
  267. /////////////////////////////////////////////////////////////////////
  268.                 LOAD_DAT:
  269.                         nxt_st <= LOAD_DAT2;
  270. /////////////////////////////////////////////////////////////////////
  271.                 LOAD_DAT2:
  272.                         nxt_st <= START_MUL;
  273. /////////////////////////////////////////////////////////////////////
  274.                 START_MUL:
  275.                         nxt_st <= WAIT_STOP;
  276. /////////////////////////////////////////////////////////////////////
  277.                 WAIT_STOP:
  278.                         if( (!mulacc_ready) || (chanptr == 2'd3) )
  279.                                 nxt_st <= WAIT_STOP;
  280.                         else
  281.                                 nxt_st <= LOOP;
  282. /////////////////////////////////////////////////////////////////////
  283.                 LOOP:
  284.                         nxt_st <= LOAD_VOL;
  285. /////////////////////////////////////////////////////////////////////
  286.                 endcase
  287.         end
  288.  
  289.  
  290.         always @(posedge clock)
  291.         begin
  292.                 case( cur_st )
  293. /////////////////////////////////////////////////////////////////////
  294.                 START:
  295.                 begin
  296.                         chanptr <= 2'd0;
  297.                         mulacc_load <= 1'b0;
  298.                         mem_read <= 1'b0;
  299.                 end
  300. /////////////////////////////////////////////////////////////////////
  301.                 LOAD_VOL:
  302.                 begin
  303.                         mem_read <= 1'b1;
  304.                         datnvol <= 1'b0;
  305.                 end
  306. /////////////////////////////////////////////////////////////////////
  307.                 LOAD_VOL2:
  308.                 begin
  309.                         mem_read <= 1'b0;
  310.                 end
  311. /////////////////////////////////////////////////////////////////////
  312.                 LOAD_DAT:
  313.                 begin
  314.                         vol <= mem_do[5:0];
  315.                         mem_read <= 1'b1;
  316.                         datnvol <= 1'b1;
  317.                 end
  318. /////////////////////////////////////////////////////////////////////
  319.                 LOAD_DAT2:
  320.                 begin
  321.                         mem_read <= 1'b0;
  322.                         mulacc_load <= 1'b1;
  323.                 end
  324. /////////////////////////////////////////////////////////////////////
  325.                 START_MUL:
  326.                 begin
  327.                         mulacc_load <= 1'b0;
  328.                 end
  329. /////////////////////////////////////////////////////////////////////
  330. //              WAIT_STOP:
  331. /////////////////////////////////////////////////////////////////////
  332.                 LOOP:
  333.                 begin
  334.                         chanptr <= chanptr + 2'd1;
  335.                 end
  336. /////////////////////////////////////////////////////////////////////
  337.                 endcase
  338.         end
  339.  
  340.  
  341.  
  342.  
  343.  
  344.  
  345.  
  346.  
  347.  
  348. // controlling writes to memory
  349.  
  350.         // toggles
  351.         always @(negedge clock)
  352.                 wrtgl1 <= in_wrtoggle;
  353.         always @(posedge clock)
  354.                 {wrtgl3,wrtgl2} <= {wrtgl2,wrtgl1};
  355.  
  356.  
  357.         // intermediate buffers and writing
  358.         always @(posedge clock)
  359.         begin
  360.  
  361.                 if( wrtgl3!=wrtgl2 )
  362.                 begin
  363.                         bf_wraddr  <= in_wraddr;
  364.                         bf_data    <= in_data;
  365.                         bf_datnvol <= in_datnvol;
  366.  
  367.                         do_write <= 1'b1;
  368.                 end
  369.  
  370.                 else if( mem_we )
  371.                 begin
  372.                         do_write <= 1'b0;
  373.                 end
  374.  
  375.         end
  376.  
  377.         always @*
  378.         begin
  379.                 mem_we <= do_write & (~mem_read);
  380.         end
  381.  
  382.  
  383. endmodule
  384.  
  385.