//+FHDR--------------------------------------------------------------------------------------------------------
//  Company: 
//-----------------------------------------------------------------------------------------------------------------
//  File Name             :    awg_top.v
//  Department            :    
//  Author                :    hdzhang
//  Author's Tel          :     
//-----------------------------------------------------------------------------------------------------------------
//  Relese History
//  Version     Date            Author          Description
//  0.1         2026-03-01      hdzhang         awg-top
//-----------------------------------------------------------------------------------------------------------------
//  Keywords            :       
//
//-----------------------------------------------------------------------------------------------------------------
//  Parameter
//
//-----------------------------------------------------------------------------------------------------------------
//  Purpose                 :
//                      
//-----------------------------------------------------------------------------------------------------------------
//  Target Device:        
//  Tool versions:        
//-----------------------------------------------------------------------------------------------------------------
//  Reuse Issues
//  Reset Strategy: 
//  Clock Domains: 
//  Critical Timing:
//  Asynchronous I/F:
//  Synthesizable (y/n): 
//  Other:
//-FHDR--------------------------------------------------------------------------------------------------------

module awg_top (
  //system port
   input          clk                              // System Main Clock
  ,input          rst_n                            // Spi Reset active low
  ,input          start
  //----------------------------from spi-----------------------------------------------------------
  //Wave storage read/write signal
  //A-port
  ,input  [511:0] wave_awrdata 
  ,input  [0  :0] wave_awren   
  ,input  [12 :0] wave_arwaddr 
  ,input  [63 :0] wave_awrmask

  //B-port
  ,input  [31 :0] wave_bwrdata 
  ,input  [0  :0] wave_bwren   
  ,input  [18 :0] wave_brwaddr 
  ,input  [0  :0] wave_brden   
  ,output [31 :0] wave_brddata 
  //cmd fifo read-write signal
  ,input  [31 :0] cmd_fifo_bwrdata 
  ,input  [0  :0] cmd_fifo_bwren   
  ,input  [7  :0] cmd_fifo_brwaddr 
  ,input  [0  :0] cmd_fifo_brden   
  ,output [31 :0] cmd_fifo_brddata 
  //----------------------------to system regfile------------------------------------------------------
  //CMD FIFO Empty & Full
  ,output         cmd_fifo_empty
  ,output         cmd_fifo_full
  //AWG Ctrl Status
  ,output [2  :0] status
  ,output         wave_busy
  //----------------------------to DEM----------------------------------------------------------------  
  ,output [511:0] wave_data_out
  ,output         wave_valid_out
  );

wire         start_r;
sirv_gnrl_dffr #(1) start_dffr (start, start_r, clk, rst_n);

wire         start_posedge = start && ~start_r;
wire         sync_start;
sirv_gnrl_dffr #(1) sync_start_dffr (start_posedge, sync_start, clk, rst_n);

wire         cmd_fifo_rd_en       ;
wire [31 :0] cmd_fifo_data        ;
//wire         cmd_fifo_empty       ;
wire         sram_rd_en           ;
wire [12 :0] sram_rd_addr         ;
wire [511:0] sram_rd_data         ;

awg_ctrl awg_ctrl_inst(
   .clk                                ( clk                           )
  ,.rst_n                              ( rst_n                         )
  ,.start                              ( sync_start                    )
  ,.cmd_fifo_rd_en                     ( cmd_fifo_rd_en                )
  ,.cmd_fifo_data                      ( cmd_fifo_data                 )
  ,.cmd_fifo_empty                     ( cmd_fifo_empty                )
  ,.sram_rd_en                         ( sram_rd_en                    )
  ,.sram_rd_addr                       ( sram_rd_addr                  )
  ,.sram_rd_data                       ( sram_rd_data                  )
  ,.wave_data_out                      ( wave_data_out                 )
  ,.wave_valid_out                     ( wave_valid_out                )
  ,.status                             ( status                        )
  ,.wave_busy                          ( wave_busy                     )
);

//wire         cmd_fifo_full        ;
wire         cmd_fifo_almost_full ;
wire         cmd_fifo_almost_empty;
wire         cmd_fifo_prog_full   ;
wire         cmd_fifo_prog_empty  ;
wire [5  :0] cmd_fifo_cnt         ;

