aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp2/gpmc/gpmc_to_fifo.v
diff options
context:
space:
mode:
Diffstat (limited to 'fpga/usrp2/gpmc/gpmc_to_fifo.v')
-rw-r--r--fpga/usrp2/gpmc/gpmc_to_fifo.v45
1 files changed, 30 insertions, 15 deletions
diff --git a/fpga/usrp2/gpmc/gpmc_to_fifo.v b/fpga/usrp2/gpmc/gpmc_to_fifo.v
index cfc5aaa8b..3932b81ac 100644
--- a/fpga/usrp2/gpmc/gpmc_to_fifo.v
+++ b/fpga/usrp2/gpmc/gpmc_to_fifo.v
@@ -1,5 +1,5 @@
//
-// Copyright 2011 Ettus Research LLC
+// Copyright 2011-2012 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -22,7 +22,7 @@
// The GPMC is asynchronously alerted when a BRAM page is available.
//
// EM_CLK:
-// A GPMC read transaction consists of one EM_CLK cycle (idle low).
+// A GPMC write transaction consists of one EM_CLK cycle (idle low).
//
// EM_WE:
// Write enable is actually the combination of ~NWE & ~NCS.
@@ -36,7 +36,7 @@
////////////////////////////////////////////////////////////////////////
module gpmc_to_fifo
- #(parameter PTR_WIDTH = 2, parameter ADDR_WIDTH = 10)
+ #(parameter PTR_WIDTH = 2, parameter ADDR_WIDTH = 10, parameter XFER_OFFSET = 2)
(input [15:0] EM_D, input [ADDR_WIDTH:1] EM_A, input EM_CLK, input EM_WE,
input clk, input reset, input clear, input arst,
output [17:0] data_o, output src_rdy_o, input dst_rdy_i,
@@ -45,17 +45,20 @@ module gpmc_to_fifo
//states for the GPMC side of things
wire [17:0] data_i;
reg gpmc_state;
- reg [ADDR_WIDTH:1] last_addr;
+ reg [15:0] vita_len;
+ reg [ADDR_WIDTH:1] addr;
+ wire [ADDR_WIDTH:1] last_addr = {vita_len[ADDR_WIDTH-2:0], 1'b0} - 1'b1 + XFER_OFFSET;
reg [PTR_WIDTH:0] gpmc_ptr, next_gpmc_ptr;
localparam GPMC_STATE_START = 0;
localparam GPMC_STATE_FILL = 1;
//states for the FIFO side of things
- reg fifo_state;
+ reg [1:0] fifo_state;
reg [ADDR_WIDTH-1:0] counter;
reg [PTR_WIDTH:0] fifo_ptr;
localparam FIFO_STATE_CLAIM = 0;
localparam FIFO_STATE_EMPTY = 1;
+ localparam FIFO_STATE_PRE = 2;
//------------------------------------------------------------------
// State machine to control the data from GPMC to BRAM
@@ -65,14 +68,16 @@ module gpmc_to_fifo
gpmc_state <= GPMC_STATE_START;
gpmc_ptr <= 0;
next_gpmc_ptr <= 0;
+ addr <= 0;
end
else if (EM_WE) begin
+ addr <= EM_A + 1;
case(gpmc_state)
GPMC_STATE_START: begin
- if (EM_A == 2) begin
+ if (data_i[16]) begin
gpmc_state <= GPMC_STATE_FILL;
- last_addr <= {EM_D[ADDR_WIDTH-2:0], 1'b0} - 1'b1 + 2;
+ vita_len <= EM_D;
next_gpmc_ptr <= gpmc_ptr + 1;
end
end
@@ -81,6 +86,7 @@ module gpmc_to_fifo
if (data_i[17]) begin
gpmc_state <= GPMC_STATE_START;
gpmc_ptr <= next_gpmc_ptr;
+ addr <= 0;
end
end
@@ -105,6 +111,7 @@ module gpmc_to_fifo
cross_clock_reader #(.WIDTH(PTR_WIDTH+1)) read_next_gpmc_ptr
(.clk(clk), .rst(reset | clear), .in(next_gpmc_ptr), .out(safe_next_gpmc_ptr));
+ wire [PTR_WIDTH:0] fifo_ptr_next = fifo_ptr + 1;
always @(posedge clk)
if (reset | clear) have_space <= 0;
else have_space <= (fifo_ptr ^ (1 << PTR_WIDTH)) != safe_next_gpmc_ptr;
@@ -116,22 +123,28 @@ module gpmc_to_fifo
if (reset | clear) begin
fifo_state <= FIFO_STATE_CLAIM;
fifo_ptr <= 0;
- counter <= 2;
+ counter <= XFER_OFFSET;
end
else begin
case(fifo_state)
FIFO_STATE_CLAIM: begin
- if (bram_available_to_empty) fifo_state <= FIFO_STATE_EMPTY;
- counter <= 2;
+ if (bram_available_to_empty && data_o[16]) fifo_state <= FIFO_STATE_PRE;
+ counter <= XFER_OFFSET;
+ end
+
+ FIFO_STATE_PRE: begin
+ fifo_state <= FIFO_STATE_EMPTY;
+ counter <= counter + 1;
end
FIFO_STATE_EMPTY: begin
if (src_rdy_o && dst_rdy_i && data_o[17]) begin
fifo_state <= FIFO_STATE_CLAIM;
fifo_ptr <= fifo_ptr + 1;
+ counter <= XFER_OFFSET;
end
- if (src_rdy_o && dst_rdy_i) begin
+ else if (src_rdy_o && dst_rdy_i) begin
counter <= counter + 1;
end
end
@@ -140,18 +153,20 @@ module gpmc_to_fifo
end
end //always
+ wire enable = (fifo_state != FIFO_STATE_EMPTY) || dst_rdy_i;
+
assign src_rdy_o = fifo_state == FIFO_STATE_EMPTY;
//assign data and frame bits to bram input
assign data_i[15:0] = EM_D;
- assign data_i[16] = (gpmc_state == GPMC_STATE_START);
- assign data_i[17] = (EM_A == last_addr);
+ assign data_i[16] = (addr == XFER_OFFSET);
+ assign data_i[17] = (addr == last_addr);
//instantiate dual ported bram for async read + write
ram_2port #(.DWIDTH(18),.AWIDTH(PTR_WIDTH + ADDR_WIDTH)) async_fifo_bram
(.clka(~EM_CLK),.ena(1'b1),.wea(EM_WE),
- .addra({gpmc_ptr[PTR_WIDTH-1:0], EM_A}),.dia(data_i),.doa(),
- .clkb(~clk),.enb(1'b1),.web(1'b0),
+ .addra({gpmc_ptr[PTR_WIDTH-1:0], addr}),.dia(data_i),.doa(),
+ .clkb(clk),.enb(enable),.web(1'b0),
.addrb({fifo_ptr[PTR_WIDTH-1:0], counter}),.dib(18'h3ffff),.dob(data_o));
endmodule // gpmc_to_fifo