diff options
| -rw-r--r-- | usrp2/fifo/buffer_int2.v | 169 | 
1 files changed, 169 insertions, 0 deletions
diff --git a/usrp2/fifo/buffer_int2.v b/usrp2/fifo/buffer_int2.v new file mode 100644 index 000000000..2ab94f589 --- /dev/null +++ b/usrp2/fifo/buffer_int2.v @@ -0,0 +1,169 @@ + +// FIFO Interface to the 2K buffer RAMs +// Read port is read-acknowledge +// FIXME do we want to be able to interleave reads and writes? + +module buffer_int2 +  #(parameter BASE = 0, +    parameter BUF_SIZE = 9) +    (// Control Interface +     input clk, +     input rst, + +     input set_stb, input [7:0] set_addr, input [31:0] set_data, +     output [31:0] status, +     output sys_int_o,   // unused + +     // Wishbone interface to RAM +     input wb_clk_i, +     input wb_rst_i, +     input wb_we_i, +     input wb_stb_i, +     input [15:0] wb_adr_i, +     input [31:0] wb_dat_i,    +     output [31:0] wb_dat_o, +     output reg wb_ack_o, + +     // Write FIFO Interface +     input [35:0] wr_data_i, +     input wr_ready_i, +     output wr_ready_o, +      +     // Read FIFO Interface +     output [35:0] rd_data_o, +     output rd_ready_o, +     input rd_ready_i +     ); + +   reg [BUF_SIZE-1:0] addr; +   wire [31:0] 	      ctrl; +   wire 	      we, en, done, error, idle, go; +    +   wire [BUF_SIZE-1:0] firstline = 0; +   wire [BUF_SIZE-1:0] lastline = ctrl[15+BUF_SIZE:16]; +    +   wire 	       read = ctrl[2]; +   wire 	       write = ctrl[1]; +   wire 	       clear = ctrl[0]; +    +   reg [2:0] 	       state; +   reg 		       rd_sop, rd_eop; +   wire 	       wr_sop, wr_eop, wr_error; +   reg [1:0] 	       rd_occ; +   wire [1:0] 	       wr_occ; +    +   localparam IDLE = 3'd0; +   localparam PRE_READ = 3'd1; +   localparam READING = 3'd2; +   localparam WRITING = 3'd3; +   localparam ERROR = 3'd4; +   localparam DONE = 3'd5; +    +   always @(posedge clk) +     if(rst) +       begin +	  state <= IDLE; +	  rd_sop <= 0; +	  rd_eop <= 0; +	  rd_occ <= 0; +       end +     else +       if(clear) +	 begin +	    state <= IDLE; +	    rd_sop <= 0; +	    rd_eop <= 0; +	    rd_occ <= 0; +	 end +       else  +	 case(state) +	   IDLE : +	     if(go & read) +	       begin +		  addr <= firstline; +		  state <= PRE_READ; +	       end +	     else if(go & write) +	       begin +		  addr <= firstline; +		  state <= WRITING; +	       end +	    +	   PRE_READ : +	     begin +		state <= READING; +		addr <= addr + 1; +		rd_occ <= 2'b00; +		rd_sop <= 1; +		rd_eop <= 0; +	     end +	    +	   READING : +	     if(rd_ready_i) +	       begin +		  rd_sop <= 0; +		  addr <= addr + 1; +		  if(addr == lastline) +		    begin +		       rd_eop <= 1; +		       // FIXME assign occ here +		       rd_occ <= 0; +		    end +		  else +		    rd_eop <= 0; +		  if(rd_eop) +		    state <= DONE; +	       end +	    +	   WRITING : +	     begin +		if(wr_ready_i) +		  begin +		     addr <= addr + 1; +		     if(wr_error) +		       begin +			  state <= ERROR; +			  // Save OCC flags here +		       end +		     else if((addr == lastline)||wr_eop) +		       state <= DONE; +		  end // if (wr_ready_i) +	     end // case: WRITING +	    +	 endcase // case(state) +    +   assign     rd_data_o[35:32] = { rd_occ[1:0], rd_eop, rd_sop }; +   assign     rd_ready_o = (state == READING); +    +   assign     wr_sop = wr_data_i[32]; +   assign     wr_eop = wr_data_i[33]; +   assign     wr_occ = wr_data_i[35:34]; +   assign     wr_error = wr_sop & wr_eop; +   assign     wr_ready_o = (state == WRITING); + +   assign     we = (state == WRITING); // always write to avoid timing issue +   assign     en = ~((state==READING)& ~rd_ready_i);   // FIXME potential critical path +    +   assign     done = (state == DONE); +   assign     error = (state == ERROR); +   assign     idle = (state == IDLE); + +   ram_2port #(.DWIDTH(32),.AWIDTH(BUF_SIZE)) buffer +     (.clka(wb_clk_i),.ena(wb_stb_i),.wea(wb_we_i), +      .addra(wb_adr_i[BUF_SIZE+1:2]),.dia(wb_dat_i),.doa(wb_dat_o), +      .clkb(clk),.enb(en),.web(we), +      .addrb(addr),.dib(wr_data_i[31:0]),.dob(rd_data_o[31:0])); +    +   always @(posedge wb_clk_i) +     if(wb_rst_i) +       wb_ack_o <= 0; +     else +       wb_ack_o <= wb_stb_i & ~wb_ack_o; + +   setting_reg #(.my_addr(BASE))  +   sreg(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),.in(set_data), +	.out(ctrl),.changed(go)); +    +   assign status = { {(16-BUF_SIZE){1'b0}},addr,8'b0,5'b0,idle,error,done}; + +endmodule // buffer_int2  | 
