summaryrefslogtreecommitdiffstats
path: root/usrp2/fifo
diff options
context:
space:
mode:
authorMatt Ettus <matt@ettus.com>2010-12-28 15:32:27 -0800
committerMatt Ettus <matt@ettus.com>2010-12-28 15:32:27 -0800
commit8d6e6985f9f8e6e965621ca7ae40b4b89583fd45 (patch)
tree1721c826a2fa51f76e345c148a063f7bb5068e54 /usrp2/fifo
parent8cf7fb2829aae3f99a93672a2e9747a633bab9d0 (diff)
downloaduhd-8d6e6985f9f8e6e965621ca7ae40b4b89583fd45.tar.gz
uhd-8d6e6985f9f8e6e965621ca7ae40b4b89583fd45.tar.bz2
uhd-8d6e6985f9f8e6e965621ca7ae40b4b89583fd45.zip
first cut at new buffer interface for CPU. Like old buffer_int plus
a single buffer.
Diffstat (limited to 'usrp2/fifo')
-rw-r--r--usrp2/fifo/buffer_int2.v169
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