- // part of NeoGS project (c) 2007-2008 NedoPC 
- // 
- // sound_main is the main sound module: it incorporates data storage (512b memory), from which 
- //  it reads data, prepares it through sound_mulacc and sends to sound_dac. It incorporates in itself 
- //  sound_dac, so it has outs to the DAC. 
- // clock is ordinary 24 MHz clock, mode_8chans is asynchronous input signal controlling mode of operation, 
- //  either 4 or 8 channels. 
- // 
- // channels in 4 channel mode (mode_8chans=0,mode_pan4ch=0) 
- // 1,2 -> left 
- // 3,4 -> right 
- // channels in 8 channel mode (mode_8chans=1,mode_pan4ch=0) 
- // 1,2,5,6 -> left 
- // 3,4,7,8 -> right 
- // channels in panning 4 channel mode (mode_8chans=0,mode_pan4ch=1) 
- // 1,2,3,4 (vols 1,2,5,6) -> left 
- // 1,2,3,4 (vols 3,4,7,8) -> right 
- // channels in mem are at addressed 0-7 (corresponding to channels 1-8, respectively). 
- // mem contains volumes (lower 6 bits, 0-zero volume, 63-max volume) and sound data (signed value with sign inverted: 
- // -data in mem---+----value-- 
- //          $FF   |     +$7F 
- //          $81   |     +$01 
- //          $80   |     +$00 
- //          $7F   |     -$01 (or $FF) 
- //          $01   |     -$7F (or $81) 
- //          $00   |     -$80 (or $80) 
- // alternatively, it could be treated as unsigned positive samples with middle point of $7F-$80. 
- // 
- // clock      ``\__/``\__/``\__/``\__/``\__/``\__/``\__/``\__ 
- // mem_read   ______/`````\__________________________________ 
- // mem_wraddr       |  no |     |addr | 
- // mem_di           |write|     |data | 
- // mem_***_we ______|here!|_____/`````\______________________ 
- //                                   ^-- data written here! 
-   
- module sound_main( 
-   
-         clock,         // system clock (24 MHz) 
-   
-         mode_8chans,   // =1 - 8 channels, =0 - 4 channels 
-         mode_pan4ch,   // =1 - 4 channels with panning 
-   
-   
-         in_wrtoggle,   // from ports.v module (async to clock) 
-         in_datnvol,    // 
-         in_wraddr,     // 
-         in_data,       // 
-   
-   
-         dac_clock,     // output to DAC 
-         dac_leftright, // output to DAC 
-         dac_data       // output to DAC 
- ); 
-   
-     // input-output description 
-   
-         input clock; 
-   
-         input mode_8chans; 
-         input mode_pan4ch; 
-   
-         input in_wrtoggle; 
-         input in_datnvol; 
-         input [2:0] in_wraddr; 
-         input [7:0] in_data; 
-   
-         output dac_clock; 
-   
-         output dac_leftright; 
-   
-         output dac_data; 
-   
-   
-         // internal regs/wires 
-   
-         reg mem_read; // write to mem is forbidden while mem_read=1 
-   
-         reg datnvol; 
-   
-         reg [5:0] vol; // temporary storage for volume 
-   
-         reg mem_we; // write strobe 
-   
-         reg wrtgl1, wrtgl2, wrtgl3; // sync in and edge detect of in_wrtoggle 
-   
-         reg do_write; // indicates that write should be performed 
-   
-         reg [2:0] bf_wraddr; 
-         reg [7:0] bf_data; 
-         reg       bf_datnvol; 
-   
-   
-   
-         wire dac_load; // signal from sound_dac module (when it loads new data) 
-   
-         wire [15:0] dac_pardata; // parallel data from sound_mulacc to sound_dac 
-   
-         reg mulacc_load;   // load to sound_mulacc 
-         reg mulacc_clrsum; // clr_sum to sound_mulacc 
-         wire mulacc_ready; // ready from sound_mulacc 
-   
-         wire [7:0] mem_do; // data output of DAT or VOL 
-   
-         reg [8:0] mem_rdaddr;  // read address for both memory blocks 
-   
-         reg int_mode_8chans;  // internal and sync-in mode_8chans signals 
-         reg sync_mode_8chans; // 
-   
-         reg int_mode_pan4ch,sync_mode_pan4ch; // same for pan4ch signal 
-   
-         reg [1:0] chanptr; // pointer to channels (4 channels total: 0,1,4,5 or 2,3,6,7 depending on lrptr state) 
-         reg lrptr;         // left-right pointer (selects either left (0) or right (1) channels) 
-   
-   
-   
-   
-         reg [2:0] cur_st,nxt_st; 
-   
-   
-   
-   
-   
-   
-         // for simulation purposes 
-         initial 
-         begin 
-                 bf_wraddr <= 0; 
-                 bf_datnvol <= 0; 
-                 bf_data <= 0; 
-                 do_write <= 0; 
-                 cur_st <= START; 
-         end 
-   
-   
-   
-         // instantiating modules 
-   
-         sound_dac my_dac( .clock(clock), 
-                           .dac_clock(dac_clock), 
-                           .dac_leftright(dac_leftright), 
-                           .dac_data(dac_data), 
-                           .load(dac_load), 
-                           .datain(dac_pardata) ); 
-   
-         sound_mulacc my_mulacc( .clock(clock), 
-                                 .vol_in(vol), 
-                                 .dat_in(mem_do), 
-                                 .load(mulacc_load), 
-                                 .clr_sum(mulacc_clrsum), 
-                                 .ready(mulacc_ready), 
-                                 .sum_out(dac_pardata) ); 
-   
-         // DAT-VOL memory block 
-         mem512b my_mem( .clk(clock), 
-                         .rdaddr(mem_rdaddr), 
-                         .dataout(mem_do), 
-                         .wraddr({5'b0,bf_datnvol,bf_wraddr}), 
-                         .datain(bf_data), 
-                         .we(mem_we) ); 
-   
-   
-   
-   
-   
-         // syncing in asynchronous control signals 
-         always @(posedge clock) 
-         begin 
-                 { int_mode_8chans,sync_mode_8chans } <= { sync_mode_8chans, mode_8chans }; 
-                 { int_mode_pan4ch,sync_mode_pan4ch } <= { sync_mode_pan4ch, mode_pan4ch }; 
-         end 
-   
-   
-         // load lrptr (left-right pointer) on dac_load pulse 
-         always @(posedge clock) 
-         begin 
-                 if( dac_load ) 
-                         lrptr <= ~dac_leftright; 
-         end 
-   
-         // make memory read address from chanptr and lrptr 
-         always @* 
-         begin 
- /*              mem_rdaddr[8:4] <= 5'd0; 
-                 mem_rdaddr[3]   <= datnvol; 
-                 mem_rdaddr[2]   <= int_mode_8chans ? chanptr[1] : 1'b0; 
-                 mem_rdaddr[1]   <= lrptr; 
-                 mem_rdaddr[0]   <= chanptr[0];*/ 
-   
-                 mem_rdaddr[8:4] <= 5'd0; 
-   
-                 if( int_mode_8chans ) 
-                 begin 
-                         mem_rdaddr[3]   <= datnvol; 
-                         mem_rdaddr[2]   <= chanptr[1]; 
-                         mem_rdaddr[1]   <= lrptr; 
-                         mem_rdaddr[0]   <= chanptr[0]; 
-                 end 
-                 else if( int_mode_pan4ch ) 
-                 begin 
-                         mem_rdaddr[3] <= datnvol; 
-   
-                         if( datnvol ) // sample data 
-                         begin 
-                                 mem_rdaddr[2] <= 1'b0; 
-                                 mem_rdaddr[1] <= chanptr[1]; 
-                                 mem_rdaddr[0] <= chanptr[0]; 
-                         end 
-                         else // !datnvol: volumes 
-                         begin 
-                                 mem_rdaddr[2]   <= chanptr[1]; // same as in 8 channel 
-                                 mem_rdaddr[1]   <= lrptr; 
-                                 mem_rdaddr[0]   <= chanptr[0]; 
-                         end 
-                 end 
-                 else //normal 4 channel mode 
-                 begin 
-                         mem_rdaddr[3]   <= datnvol; 
-                         mem_rdaddr[2]   <= 1'b0; 
-                         mem_rdaddr[1]   <= lrptr; 
-                         mem_rdaddr[0]   <= chanptr[0]; 
-                 end 
-         end 
-   
-         // handle mulacc_clrsum signal 
-         always @(posedge clock) 
-         begin 
-                 if( dac_load ) 
-                         mulacc_clrsum <= 1'b1;     // set on dac_load pulse 
-                 else if( mulacc_load ) 
-                         mulacc_clrsum <= 1'b0;     // clear on mulacc_load pulse, so only first mulacc cycle will read clrsum high 
-         end 
-   
-   
-   
-   
-   
-         localparam START      = 0; 
-         localparam LOAD_VOL   = 1; 
-         localparam LOAD_VOL2  = 2; 
-         localparam LOAD_DAT   = 3; 
-         localparam LOAD_DAT2  = 4; 
-         localparam START_MUL  = 5; 
-         localparam WAIT_STOP  = 6; 
-         localparam LOOP       = 7; 
-   
-         // FSM! 
-         always @(posedge clock) 
-         begin 
-                 if( dac_load ) 
-                         cur_st <= START; 
-                 else 
-                         cur_st <= nxt_st; 
-         end 
-   
-         always @* 
-         begin 
-                 case( cur_st ) 
- ///////////////////////////////////////////////////////////////////// 
-                 START: 
-                         nxt_st <= LOAD_VOL; 
- ///////////////////////////////////////////////////////////////////// 
-                 LOAD_VOL: 
-                         nxt_st <= LOAD_VOL2; 
- ///////////////////////////////////////////////////////////////////// 
-                 LOAD_VOL2: 
-                         nxt_st <= LOAD_DAT; 
- ///////////////////////////////////////////////////////////////////// 
-                 LOAD_DAT: 
-                         nxt_st <= LOAD_DAT2; 
- ///////////////////////////////////////////////////////////////////// 
-                 LOAD_DAT2: 
-                         nxt_st <= START_MUL; 
- ///////////////////////////////////////////////////////////////////// 
-                 START_MUL: 
-                         nxt_st <= WAIT_STOP; 
- ///////////////////////////////////////////////////////////////////// 
-                 WAIT_STOP: 
-                         if( (!mulacc_ready) || (chanptr == 2'd3) ) 
-                                 nxt_st <= WAIT_STOP; 
-                         else 
-                                 nxt_st <= LOOP; 
- ///////////////////////////////////////////////////////////////////// 
-                 LOOP: 
-                         nxt_st <= LOAD_VOL; 
- ///////////////////////////////////////////////////////////////////// 
-                 endcase 
-         end 
-   
-   
-         always @(posedge clock) 
-         begin 
-                 case( cur_st ) 
- ///////////////////////////////////////////////////////////////////// 
-                 START: 
-                 begin 
-                         chanptr <= 2'd0; 
-                         mulacc_load <= 1'b0; 
-                         mem_read <= 1'b0; 
-                 end 
- ///////////////////////////////////////////////////////////////////// 
-                 LOAD_VOL: 
-                 begin 
-                         mem_read <= 1'b1; 
-                         datnvol <= 1'b0; 
-                 end 
- ///////////////////////////////////////////////////////////////////// 
-                 LOAD_VOL2: 
-                 begin 
-                         mem_read <= 1'b0; 
-                 end 
- ///////////////////////////////////////////////////////////////////// 
-                 LOAD_DAT: 
-                 begin 
-                         vol <= mem_do[5:0]; 
-                         mem_read <= 1'b1; 
-                         datnvol <= 1'b1; 
-                 end 
- ///////////////////////////////////////////////////////////////////// 
-                 LOAD_DAT2: 
-                 begin 
-                         mem_read <= 1'b0; 
-                         mulacc_load <= 1'b1; 
-                 end 
- ///////////////////////////////////////////////////////////////////// 
-                 START_MUL: 
-                 begin 
-                         mulacc_load <= 1'b0; 
-                 end 
- ///////////////////////////////////////////////////////////////////// 
- //              WAIT_STOP: 
- ///////////////////////////////////////////////////////////////////// 
-                 LOOP: 
-                 begin 
-                         chanptr <= chanptr + 2'd1; 
-                 end 
- ///////////////////////////////////////////////////////////////////// 
-                 endcase 
-         end 
-   
-   
-   
-   
-   
-   
-   
-   
-   
- // controlling writes to memory 
-   
-         // toggles 
-         always @(negedge clock) 
-                 wrtgl1 <= in_wrtoggle; 
-         always @(posedge clock) 
-                 {wrtgl3,wrtgl2} <= {wrtgl2,wrtgl1}; 
-   
-   
-         // intermediate buffers and writing 
-         always @(posedge clock) 
-         begin 
-   
-                 if( wrtgl3!=wrtgl2 ) 
-                 begin 
-                         bf_wraddr  <= in_wraddr; 
-                         bf_data    <= in_data; 
-                         bf_datnvol <= in_datnvol; 
-   
-                         do_write <= 1'b1; 
-                 end 
-   
-                 else if( mem_we ) 
-                 begin 
-                         do_write <= 1'b0; 
-                 end 
-   
-         end 
-   
-         always @* 
-         begin 
-                 mem_we <= do_write & (~mem_read); 
-         end 
-   
-   
- endmodule 
-   
-