module ramaddr(clk40x, n_reset, wr_strobe, addr, fir_en, 
		paddr, firwe, prog);

  input clk40x, wr_strobe, fir_en, n_reset;
  input [7:0] addr;

  output [11:0] firwe;
  output [3:0] paddr;
  output prog;
 
  reg pd, sync1, ween, ws_edge_det;
  reg [11:0] teaddr;
  reg [11:0] firwe;

  wire [3:0] paddr;
  wire prog, reset;

  assign paddr = addr[3:0];
  assign prog = pd | ws_edge_det;
  assign reset = !n_reset;

  //FIR we address decoding
  always @(addr[7:4] )
   begin
     case (addr[7:4])
       4'h0: teaddr = 12'h1;
       4'h1: teaddr = 12'h2;
       4'h2: teaddr = 12'h4;
       4'h3: teaddr = 12'h8;
       4'h4: teaddr = 12'h10;
       4'h5: teaddr = 12'h20;
       4'h6: teaddr = 12'h40;
       4'h7: teaddr = 12'h80;
       4'h8: teaddr = 12'h100;
       4'h9: teaddr = 12'h200;
       4'ha: teaddr = 12'h400;
       4'hb: teaddr = 12'h800;
       default: teaddr = 12'h0;
     endcase
   end

  always @(ween or teaddr)
     firwe[11:0]  = teaddr[11:0] & {12{ween}};

  // Stretch the prog switch til after we has deselected
  always @(posedge clk40x or posedge reset)
   begin 
     if(reset)
       pd <= 1'b0;
     else
       pd <= ws_edge_det | ween;
   end

 // 2.5 stage synchronizer, based on +edge of wr_strobe with fir_en==1
  always @ (posedge clk40x or posedge reset or posedge ween)
   begin
     if(reset | ween )
	sync1 <= 1'b0;
     else
	 sync1 <= ws_edge_det; 
   end

  always @(posedge clk40x or posedge reset)
   begin
     if(reset)
       ween <= 1'b0;
     else 
       ween <= sync1;
   end
 
  always @(posedge wr_strobe or posedge ween or posedge reset)
   begin
     if(reset | ween)
       ws_edge_det <= 1'b0;
     else
       ws_edge_det <= fir_en;
   end
endmodule
