aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp2/fifo/buffer_int.v
diff options
context:
space:
mode:
authorJosh Blum <josh@joshknows.com>2010-06-18 12:33:40 -0700
committerJosh Blum <josh@joshknows.com>2010-06-18 12:33:40 -0700
commitefbeb60d1dd7e870a48cf42df9a3650aefbf26cd (patch)
tree12131942ff9f85f7776a864cb79120bab778d8f9 /fpga/usrp2/fifo/buffer_int.v
parentdf80be9c61d95402976d3349acf62630044c1939 (diff)
parentedcc2df10ba59ed91ac9513c2dc1d36e155caaec (diff)
downloaduhd-efbeb60d1dd7e870a48cf42df9a3650aefbf26cd.tar.gz
uhd-efbeb60d1dd7e870a48cf42df9a3650aefbf26cd.tar.bz2
uhd-efbeb60d1dd7e870a48cf42df9a3650aefbf26cd.zip
Merge branch 'uhd_fpga_merge' into pre_merge
Diffstat (limited to 'fpga/usrp2/fifo/buffer_int.v')
-rw-r--r--fpga/usrp2/fifo/buffer_int.v168
1 files changed, 168 insertions, 0 deletions
diff --git a/fpga/usrp2/fifo/buffer_int.v b/fpga/usrp2/fifo/buffer_int.v
new file mode 100644
index 000000000..b45ed3532
--- /dev/null
+++ b/fpga/usrp2/fifo/buffer_int.v
@@ -0,0 +1,168 @@
+
+// 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_int
+ #(parameter BUF_NUM = 0,
+ parameter BUF_SIZE = 9)
+ (// Control Interface
+ input clk,
+ input rst,
+ input [31:0] ctrl_word,
+ input go,
+ output done,
+ output error,
+ output idle,
+ output [1:0] flag,
+
+ // Buffer Interface
+ output en_o,
+ output we_o,
+ output reg [BUF_SIZE-1:0] addr_o,
+ output [31:0] dat_to_buf,
+ input [31:0] dat_from_buf,
+
+ // Write FIFO Interface
+ input [31:0] wr_data_i,
+ input [3:0] wr_flags_i,
+ input wr_ready_i,
+ output wr_ready_o,
+
+ // Read FIFO Interface
+ output [31:0] rd_data_o,
+ output [3:0] rd_flags_o,
+ output rd_ready_o,
+ input rd_ready_i
+ );
+
+ reg [31:0] ctrl_reg;
+ reg go_reg;
+
+ always @(posedge clk)
+ go_reg <= go;
+
+ always @(posedge clk)
+ if(rst)
+ ctrl_reg <= 0;
+ else
+ if(go & (ctrl_word[31:28] == BUF_NUM))
+ ctrl_reg <= ctrl_word;
+
+ wire [BUF_SIZE-1:0] firstline = ctrl_reg[BUF_SIZE-1:0];
+ wire [BUF_SIZE-1:0] lastline = ctrl_reg[2*BUF_SIZE-1:BUF_SIZE];
+
+ wire read = ctrl_reg[22];
+ wire write = ctrl_reg[23];
+ wire clear = ctrl_reg[24];
+ //wire [2:0] port = ctrl_reg[27:25]; // Ignored in this block
+ //wire [3:0] buff_num = ctrl_reg[31:28]; // Ignored here ?
+
+ 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;
+
+ 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;
+
+ 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_reg & read)
+ begin
+ addr_o <= firstline;
+ state <= PRE_READ;
+ end
+ else if(go_reg & write)
+ begin
+ addr_o <= firstline;
+ state <= WRITING;
+ end
+
+ PRE_READ :
+ begin
+ state <= READING;
+ addr_o <= addr_o + 1;
+ rd_occ <= 2'b00;
+ rd_sop <= 1;
+ rd_eop <= 0;
+ end
+
+ READING :
+ if(rd_ready_i)
+ begin
+ rd_sop <= 0;
+ addr_o <= addr_o + 1;
+ if(addr_o == 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_o <= addr_o + 1;
+ if(wr_error)
+ begin
+ state <= ERROR;
+ // Save OCC flags here
+ end
+ else if((addr_o == lastline)||wr_eop)
+ state <= DONE;
+ end // if (wr_ready_i)
+ end // case: WRITING
+
+ endcase // case(state)
+
+ assign dat_to_buf = wr_data_i;
+ assign rd_data_o = dat_from_buf;
+
+ assign rd_flags_o = { rd_occ[1:0], rd_eop, rd_sop };
+ assign rd_ready_o = (state == READING);
+
+ assign wr_sop = wr_flags_i[0];
+ assign wr_eop = wr_flags_i[1];
+ assign wr_occ = wr_flags_i[3:2];
+ assign wr_error = wr_sop & wr_eop;
+ assign wr_ready_o = (state == WRITING);
+
+ assign we_o = (state == WRITING);
+ //assign we_o = (state == WRITING) && wr_ready_i; // always write to avoid timing issue
+
+ assign en_o = ~((state==READING)& ~rd_ready_i); // FIXME potential critical path
+
+ assign done = (state == DONE);
+ assign error = (state == ERROR);
+ assign idle = (state == IDLE);
+
+endmodule // buffer_int