syn_fwft_fifo #(.width(32), .depth(64), .prog_full_thre(32), .prog_empty_thre(16))
cmd_fifo_inst(
   .clk                                ( clk                           )
  ,.rst                                ( ~rst_n                        )
  ,.clr                                ( 1'b0                          )
  ,.wr_en                              ( cmd_fifo_bwren                )
  ,.rd_en                              ( cmd_fifo_rd_en                )
  ,.din                                ( cmd_fifo_bwrdata              )
  ,.dout                               ( cmd_fifo_data                 )
  ,.full                               ( cmd_fifo_full                 )
  ,.empty                              ( cmd_fifo_empty                )
  ,.almost_full                        ( cmd_fifo_almost_full          )
  ,.almost_empty                       ( cmd_fifo_almost_empty         )
  ,.prog_full                          ( cmd_fifo_prog_full            )
  ,.prog_empty                         ( cmd_fifo_prog_empty           )
  ,.cnt                                ( cmd_fifo_cnt                  )
);

//------------------------------------------------------------------------------------------
// wave sram
//------------------------------------------------------------------------------------------
sram_if #(19, 32) wave_sram_muxin (clk);
sram_if #(19,512) wave_sram_muxout(clk);
assign wave_sram_muxin.addr    = wave_brwaddr[18:0]    ;
assign wave_sram_muxin.din     = wave_bwrdata          ;
assign wave_sram_muxin.wben    = 4'b1111               ;
assign wave_sram_muxin.wren    = wave_bwren            ;
assign wave_sram_muxin.rden    = wave_brden            ;
assign wave_brddata            = wave_sram_muxin.dout  ;
sram_dmux_w #(.ADDR_WIDTH(19), .DATA_WIDTH_I(32), .DATA_WIDTH_O(512)) 
U_sram_dmux_w(                                                                                    
   .clk                                ( clk                           )
  ,.rst_n                              ( rst_n                         )
  ,.port_in                            ( wave_sram_muxin               )
  ,.port_out                           ( wave_sram_muxout              )
);
//Wave Memory Clock
  
wire [0      :0] Wave_PortClk              = clk                        ; 
//The wave storage A port is connected to the internal AWG controller                                          
wire [18     :0] Wave_PortAAddr            = wave_awren ? {wave_arwaddr[12:0],6'b0} : {sram_rd_addr[12:0],6'b0};
wire [511    :0] Wave_PortADataIn          = wave_awrdata               ;
wire [0      :0] Wave_PortAWriteEnable     = ~wave_awren                ;
wire [0      :0] Wave_PortAChipEnable      = ~wave_awren&~sram_rd_en    ;
wire [512/8-1:0] Wave_PortAByteWriteEnable = ~wave_awrmask              ;
wire [511    :0] Wave_PortADataOut                                      ;
assign sram_rd_data = Wave_PortADataOut                                 ;
//The B port of the wave storage connects to an external SPI bus decode
wire [18     :0] Wave_PortBAddr            = wave_sram_muxout.addr[18:0]                         ;
wire [511    :0] Wave_PortBDataIn          = wave_sram_muxout.din                                ;
wire [0      :0] Wave_PortBWriteEnable     = ~wave_sram_muxout.wren & wave_sram_muxout.rden      ;
wire [0      :0] Wave_PortBChipEnable      = ~(wave_sram_muxout.wren | wave_sram_muxout.rden)    ;
wire [512/8-1:0] Wave_PortBByteWriteEnable = ~wave_sram_muxout.wben                              ;
wire [511    :0] Wave_PortBDataOut                                                               ;
assign wave_sram_muxout.dout = Wave_PortBDataOut                                                 ;

dpram #(.DATAWIDTH(512), .ADDRWIDTH(19)) wave_dpram(                                                                          
   .PortClk                            ( Wave_PortClk                  )
  ,.PortAAddr                          ( Wave_PortAAddr                )
  ,.PortADataIn                        ( Wave_PortADataIn              )
  ,.PortAWriteEnable                   ( Wave_PortAWriteEnable         )
  ,.PortAChipEnable                    ( Wave_PortAChipEnable          )
  ,.PortAByteWriteEnable               ( Wave_PortAByteWriteEnable     )
  ,.PortADataOut                       ( Wave_PortADataOut             )
  ,.PortBAddr                          ( Wave_PortBAddr                )
  ,.PortBDataIn                        ( Wave_PortBDataIn              )
  ,.PortBWriteEnable                   ( Wave_PortBWriteEnable         )
  ,.PortBChipEnable                    ( Wave_PortBChipEnable          )
  ,.PortBByteWriteEnable               ( Wave_PortBByteWriteEnable     )
  ,.PortBDataOut                       ( Wave_PortBDataOut             )
);
endmodule

