Removed copy of FPGA source files.

Original-commit: fd3e84941de463fa1a7ebab0a69515b4bf2614cd
This commit is contained in:
Martin Braun
2014-10-07 11:25:20 +02:00
parent 56e84828fe
commit 74893643ca
2415 changed files with 0 additions and 1492030 deletions
View File
-17
View File
@@ -1,17 +0,0 @@
#
# Copyright 2012-2013 Ettus Research LLC
#
##################################################
# FIFO Sources
##################################################
AXI_SRCS = $(abspath $(addprefix $(BASE_DIR)/../lib/axi/, \
axi_dma_master.v \
axi_dram_fifo.v \
axi_embed_tlast.v \
axi_extract_tlast.v \
axi_chdr_test_pattern.v \
axi_fast_fifo.v \
axi_fast_extract_tlast.v \
axi_chdr_header_trigger.v \
))
-40
View File
@@ -1,40 +0,0 @@
// Copyright 2014 Ettus Research LLC
module axi_chdr_header_trigger
#(
parameter WIDTH=64,
parameter SID=0
)
(input clk, input reset, input clear,
input [WIDTH-1:0] i_tdata, input i_tlast, input i_tvalid, input i_tready,
output trigger
);
reg state;
localparam IDLE = 0;
localparam RUN = 1;
always @(posedge clk)
if(reset | clear)
state <= IDLE;
else
case (state)
IDLE :
if(i_tvalid && i_tready)
state <= RUN;
RUN :
if(i_tready && i_tvalid && i_tlast)
state <= IDLE;
default :
state <= IDLE;
endcase // case (state)
assign trigger = i_tvalid && i_tready && (state == IDLE) && (i_tdata[15:0] != SID);
endmodule // axi_chdr_header_trigger
-314
View File
@@ -1,314 +0,0 @@
//
// Synthesizable test pattern generators and checkers
// for CHDR that can be used to test transparent blocks
// (FIFOs, switches, etc)
//
//`define MTU 8192
`define MTU 1536
module axi_chdr_test_pattern
(
input clk,
input reset,
//
// CHDR friendly AXI stream input
//
output reg [63:0] i_tdata,
output reg i_tlast,
output reg i_tvalid,
input wire i_tready,
//
// CHDR friendly AXI Stream output
//
input wire [63:0] o_tdata,
input wire o_tlast,
input wire o_tvalid,
output reg o_tready,
//
// Test flags
//
input start,
input [15:0] control,
output reg fail,
output reg done
);
wire [7:0] bist_rx_delay = control[7:0];
wire [7:0] bist_tx_delay = control[15:8];
reg [15:0] tx_count, rx_count;
reg [15:0] tx_data, rx_data;
reg [7:0] tx_delay, rx_delay;
localparam TX_IDLE = 0;
localparam TX_START = 1;
localparam TX_ACTIVE = 2;
localparam TX_GAP = 3;
localparam TX_DONE = 4;
localparam TX_WAIT = 5;
localparam RX_IDLE = 0;
localparam RX_ACTIVE = 1;
localparam RX_FAIL = 2;
localparam RX_DONE = 3;
localparam RX_WAIT = 4;
reg [2:0] tx_state, rx_state;
//
// Transmitter
//
always @(posedge clk)
if (reset)
begin
tx_delay <= 0;
tx_count <= 8;
tx_data <= 0;
i_tdata <= 64'h0;
i_tlast <= 1'b0;
i_tvalid <= 1'b0;
tx_state <= TX_IDLE;
end
else
begin
case(tx_state)
TX_IDLE: begin
tx_delay <= 0;
i_tdata <= 64'h0;
i_tlast <= 1'b0;
i_tvalid <= 1'b0;
tx_data <= 0;
tx_count <= 4;
// Run whilst start asserted.
if (start) begin
tx_state <= TX_START;
// ....Go back to initialized state if start deasserted.
end else begin
tx_state <= TX_IDLE;
end
end // case: TX_IDLE
//
// START signal is asserted.
// Now need to start transmiting a packet.
//
TX_START: begin
// At the next clock edge drive first beat of new packet onto HDR bus.
i_tlast <= 1'b0;
i_tvalid <= 1'b1;
tx_data <= tx_data + 4;
// i_tdata <= {tx_data,tx_data+16'd1,tx_data+16'd2,tx_data+16'd3};
i_tdata <= {4{(tx_data[2]?16'hffff:16'h0000)^tx_data[15:0]}};
tx_state <= TX_ACTIVE;
end
//
// Valid data is (already) being driven onto the CHDR bus.
// i_tlast may also be driven asserted if current data count has reached EOP.
// Watch i_tready to see when it's consumed.
// When packets are consumed increment data counter or transition state if
// EOP has sucsesfully concluded.
//
TX_ACTIVE: begin
i_tvalid <= 1'b1; // Always assert tvalid
if (i_tready) begin
// i_tdata <= {tx_data,tx_data+16'd1,tx_data+16'd2,tx_data+16'd3};
i_tdata <= {4{(tx_data[2]?16'hffff:16'h0000)^tx_data[15:0]}};
// Will this next beat be the last in a packet?
if (tx_data == tx_count) begin
tx_data <= 0;
i_tlast <= 1'b1;
tx_state <= TX_GAP;
end else begin
tx_data <= tx_data + 4;
i_tlast <= 1'b0;
tx_state <= TX_ACTIVE;
end
end else begin
// Keep driving all CHDR bus signals as-is until i_tready is asserted.
tx_state <= TX_ACTIVE;
end
end // case: TX_ACTIVE
//
// Force an inter-packet gap between packets in a BIST sequence where tvalid is driven low.
// As we leave this state check if all packets in BIST sequence have been generated yet,
// and if so go to done state.
//
TX_GAP: begin
if (i_tready) begin
i_tvalid <= 1'b0;
i_tdata <= 64'h0;
i_tlast <= 1'b0;
tx_count <= tx_count + 4;
if (tx_count < `MTU) begin
tx_state <= TX_WAIT;
tx_delay <= bist_tx_delay;
end else
tx_state <= TX_DONE;
end else begin // if (i_tready)
tx_state <= TX_GAP;
end
end // case: TX_GAP
//
// Simulate inter packet gap in real UHD system
TX_WAIT: begin
if (tx_delay == 0)
tx_state <= TX_START;
else begin
tx_delay <= tx_delay - 1;
tx_state <= TX_WAIT;
end
end
//
// Complete test pattern BIST sequence has been transmitted. Sit in this
// state indefinately if START is taken low, which re-inits the whole BIST solution.
//
TX_DONE: begin
if (!start) begin
tx_state <= TX_DONE;
end else begin
tx_state <= TX_IDLE;
end
i_tvalid <= 1'b0;
i_tdata <= 64'd0;
i_tlast <= 1'b0;
end
endcase // case (tx_state)
end
//
// Receiver
//
always @(posedge clk)
if (reset)
begin
rx_delay <= 0;
rx_count <= 0;
rx_data <= 0;
o_tready <= 1'b0;
rx_state <= RX_IDLE;
fail <= 1'b0;
done <= 1'b0;
end
else begin
case (rx_state)
RX_IDLE: begin
rx_delay <= 0;
o_tready <= 1'b0;
rx_data <= 0;
rx_count <= 4;
fail <= 1'b0;
done <= 1'b0;
// Not accepting data whilst Idle,
// switch to active when packet arrives
if (o_tvalid) begin
o_tready <= 1'b1;
rx_state <= RX_ACTIVE;
end else
rx_state <= RX_IDLE;
end
RX_ACTIVE: begin
o_tready <= 1'b1;
if (o_tvalid)
// if (o_tdata != {rx_data,rx_data+16'd1,rx_data+16'd2,rx_data+16'd3})
if (o_tdata != {4{(rx_data[2]?16'hffff:16'h0000)^rx_data[15:0]}})
begin
$display("o_tdata: %x != expected: %x @ time: %d",o_tdata,
// {rx_data,rx_data+16'd1,rx_data+16'd2,rx_data+16'd3},
{4{(rx_data[2]?16'hffff:16'h0000)^rx_data[15:0]}},
$time);
rx_state <= RX_FAIL;
end
else
// Should last be asserted?
if (rx_data == rx_count)
// ...last not asserted when it should be!
if (~(o_tlast===1)) begin
$display("o_tlast not asserted when it should be @ time: %d",$time);
rx_state <= RX_FAIL;
end else begin
// End of packet, set up to RX next
rx_data <= 0;
rx_count <= rx_count + 4;
rx_delay <= bist_rx_delay;
if (rx_count == `MTU) begin
rx_state <= RX_DONE;
end else begin
rx_state <= RX_WAIT;
end
o_tready <= 1'b0;
end
else
// ...last asserted when it should not be!
if (~(o_tlast===0)) begin
$display("o_tlast asserted when it should not be @ time: %d",$time);
rx_state <= RX_FAIL;
end else begin
// Still in packet body
rx_data <= rx_data + 4;
rx_delay <= bist_rx_delay;
rx_state <= RX_WAIT;
o_tready <= 1'b0;
end
else
// Nothing to do this cycle
rx_state <= RX_ACTIVE;
end // case: RX_ACTIVE
// To simulate the radio consuming samples at a steady rate set by the decimation
// have a programable delay here
RX_WAIT: begin
if (rx_delay == 0) begin
rx_state <= RX_ACTIVE;
o_tready <= 1'b1;
end else begin
rx_delay <= rx_delay - 1;
rx_state <= RX_WAIT;
end
end
RX_FAIL: begin
o_tready <= 1'b0;
done <= 1'b1;
fail <= 1'b1;
// If start is deasserted allow BIST logic to reset and rearm
if (start)
rx_state <= RX_FAIL;
else
rx_state <= RX_IDLE;
end
RX_DONE: begin
o_tready <= 1'b0;
done <= 1'b1;
fail <= 1'b0;
// If start is asserted allow BIST logic to reset, rearm & restart
if (!start)
rx_state <= RX_DONE;
else
rx_state <= RX_IDLE;
end
endcase // case (rx_state)
end
endmodule
-34
View File
@@ -1,34 +0,0 @@
//
// AXI4 Burst enumeration
//
`define AXI4_BURST_FIXED 2'b00
`define AXI4_BURST_INCR 2'b01
`define AXI4_BURST_WRAP 2'b10
`define AXI4_BURST_RSVD 2'b11
//
// AXI4 response code enumeration
//
`define AXI4_RESP_OKAY 2'b00
`define AXI4_RESP_EXOKAY 2'b01
`define AXI4_RESP_SLVERR 2'b10
`define AXI4_RESP_DECERR 2'b11
//
// AXI4 lock enumeration
//
`define AXI4_LOCK_NORMAL 1'b0
`define AXI4_LOCK_EXCLUSIVE 1'b1
//
// AXI4 memory attrubutes
//
`define AXI4_CACHE_ALLOCATE 4'h8
`define AXI4_CACHE_OTHER_ALLOCATE 4'h4
`define AXI4_CACHE_MODIFIABLE 4'h2
`define AXI4_CACHE_BUFFERABLE 4'h1
//
// AXI4 PROT attributes
//
`define AXI4_PROT_PRIVILEDGED 3'h1
`define AXI4_PROT_NON_SECURE 3'h2
`define AXI4_PROT_INSTRUCTION 3'h4
-538
View File
@@ -1,538 +0,0 @@
`include "axi_defs.v"
`define DEBUG if (1)
module axi_dma_master
(
input aclk, // Global AXI clock
input areset, // Global AXI reset
//
// AXI Write address channel
//
output [0 : 0] m_axi_awid, // Write address ID. This signal is the identification tag for the write address signals
output reg [31 : 0] m_axi_awaddr, // Write address. The write address gives the address of the first transfer in a write burst
output reg [7 : 0] m_axi_awlen, // Burst length. The burst length gives the exact number of transfers in a burst.
output [2 : 0] m_axi_awsize, // Burst size. This signal indicates the size of each transfer in the burst.
output [1 : 0] m_axi_awburst, // Burst type. The burst type and the size information, determine how the address is calculated
output [0 : 0] m_axi_awlock, // Lock type. Provides additional information about the atomic characteristics of the transfer.
output [3 : 0] m_axi_awcache, // Memory type. This signal indicates how transactions are required to progress
output [2 : 0] m_axi_awprot, // Protection type. This signal indicates the privilege and security level of the transaction
output [3 : 0] m_axi_awqos, // Quality of Service, QoS. The QoS identifier sent for each write transaction
output [3 : 0] m_axi_awregion, // Region identifier. Permits a single physical interface on a slave to be re-used.
output [0 : 0] m_axi_awuser, // User signal. Optional User-defined signal in the write address channel.
output reg m_axi_awvalid, // Write address valid. This signal indicates that the channel is signaling valid write addr
input m_axi_awready, // Write address ready. This signal indicates that the slave is ready to accept an address
//
// AXI Write data channel.
//
output [63 : 0] m_axi_wdata, // Write data
output [7 : 0] m_axi_wstrb, // Write strobes. This signal indicates which byte lanes hold valid data.
output reg m_axi_wlast, // Write last. This signal indicates the last transfer in a write burst
output [0 : 0] m_axi_wuser, // User signal. Optional User-defined signal in the write data channel.
output m_axi_wvalid, // Write valid. This signal indicates that valid write data and strobes are available.
input m_axi_wready, // Write ready. This signal indicates that the slave can accept the write data.
//
// AXI Write response channel signals
//
input [0 : 0] m_axi_bid, // Response ID tag. This signal is the ID tag of the write response.
input [1 : 0] m_axi_bresp, // Write response. This signal indicates the status of the write transaction.
input [0 : 0] m_axi_buser, // User signal. Optional User-defined signal in the write response channel.
input m_axi_bvalid, // Write response valid. This signal indicates that the channel is signaling a valid response
output reg m_axi_bready, // Response ready. This signal indicates that the master can accept a write response
//
// AXI Read address channel
//
output [0 : 0] m_axi_arid, // Read address ID. This signal is the identification tag for the read address group of signals
output reg [31 : 0] m_axi_araddr, // Read address. The read address gives the address of the first transfer in a read burst
output reg [7 : 0] m_axi_arlen, // Burst length. This signal indicates the exact number of transfers in a burst.
output [2 : 0] m_axi_arsize, // Burst size. This signal indicates the size of each transfer in the burst.
output [1 : 0] m_axi_arburst, // Burst type. The burst type and the size information determine how the address for each transfer
output [0 : 0] m_axi_arlock, // Lock type. This signal provides additional information about the atomic characteristics
output [3 : 0] m_axi_arcache, // Memory type. This signal indicates how transactions are required to progress
output [2 : 0] m_axi_arprot, // Protection type. This signal indicates the privilege and security level of the transaction
output [3 : 0] m_axi_arqos, // Quality of Service, QoS. QoS identifier sent for each read transaction.
output [3 : 0] m_axi_arregion, // Region identifier. Permits a single physical interface on a slave to be re-used
output [0 : 0] m_axi_aruser, // User signal. Optional User-defined signal in the read address channel.
output reg m_axi_arvalid, // Read address valid. This signal indicates that the channel is signaling valid read addr
input m_axi_arready, // Read address ready. This signal indicates that the slave is ready to accept an address
//
// AXI Read data channel
//
input [0 : 0] m_axi_rid, // Read ID tag. This signal is the identification tag for the read data group of signals
input [63 : 0] m_axi_rdata, // Read data.
input [1 : 0] m_axi_rresp, // Read response. This signal indicates the status of the read transfer
input m_axi_rlast, // Read last. This signal indicates the last transfer in a read burst.
input [0 : 0] m_axi_ruser, // User signal. Optional User-defined signal in the read data channel.
input m_axi_rvalid, // Read valid. This signal indicates that the channel is signaling the required read data.
output m_axi_rready, // Read ready. This signal indicates that the master can accept the read data and response
//
// DMA interface for Write transaction
//
input [31:0] write_addr, // Byte address for start of write transaction (should be 64bit alligned)
input [7:0] write_count, // Count of 64bit words to write. (minus one)
input write_ctrl_valid,
output reg write_ctrl_ready,
input [63:0] write_data,
input write_data_valid,
output write_data_ready,
//
// DMA interface for Read
//
input [31:0] read_addr, // Byte address for start of read transaction (should be 64bit alligned)
input [7:0] read_count, // Count of 64bit words to read.
input read_ctrl_valid,
output reg read_ctrl_ready,
output [63:0] read_data,
output read_data_valid,
input read_data_ready,
//
// Debug Bus
//
output [31:0] debug
);
localparam AW_IDLE = 0;
localparam WAIT_AWREADY = 1;
localparam WAIT_BVALID = 2;
localparam AW_ERROR = 3;
reg [1:0] write_addr_state;
reg [7:0] write_data_count; // Count write transfers.
reg enable_data_write;
localparam DW_IDLE = 0;
localparam DW_RUN = 1;
localparam DW_LAST = 2;
reg [1:0] write_data_state;
localparam AR_IDLE = 0;
localparam WAIT_ARREADY = 1;
localparam WAIT_READ_DONE = 2;
localparam AR_ERROR = 3;
reg [1:0] read_addr_state;
localparam DR_IDLE = 0;
localparam DR_RUN = 1;
localparam DR_WAIT_ERROR = 2;
localparam DR_ERROR = 3;
reg [1:0] read_data_state;
reg [7:0] read_data_count;
reg enable_data_read;
///////////////////////////
// DEBUG
///////////////////////////
assign debug= {24'h0,write_addr_state[1:0],write_data_state[1:0],read_addr_state[1:0],read_data_state[1:0]};
//
//
//
/////////////////////////////////////////////////////////////////////////////////
//
// AXI Write address channel
//
/////////////////////////////////////////////////////////////////////////////////
assign m_axi_awid = 1'b0;
assign m_axi_awsize = 3'h3; // 8 bytes.
assign m_axi_awburst = `AXI4_BURST_INCR;
assign m_axi_awlock = `AXI4_LOCK_NORMAL;
assign m_axi_awcache = `AXI4_CACHE_ALLOCATE | `AXI4_CACHE_OTHER_ALLOCATE | `AXI4_CACHE_MODIFIABLE | `AXI4_CACHE_BUFFERABLE;
assign m_axi_awprot = `AXI4_PROT_NON_SECURE;
assign m_axi_awqos = 4'h0;
assign m_axi_awregion = 4'h0;
assign m_axi_awuser = 1'b0;
//
// AXI Write address state machine
//
always @(posedge aclk)
if (areset) begin
write_ctrl_ready <= 1'b0;
write_addr_state <= AW_IDLE;
m_axi_awaddr[31:0] <= 32'h0;
m_axi_awlen[7:0] <= 8'h0;
m_axi_awvalid <= 1'b0;
m_axi_bready <= 1'b0;
end else
case (write_addr_state)
//
// AW_IDLE
// We are ready to accept a new write transaction.
//
AW_IDLE: begin
// Premptively accept new write transaction since we are idle.
write_ctrl_ready <= 1'b1;
// No need to be waiting for a response while idle.
m_axi_bready <= 1'b0;
// If we are offered a new transaction then.....
if (write_ctrl_valid) begin
// Drive all the relevent AXI4 write address channel signals next cycle.
m_axi_awaddr[31:0] <= write_addr[31:0];
m_axi_awlen[7:0] <= {write_count};
m_axi_awvalid <= 1'b1;
// If the AXI4 write channel is pre-emptively accepting the transaction...
if (m_axi_awready == 1'b1) begin
// ...go straight to looking for a transaction response...
`DEBUG $display("WRITE TRANSACTION: ADDR: %x LEN: %x @ time %d",write_addr[31:0],write_count,$time);
write_addr_state <= WAIT_BVALID;
m_axi_bready <= 1'b1;
end else begin
// ...otherwise wait to get the transaction accepted.
write_addr_state <= WAIT_AWREADY;
end
end
end
//
// WAIT_AWREADY
// Waiting for AXI4 slave to accept new write transaction.
//
WAIT_AWREADY: begin
write_ctrl_ready <= 1'b0;
// If the AXI4 write channel is accepting the transaction...
if (m_axi_awready == 1'b1) begin
// ...go to looking for a transaction response...
write_addr_state <= WAIT_BVALID;
m_axi_bready <= 1'b1;
`DEBUG $display("WRITE TRANSACTION: ADDR: %x LEN: %x @ time %d",m_axi_awaddr[31:0],m_axi_awlen[7:0],$time);
end else begin
// ...otherwise wait to get the trasaction accepted.
write_addr_state <= WAIT_AWREADY;
end
end // case: WAIT_AWREADY
//
// WAIT_BVALID
// Write transaction has been accepted, now waiting for a response to signal it's sucsesful.
// Ignoring ID tag for the moment
//
WAIT_BVALID: begin
write_ctrl_ready <= 1'b0;
m_axi_awvalid <= 1'b0;
// Wait for response channel to signal how write transaction went down....
if (m_axi_bvalid == 1'b1) begin
if ((m_axi_bresp == `AXI4_RESP_OKAY) || (m_axi_bresp == `AXI4_RESP_EXOKAY)) begin
// ....it went well, we are ready to start something new.
write_addr_state <= AW_IDLE;
m_axi_bready <= 1'b0;
write_ctrl_ready <= 1'b1; // Ready to run again as soon as we hit idle.
end else if ((m_axi_bresp == `AXI4_RESP_SLVERR) || (m_axi_bresp == `AXI4_RESP_DECERR)) begin
// ....things got ugly, retreat to an error stat and wait for intervention.
write_addr_state <= AW_ERROR;
m_axi_bready <= 1'b0;
end
end else begin
write_addr_state <= WAIT_BVALID;
m_axi_bready <= 1'b1;
end
end // case: WAIT_BVALID
//
// AW_ERROR
// Something bad happened, going to need external intervention to restore a safe state.
//
AW_ERROR: begin
write_ctrl_ready <= 1'b0;
write_addr_state <= AW_ERROR;
m_axi_awaddr[31:0] <= 32'h0;
m_axi_awlen[7:0] <= 8'h0;
m_axi_awvalid <= 1'b0;
m_axi_bready <= 1'b0;
end
endcase // case(write_addr_state)
/////////////////////////////////////////////////////////////////////////////////
//
// AXI Write data channel
//
/////////////////////////////////////////////////////////////////////////////////
assign m_axi_wstrb = 8'hff;
assign m_axi_wuser = 1'b0;
//
// AXI Write data state machine
//
always @(posedge aclk)
if (areset) begin
write_data_state <= AW_IDLE;
write_data_count <= 1;
enable_data_write <= 1'b0;
m_axi_wlast <= 1'b0;
end else
case (write_data_state)
//
// DW_IDLE
// Sit in this state until presented with the control details of a new write transaction.
//
DW_IDLE: begin
write_data_count <= 1;
m_axi_wlast <= 1'b0;
if (write_ctrl_valid && write_ctrl_ready) begin
enable_data_write <= 1'b1;
if (write_count[7:0] == 8'h0) begin
// Single transfer transaction
write_data_state <= DW_LAST;
m_axi_wlast <= 1'b1;
end else begin
write_data_state <= DW_RUN;
end
end else begin
write_data_state <= DW_IDLE;
end
end
//
// DW_RUN
//
DW_RUN : begin
enable_data_write <= 1'b1;
m_axi_wlast <= 1'b0;
if (write_data_valid && m_axi_wready) begin
// Single write transfer
write_data_count <= write_data_count + 1;
if (write_data_count == m_axi_awlen[7:0]) begin
write_data_state <= DW_LAST;
m_axi_wlast <= 1'b1;
end else begin
write_data_state <= DW_RUN;
end
end else begin
write_data_state <= DW_RUN;
end
end
//
// DW_LAST
//
DW_LAST: begin
if (write_data_valid && m_axi_wready) begin
enable_data_write <= 1'b0;
write_data_state <= DW_IDLE;
m_axi_wlast <= 1'b0;
end else begin
enable_data_write <= 1'b1;
write_data_state <= DW_LAST;
m_axi_wlast <= 1'b1;
end
end // case: DW_LAST
//
default:
write_data_state <= DW_IDLE;
endcase // case(write_data_state)
assign m_axi_wdata = write_data;
assign m_axi_wvalid = enable_data_write && write_data_valid;
assign write_data_ready = enable_data_write && m_axi_wready;
/////////////////////////////////////////////////////////////////////////////////
//
// AXI Read address channel
//
/////////////////////////////////////////////////////////////////////////////////
assign m_axi_arid = 1'b0;
assign m_axi_arsize = 3'h3; // 8 bytes
assign m_axi_arburst = `AXI4_BURST_INCR;
assign m_axi_arlock = `AXI4_LOCK_NORMAL;
assign m_axi_arcache = `AXI4_CACHE_ALLOCATE | `AXI4_CACHE_OTHER_ALLOCATE | `AXI4_CACHE_MODIFIABLE | `AXI4_CACHE_BUFFERABLE;
assign m_axi_arprot = `AXI4_PROT_NON_SECURE;
assign m_axi_arqos = 4'h0;
assign m_axi_arregion = 4'h0;
assign m_axi_aruser = 1'b0;
//
// AXI Read address state machine
//
always @(posedge aclk)
if (areset) begin
read_ctrl_ready <= 1'b0;
read_addr_state <= AR_IDLE;
m_axi_araddr[31:0] <= 32'h0;
m_axi_arlen[7:0] <= 8'h0;
m_axi_arvalid <= 1'b0;
end else
case (read_addr_state)
//
// AR_IDLE
// We are ready to accept a new read transaction.
//
AR_IDLE: begin
// Premptively accept new read transaction since we are idle.
read_ctrl_ready <= 1'b1;
// If we are offered a new transaction then.....
if (read_ctrl_valid) begin
// Drive all the relevent AXI4 read address channel signals next cycle.
m_axi_araddr[31:0] <= read_addr[31:0];
m_axi_arlen[7:0] <= {read_count};
m_axi_arvalid <= 1'b1;
// If the AXI4 read channel is pre-emptively accepting the transaction...
if (m_axi_arready == 1'b1) begin
// ...go straight to looking for the transaction to complete
`DEBUG $display("READ TRANSACTION: ADDR: %x LEN: %x @ time %d",read_addr[31:0],read_count,$time);
read_addr_state <= WAIT_READ_DONE;
end else begin
// ...otherwise wait to get the transaction accepted.
read_addr_state <= WAIT_ARREADY;
end
end
end
//
// WAIT_ARREADY
// Waiting for AXI4 slave to accept new read transaction.
//
WAIT_ARREADY: begin
read_ctrl_ready <= 1'b0;
// If the AXI4 read channel is accepting the transaction...
if (m_axi_arready == 1'b1) begin
// ...go to looking for the transaction to complete...
read_addr_state <= WAIT_READ_DONE;
`DEBUG $display("READ TRANSACTION: ADDR: %x LEN: %x @ time %d",m_axi_araddr[31:0],m_axi_arlen[7:0],$time);
end else begin
// ...otherwise wait to get the trasaction accepted.
read_addr_state <= WAIT_ARREADY;
end
end // case: WAIT_ARREADY
//
// WAIT_READ_DONE
// Read transaction has been accepted, now waiting for the data transfer to complete
// Ignoring ID tag for the moment
//
WAIT_READ_DONE: begin
read_ctrl_ready <= 1'b0;
m_axi_arvalid <= 1'b0;
// Wait for read transaction to complete
if (read_data_state == DR_IDLE) begin
// ....it went well, we are ready to start something new.
read_addr_state <= AR_IDLE;
read_ctrl_ready <= 1'b1; // Ready to run again as soon as we hit idle.
end else if (read_data_state == DR_ERROR) begin
// ....things got ugly, retreat to an error stat and wait for intervention.
read_addr_state <= AR_ERROR;
end else begin
read_addr_state <= WAIT_READ_DONE;
end
end // case: WAIT_BVALID
//
// AR_ERROR
// Something bad happened, going to need external intervention to restore a safe state.
//
AR_ERROR: begin
read_ctrl_ready <= 1'b0;
read_addr_state <= AR_ERROR;
m_axi_araddr[31:0] <= 32'h0;
m_axi_arlen[7:0] <= 8'h0;
m_axi_arvalid <= 1'b0;
end
endcase // case(read_addr_state)
/////////////////////////////////////////////////////////////////////////////////
//
// AXI Read data channel
//
/////////////////////////////////////////////////////////////////////////////////
//
// AXI Read data state machine
//
always @(posedge aclk)
if (areset) begin
read_data_state <= AR_IDLE;
read_data_count <= 0;
enable_data_read <= 1'b0;
end else
case (read_data_state)
//
// DR_IDLE
// Sit in this state until presented with the control details of a new read transaction.
//
DR_IDLE: begin
read_data_count <= 0;
if (read_ctrl_valid && read_ctrl_ready) begin
enable_data_read <= 1'b1;
read_data_state <= DR_RUN;
end else begin
read_data_state <= DR_IDLE;
end
end
//
// DR_RUN
// Sit here counting read transfers. If any have error's shift to error state.
//
DR_RUN : begin
enable_data_read <= 1'b1;
if (read_data_ready && m_axi_rvalid) begin
// Single read transfer
read_data_count <= read_data_count + 1;
if ((m_axi_rresp == `AXI4_RESP_SLVERR) || (m_axi_rresp == `AXI4_RESP_DECERR)) begin
if (m_axi_rlast) begin
read_data_state <= DR_ERROR;
end else begin
read_data_state <= DR_WAIT_ERROR;
end
end else if (m_axi_rlast) begin // Implicitly good response signalled this transfer.
if (read_data_count == m_axi_arlen[7:0]) begin
read_data_state <= DR_IDLE;
end else begin
read_data_state <= DR_ERROR;
end
end else begin
read_data_state <= DR_RUN;
end
end else begin
read_data_state <= DR_RUN;
end
end
//
// DR_WAIT_ERROR
// Something bad happened, wait for last signalled in this burst
//
DR_WAIT_ERROR: begin
if (read_data_ready && m_axi_rvalid && m_axi_rlast) begin
enable_data_read <= 1'b0;
read_data_state <= DR_ERROR;
end else begin
enable_data_read <= 1'b1;
read_data_state <= DR_WAIT_ERROR;
end
end // case: DR_WAIT_ERROR
//
// DR_ERROR
// Something bad happened, going to need external intervention to restore a safe state.
//
DR_ERROR: begin
enable_data_read <= 1'b0;
read_data_state <= DR_ERROR;
end // case: DR_ERROR
endcase // case(read_data_state)
assign read_data = m_axi_rdata;
assign m_axi_rready = enable_data_read && read_data_ready;
assign read_data_valid = enable_data_read && m_axi_rvalid;
endmodule // axi_dma_master
-165
View File
@@ -1,165 +0,0 @@
module axi_dma_master_tb;
wire aclk; // Global AXI clock
wire aresetn; // Global AXI reset, active low.
//
// AXI Write address channel
//
wire [0 : 0] m_axi_awid; // Write address ID. This signal is the identification tag for the write address signals
wire [31 : 0] m_axi_awaddr; // Write address. The write address gives the address of the first transfer in a write burst
wire [7 : 0] m_axi_awlen; // Burst length. The burst length gives the exact number of transfers in a burst.
wire [2 : 0] m_axi_awsize; // Burst size. This signal indicates the size of each transfer in the burst.
wire [1 : 0] m_axi_awburst; // Burst type. The burst type and the size information, determine how the address is calculated
wire [0 : 0] m_axi_awlock; // Lock type. Provides additional information about the atomic characteristics of the transfer.
wire [3 : 0] m_axi_awcache; // Memory type. This signal indicates how transactions are required to progress
wire [2 : 0] m_axi_awprot; // Protection type. This signal indicates the privilege and security level of the transaction
wire [3 : 0] m_axi_awqos; // Quality of Service, QoS. The QoS identifier sent for each write transaction
wire [3 : 0] m_axi_awregion; // Region identifier. Permits a single physical interface on a slave to be re-used.
wire [0 : 0] m_axi_awuser; // User signal. Optional User-defined signal in the write address channel.
wire m_axi_awvalid; // Write address valid. This signal indicates that the channel is signaling valid write addr
wire m_axi_awready; // Write address ready. This signal indicates that the slave is ready to accept an address
//
// AXI Write data channel.
//
wire [63 : 0] m_axi_wdata; // Write data
wire [7 : 0] m_axi_wstrb; // Write strobes. This signal indicates which byte lanes hold valid data.
wire m_axi_wlast; // Write last. This signal indicates the last transfer in a write burst
wire [0 : 0] m_axi_wuser; // User signal. Optional User-defined signal in the write data channel.
wire m_axi_wvalid; // Write valid. This signal indicates that valid write data and strobes are available.
wire m_axi_wready; // Write ready. This signal indicates that the slave can accept the write data.
//
// AXI Write response channel signals
//
wire [0 : 0] m_axi_bid; // Response ID tag. This signal is the ID tag of the write response.
wire [1 : 0] m_axi_bresp; // Write response. This signal indicates the status of the write transaction.
wire [0 : 0] m_axi_buser; // User signal. Optional User-defined signal in the write response channel.
wire m_axi_bvalid; // Write response valid. This signal indicates that the channel is signaling a valid response
wire m_axi_bready; // Response ready. This signal indicates that the master can accept a write response
//
// AXI Read address channel
//
wire [0 : 0] m_axi_arid; // Read address ID. This signal is the identification tag for the read address group of signals
wire [31 : 0] m_axi_araddr; // Read address. The read address gives the address of the first transfer in a read burst
wire [7 : 0] m_axi_arlen; // Burst length. This signal indicates the exact number of transfers in a burst.
wire [2 : 0] m_axi_arsize; // Burst size. This signal indicates the size of each transfer in the burst.
wire [1 : 0] m_axi_arburst; // Burst type. The burst type and the size information determine how the address for each transfer
wire [0 : 0] m_axi_arlock; // Lock type. This signal provides additional information about the atomic characteristics
wire [3 : 0] m_axi_arcache; // Memory type. This signal indicates how transactions are required to progress
wire [2 : 0] m_axi_arprot; // Protection type. This signal indicates the privilege and security level of the transaction
wire [3 : 0] m_axi_arqos; // Quality of Service, QoS. QoS identifier sent for each read transaction.
wire [3 : 0] m_axi_arregion; // Region identifier. Permits a single physical interface on a slave to be re-used
wire [0 : 0] m_axi_aruser; // User signal. Optional User-defined signal in the read address channel.
wire m_axi_arvalid; // Read address valid. This signal indicates that the channel is signaling valid read addr
wire m_axi_arready; // Read address ready. This signal indicates that the slave is ready to accept an address
//
// AXI Read data channel
//
wire [0 : 0] m_axi_rid; // Read ID tag. This signal is the identification tag for the read data group of signals
wire [63 : 0] m_axi_rdata; // Read data.
wire [1 : 0] m_axi_rresp; // Read response. This signal indicates the status of the read transfer
wire m_axi_rlast; // Read last. This signal indicates the last transfer in a read burst.
wire [0 : 0] m_axi_ruser; // User signal. Optional User-defined signal in the read data channel.
wire m_axi_rvalid; // Read valid. This signal indicates that the channel is signaling the required read data.
wire m_axi_rready; // Read ready. This signal indicates that the master can accept the read data and response
//
// DMA interface for Write transaction
//
wire [31:0] write_addr; // Byte address for start of write transaction (should be 64bit alligned)
wire [3:0] write_count; // Count of 64 words to write.
wire write_ctrl_valid;
wire write_ctrl_ready;
wire [63:0] write_data;
wire write_data_valid;
wire write_data_ready;
//
// DMA interface for Read
//
wire [31:0] read_addr; // Byte address for start of read transaction (should be 64bit alligned)
wire [3:0] read_count; // Count of 64 words to read.
wire read_ctrl_valid;
wire read_ctrl_ready;
wire [63:0] read_data;
wire read_data_valid;
wire read_data_ready;
axi_dma_master axi_dma_master_i1
(
.aclk(s_aclk), // input s_aclk
.aresetn(s_aresetn), // input s_aresetn
//
.s_axi_awid(s_axi_awid), // input [0 : 0] s_axi_awid
.s_axi_awaddr(s_axi_awaddr), // input [31 : 0] s_axi_awaddr
.s_axi_awlen(s_axi_awlen), // input [7 : 0] s_axi_awlen
.s_axi_awsize(s_axi_awsize), // input [2 : 0] s_axi_awsize
.s_axi_awburst(s_axi_awburst), // input [1 : 0] s_axi_awburst
.s_axi_awvalid(s_axi_awvalid), // input s_axi_awvalid
.s_axi_awready(s_axi_awready), // output s_axi_awready
//
.s_axi_wdata(s_axi_wdata), // input [63 : 0] s_axi_wdata
.s_axi_wstrb(s_axi_wstrb), // input [7 : 0] s_axi_wstrb
.s_axi_wlast(s_axi_wlast), // input s_axi_wlast
.s_axi_wvalid(s_axi_wvalid), // input s_axi_wvalid
.s_axi_wready(s_axi_wready), // output s_axi_wready
//
.s_axi_bid(s_axi_bid), // output [0 : 0] s_axi_bid
.s_axi_bresp(s_axi_bresp), // output [1 : 0] s_axi_bresp
.s_axi_bvalid(s_axi_bvalid), // output s_axi_bvalid
.s_axi_bready(s_axi_bready), // input s_axi_bready
//
.s_axi_arid(s_axi_arid), // input [0 : 0] s_axi_arid
.s_axi_araddr(s_axi_araddr), // input [31 : 0] s_axi_araddr
.s_axi_arlen(s_axi_arlen), // input [7 : 0] s_axi_arlen
.s_axi_arsize(s_axi_arsize), // input [2 : 0] s_axi_arsize
.s_axi_arburst(s_axi_arburst), // input [1 : 0] s_axi_arburst
.s_axi_arvalid(s_axi_arvalid), // input s_axi_arvalid
.s_axi_arready(s_axi_arready), // output s_axi_arready
//
.s_axi_rid(s_axi_rid), // output [0 : 0] s_axi_rid
.s_axi_rdata(s_axi_rdata), // output [63 : 0] s_axi_rdata
.s_axi_rresp(s_axi_rresp), // output [1 : 0] s_axi_rresp
.s_axi_rlast(s_axi_rlast), // output s_axi_rlast
.s_axi_rvalid(s_axi_rvalid), // output s_axi_rvalid
.s_axi_rready(s_axi_rready) // input s_axi_rready
);
axi4_bram_1kx64 axi4_bram_1kx64_i1
(
.s_aclk(s_aclk), // input s_aclk
.s_aresetn(s_aresetn), // input s_aresetn
.s_axi_awid(s_axi_awid), // input [0 : 0] s_axi_awid
.s_axi_awaddr(s_axi_awaddr), // input [31 : 0] s_axi_awaddr
.s_axi_awlen(s_axi_awlen), // input [7 : 0] s_axi_awlen
.s_axi_awsize(s_axi_awsize), // input [2 : 0] s_axi_awsize
.s_axi_awburst(s_axi_awburst), // input [1 : 0] s_axi_awburst
.s_axi_awvalid(s_axi_awvalid), // input s_axi_awvalid
.s_axi_awready(s_axi_awready), // output s_axi_awready
.s_axi_wdata(s_axi_wdata), // input [63 : 0] s_axi_wdata
.s_axi_wstrb(s_axi_wstrb), // input [7 : 0] s_axi_wstrb
.s_axi_wlast(s_axi_wlast), // input s_axi_wlast
.s_axi_wvalid(s_axi_wvalid), // input s_axi_wvalid
.s_axi_wready(s_axi_wready), // output s_axi_wready
.s_axi_bid(s_axi_bid), // output [0 : 0] s_axi_bid
.s_axi_bresp(s_axi_bresp), // output [1 : 0] s_axi_bresp
.s_axi_bvalid(s_axi_bvalid), // output s_axi_bvalid
.s_axi_bready(s_axi_bready), // input s_axi_bready
.s_axi_arid(s_axi_arid), // input [0 : 0] s_axi_arid
.s_axi_araddr(s_axi_araddr), // input [31 : 0] s_axi_araddr
.s_axi_arlen(s_axi_arlen), // input [7 : 0] s_axi_arlen
.s_axi_arsize(s_axi_arsize), // input [2 : 0] s_axi_arsize
.s_axi_arburst(s_axi_arburst), // input [1 : 0] s_axi_arburst
.s_axi_arvalid(s_axi_arvalid), // input s_axi_arvalid
.s_axi_arready(s_axi_arready), // output s_axi_arready
.s_axi_rid(s_axi_rid), // output [0 : 0] s_axi_rid
.s_axi_rdata(s_axi_rdata), // output [63 : 0] s_axi_rdata
.s_axi_rresp(s_axi_rresp), // output [1 : 0] s_axi_rresp
.s_axi_rlast(s_axi_rlast), // output s_axi_rlast
.s_axi_rvalid(s_axi_rvalid), // output s_axi_rvalid
.s_axi_rready(s_axi_rready) // input s_axi_rready
);
endmodule // axi_dma_master_tb
-816
View File
@@ -1,816 +0,0 @@
//
// There are various obligations put on this code not present in regular BRAM based FIFO's
//
// 1) Bursts are way more efficient, use local small FIFO's to interact with DRAM
// 2) Never cross a 4KByte address boundry within a single transaction, this is an AXI4 rule.
// 3) 2^SIZE must be greater than 4KB so that the 4KByte page protection also deals with FIFO wrap corner case.
//
module axi_dram_fifo
// NOTE: SIZE is log2 of size of FIFO buffer in bytes. i.e 13 for 8KBytes which is 1kx64
#(parameter BASE=0, SIZE=16, TIMEOUT=64)
(
input bus_clk,
input bus_reset,
input clear,
input dram_clk,
input dram_reset,
//
// AXI Write address channel
//
output [0 : 0] m_axi_awid, // Write address ID. This signal is the identification tag for the write address signals
output [31 : 0] m_axi_awaddr, // Write address. The write address gives the address of the first transfer in a write burst
output [7 : 0] m_axi_awlen, // Burst length. The burst length gives the exact number of transfers in a burst.
output [2 : 0] m_axi_awsize, // Burst size. This signal indicates the size of each transfer in the burst.
output [1 : 0] m_axi_awburst, // Burst type. The burst type and the size information, determine how the address is calculated
output [0 : 0] m_axi_awlock, // Lock type. Provides additional information about the atomic characteristics of the transfer.
output [3 : 0] m_axi_awcache, // Memory type. This signal indicates how transactions are required to progress
output [2 : 0] m_axi_awprot, // Protection type. This signal indicates the privilege and security level of the transaction
output [3 : 0] m_axi_awqos, // Quality of Service, QoS. The QoS identifier sent for each write transaction
output [3 : 0] m_axi_awregion, // Region identifier. Permits a single physical interface on a slave to be re-used.
output [0 : 0] m_axi_awuser, // User signal. Optional User-defined signal in the write address channel.
output m_axi_awvalid, // Write address valid. This signal indicates that the channel is signaling valid write addr
input m_axi_awready, // Write address ready. This signal indicates that the slave is ready to accept an address
//
// AXI Write data channel.
//
output [63 : 0] m_axi_wdata, // Write data
output [7 : 0] m_axi_wstrb, // Write strobes. This signal indicates which byte lanes hold valid data.
output m_axi_wlast, // Write last. This signal indicates the last transfer in a write burst
output [0 : 0] m_axi_wuser, // User signal. Optional User-defined signal in the write data channel.
output m_axi_wvalid, // Write valid. This signal indicates that valid write data and strobes are available.
input m_axi_wready, // Write ready. This signal indicates that the slave can accept the write data.
//
// AXI Write response channel signals
//
input [0 : 0] m_axi_bid, // Response ID tag. This signal is the ID tag of the write response.
input [1 : 0] m_axi_bresp, // Write response. This signal indicates the status of the write transaction.
input [0 : 0] m_axi_buser, // User signal. Optional User-defined signal in the write response channel.
input m_axi_bvalid, // Write response valid. This signal indicates that the channel is signaling a valid response
output m_axi_bready, // Response ready. This signal indicates that the master can accept a write response
//
// AXI Read address channel
//
output [0 : 0] m_axi_arid, // Read address ID. This signal is the identification tag for the read address group of signals
output [31 : 0] m_axi_araddr, // Read address. The read address gives the address of the first transfer in a read burst
output [7 : 0] m_axi_arlen, // Burst length. This signal indicates the exact number of transfers in a burst.
output [2 : 0] m_axi_arsize, // Burst size. This signal indicates the size of each transfer in the burst.
output [1 : 0] m_axi_arburst, // Burst type. The burst type and the size information determine how the address for each transfer
output [0 : 0] m_axi_arlock, // Lock type. This signal provides additional information about the atomic characteristics
output [3 : 0] m_axi_arcache, // Memory type. This signal indicates how transactions are required to progress
output [2 : 0] m_axi_arprot, // Protection type. This signal indicates the privilege and security level of the transaction
output [3 : 0] m_axi_arqos, // Quality of Service, QoS. QoS identifier sent for each read transaction.
output [3 : 0] m_axi_arregion, // Region identifier. Permits a single physical interface on a slave to be re-used
output [0 : 0] m_axi_aruser, // User signal. Optional User-defined signal in the read address channel.
output m_axi_arvalid, // Read address valid. This signal indicates that the channel is signaling valid read addr
input m_axi_arready, // Read address ready. This signal indicates that the slave is ready to accept an address
//
// AXI Read data channel
//
input [0 : 0] m_axi_rid, // Read ID tag. This signal is the identification tag for the read data group of signals
input [63 : 0] m_axi_rdata, // Read data.
input [1 : 0] m_axi_rresp, // Read response. This signal indicates the status of the read transfer
input m_axi_rlast, // Read last. This signal indicates the last transfer in a read burst.
input [0 : 0] m_axi_ruser, // User signal. Optional User-defined signal in the read data channel.
input m_axi_rvalid, // Read valid. This signal indicates that the channel is signaling the required read data.
output m_axi_rready, // Read ready. This signal indicates that the master can accept the read data and response
//
// CHDR friendly AXI stream input
//
input [63:0] i_tdata,
input i_tlast,
input i_tvalid,
output i_tready,
//
// CHDR friendly AXI Stream output
//
output [63:0] o_tdata,
output o_tlast,
output o_tvalid,
input o_tready,
//
//
//
input [15:0] supress_threshold,
input supress_enable,
//
// Debug Bus
//
output [197:0] debug
);
//
// We are only solving for width 64bits here, since it's our standard CHDR quanta
//
localparam WIDTH=64;
//
// Input side declarations
//
localparam INPUT_IDLE = 0;
localparam INPUT1 = 1;
localparam INPUT2 = 2;
localparam INPUT3 = 3;
localparam INPUT4 = 4;
localparam INPUT5 = 5;
localparam INPUT6 = 6;
reg [2:0] input_state;
reg input_timeout_triggered;
reg input_timeout_reset;
reg [8:0] input_timeout_count;
reg [31:0] write_addr;
reg write_ctrl_valid;
wire write_ctrl_ready;
reg [7:0] write_count;
reg update_write;
wire [63:0] write_data;
wire write_data_valid;
wire write_data_ready;
//
// Output side declarations
//
localparam OUTPUT_IDLE = 0;
localparam OUTPUT1 = 1;
localparam OUTPUT2 = 2;
localparam OUTPUT3 = 3;
localparam OUTPUT4 = 4;
localparam OUTPUT5 = 5;
localparam OUTPUT6 = 6;
reg [2:0] output_state;
reg output_timeout_triggered;
reg output_timeout_reset;
reg [8:0] output_timeout_count;
reg [31:0] read_addr;
reg read_ctrl_valid;
wire read_ctrl_ready;
reg [7:0] read_count;
reg update_read;
wire [63:0] read_data;
wire read_data_valid;
wire read_data_ready;
// Track main FIFO active size.
reg [SIZE-3:0] space, occupied;
wire [11:0] input_page_boundry, output_page_boundry;
//
// Buffer input in FIFO's. Embeded tlast signal using ESCape code.
//
wire [WIDTH-1:0] i_tdata_i0;
wire i_tvalid_i0, i_tready_i0, i_tlast_i0;
wire [WIDTH-1:0] i_tdata_i1;
wire i_tvalid_i1, i_tready_i1;
wire [WIDTH-1:0] i_tdata_i2;
wire i_tvalid_i2, i_tready_i2;
wire [WIDTH-1:0] i_tdata_input;
wire i_tvalid_input, i_tready_input;
wire [15:0] space_input, occupied_input;
reg [15:0] space_input_reg;
reg supress_reads;
///////////////////////////
// DEBUG
///////////////////////////
wire [31:0] debug_axi_dma_master;
//assign debug = {18'h0, input_state[2:0], output_state[2:0], debug_axi_dma_master[7:0]};
///////////////////////////////////////////////////////////////////////////////
wire write_in, read_in, empty_in, full_in;
assign i_tready = ~full_in;
assign write_in = i_tvalid & i_tready;
assign i_tvalid_i0 = ~empty_in;
assign read_in = i_tvalid_i0 & i_tready_i0;
wire [6:0] discard_i0;
fifo_short_2clk fifo_short_2clk_i0
(.rst(bus_reset),
.wr_clk(bus_clk),
.din({7'h0,i_tlast,i_tdata}), // input [71 : 0] din
.wr_en(write_in), // input wr_en
.full(full_in), // output full
.wr_data_count(), // output [9 : 0] wr_data_count
.rd_clk(dram_clk), // input rd_clk
.dout({discard_i0,i_tlast_i0,i_tdata_i0}), // output [71 : 0] dout
.rd_en(read_in), // input rd_en
.empty(empty_in), // output empty
.rd_data_count() // output [9 : 0] rd_data_count
);
axi_embed_tlast axi_embed_tlast_i
(
.clk(dram_clk),
.reset(dram_reset),
.clear(clear),
//
.i_tdata(i_tdata_i0),
.i_tlast(i_tlast_i0),
.i_tvalid(i_tvalid_i0),
.i_tready(i_tready_i0),
//
.o_tdata(i_tdata_i1),
.o_tvalid(i_tvalid_i1),
.o_tready(i_tready_i1)
);
axi_fast_fifo #(.WIDTH(WIDTH)) fast_fifo_i0
(
.clk(dram_clk),
.reset(dram_reset),
.clear(clear),
//
.i_tdata(i_tdata_i1),
.i_tvalid(i_tvalid_i1),
.i_tready(i_tready_i1),
//
.o_tdata(i_tdata_i2),
.o_tvalid(i_tvalid_i2),
.o_tready(i_tready_i2)
);
axi_fifo #(.WIDTH(WIDTH),.SIZE(12)) fifo_i1
(
.clk(dram_clk),
.reset(dram_reset),
.clear(clear),
//
.i_tdata(i_tdata_i2),
.i_tvalid(i_tvalid_i2),
.i_tready(i_tready_i2),
//
.o_tdata(i_tdata_input),
.o_tvalid(i_tvalid_input),
.o_tready(i_tready_input),
//
.space(space_input),
.occupied(occupied_input)
);
//
// Monitor occupied_input to deduce when DRAM FIFO is running short of bandwidth and there is a danger of backpressure
// passing upstream of the DRAM FIFO.
// In this situation supress read requests to the DRAM FIFO so that more bandwidth is available to writes.
//
always @(posedge dram_clk)
begin
space_input_reg <= space_input;
if ((space_input_reg < supress_threshold[15:0]) && supress_enable)
supress_reads <= 1'b1;
else
supress_reads <= 1'b0;
end
//
// Buffer output in 32entry FIFO's. Extract embeded tlast signal.
//
wire [WIDTH-1:0] o_tdata_output;
wire o_tvalid_output, o_tready_output;
wire [15:0] space_output, occupied_output;
wire [WIDTH-1:0] o_tdata_i0;
wire o_tvalid_i0, o_tready_i0;
wire [WIDTH-1:0] o_tdata_i1;
wire o_tvalid_i1, o_tready_i1, o_tlast_i1;
wire [WIDTH-1:0] o_tdata_i2;
wire o_tvalid_i2, o_tready_i2, o_tlast_i2;
wire [WIDTH-1:0] o_tdata_i3;
wire o_tvalid_i3, o_tready_i3, o_tlast_i3;
wire checksum_error;
axi_fifo #(.WIDTH(WIDTH),.SIZE(9)) fifo_i2
(
.clk(dram_clk),
.reset(dram_reset),
.clear(clear),
//
.i_tdata(o_tdata_output),
.i_tvalid(o_tvalid_output),
.i_tready(o_tready_output),
//
.o_tdata(o_tdata_i0),
.o_tvalid(o_tvalid_i0),
.o_tready(o_tready_i0),
//
.space(space_output),
.occupied(occupied_output)
);
// Place FLops straight after SRAM read access for timing.
axi_fast_fifo #(.WIDTH(WIDTH)) fast_fifo_i1
(
.clk(dram_clk),
.reset(dram_reset),
.clear(clear),
//
.i_tdata(o_tdata_i0),
.i_tvalid(o_tvalid_i0),
.i_tready(o_tready_i0),
//
.o_tdata(o_tdata_i1),
.o_tvalid(o_tvalid_i1),
.o_tready(o_tready_i1 && ~supress_reads)
);
// More pipeline flops to meet timing
axi_fast_fifo #(.WIDTH(WIDTH)) fast_fifo_i2
(
.clk(dram_clk),
.reset(dram_reset),
.clear(clear),
//
.i_tdata(o_tdata_i1),
.i_tvalid(o_tvalid_i1 && ~supress_reads),
.i_tready(o_tready_i1),
//
.o_tdata(o_tdata_i2),
.o_tvalid(o_tvalid_i2),
.o_tready(o_tready_i2)
);
axi_fast_extract_tlast axi_fast_extract_tlast_i0
(
.clk(dram_clk),
.reset(dram_reset),
.clear(clear),
//
.i_tdata(o_tdata_i2),
.i_tvalid(o_tvalid_i2),
.i_tready(o_tready_i2),
//
.o_tdata(o_tdata_i3),
.o_tlast(o_tlast_i3),
.o_tvalid(o_tvalid_i3),
.o_tready(o_tready_i3)
//
// .checksum_error_reg(checksum_error)
);
wire write_out, read_out, empty_out, full_out;
assign o_tready_i3 = ~full_out;
assign write_out = o_tvalid_i3 & o_tready_i3;
assign o_tvalid = ~empty_out;
assign read_out = o_tvalid & o_tready;
wire [6:0] discard_i1;
fifo_short_2clk fifo_short_2clk_i1
(
.rst(bus_reset),
.wr_clk(dram_clk),
.din({7'h0,o_tlast_i3,o_tdata_i3}), // input [71 : 0] din
.wr_en(write_out), // input wr_en
.full(full_out), // output full
.wr_data_count(), // output [9 : 0] wr_data_count
.rd_clk(bus_clk), // input rd_clk
.dout({discard_i1,o_tlast,o_tdata}), // output [71 : 0] dout
.rd_en(read_out), // input rd_en
.empty(empty_out), // output empty
.rd_data_count() // output [9 : 0] rd_data_count
);
//
// Simple input timeout counter for now.
// Timeout count only increments when there is some data waiting to be written.
//
always @(posedge dram_clk)
if (dram_reset | clear) begin
input_timeout_count <= 0;
input_timeout_triggered <= 1'b0;
end else if (input_timeout_reset) begin
input_timeout_count <= 0;
input_timeout_triggered <= 1'b0;
end else if (input_timeout_count == TIMEOUT) begin
input_timeout_triggered <= 1'b1;
end else if (input_state == INPUT_IDLE) begin
input_timeout_count <= input_timeout_count + (occupied_input != 0);
end
//
// Wait for 16 entries in input FIFO to trigger DRAM write burst.
// Timeout can also trigger burst so fragments of data are not left to rot in the input FIFO.
// Also if enough data is present in the input FIFO to complete a burst upto the edge
// of a 4KByte page then immediately start the burst.
//
always @(posedge dram_clk)
if (dram_reset | clear) begin
input_state <= INPUT_IDLE;
write_addr[31:SIZE] <= BASE >> SIZE;
write_addr[SIZE-1:0] <= 0;
input_timeout_reset <= 1'b0;
write_ctrl_valid <= 1'b0;
write_count <= 8'd0;
update_write <= 1'b0;
end else
case (input_state)
//
// INPUT_IDLE.
// To start an input transfer to DRAM need:
// 1) Space in the DRAM FIFO
// and either
// 2) 256 entrys in the input FIFO
// or
// 3) Timeout waiting for more data.
//
INPUT_IDLE: begin
write_ctrl_valid <= 1'b0;
update_write <= 1'b0;
if (space > 255) begin // Space in the DRAM FIFO
if (occupied_input > 255) begin // 256 or more entrys in input FIFO
input_state <= INPUT1;
input_timeout_reset <= 1'b1;
end else if (input_timeout_triggered) begin // input FIFO timeout waiting for new data.
input_state <= INPUT2;
input_timeout_reset <= 1'b1;
end else begin
input_timeout_reset <= 1'b0;
input_state <= INPUT_IDLE;
end
end else begin
input_timeout_reset <= 1'b0;
input_state <= INPUT_IDLE;
end
end
//
// INPUT1.
// Caused by input FIFO reaching 256 entries.
// Request write burst of lesser of:
// 1) Entrys until page boundry crossed
// 2) 256.
//
INPUT1: begin
write_count <= (input_page_boundry < 255) ? input_page_boundry[7:0] : 8'd255;
write_ctrl_valid <= 1'b1;
if (write_ctrl_ready)
input_state <= INPUT4; // Pre-emptive ACK
else
input_state <= INPUT3; // Wait for ACK
end
//
// INPUT2.
// Caused by timeout of input FIFO. (occupied_input was implicitly less than 256 last cycle)
// Request write burst of lesser of:
// 1) Entries until page boundry crossed
// 2) Entries in input FIFO
//
INPUT2: begin
write_count <= (input_page_boundry < ({3'h0,occupied_input[8:0]} - 12'd1)) ? input_page_boundry[7:0] : (occupied_input[8:0] - 7'd1);
write_ctrl_valid <= 1'b1;
if (write_ctrl_ready)
input_state <= INPUT4; // Pre-emptive ACK
else
input_state <= INPUT3; // Wait for ACK
end
//
// INPUT3.
// Wait in this state for AXI4_DMA engine to accept transaction.
//
INPUT3: begin
if (write_ctrl_ready) begin
write_ctrl_valid <= 1'b0;
input_state <= INPUT4; // ACK
end else begin
write_ctrl_valid <= 1'b1;
input_state <= INPUT3; // Wait for ACK
end
end
//
// INPUT4.
// Wait here until write_ctrl_ready_deasserts.
// This is important as the next time it asserts we know that a write response was receieved.
INPUT4: begin
write_ctrl_valid <= 1'b0;
if (!write_ctrl_ready)
input_state <= INPUT5; // Move on
else
input_state <= INPUT4; // Wait for deassert
end
//
// INPUT5.
// Transaction has been accepted by AXI4 DMA engine. Now we wait for the re-assertion
// of write_ctrl_ready which signals that the AXI4 DMA engine has receieved a response
// for the whole write transaction and we assume that this means it is commited to DRAM.
// We are now free to update write_addr pointer and go back to idle state.
//
INPUT5: begin
write_ctrl_valid <= 1'b0;
if (write_ctrl_ready) begin
write_addr[SIZE-1:0] <= write_addr[SIZE-1:0] + ((write_count + 1) << 3);
input_state <= INPUT6;
update_write <= 1'b1;
end else begin
input_state <= INPUT5;
end
end
//
// INPUT6:
// Need to let space update before looking if there's more to do.
//
INPUT6: begin
input_state <= INPUT_IDLE;
update_write <= 1'b0;
end
// Ass covering.
default: input_state <= INPUT_IDLE;
endcase // case(input_state)
//
// Simple output timeout counter for now
//
always @(posedge dram_clk)
if (dram_reset | clear) begin
output_timeout_count <= 0;
output_timeout_triggered <= 1'b0;
end else if (output_timeout_reset) begin
output_timeout_count <= 0;
output_timeout_triggered <= 1'b0;
end else if (output_timeout_count == TIMEOUT) begin
output_timeout_triggered <= 1'b1;
end else if (output_state == OUTPUT_IDLE) begin
output_timeout_count <= output_timeout_count + (occupied != 0 );
end
//
// Wait for 64 entries in main FIFO to trigger DRAM read burst.
// Timeout can also trigger burst so fragments of data are not left to rot in the main FIFO.
// Also if enough data is present in the main FIFO to complete a burst upto the edge
// of a 4KByte page then immediately start the burst.
//
always @(posedge dram_clk)
if (dram_reset | clear) begin
output_state <= OUTPUT_IDLE;
read_addr[31:SIZE] <= BASE >> SIZE;
read_addr[SIZE-1:0] <= 0;
output_timeout_reset <= 1'b0;
read_ctrl_valid <= 1'b0;
read_count <= 8'd0;
update_read <= 1'b0;
end else
case (output_state)
//
// OUTPUT_IDLE.
// To start an output tranfer from DRAM
// 1) Space in the small output FIFO
// and either
// 2) 256 entrys in the DRAM FIFO
// or
// 3) Timeout waiting for more data.
//
OUTPUT_IDLE: begin
read_ctrl_valid <= 1'b0;
update_read <= 1'b0;
if (space_output > 255) begin // Space in the output FIFO.
if (occupied > 255) begin // 64 or more entrys in main FIFO
output_state <= OUTPUT1;
output_timeout_reset <= 1'b1;
end else if (output_timeout_triggered) begin // output FIFO timeout waiting for new data.
output_state <= OUTPUT2;
output_timeout_reset <= 1'b1;
end else begin
output_timeout_reset <= 1'b0;
output_state <= OUTPUT_IDLE;
end
end else begin
output_timeout_reset <= 1'b0;
output_state <= OUTPUT_IDLE;
end
end // case: OUTPUT_IDLE
//
// OUTPUT1.
// Caused by main FIFO reaching 256 entries.
// Request read burst of lesser of lesser of:
// 1) Entrys until page boundry crossed
// 2) 256.
//
OUTPUT1: begin
read_count <= (output_page_boundry < 255) ? output_page_boundry : 8'd255;
read_ctrl_valid <= 1'b1;
if (read_ctrl_ready)
output_state <= OUTPUT4; // Pre-emptive ACK
else
output_state <= OUTPUT3; // Wait for ACK
end
//
// OUTPUT2.
// Caused by timeout of main FIFO
// Request read burst of lesser of:
// 1) Entries until page boundry crossed
// 2) Entries in main FIFO
//
OUTPUT2: begin
read_count <= (output_page_boundry < (occupied - 1)) ? output_page_boundry : (occupied - 1);
read_ctrl_valid <= 1'b1;
if (read_ctrl_ready)
output_state <= OUTPUT4; // Pre-emptive ACK
else
output_state <= OUTPUT3; // Wait for ACK
end
//
// OUTPUT3.
// Wait in this state for AXI4_DMA engine to accept transaction.
//
OUTPUT3: begin
if (read_ctrl_ready) begin
read_ctrl_valid <= 1'b0;
output_state <= OUTPUT4; // ACK
end else begin
read_ctrl_valid <= 1'b1;
output_state <= OUTPUT3; // Wait for ACK
end
end
//
// OUTPUT4.
// Wait here unitl read_ctrl_ready_deasserts.
// This is important as the next time it asserts we know that a read response was receieved.
OUTPUT4: begin
read_ctrl_valid <= 1'b0;
if (!read_ctrl_ready)
output_state <= OUTPUT5; // Move on
else
output_state <= OUTPUT4; // Wait for deassert
end
//
// OUTPUT5.
// Transaction has been accepted by AXI4 DMA engine. Now we wait for the re-assertion
// of read_ctrl_ready which signals that the AXI4 DMA engine has receieved a last signal and good response
// for the whole read transaction.
// We are now free to update read_addr pointer and go back to idle state.
//
OUTPUT5: begin
read_ctrl_valid <= 1'b0;
if (read_ctrl_ready) begin
read_addr[SIZE-1:0] <= read_addr[SIZE-1:0] + ((read_count + 1) << 3);
output_state <= OUTPUT6;
update_read <= 1'b1;
end else begin
output_state <= OUTPUT5;
end
end // case: OUTPUT5
//
// OUTPUT6.
// Need to get occupied value updated before checking if there's more to do.
//
OUTPUT6: begin
update_read <= 1'b0;
output_state <= OUTPUT_IDLE;
end
// Ass covering.
default: output_state <= OUTPUT_IDLE;
endcase // case(output_state)
//
// Calculate number of entries remaining until next 4KB page boundry is crossed minus 1.
// Note, units of calculation are 64bit wide words. Address is always 64bit alligned.
//
assign input_page_boundry = {write_addr[31:12],9'h1ff} - write_addr[31:3];
assign output_page_boundry = {read_addr[31:12],9'h1ff} - read_addr[31:3];
//
// Count number of used entries in main DRAM FIFO.
// Note that this is expressed in units of 64bit wide words.
//
always @(posedge dram_clk)
if (dram_reset | clear)
occupied <= 0;
else
occupied <= occupied + (update_write ? write_count + 1 : 0) - (update_read ? read_count + 1 : 0);
always @(posedge dram_clk)
if (dram_reset | clear)
space <= (1 << SIZE-3) - 'd64; // Subtract 64 from space to make allowance for read/write reordering in DRAM controller confuing pointer math.
else
space <= space - (update_write ? write_count + 1 : 0) + (update_read ? read_count + 1 : 0);
//
// Instamce of axi_dma_master
//
axi_dma_master axi_dma_master_i
(
.aclk(dram_clk), // input aclk
.areset(dram_reset | clear), // input aresetn
// Write control
.m_axi_awid(m_axi_awid), // input [0 : 0] m_axi_awid
.m_axi_awaddr(m_axi_awaddr), // input [31 : 0] m_axi_awaddr
.m_axi_awlen(m_axi_awlen), // input [7 : 0] m_axi_awlen
.m_axi_awsize(m_axi_awsize), // input [2 : 0] m_axi_awsize
.m_axi_awburst(m_axi_awburst), // input [1 : 0] m_axi_awburst
.m_axi_awvalid(m_axi_awvalid), // input m_axi_awvalid
.m_axi_awready(m_axi_awready), // output m_axi_awready
.m_axi_awlock(m_axi_awlock),
.m_axi_awcache(m_axi_awcache),
.m_axi_awprot(m_axi_awprot),
.m_axi_awqos(m_axi_awqos),
.m_axi_awregion(m_axi_awregion),
.m_axi_awuser(m_axi_awuser),
// Write Data
.m_axi_wdata(m_axi_wdata), // input [63 : 0] m_axi_wdata
.m_axi_wstrb(m_axi_wstrb), // input [7 : 0] m_axi_wstrb
.m_axi_wlast(m_axi_wlast), // input m_axi_wlast
.m_axi_wvalid(m_axi_wvalid), // input m_axi_wvalid
.m_axi_wready(m_axi_wready), // output m_axi_wready
.m_axi_wuser(),
// Write Response
.m_axi_bid(m_axi_bid), // output [0 : 0] m_axi_bid
.m_axi_bresp(m_axi_bresp), // output [1 : 0] m_axi_bresp
.m_axi_bvalid(m_axi_bvalid), // output m_axi_bvalid
.m_axi_bready(m_axi_bready), // input m_axi_bready
.m_axi_buser(),
// Read Control
.m_axi_arid(m_axi_arid), // input [0 : 0] m_axi_arid
.m_axi_araddr(m_axi_araddr), // input [31 : 0] m_axi_araddr
.m_axi_arlen(m_axi_arlen), // input [7 : 0] m_axi_arlen
.m_axi_arsize(m_axi_arsize), // input [2 : 0] m_axi_arsize
.m_axi_arburst(m_axi_arburst), // input [1 : 0] m_axi_arburst
.m_axi_arvalid(m_axi_arvalid), // input m_axi_arvalid
.m_axi_arready(m_axi_arready), // output m_axi_arready
.m_axi_arlock(m_axi_arlock),
.m_axi_arcache(m_axi_arcache),
.m_axi_arprot(m_axi_arprot),
.m_axi_arqos(m_axi_arqos),
.m_axi_arregion(m_axi_arregion),
.m_axi_aruser(m_axi_aruser),
// Read Data
.m_axi_rid(m_axi_rid), // output [0 : 0] m_axi_rid
.m_axi_rdata(m_axi_rdata), // output [63 : 0] m_axi_rdata
.m_axi_rresp(m_axi_rresp), // output [1 : 0] m_axi_rresp
.m_axi_rlast(m_axi_rlast), // output m_axi_rlast
.m_axi_rvalid(m_axi_rvalid), // output m_axi_rvalid
.m_axi_rready(m_axi_rready), // input m_axi_rready
.m_axi_ruser(),
//
// DMA interface for Write transaction
//
.write_addr(write_addr), // Byte address for start of write transaction (should be 64bit alligned)
.write_count(write_count), // Count of 64bit words to write.
.write_ctrl_valid(write_ctrl_valid),
.write_ctrl_ready(write_ctrl_ready),
.write_data(i_tdata_input),
.write_data_valid(i_tvalid_input),
.write_data_ready(i_tready_input),
//
// DMA interface for Read
//
.read_addr(read_addr), // Byte address for start of read transaction (should be 64bit alligned)
.read_count(read_count), // Count of 64bit words to read.
.read_ctrl_valid(read_ctrl_valid),
.read_ctrl_ready(read_ctrl_ready),
.read_data(o_tdata_output),
.read_data_valid(o_tvalid_output),
.read_data_ready(o_tready_output),
//
// Debug
//
.debug(debug_axi_dma_master)
);
//
// Debug
//
assign debug = { checksum_error,
/*debug_axi_dma_master[7:0]*/
input_timeout_triggered, // 195
input_state[2:0], // 194-192
output_timeout_triggered, // 191
output_state[2:0], // 190-188
space_output[15:0], // 187-172
occupied[21:0], // 171-150
occupied_input[15:0], // 149-134
i_tvalid_i0, // 133
i_tready_i0, // 132
i_tlast_i0, // 131
i_tdata_i0[63:0],// 130-67
o_tvalid_i1, // 66
o_tready_i1, // 65
o_tlast_i1, // 64
o_tdata_i1[63:0] // 63-0
};
endmodule // axi_dram_fifo
-421
View File
@@ -1,421 +0,0 @@
module axi_dram_fifo_tb;
reg clk; // Global AXI clock
reg reset; // Global reset, active high.
reg clear;
wire aresetn; // Global AXI reset, active low.
//
// AXI Write address channel
//
wire [0 : 0] axi_awid; // Write address ID. This signal is the identification tag for the write address signals
wire [31 : 0] axi_awaddr; // Write address. The write address gives the address of the first transfer in a write burst
wire [7 : 0] axi_awlen; // Burst length. The burst length gives the exact number of transfers in a burst.
wire [2 : 0] axi_awsize; // Burst size. This signal indicates the size of each transfer in the burst.
wire [1 : 0] axi_awburst; // Burst type. The burst type and the size information, determine how the address is calculated
wire [0 : 0] axi_awlock; // Lock type. Provides additional information about the atomic characteristics of the transfer.
wire [3 : 0] axi_awcache; // Memory type. This signal indicates how transactions are required to progress
wire [2 : 0] axi_awprot; // Protection type. This signal indicates the privilege and security level of the transaction
wire [3 : 0] axi_awqos; // Quality of Service, QoS. The QoS identifier sent for each write transaction
wire [3 : 0] axi_awregion; // Region identifier. Permits a single physical interface on a slave to be re-used.
wire [0 : 0] axi_awuser; // User signal. Optional User-defined signal in the write address channel.
wire axi_awvalid; // Write address valid. This signal indicates that the channel is signaling valid write addr
wire axi_awready; // Write address ready. This signal indicates that the slave is ready to accept an address
//
// AXI Write data channel.
//
wire [63 : 0] axi_wdata; // Write data
wire [7 : 0] axi_wstrb; // Write strobes. This signal indicates which byte lanes hold valid data.
wire axi_wlast; // Write last. This signal indicates the last transfer in a write burst
wire [0 : 0] axi_wuser; // User signal. Optional User-defined signal in the write data channel.
wire axi_wvalid; // Write valid. This signal indicates that valid write data and strobes are available.
wire axi_wready; // Write ready. This signal indicates that the slave can accept the write data.
//
// AXI Write response channel signals
//
wire [0 : 0] axi_bid; // Response ID tag. This signal is the ID tag of the write response.
wire [1 : 0] axi_bresp; // Write response. This signal indicates the status of the write transaction.
wire [0 : 0] axi_buser; // User signal. Optional User-defined signal in the write response channel.
wire axi_bvalid; // Write response valid. This signal indicates that the channel is signaling a valid response
wire axi_bready; // Response ready. This signal indicates that the master can accept a write response
//
// AXI Read address channel
//
wire [0 : 0] axi_arid; // Read address ID. This signal is the identification tag for the read address group of signals
wire [31 : 0] axi_araddr; // Read address. The read address gives the address of the first transfer in a read burst
wire [7 : 0] axi_arlen; // Burst length. This signal indicates the exact number of transfers in a burst.
wire [2 : 0] axi_arsize; // Burst size. This signal indicates the size of each transfer in the burst.
wire [1 : 0] axi_arburst; // Burst type. The burst type and the size information determine how the address for each transfer
wire [0 : 0] axi_arlock; // Lock type. This signal provides additional information about the atomic characteristics
wire [3 : 0] axi_arcache; // Memory type. This signal indicates how transactions are required to progress
wire [2 : 0] axi_arprot; // Protection type. This signal indicates the privilege and security level of the transaction
wire [3 : 0] axi_arqos; // Quality of Service, QoS. QoS identifier sent for each read transaction.
wire [3 : 0] axi_arregion; // Region identifier. Permits a single physical interface on a slave to be re-used
wire [0 : 0] axi_aruser; // User signal. Optional User-defined signal in the read address channel.
wire axi_arvalid; // Read address valid. This signal indicates that the channel is signaling valid read addr
wire axi_arready; // Read address ready. This signal indicates that the slave is ready to accept an address
//
// AXI Read data channel
//
wire [0 : 0] axi_rid; // Read ID tag. This signal is the identification tag for the read data group of signals
wire [63 : 0] axi_rdata; // Read data.
wire [1 : 0] axi_rresp; // Read response. This signal indicates the status of the read transfer
wire axi_rlast; // Read last. This signal indicates the last transfer in a read burst.
wire [0 : 0] axi_ruser; // User signal. Optional User-defined signal in the read data channel.
wire axi_rvalid; // Read valid. This signal indicates that the channel is signaling the required read data.
wire axi_rready; // Read ready. This signal indicates that the master can accept the read data and response
//
// CHDR friendly AXI stream input
//
wire [63:0] i_tdata;
wire i_tlast;
wire i_tvalid;
wire i_tready;
//
// CHDR friendly AXI Stream output
//
wire [63:0] o_tdata;
wire o_tlast;
wire o_tvalid;
wire o_tready;
//
// These registers optionaly used
// to drive nets through procedural assignments in test bench.
// These drivers default to tri-stated.
//
reg [63:0] i_tdata_r;
reg i_tlast_r;
reg i_tvalid_r;
reg o_tready_r;
assign i_tdata = i_tdata_r;
assign i_tlast = i_tlast_r;
assign i_tvalid = i_tvalid_r;
assign o_tready = o_tready_r;
initial
begin
i_tdata_r <= 64'hzzzz_zzzz_zzzz_zzzz;
i_tlast_r <= 1'bz;
i_tvalid_r <= 1'bz;
o_tready_r <= 1'bz;
end
axi_dram_fifo
#(.SIZE(13))
axi_dram_fifo_i1
(
.bus_clk(clk), // input s_aclk
.bus_reset(reset), // input s_aresetn
.clear(clear),
.dram_clk(clk), // input s_aclk
.dram_reset(reset), // input s_aresetn
// Write control
.m_axi_awid(axi_awid), // input [0 : 0] s_axi_awid
.m_axi_awaddr(axi_awaddr), // input [31 : 0] s_axi_awaddr
.m_axi_awlen(axi_awlen), // input [7 : 0] s_axi_awlen
.m_axi_awsize(axi_awsize), // input [2 : 0] s_axi_awsize
.m_axi_awburst(axi_awburst), // input [1 : 0] s_axi_awburst
.m_axi_awvalid(axi_awvalid), // input s_axi_awvalid
.m_axi_awready(axi_awready), // output s_axi_awready
.m_axi_awlock(),
.m_axi_awcache(),
.m_axi_awprot(),
.m_axi_awqos(),
.m_axi_awregion(),
.m_axi_awuser(),
// Write Data
.m_axi_wdata(axi_wdata), // input [63 : 0] s_axi_wdata
.m_axi_wstrb(axi_wstrb), // input [7 : 0] s_axi_wstrb
.m_axi_wlast(axi_wlast), // input s_axi_wlast
.m_axi_wvalid(axi_wvalid), // input s_axi_wvalid
.m_axi_wready(axi_wready), // output s_axi_wready
.m_axi_wuser(),
// Write Response
.m_axi_bid(axi_bid), // output [0 : 0] s_axi_bid
.m_axi_bresp(axi_bresp), // output [1 : 0] s_axi_bresp
.m_axi_bvalid(axi_bvalid), // output s_axi_bvalid
.m_axi_bready(axi_bready), // input s_axi_bready
.m_axi_buser(),
// Read Control
.m_axi_arid(axi_arid), // input [0 : 0] s_axi_arid
.m_axi_araddr(axi_araddr), // input [31 : 0] s_axi_araddr
.m_axi_arlen(axi_arlen), // input [7 : 0] s_axi_arlen
.m_axi_arsize(axi_arsize), // input [2 : 0] s_axi_arsize
.m_axi_arburst(axi_arburst), // input [1 : 0] s_axi_arburst
.m_axi_arvalid(axi_arvalid), // input s_axi_arvalid
.m_axi_arready(axi_arready), // output s_axi_arready
.m_axi_arlock(),
.m_axi_arcache(),
.m_axi_arprot(),
.m_axi_arqos(),
.m_axi_arregion(),
.m_axi_aruser(),
// Read Data
.m_axi_rid(axi_rid), // output [0 : 0] s_axi_rid
.m_axi_rdata(axi_rdata), // output [63 : 0] s_axi_rdata
.m_axi_rresp(axi_rresp), // output [1 : 0] s_axi_rresp
.m_axi_rlast(axi_rlast), // output s_axi_rlast
.m_axi_rvalid(axi_rvalid), // output s_axi_rvalid
.m_axi_rready(axi_rready), // input s_axi_rready
.m_axi_ruser(),
// CHDR in
.i_tdata(i_tdata),
.i_tlast(i_tlast),
.i_tvalid(i_tvalid),
.i_tready(i_tready),
// CHDR out
.o_tdata(o_tdata),
.o_tlast(o_tlast),
.o_tvalid(o_tvalid),
.o_tready(o_tready),
//
.supress_threshold(16'h0),
.supress_enable(1'b0)
);
axi4_bram_1kx64 axi4_bram_1kx64_i1
(
.s_aclk(clk), // input s_aclk
.s_aresetn(aresetn), // input s_aresetn
.s_axi_awid(axi_awid), // input [0 : 0] s_axi_awid
.s_axi_awaddr(axi_awaddr), // input [31 : 0] s_axi_awaddr
.s_axi_awlen(axi_awlen), // input [7 : 0] s_axi_awlen
.s_axi_awsize(axi_awsize), // input [2 : 0] s_axi_awsize
.s_axi_awburst(axi_awburst), // input [1 : 0] s_axi_awburst
.s_axi_awvalid(axi_awvalid), // input s_axi_awvalid
.s_axi_awready(axi_awready), // output s_axi_awready
.s_axi_wdata(axi_wdata), // input [63 : 0] s_axi_wdata
.s_axi_wstrb(axi_wstrb), // input [7 : 0] s_axi_wstrb
.s_axi_wlast(axi_wlast), // input s_axi_wlast
.s_axi_wvalid(axi_wvalid), // input s_axi_wvalid
.s_axi_wready(axi_wready), // output s_axi_wready
.s_axi_bid(axi_bid), // output [0 : 0] s_axi_bid
.s_axi_bresp(axi_bresp), // output [1 : 0] s_axi_bresp
.s_axi_bvalid(axi_bvalid), // output s_axi_bvalid
.s_axi_bready(axi_bready), // input s_axi_bready
.s_axi_arid(axi_arid), // input [0 : 0] s_axi_arid
.s_axi_araddr(axi_araddr), // input [31 : 0] s_axi_araddr
.s_axi_arlen(axi_arlen), // input [7 : 0] s_axi_arlen
.s_axi_arsize(axi_arsize), // input [2 : 0] s_axi_arsize
.s_axi_arburst(axi_arburst), // input [1 : 0] s_axi_arburst
.s_axi_arvalid(axi_arvalid), // input s_axi_arvalid
.s_axi_arready(axi_arready), // output s_axi_arready
.s_axi_rid(axi_rid), // output [0 : 0] s_axi_rid
.s_axi_rdata(axi_rdata), // output [63 : 0] s_axi_rdata
.s_axi_rresp(axi_rresp), // output [1 : 0] s_axi_rresp
.s_axi_rlast(axi_rlast), // output s_axi_rlast
.s_axi_rvalid(axi_rvalid), // output s_axi_rvalid
.s_axi_rready(axi_rready) // input s_axi_rready
);
//
//
//
task send_ramp;
input [31:0] burst_count;
input [31:0] len;
input [31:0] sid;
reg [31:0] data;
reg [11:0] seqno;
begin
seqno = 0;
data = 0;
send_packet(len, data, 0, seqno, (burst_count==1), 0, sid);
seqno = seqno + 1;
data <= data + len;
if(burst_count > 2)
repeat (burst_count - 2)
begin
send_packet(len, data, 64'h0, seqno, 0, 0, sid);
seqno = seqno + 1;
data <= data + len;
end
if(burst_count > 1)
send_packet(len, data, 64'h0, seqno, 1, 0, sid);
end
endtask // send_ramp
task send_dc;
input [31:0] burst_count;
input [31:0] len;
input [31:0] sid;
reg [31:0] data;
reg [11:0] seqno;
begin
seqno = 0;
data = 1 << 14;
send_packet(len, data, 0, seqno, (burst_count==1), 0, sid);
seqno = seqno + 1;
if(burst_count > 2)
repeat (burst_count - 2)
begin
send_packet(len, data, 64'h0, seqno, 0, 0, sid);
seqno = seqno + 1;
end
if(burst_count > 1)
send_packet(len, data, 64'h0, seqno, 1, 0, sid);
end
endtask // send_ramp
task send_burst;
input [31:0] burst_count;
input [31:0] len;
input [31:0] start_data;
input [63:0] send_time;
input [11:0] start_seqnum;
input send_at;
input [31:0] sid;
reg [11:0] seqno;
begin
seqno = start_seqnum;
send_packet(len, {seqno,start_data[15:0]}, send_time, seqno, (burst_count==1), send_at, sid);
seqno = seqno + 1;
if(burst_count > 2)
repeat (burst_count - 2)
begin
send_packet(len, {seqno,start_data[15:0]}, 64'h0, seqno, 0, 0, sid);
seqno = seqno + 1;
end
if(burst_count > 1)
send_packet(len, {seqno,start_data[15:0]}, 64'h0, seqno, 1, 0, sid);
end
endtask // send_burst
task send_packet;
input [31:0] len;
input [31:0] start_data;
input [63:0] send_time;
input [11:0] pkt_seqnum;
input eob;
input send_at;
input [31:0] sid;
reg [31:0] samp0, samp1;
begin
// Send a packet
samp0 <= start_data;
samp1 <= start_data + 1;
@(posedge clk);
i_tlast_r <= 0;
i_tdata_r <= { 1'b0, 1'b0 /*trl*/, send_at, eob, pkt_seqnum, len[15:0]+16'd2+send_at+send_at, sid };
i_tvalid_r <= 1;
@(posedge clk)
if(send_at)
begin
i_tdata_r <= send_time;
@(posedge clk);
end
repeat (len[31:1]+len[0]-1)
begin
i_tdata_r <= {samp0,samp1};
samp0 <= samp0 + 2;
samp1 <= samp1 + 2;
@(posedge clk);
end
i_tdata_r <= {samp0,samp1};
i_tlast_r <= 1'b1;
@(posedge clk);
i_tvalid_r <= 0;
@(posedge clk);
end
endtask // send_packet
task send_raw_packet;
input [31:0] len;
reg [63:0] data;
begin
data = 0;
@(posedge clk);
repeat (len-1) begin
i_tlast_r <= 0;
i_tdata_r <= data;
i_tvalid_r <= 1;
@(posedge clk);
while (~i_tready) @(posedge clk);
data = data + 1;
end
i_tlast_r <= 1;
i_tdata_r <= data;
i_tvalid_r <= 1;
@(posedge clk);
while (~i_tready) @(posedge clk);
i_tvalid_r <= 0;
@(posedge clk);
end
endtask // send_raw_packet
task receive_raw_packet;
input [31:0] len;
output fail;
reg [63:0] data;
begin
data = 0;
fail = 0;
@(posedge clk);
repeat (len-1) begin
o_tready_r <= 1;
@(posedge clk);
while (~o_tvalid) @(posedge clk);
//$display("Data = %d, o_tdata = %d, o_tlast = %d",data,o_tdata,o_tlast);
fail = fail || (data !== o_tdata);
fail = fail || ~(o_tlast === 0);
data = data + 1;
end
o_tready_r <= 1;
@(posedge clk);
while (~o_tvalid) @(posedge clk);
//$display("Data = %d, o_tdata = %d, o_tlast = %d",data,o_tdata,o_tlast);
fail = fail || (data !== o_tdata);
fail = fail || ~(o_tlast === 1);
o_tready_r <= 0;
@(posedge clk);
if (fail) $display("receive_raw_packet size %d failed",len);
end
endtask // receive_raw_packet
assign aresetn = ~reset;
//
// Bring in a simulation script here
//
`include "simulation_script.v"
endmodule // axi_dram_fifo_tb
-128
View File
@@ -1,128 +0,0 @@
//
// AXI stream neds N+1 bits to transmit packets of N bits so that the LAST bit can be represented.
// LAST occurs relatively infrequently and can be synthesized by using an in-band ESC code to generate
// a multi-word sequence to encode it (and the escape character when it appears as data input).
//
// 0x1234567887654321 with last becomes
// 0xDEADBEEFFEEDCAFE 0x0000000000000001 0x1234567887654321
//
// 0xDEADBEEFFEEDCAFE with last becomes
// 0xDEADBEEFFEEDCAFE 0x0000000000000001 0xDEADBEEFFEEDCAFE
//
// 0xDEADBEEFFEEDCAFE without last becomes
// 0xDEADBEEFFEEDCAFE 0x0000000000000000 0xDEADBEEFFEEDCAFE
//
module axi_embed_tlast
#(parameter WIDTH=64)
(
input clk,
input reset,
input clear,
//
input [WIDTH-1:0] i_tdata,
input i_tlast,
input i_tvalid,
output i_tready,
//
output reg [WIDTH-1:0] o_tdata,
output o_tvalid,
input o_tready
);
localparam PASS = 0;
localparam ZERO = 1;
localparam ONE = 2;
localparam ESCAPE = 3;
localparam IDLE = 0;
localparam LAST = 1;
localparam ESC = 2;
localparam FINISH = 3;
reg [1:0] state, next_state;
reg [1:0] select;
reg [31:0] checksum;
always @(posedge clk)
if (reset | clear) begin
checksum <= 0;
end else if (i_tready && i_tvalid && i_tlast) begin
checksum <= 0;
end else if (i_tready && i_tvalid) begin
checksum <= checksum + i_tdata[31:0] + i_tdata[63:32];
end
always @(posedge clk)
if (reset | clear) begin
state <= IDLE;
end else begin if (o_tready)
state <= next_state;
end
always @(*) begin
case(state)
IDLE: begin
if (i_tlast && i_tvalid)
begin
next_state = LAST;
select = ESCAPE;
end
else if ((i_tdata == 64'hDEADBEEFFEEDCAFE) && i_tvalid)
begin
next_state = ESC;
select = ESCAPE;
end
else
begin
next_state = IDLE;
select = PASS;
end
end // case: IDLE
//
//
LAST: begin
select = ONE;
next_state = FINISH;
end
//
//
ESC: begin
select = ZERO;
next_state = FINISH;
end
//
//
FINISH: begin
select = PASS;
if (i_tvalid)
next_state = IDLE;
else
next_state = FINISH;
end
endcase // case(state)
end // always @ (*)
//
// Muxes
//
always @*
begin
case(select)
PASS: o_tdata = i_tdata;
ZERO: o_tdata = 0;
ONE: o_tdata = {checksum[31:0],32'h1};
ESCAPE: o_tdata = 64'hDEADBEEFFEEDCAFE;
endcase // case(select)
end
assign o_tvalid = (select == PASS) ? i_tvalid : 1'b1;
assign i_tready = (select == PASS) ? o_tready : 1'b0;
endmodule // axi_embed_tlast
-149
View File
@@ -1,149 +0,0 @@
//
// AXI stream neds N+1 bits to transmit packets of N bits so that the LAST bit can be represented.
// LAST occurs relatively infrequently and can be synthesized by using an in-band ESC code to generate
// a multi-word sequence to encode it (and the escape character when it appears as data input).
//
// 0x1234567887654321 with last becomes
// 0xDEADBEEFFEEDCAFE 0x0000000000000001 0x1234567887654321
//
// 0xDEADBEEFFEEDCAFE with last becomes
// 0xDEADBEEFFEEDCAFE 0x0000000000000001 0xDEADBEEFFEEDCAFE
//
// 0xDEADBEEFFEEDCAFE without last becomes
// 0xDEADBEEFFEEDCAFE 0x0000000000000000 0xDEADBEEFFEEDCAFE
//
module axi_extract_tlast
#(parameter WIDTH=64)
(
input clk,
input reset,
input clear,
//
input [WIDTH-1:0] i_tdata,
input i_tvalid,
output reg i_tready,
//
output [WIDTH-1:0] o_tdata,
output reg o_tlast,
output reg o_tvalid,
input o_tready,
//
output reg checksum_error_reg
);
reg [1:0] state, next_state;
localparam IDLE = 0;
localparam EXTRACT1 = 1;
localparam EXTRACT2 = 2;
localparam EXTRACT3 = 3;
assign o_tdata = i_tdata;
reg [31:0] checksum, old_checksum;
reg checksum_error;
always @(posedge clk)
if (reset | clear) begin
checksum <= 0;
old_checksum <= 0;
end else if (o_tready && i_tvalid && o_tlast) begin
checksum <= 0;
old_checksum <= 0;
end else if (i_tready && i_tvalid && (state == IDLE)) begin
checksum <= checksum + i_tdata[31:0] + i_tdata[63:32];
old_checksum <= checksum;
end
always @(posedge clk)
checksum_error_reg <= checksum_error;
always @(posedge clk)
if (reset | clear) begin
state <= IDLE;
end else begin
state <= next_state;
end
always @(*) begin
checksum_error = 0;
case(state)
//
// Search for Escape sequence "0xDEADBEEFFEEDCAFE"
// If ESC found don't pass data downstream but transition to next state.
// else pass data downstream.
//
IDLE: begin
o_tlast = 1'b0;
if ((i_tdata == 64'hDEADBEEFFEEDCAFE) && i_tvalid)
begin
next_state = EXTRACT1;
o_tvalid = 1'b0;
i_tready = 1'b1;
end
else
begin
next_state = IDLE;
o_tvalid = i_tvalid;
i_tready = o_tready;
end // else: !if((i_tdata == 'hDEADBEEFFEEDCAFE) && i_tvalid)
end // case: IDLE
//
// Look at next data. If it's a 0x1 then o_tlast should be asserted with next data word.
// if it's 0x0 then it signals emulation of the Escape code in the original data stream
// and we should just pass the next data word through unchanged with no o_tlast indication.
//
EXTRACT1: begin
o_tvalid = 1'b0;
i_tready = 1'b1;
o_tlast = 1'b0;
if (i_tvalid) begin
if (i_tdata[31:0] == 'h1)
begin
if (old_checksum != i_tdata[63:32])
checksum_error = 1'b1;
next_state = EXTRACT2;
end
else // We assume emulation and don't look for illegal codes.
begin
next_state = EXTRACT3;
end // else: !if(i_tdata == 'h1)
end else begin // if (i_tvalid)
next_state = EXTRACT1;
end // else: !if(i_tvalid)
end // case: EXTRACT1
//
// Assert o_tlast with data word.
//
EXTRACT2: begin
o_tvalid = i_tvalid;
i_tready = o_tready;
o_tlast = 1'b1;
if (i_tvalid & o_tready)
next_state = IDLE;
else
next_state = EXTRACT2;
end
//
// Emulation, don't assert o_tlast with dataword.
//
EXTRACT3: begin
o_tvalid = i_tvalid;
i_tready = o_tready;
o_tlast = 1'b0;
if (i_tvalid & o_tready)
next_state = IDLE;
else
next_state = EXTRACT2;
end
endcase // case(state)
end
endmodule // axi_extract_tlast
-187
View File
@@ -1,187 +0,0 @@
//
// Ultra fast critical path FIFO.
// Only 2 entrys but no combinatorial feed through paths
//
module axi_fast_extract_tlast
#(parameter WIDTH=64)
(
input clk,
input reset,
input clear,
//
input [WIDTH-1:0] i_tdata,
input i_tvalid,
output reg i_tready,
//
output [WIDTH-1:0] o_tdata,
output o_tlast,
output reg o_tvalid,
input o_tready
);
reg [WIDTH:0] data_reg1, data_reg2;
reg [1:0] fifo_state;
localparam EMPTY = 0;
localparam HALF = 1;
localparam FULL = 2;
reg [1:0] extract_state;
localparam IDLE = 0;
localparam EXTRACT1 = 1;
localparam EXTRACT2 = 2;
localparam EXTRACT3 = 3;
always @(posedge clk)
if (reset | clear) begin
fifo_state <= EMPTY;
end else begin
case (fifo_state)
// Nothing in either register.
// Upstream can always push data to us.
// Downstream has nothing to take from us.
EMPTY: begin
if ((extract_state == IDLE) && (i_tdata == 64'hDEADBEEFFEEDCAFE) && i_tvalid) begin
// Embeded escpae code received.
extract_state <= EXTRACT1;
i_tready <= 1'b1;
o_tvalid <= 1'b0;
fifo_state <= EMPTY;
end else if ((extract_state == EXTRACT1) && i_tvalid) begin
// Now work out if its a genuine embeded tlast or emulation.
i_tready <= 1'b1;
o_tvalid <= 1'b0;
fifo_state <= EMPTY;
if (i_tdata[31:0] == 'h1) begin
extract_state <= EXTRACT2;
end else begin
extract_state <= EXTRACT3;
end
end else if ((extract_state == EXTRACT2) && i_tvalid) begin
// Extract tlast.
data_reg1 <= {1'b1,i_tdata};
i_tready <= 1'b1;
o_tvalid <= 1'b1;
fifo_state <= HALF;
extract_state <= IDLE;
end else if (i_tvalid) begin
// Get here both for normal data and for EXTRACT3 emulation data.
data_reg1 <= {1'b0,i_tdata};
fifo_state <= HALF;
extract_state <= IDLE;
i_tready <= 1'b1;
o_tvalid <= 1'b1;
end else begin
// Nothing to do.
fifo_state <= EMPTY;
i_tready <= 1'b1;
o_tvalid <= 1'b0;
end
end
// First Register Full.
// Upstream can always push data to us.
// Downstream can always read from us.
HALF: begin
if ((extract_state == IDLE) && (i_tdata == 64'hDEADBEEFFEEDCAFE) && i_tvalid) begin
// Embeded escpae code received.
extract_state <= EXTRACT1;
if (o_tready) begin
// If meanwhile we get read then go empty...
i_tready <= 1'b1;
o_tvalid <= 1'b0;
fifo_state <= EMPTY;
end else begin
// ...else stay half full.
fifo_state <= HALF;
i_tready <= 1'b1;
o_tvalid <= 1'b1;
end
end else if ((extract_state == EXTRACT1) && i_tvalid) begin
// Now work out if its a genuine embeded tlast or emulation.
if (i_tdata[31:0] == 'h1) begin
extract_state <= EXTRACT2;
end else begin
extract_state <= EXTRACT3;
end
if (o_tready) begin
// If meanwhile we get read then go empty...
i_tready <= 1'b1;
o_tvalid <= 1'b0;
fifo_state <= EMPTY;
end else begin
// ...else stay half full.
fifo_state <= HALF;
i_tready <= 1'b1;
o_tvalid <= 1'b1;
end
end else if ((extract_state == EXTRACT2) && i_tvalid) begin
// Extract tlast.
data_reg1 <= {1'b1,i_tdata};
extract_state <= IDLE;
if (o_tready) begin
// We get read and writen same cycle...
i_tready <= 1'b1;
o_tvalid <= 1'b1;
fifo_state <= HALF;
end else begin
// ...or we get written and go full.
data_reg2 <= data_reg1;
i_tready <= 1'b0;
o_tvalid <= 1'b1;
fifo_state <= FULL;
end
end else if (i_tvalid) begin
// Get here both for normal data and for EXTRACT3 emulation data.
data_reg1 <= {1'b0,i_tdata};
extract_state <= IDLE;
if (o_tready) begin
// We get read and writen same cycle...
fifo_state <= HALF;
i_tready <= 1'b1;
o_tvalid <= 1'b1;
end else begin
// ...or we get written and go full.
data_reg2 <= data_reg1;
i_tready <= 1'b0;
o_tvalid <= 1'b1;
fifo_state <= FULL;
end
end else if (o_tready) begin // if (i_tvalid)
// Only getting read this cycle so go empty
fifo_state <= EMPTY;
i_tready <= 1'b1;
o_tvalid <= 1'b0;
end else begin
// Absolutley nothing happens, everything stays the same.
fifo_state <= HALF;
i_tready <= 1'b1;
o_tvalid <= 1'b1;
end
end // case: HALF
// Both Registers Full.
// Upstream can not push to us in this fifo_state.
// Downstream can always read from us.
FULL: begin
if (o_tready) begin
fifo_state <= HALF;
i_tready <= 1'b1;
o_tvalid <= 1'b1;
end
else begin
fifo_state <= FULL;
i_tready <= 1'b0;
o_tvalid <= 1'b1;
end
end
endcase // case(fifo_state)
end // else: !if(reset | clear)
assign {o_tlast,o_tdata} = (fifo_state == FULL) ? data_reg2 : data_reg1;
endmodule // axi_fast_fifo
-102
View File
@@ -1,102 +0,0 @@
//
// Ultra fast critical path FIFO.
// Only 2 entrys but no combinatorial feed through paths
//
module axi_fast_fifo
#(parameter WIDTH=64)
(
input clk,
input reset,
input clear,
//
input [WIDTH-1:0] i_tdata,
input i_tvalid,
output reg i_tready,
//
output [WIDTH-1:0] o_tdata,
output reg o_tvalid,
input o_tready
);
reg [WIDTH-1:0] data_reg1, data_reg2;
reg [1:0] state;
localparam EMPTY = 0;
localparam HALF = 1;
localparam FULL = 2;
always @(posedge clk)
if (reset | clear) begin
state <= EMPTY;
data_reg1 <= 0;
data_reg2 <= 0;
o_tvalid <= 1'b0;
i_tready <= 1'b0;
end else begin
case (state)
// Nothing in either register.
// Upstream can always push data to us.
// Downstream has nothing to take from us.
EMPTY: begin
if (i_tvalid) begin
data_reg1 <= i_tdata;
state <= HALF;
i_tready <= 1'b1;
o_tvalid <= 1'b1;
end else begin
state <= EMPTY;
i_tready <= 1'b1;
o_tvalid <= 1'b0;
end
end
// First Register Full.
// Upstream can always push data to us.
// Downstream can always read from us.
HALF: begin
if (i_tvalid && o_tready) begin
data_reg1 <= i_tdata;
state <= HALF;
i_tready <= 1'b1;
o_tvalid <= 1'b1;
end else if (i_tvalid) begin
data_reg1 <= i_tdata;
data_reg2 <= data_reg1;
state <= FULL;
i_tready <= 1'b0;
o_tvalid <= 1'b1;
end else if (o_tready) begin
state <= EMPTY;
i_tready <= 1'b1;
o_tvalid <= 1'b0;
end else begin
state <= HALF;
i_tready <= 1'b1;
o_tvalid <= 1'b1;
end
end // case: HALF
// Both Registers Full.
// Upstream can not push to us in this state.
// Downstream can always read from us.
FULL: begin
if (o_tready) begin
state <= HALF;
i_tready <= 1'b1;
o_tvalid <= 1'b1;
end
else begin
state <= FULL;
i_tready <= 1'b0;
o_tvalid <= 1'b1;
end
end
endcase // case(state)
end // else: !if(reset | clear)
assign o_tdata = (state == FULL) ? data_reg2 : data_reg1;
endmodule // axi_fast_fifo
-42
View File
@@ -1,42 +0,0 @@
module axi_lite_slave
(
input aclk, // Global AXI clock
input aresetn, // Global AXI reset, active low.
//
// AXI Write address channel
//
input [31 : 0] m_axi_awaddr, // Write address. The write address gives the address of the first transfer in a write burst
input [2 : 0] m_axi_awprot, // Protection type. This signal indicates the privilege and security level of the transaction
input m_axi_awvalid, // Write address valid. This signal indicates that the channel is signaling valid write addr
output m_axi_awready, // Write address ready. This signal indicates that the slave is ready to accept an address
//
// AXI Write data channel.
//
input [31 : 0] m_axi_wdata, // Write data
input [3 : 0] m_axi_wstrb, // Write strobes. This signal indicates which byte lanes hold valid data.
input m_axi_wvalid, // Write valid. This signal indicates that valid write data and strobes are available.
output m_axi_wready, // Write ready. This signal indicates that the slave can accept the write data.
//
// AXI Write response channel signals
//
output [1 : 0] m_axi_bresp, // Write response. This signal indicates the status of the write transaction.
output m_axi_bvalid, // Write response valid. This signal indicates that the channel is signaling a valid response
input m_axi_bready, // Response ready. This signal indicates that the master can accept a write response
//
// AXI Read address channel
//
input [31 : 0] m_axi_araddr, // Read address. The read address gives the address of the first transfer in a read burst
input [2 : 0] m_axi_arprot, // Protection type. This signal indicates the privilege and security level of the transaction
input m_axi_arvalid, // Read address valid. This signal indicates that the channel is signaling valid read addr
output m_axi_arready, // Read address ready. This signal indicates that the slave is ready to accept an address
//
// AXI Read data channel
//
output [31 : 0] m_axi_rdata, // Read data.
output [1 : 0] m_axi_rresp, // Read response. This signal indicates the status of the read transfer
output m_axi_rvalid, // Read valid. This signal indicates that the channel is signaling the required read data.
input m_axi_rready, // Read ready. This signal indicates that the master can accept the read data and response
//
//
//
)
-28
View File
@@ -1,28 +0,0 @@
#
# Copyright 2013 Ettus Research LLC
#
##################################################
# Control Lib Sources
##################################################
CONTROL_LIB_SRCS = $(abspath $(addprefix $(BASE_DIR)/../lib/control/, \
reset_sync.v \
por_gen.v \
gpio_atr.v \
simple_spi_core.v \
simple_i2c_core.v \
setting_reg.v \
settings_bus_crossclock.v \
radio_ctrl_proc.v \
ram_2port.v \
axi_crossbar.v \
axi_slave_mux.v \
axi_fifo_header.v \
arb_qualify_master.v \
axi_forwarding_cam.v \
axi_test_vfifo.v \
dram_2port.v \
cvita_uart.v \
serial_to_settings.v \
filter_bad_sid.v \
))
View File
-88
View File
@@ -1,88 +0,0 @@
//
// Copyright 2012 Ettus Research LLC
//
//
// This module forms the qualification engine for a single master as
// part of a larger arbitration engine for a slave. It would typically
// be instantiated from arb_select_master.v to form a complete arbitor solution.
//
module arb_qualify_master
#(
parameter WIDTH=16 // Bit width of destination field.
)
(
input clk,
input reset,
input clear,
// Header signals
input [WIDTH-1:0] header,
input header_valid,
// Slave Confg Signals
input [WIDTH-1:0] slave_addr,
input [WIDTH-1:0] slave_mask,
input slave_valid,
// Arbitration flags
output reg master_valid,
input master_ack
);
localparam WAIT_HEADER_VALID = 0;
localparam MATCH = 1;
localparam WAIT_HEADER_NOT_VALID = 2;
reg [1:0] state, next_state;
// Does masked slave address match header field for dest from master?
assign header_match = ((header & slave_mask) == (slave_addr & slave_mask)) && slave_valid;
always @(posedge clk)
if (reset | clear) begin
state <= WAIT_HEADER_VALID;
master_valid <= 0;
end else
begin
case(state)
//
// Wait here until Masters FIFO presents a valid header word.
//
WAIT_HEADER_VALID: begin
if (header_valid)
if (header_match) begin
state <= MATCH;
master_valid <= 1;
end else
next_state <= WAIT_HEADER_NOT_VALID;
end
//
// There should only ever be one match across various arbitors
// if they are configured correctly and since the backing FIFO in the
// master should not start to drain until the arbitration is won
// by that master, master_ack should always preceed de-assertion of
// header_valid so we don't check for the other order of deassertion.
//
MATCH: begin
if (master_ack) begin
master_valid <= 0;
state <= WAIT_HEADER_NOT_VALID;
end
end
//
// Wait here until this master starts to drain this packet from his FIFO.
//
WAIT_HEADER_NOT_VALID: begin
if (!header_valid) begin
state <= WAIT_HEADER_VALID;
end
end
endcase // case(state)
end // else: !if(reset | clear)
endmodule // arb_qualify_master
-167
View File
@@ -1,167 +0,0 @@
//
// Copyright 2012 Ettus Research LLC
//
`define LOG2(N) (\
N < 2 ? 0 : \
N < 4 ? 1 : \
N < 8 ? 2 : \
N < 16 ? 3 : \
N < 32 ? 4 : \
N < 64 ? 5 : \
N < 128 ? 6 : \
N < 256 ? 7 : \
N < 512 ? 8 : \
N < 1024 ? 9 : \
10)
module axi_crossbar
#(
parameter FIFO_WIDTH = 64, // AXI4-STREAM data bus width
parameter DST_WIDTH = 16, // Width of DST field we are routing on.
parameter NUM_INPUTS = 2, // number of input AXI4-STREAM buses
parameter NUM_OUTPUTS = 2 // number of output AXI4-STREAM buses
)
(
input clk,
input reset,
input clear,
input [7:0] local_addr,
// Inputs
input [(FIFO_WIDTH*NUM_INPUTS)-1:0] i_tdata,
input [NUM_INPUTS-1:0] i_tvalid,
input [NUM_INPUTS-1:0] i_tlast,
output [NUM_INPUTS-1:0] i_tready,
input [NUM_INPUTS-1:0] pkt_present,
// Setting Bus
input set_stb,
input [15:0] set_addr,
input [31:0] set_data,
// Output
output [(FIFO_WIDTH*NUM_OUTPUTS)-1:0] o_tdata,
output [NUM_OUTPUTS-1:0] o_tvalid,
output [NUM_OUTPUTS-1:0] o_tlast,
input [NUM_OUTPUTS-1:0] o_tready,
// readback bus
input rb_rd_stb,
input [`LOG2(NUM_OUTPUTS)+`LOG2(NUM_INPUTS)-1:0] rb_addr,
output [31:0] rb_data
);
genvar m,n;
wire [(NUM_INPUTS*NUM_OUTPUTS)-1:0] forward_valid_in;
wire [(NUM_INPUTS*NUM_OUTPUTS)-1:0] forward_ack_in;
wire [(NUM_INPUTS*NUM_OUTPUTS)-1:0] forward_valid_out;
wire [(NUM_INPUTS*NUM_OUTPUTS)-1:0] forward_ack_out;
wire [NUM_INPUTS-1:0] i_tready_slave [0:NUM_OUTPUTS-1];
//
// Instantiate an axi_slave_mux for every slave/output of the Crossbar switch.
// Each axi_slave_mux contains logic to maux and resolve arbitration
// for this particular slave/output.
//
generate
for (m = 0; m < NUM_OUTPUTS; m = m + 1) begin: instantiate_slave_mux
wire [NUM_INPUTS-1:0] i_tready_tmp;
axi_slave_mux
#(
.FIFO_WIDTH(FIFO_WIDTH), // AXI4-STREAM data bus width
.DST_WIDTH(DST_WIDTH), // Width of DST field we are routing on.
.NUM_INPUTS(NUM_INPUTS) // number of input AXI buses
) axi_slave_mux_i
(
.clk(clk),
.reset(reset),
.clear(clear),
// Inputs
.i_tdata(i_tdata),
.i_tvalid(i_tvalid),
.i_tlast(i_tlast),
.i_tready(i_tready_tmp),
// Forwarding flags (One from each Input/Master)
.forward_valid(forward_valid_in[(m+1)*NUM_INPUTS-1:m*NUM_INPUTS]),
.forward_ack(forward_ack_out[(m+1)*NUM_INPUTS-1:m*NUM_INPUTS]),
// Output
.o_tdata(o_tdata[(m*FIFO_WIDTH)+FIFO_WIDTH-1:m*FIFO_WIDTH]),
.o_tvalid(o_tvalid[m]),
.o_tlast(o_tlast[m]),
.o_tready(o_tready[m])
);
if (m==0)
assign i_tready_slave[0] = i_tready_tmp;
else
assign i_tready_slave[m] = i_tready_tmp | i_tready_slave[m-1] ;
end // block: instantiate_slave_mux
endgenerate
assign i_tready = i_tready_slave[NUM_OUTPUTS-1];
//
// Permute the forwarding flag buses
//
generate
for (m = 0; m < NUM_OUTPUTS; m = m + 1) begin: permute_outer
for (n = 0; n < NUM_INPUTS; n = n + 1) begin: permute_inner
assign forward_valid_in[n*NUM_OUTPUTS+m] = forward_valid_out[n+m*NUM_INPUTS];
assign forward_ack_in[n+m*NUM_INPUTS] = forward_ack_out[n*NUM_OUTPUTS+m];
end
end
endgenerate
//
// Instantiate an axi_forwarding_cam for every Input/Master of the Crossbar switch.
// Each contains a TCAM like lookup that allocates an egress port.
//
wire [31:0] rb_data_mux[0:NUM_INPUTS-1];
generate
for (m = 0; m < NUM_INPUTS; m = m + 1) begin: instantiate_cam
axi_forwarding_cam
#(
.BASE(0),
.WIDTH(FIFO_WIDTH), // Bit width of FIFO word.
.NUM_OUTPUTS(NUM_OUTPUTS)
) axi_forwarding_cam_i
(
.clk(clk),
.reset(reset),
.clear(clear),
// Monitored FIFO signals
.o_tdata(i_tdata[(m*FIFO_WIDTH)+FIFO_WIDTH-1:m*FIFO_WIDTH]),
.o_tvalid(i_tvalid[m]),
.o_tready(i_tready[m]),
.o_tlast(i_tlast[m]),
.pkt_present(pkt_present[m]),
// Configuration
.local_addr(local_addr),
// Setting Bus
.set_stb(set_stb),
.set_addr(set_addr),
.set_data(set_data),
// Header signals
.forward_valid(forward_valid_out[(m+1)*NUM_OUTPUTS-1:m*NUM_OUTPUTS]),
.forward_ack(forward_ack_in[(m+1)*NUM_OUTPUTS-1:m*NUM_OUTPUTS]),
// Readback bus
.rb_rd_stb(rb_rd_strobe && (rb_addr[`LOG2(NUM_OUTPUTS)+`LOG2(NUM_INPUTS)-1:`LOG2(NUM_OUTPUTS)] == m)),
.rb_addr(rb_addr[`LOG2(NUM_OUTPUTS)-1:0]),
.rb_data(rb_data_mux[m])
);
end // block: instantiate_fifo_header
endgenerate
assign rb_data = rb_data_mux[rb_addr[`LOG2(NUM_OUTPUTS)+`LOG2(NUM_INPUTS)-1:`LOG2(NUM_OUTPUTS)]];
endmodule // axi_crossbar
-214
View File
@@ -1,214 +0,0 @@
//
// Copyright 2012 Ettus Research LLC
//
`timescale 1 ps / 1 ps
module axi_crossbar_tb;
localparam STREAM_WIDTH = 64;
// Currently support simulations upto 8x8 configurations
localparam MAX_NUM_INPUTS = 8;
localparam MAX_NUM_OUTPUTS = 8;
wire [(MAX_NUM_INPUTS*STREAM_WIDTH)-1:0] i_tdata;
wire [STREAM_WIDTH-1:0] i_tdata_array [0:MAX_NUM_INPUTS-1];
wire [MAX_NUM_INPUTS-1:0] i_tvalid;
wire [MAX_NUM_INPUTS-1:0] i_tready;
wire [MAX_NUM_INPUTS-1:0] i_tlast;
wire [MAX_NUM_INPUTS-1:0] pkt_present;
reg [STREAM_WIDTH-1:0] data_in [0:MAX_NUM_INPUTS-1];
reg [MAX_NUM_INPUTS-1:0] valid_in;
wire [MAX_NUM_INPUTS-1:0] ready_in;
reg [MAX_NUM_INPUTS-1:0] last_in;
wire [(MAX_NUM_OUTPUTS*STREAM_WIDTH)-1:0] o_tdata;
wire [STREAM_WIDTH-1:0] o_tdata_array [0:MAX_NUM_OUTPUTS-1];
wire [MAX_NUM_OUTPUTS-1:0] o_tvalid;
wire [MAX_NUM_OUTPUTS-1:0] o_tready;
wire [MAX_NUM_OUTPUTS-1:0] o_tlast;
wire [STREAM_WIDTH-1:0] data_out [0:MAX_NUM_OUTPUTS-1];
wire [MAX_NUM_OUTPUTS-1:0] valid_out;
reg [MAX_NUM_OUTPUTS-1:0] ready_out;
wire [MAX_NUM_OUTPUTS-1:0] last_out;
genvar m;
reg clk;
reg reset;
reg clear;
reg set_stb;
reg [15:0] set_addr;
reg [31:0] set_data;
// reg reset;
//
// Simulation specific testbench is included here
//
`include "task_library.v"
`include "simulation_script.v"
//
// Define Clocks
//
initial begin
clk = 1'b1;
end
// 125MHz clock
always #4000 clk = ~clk;
//
// Good starting state
//
initial begin
reset <= 0;
clear <= 0;
set_stb <= 0;
set_addr <= 0;
set_data <= 0;
/* -----\/----- EXCLUDED -----\/-----
data_in[0] <= 0;
valid_in[0] <= 0;
last_in[0] <= 0;
data_in[1] <= 0;
valid_in[1] <= 0;
last_in[1] <= 0;
-----/\----- EXCLUDED -----/\----- */
end
//
// AXI Crossbar instance
//
localparam SR_AWIDTH = 16;
localparam SR_XB_LOCAL = 512;
wire [7:0] local_addr;
setting_reg #(.my_addr(SR_XB_LOCAL), .awidth(SR_AWIDTH), .width(8)) sr_local_addr
(.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr),
.in(set_data),.out(local_addr),.changed());
axi_crossbar
#(
.FIFO_WIDTH(STREAM_WIDTH), // AXI4-STREAM data bus width
.DST_WIDTH(16), // Width of DST field we are routing on.
.NUM_INPUTS(NUM_INPUTS), // number of input AXI4-STREAM buses
.NUM_OUTPUTS(NUM_OUTPUTS) // number of output AXI4-STREAM buses
) axi_crossbar_i
(
.clk(clk),
.reset(reset),
.clear(clear),
.local_addr(local_addr),
// Inputs
.i_tdata(i_tdata[(NUM_INPUTS*STREAM_WIDTH)-1:0]),
.i_tvalid(i_tvalid[NUM_INPUTS-1:0]),
.i_tlast(i_tlast[NUM_INPUTS-1:0]),
.i_tready(i_tready[NUM_INPUTS-1:0]),
.pkt_present(pkt_present[NUM_INPUTS-1:0]),
// Settings bus
.set_stb(set_stb),
.set_addr(set_addr),
.set_data(set_data),
// Output
.o_tdata(o_tdata[(NUM_OUTPUTS*STREAM_WIDTH)-1:0]),
.o_tvalid(o_tvalid[NUM_OUTPUTS-1:0]),
.o_tlast(o_tlast[NUM_OUTPUTS-1:0]),
.o_tready(o_tready[NUM_OUTPUTS-1:0]),
// Readback Bus
.rb_rd_stb(1'b0),
.rb_addr(0),
.rb_data()
);
//
// Input FIFOs
//
generate
for (m=0;m<NUM_INPUTS;m=m+1)
begin: input_fifos
assign i_tdata[(STREAM_WIDTH*m)+STREAM_WIDTH-1:STREAM_WIDTH*m] = i_tdata_array[m];
axi_fifo_short
#(.WIDTH(STREAM_WIDTH+1)) axi_fifo_short_in
(
.clk(clk),
.reset(reset),
.clear(clear),
.o_tdata({i_tlast[m],i_tdata_array[m]}),
.o_tvalid(i_tvalid[m]),
.o_tready(i_tready[m]),
.i_tdata({last_in[m],data_in[m]}),
.i_tvalid(valid_in[m]),
.i_tready(ready_in[m]),
.space(),
.occupied()
);
monitor_axi_fifo
#(
.COUNT_BITS(8)
) monitor_axi_fifo_in
(
.clk(clk),
.reset(reset),
.clear(clear),
// Monitored FIFO signals
.i_tvalid(valid_in[m]),
.i_tready(ready_in[m]),
.i_tlast(last_in[m]),
.o_tvalid(i_tvalid[m]),
.o_tready(i_tready[m]),
.o_tlast(i_tlast[m]),
// FIFO status output
.pkt_present(pkt_present[m]), // Flags any whole packets present
.pkt_count()
);
end
endgenerate
//
// Output FIFO's
//
generate
for (m=0;m<NUM_OUTPUTS;m=m+1)
begin: output_fifos
assign o_tdata_array[m] = o_tdata[(STREAM_WIDTH*m)+STREAM_WIDTH-1:STREAM_WIDTH*m];
axi_fifo_short
#(.WIDTH(STREAM_WIDTH+1)) axi_fifo_short_out
(
.clk(clk),
.reset(reset),
.clear(clear),
.i_tdata({o_tlast[m],o_tdata_array[m]}),
.i_tvalid(o_tvalid[m]),
.i_tready(o_tready[m]),
.o_tdata({last_out[m],data_out[m]}),
.o_tvalid(valid_out[m]),
.o_tready(ready_out[m]),
.space(),
.occupied()
);
end
endgenerate // block: output_fifos
endmodule // axi_crossbar_tb
-84
View File
@@ -1,84 +0,0 @@
//
// Copyright 2012 Ettus Research LLC
//
//
// This module is connected to the output port of an AXI4-STREAM FIFO that is used to move packetized data.
// It extracts and indicates the header (first word) of a packet in the FIFO. The header and flag are pipelined
// for timing closure.
//
module axi_fifo_header
#(
parameter WIDTH=64 // Bit width of FIFO word.
)
(
input clk,
input reset,
input clear,
// Monitored FIFO signals
input [WIDTH-1:0] o_tdata,
input o_tvalid,
input o_tready,
input o_tlast,
input pkt_present,
// Header signals
output reg [WIDTH-1:0] header,
output reg header_valid
);
localparam WAIT_SOF = 0;
localparam WAIT_EOF = 1;
reg out_state;
//
// Monitor packets leaving FIFO
//
always @(posedge clk)
if (reset | clear) begin
out_state <= WAIT_SOF;
end else
case(out_state)
//
// After RESET or the EOF of previous packet, the first cycle with
// output valid asserted is the SOF and presents the Header word.
// The cycle following the concurrent presentation of asserted output
// valid and output ready presents the word following the header.
//
WAIT_SOF:
if (o_tvalid && o_tready) begin
out_state <= WAIT_EOF;
end else begin
out_state <= WAIT_SOF;
end
//
// EOF is signalled by o_tlast asserted whilst output valid and ready asserted.
//
WAIT_EOF:
if (o_tlast && o_tvalid && o_tready) begin
out_state <= WAIT_SOF;
end else begin
out_state <= WAIT_EOF;
end
endcase // case(in_state)
//
// Pipeline Header signals
//
always @(posedge clk)
if (reset | clear) begin
header <= 0;
header_valid <= 0;
end else if (o_tvalid && (out_state == WAIT_SOF) && pkt_present) begin
// Header will remian valid until o_tready is asserted as this will cause a state transition.
header <= o_tdata;
header_valid <= 1;
end else begin
header_valid <= 0;
end
endmodule // axi_fifo_header
-232
View File
@@ -1,232 +0,0 @@
//
// Copyright 2013 Ettus Research LLC
//
//
// This module implements a highly customized TCAM that enbales forwarding
// decisions to be made on a 16bit field from a VITA SID field.
// The 16bits are allocated by convention as 8 bits of Network address
// (Addresses USRP's etc) and 8 bits of Host address (adresses endpoints in
// a USRP). By definition if the DEST field in the SID addresses a different
// USRP than this one then we don't care about the Host field, only the Network Field.
// We only look at the Host Field when the Network field addresses us.
// Thus Need TCAM of 256+256 entries with Log2(N) bits, where N is the number of
// slave(output) ports on the crossbar switch.
//
//
//
// SID format:
//
// |--------|---------|--------|---------|
// | SOURCE | DEST | DEST |
// | ADDRESS | NETWORK| HOST |
// |--------|---------|--------|---------|
// 8 8 8 8
//
`define LOG2(N) (\
N < 2 ? 0 : \
N < 4 ? 1 : \
N < 8 ? 2 : \
N < 16 ? 3 : \
N < 32 ? 4 : \
N < 64 ? 5 : \
N < 128 ? 6 : \
N < 256 ? 7 : \
N < 512 ? 8 : \
N < 1024 ? 9 : \
10)
module axi_forwarding_cam
#(
parameter BASE = 0, // BASE address for setting registers in this block. (512 addrs used)
parameter WIDTH=64, // Bit width of FIFO word.
parameter NUM_OUTPUTS=2 // Number of outputs (destinations) in crossbar.
)
(
input clk,
input reset,
input clear,
// Monitored FIFO signals
input [WIDTH-1:0] o_tdata,
input o_tvalid,
input o_tready,
input o_tlast,
input pkt_present,
// Configuration
input [7:0] local_addr,
// Setting Bus
input set_stb,
input [15:0] set_addr,
input [31:0] set_data,
// Forwarding Flags
output reg [NUM_OUTPUTS-1:0] forward_valid,
input [NUM_OUTPUTS-1:0] forward_ack,
// readback bus
input rb_rd_stb,
input [`LOG2(NUM_OUTPUTS)-1:0] rb_addr,
output [31:0] rb_data
);
localparam WAIT_SOF = 0;
localparam WAIT_EOF = 1;
reg state;
localparam IDLE = 0;
localparam FORWARD = 1;
localparam WAIT = 2;
reg [1:0] demux_state;
reg [15:0] dst;
reg dst_valid, dst_valid_reg;
wire local_dst;
wire [8:0] read_addr;
//
// Monitor packets leaving FIFO
//
always @(posedge clk)
if (reset | clear) begin
state <= WAIT_SOF;
end else
case(state)
//
// After RESET or the EOF of previous packet, the first cycle with
// output valid asserted is the SOF and presents the Header word.
// The cycle following the concurrent presentation of asserted output
// valid and output ready presents the word following the header.
//
WAIT_SOF:
if (o_tvalid && o_tready) begin
state <= WAIT_EOF;
end else begin
state <= WAIT_SOF;
end
//
// EOF is signalled by o_tlast asserted whilst output valid and ready asserted.
//
WAIT_EOF:
if (o_tlast && o_tvalid && o_tready) begin
state <= WAIT_SOF;
end else begin
state <= WAIT_EOF;
end
endcase // case(in_state)
//
// Extract Destination fields(s) from SID
//
always @(posedge clk)
if (reset | clear) begin
dst <= 0;
dst_valid <= 0;
dst_valid_reg <= 0;
end else if (o_tvalid && (state == WAIT_SOF) && pkt_present) begin
// SID will remain valid until o_tready is asserted as this will cause a state transition.
dst <= o_tdata[15:0];
dst_valid <= 1;
dst_valid_reg <= dst_valid;
end else begin
dst_valid <= 0;
dst_valid_reg <= dst_valid;
end
//
// Is Network field in DST our local address?
//
assign local_dst = (dst[15:8] == local_addr) && dst_valid;
//
// Mux address to RAM so that it searches CAM for Network field or Host field.
// Network addresses are stored in the lower 256 locations, host addresses the upper 256.
//
assign read_addr = {local_dst,(local_dst ? dst[7:0] : dst[15:8])};
//
// Imply a block RAM here, 512xCeil(Log2(NUM_OUTPUTS))
//
//synthesis attribute ram_style of mem is block
reg [(`LOG2(NUM_OUTPUTS))-1 : 0] mem [0:511];
reg [8:0] read_addr_reg;
wire write;
wire [`LOG2(NUM_OUTPUTS)-1:0] read_data;
assign write = (set_addr[15:9] == (BASE >>9)) && set_stb; // Addr decode.
always @(posedge clk)
begin
read_addr_reg <= read_addr;
if (write) begin
mem[set_addr[8:0]] <= set_data[`LOG2(NUM_OUTPUTS)-1:0];
end
end
assign read_data = mem[read_addr_reg];
//
// State machine to manage forwarding flags.
//
always @(posedge clk)
if (reset | clear) begin
demux_state <= IDLE;
end else
case(demux_state)
// Wait for Valid DST which indicates a new packet lookup in the CAM.
IDLE: begin
if (dst_valid_reg == 1) begin
forward_valid <= 1 << read_data;
demux_state <= FORWARD;
end
end
// When Slave/Output thats forwarding ACK's the forward flag, clear request and wait for packet to be transfered
FORWARD: begin
if ((forward_ack & forward_valid) != 0) begin
forward_valid <= 0;
demux_state <= WAIT;
end
end
// When packet transfered go back to idle.
WAIT: begin
if (forward_ack == 0)
demux_state <= IDLE;
end
endcase // case (demux_state)
//
// Compile forwarding statistics
// (This uses a lot of registers!)
//
genvar m;
reg [31:0] statistics [0:NUM_OUTPUTS-1];
generate
for (m = 0; m < NUM_OUTPUTS; m = m + 1) begin: generate_stats
always @(posedge clk)
if (reset | clear)
statistics[m] <= 0;
else if ((rb_addr == m) && rb_rd_stb)
statistics[m] <= 0;
else if (forward_ack[m] & forward_valid[m])
statistics[m] <= statistics[m] + 1;
end
endgenerate
assign rb_data = statistics[rb_addr];
endmodule
-122
View File
@@ -1,122 +0,0 @@
//
// Copyright 2012 Ettus Research LLC
//
`define LOG2(N) (\
N < 2 ? 0 : \
N < 4 ? 1 : \
N < 8 ? 2 : \
N < 16 ? 3 : \
N < 32 ? 4 : \
N < 64 ? 5 : \
N < 128 ? 6 : \
N < 256 ? 7 : \
N < 512 ? 8 : \
N < 1024 ? 9 : \
10)
module axi_slave_mux
#(
parameter FIFO_WIDTH = 64, // AXI4-STREAM data bus width
parameter DST_WIDTH = 16, // Width of DST field we are routing on.
parameter NUM_INPUTS = 2 // number of input AXI buses
)
(
input clk,
input reset,
input clear,
// Inputs
input [(FIFO_WIDTH*NUM_INPUTS)-1:0] i_tdata,
input [NUM_INPUTS-1:0] i_tvalid,
input [NUM_INPUTS-1:0] i_tlast,
output [NUM_INPUTS-1:0] i_tready,
// Forwarding Flags
input [NUM_INPUTS-1:0] forward_valid,
output reg [NUM_INPUTS-1:0] forward_ack,
// Output
output [FIFO_WIDTH-1:0] o_tdata,
output o_tvalid,
output o_tlast,
input o_tready
);
wire [FIFO_WIDTH-1:0] i_tdata_array [0:NUM_INPUTS-1];
reg [`LOG2(NUM_INPUTS):0] select;
reg enable;
reg state;
localparam CHECK_THIS_INPUT = 0;
localparam WAIT_LAST = 1;
always @(posedge clk)
if (reset | clear) begin
state <= CHECK_THIS_INPUT;
select <= 0;
enable <= 0;
forward_ack <= 0;
end else begin
case(state)
// Is the currently selected input addressing this slave with a ready packet?
CHECK_THIS_INPUT: begin
if (forward_valid[select]) begin
enable <= 1;
forward_ack[select] <= 1;
state <= WAIT_LAST;
end else if (select == NUM_INPUTS - 1 ) begin
select <= 0;
end else begin
select <= select + 1;
end
end
// Assert ACK immediately to forwarding logic and then wait for end of packet.
WAIT_LAST: begin
if (i_tlast[select] && i_tvalid[select] && o_tready) begin
if (select == NUM_INPUTS - 1 ) begin
select <= 0;
end else begin
select <= select + 1;
end
state <= CHECK_THIS_INPUT;
forward_ack <= 0;
enable <= 0;
end else begin
forward_ack[select] <= 1;
enable <= 1;
end
end
endcase // case(state)
end
//
// Combinatorial mux
//
genvar m;
generate
for (m = 0; m < NUM_INPUTS; m = m + 1) begin: form_buses
assign i_tdata_array[m] = i_tdata[(m*FIFO_WIDTH)+FIFO_WIDTH-1:m*FIFO_WIDTH];
end
endgenerate
assign o_tdata = i_tdata_array[select];
assign o_tvalid = enable && i_tvalid[select];
assign o_tlast = enable && i_tlast[select];
// assign i_tready = {NUM_INPUTS{o_tready}} & (enable << select);
generate
for (m = 0; m < NUM_INPUTS; m = m + 1) begin: form_ready
assign i_tready[m] = o_tready && enable && (select == m);
end
endgenerate
endmodule // axi_slave_mux
-139
View File
@@ -1,139 +0,0 @@
//
// Test Virtual FIFO's by streaming modulo 2^32 counter (replicated in upper
// and lower 32bits). Test result by tracking count on receive and using
// sticky flag for error indication.
// Also provide signal from MSB of 32bit count to blink LED.
//
module axi_test_vfifo
#(parameter PACKET_SIZE = 128)
(
input aclk,
input aresetn,
input enable,
// AXI Stream Out
output reg out_axis_tvalid,
input out_axis_tready,
output [63 : 0] out_axis_tdata,
output reg [7 : 0] out_axis_tstrb,
output reg [7 : 0] out_axis_tkeep,
output reg out_axis_tlast,
output reg [0 : 0] out_axis_tid,
output reg [0 : 0] out_axis_tdest,
input vfifo_full,
// AXI Stream In
input in_axis_tvalid,
output reg in_axis_tready,
input [63 : 0] in_axis_tdata,
input [7 : 0] in_axis_tstrb,
input [7 : 0] in_axis_tkeep,
input in_axis_tlast,
input [0 : 0] in_axis_tid,
input [0 : 0] in_axis_tdest,
// Flags
output reg flag_error,
output heartbeat_in,
output heartbeat_out,
output [31:0] expected_count
);
reg [31:0] out_count;
reg [31:0] in_count;
reg [63:0] in_axis_tdata_reg;
reg in_data_valid;
//
// Output
//
always @(posedge aclk)
if (!aresetn) begin
out_count <= 0;
out_axis_tvalid <= 0;
out_axis_tid <= 0; // Don't care.
out_axis_tdest <= 0; // Only use port 0 of VFIFO.
out_axis_tstrb <= 0; // Unused in VFIFO
out_axis_tkeep <= 8'hFF; // Always use every byte of data
out_axis_tlast <= 1'b0;
end else if (enable) begin
if (~vfifo_full) begin
// Always ready to output new count value.
out_axis_tvalid <= 1;
if (out_axis_tready)
out_count <= out_count + 1;
// Assert TLAST every PACKET_SIZE beats.
if (out_count[15:0] == PACKET_SIZE)
out_axis_tlast <= 1'b1;
else
out_axis_tlast <= 1'b0;
end else begin
out_axis_tvalid <= 0;
end
end else begin
out_axis_tlast <= 1'b0;
out_axis_tvalid <= 0;
end
assign out_axis_tdata = {out_count,out_count};
assign heartbeat_out = out_count[28];
//
// Input (Ignore TLAST signal)
//
always @(posedge aclk)
if (!aresetn) begin
in_axis_tready <= 0;
in_axis_tdata_reg <= 0;
in_data_valid <= 0;
end else if (enable) begin
in_axis_tready <= 1;
in_axis_tdata_reg <= in_axis_tdata;
if (in_axis_tvalid)
in_data_valid <= 1;
else
in_data_valid <= 0;
end else begin
in_data_valid <= 0;
in_axis_tready <= 0;
end // else: !if(enable)
assign heartbeat_in = in_count[28];
//
// Input Checker
//
always @(posedge aclk)
if (!aresetn) begin
in_count <= 0;
flag_error <= 0;
end else if (enable) begin
if (in_data_valid) begin
if ((in_axis_tdata_reg[63:32] != in_count) || (in_axis_tdata_reg[31:0] != in_count))
begin
flag_error <= 1;
in_count <= in_axis_tdata_reg[63:32] + 1;
end
else
begin
flag_error <= 0;
in_count <= in_count + 1;
end
end
end
assign expected_count = in_count;
endmodule // axi_test_vfifo
-42
View File
@@ -1,42 +0,0 @@
`define LOG2(N) (\
N < 2 ? 0 : \
N < 4 ? 1 : \
N < 8 ? 2 : \
N < 16 ? 3 : \
N < 32 ? 4 : \
N < 64 ? 5 : \
N < 128 ? 6 : \
N < 256 ? 7 : \
N < 512 ? 8 : \
N < 1024 ? 9 : \
10)
module binary_encoder
#(
parameter SIZE = 16
)
(
input [SIZE-1:0] in,
output [`LOG2(SIZE)-1:0] out
);
genvar m,n;
generate
// Loop enough times to represent the total number of input bits as an encoded value
for (m = 0; m <= `log2(SIZE-1); m = m + 1) begin: expand_or_tree
wire [SIZE-1:0] encoding;
// Build enable mask by iterating through every input bit.
for (n = 0; n < SIZE ; n = n + 1) begin: encode_this_bit
assign encoding[n] = n[m];
end
// OR tree for this output bit with appropraite bits enabled.
assign out[m] = |(encoding & in);
end
endgenerate
endmodule // binary_encoder
-164
View File
@@ -1,164 +0,0 @@
//
// Copyright 2013 Ettus Research LLC
//
//create a compressed vita based uart data interface
module cvita_uart
#(
parameter SIZE = 0
)
(
//clocking interface
input clk, input rst,
//uart interface
input rxd, output txd,
//chdr fifo input
input [63:0] i_tdata,
input i_tlast,
input i_tvalid,
output i_tready,
//chdr fifo output
output [63:0] o_tdata,
output o_tlast,
output o_tvalid,
input o_tready
);
reg [31:0] sid;
//baud clock divider
reg [15:0] clkdiv;
//hold rx in disable until a tx event
reg rxd_enable;
//==================================================================
//== RXD capture and packet generation interface
//==================================================================
wire [7:0] rx_char;
wire fifo_empty;
wire fifo_read;
reg [11:0] seqnum;
wire pgen_trigger;
wire pgen_done;
//rx uart capture
simple_uart_rx #(.SIZE(SIZE)) simple_uart_rx
(
.clk(clk), .rst(rst),
.fifo_out(rx_char), .fifo_read(fifo_read), .fifo_level(), .fifo_empty(fifo_empty),
.clkdiv(clkdiv), .rx(rxd)
);
//packet generation - holds rx character
context_packet_gen context_packet_gen
(
.clk(clk), .reset(rst), .clear(1'b0),
.trigger(pgen_trigger),
.seqnum(seqnum),
.sid({sid[15:0], sid[31:16]}),
.body({56'b0, rx_char}),
.vita_time(64'b0),
.done(pgen_done),
.o_tdata(o_tdata), .o_tlast(o_tlast), .o_tvalid(o_tvalid), .o_tready(o_tready)
);
//state machine to manage pgen and rx uart
reg [1:0] rxd_state;
localparam RXD_STATE_RECV_CHAR = 0;
localparam RXD_STATE_PGEN_TRIG = 1;
localparam RXD_STATE_WAIT_DONE = 2;
localparam RXD_STATE_READ_FIFO = 3;
always @(posedge clk) begin
if (rst) begin
seqnum <= 12'b0;
rxd_state <= RXD_STATE_RECV_CHAR;
end
else case (rxd_state)
RXD_STATE_RECV_CHAR: begin
if (!fifo_empty && rxd_enable) rxd_state <= RXD_STATE_PGEN_TRIG;
end
RXD_STATE_PGEN_TRIG: begin
rxd_state <= RXD_STATE_WAIT_DONE;
end
RXD_STATE_WAIT_DONE: begin
if (pgen_done) rxd_state <= RXD_STATE_READ_FIFO;
end
RXD_STATE_READ_FIFO: begin
rxd_state <= RXD_STATE_RECV_CHAR;
seqnum <= seqnum + 1'b1;
end
endcase //rxd_state
end
assign fifo_read = (rxd_state == RXD_STATE_READ_FIFO) || (!rxd_enable);
assign pgen_trigger = (rxd_state == RXD_STATE_PGEN_TRIG);
//==================================================================
//== TXD generation and packet control interface
//==================================================================
wire [7:0] tx_char;
wire fifo_write;
wire fifo_full;
simple_uart_tx #(.SIZE(SIZE)) simple_uart_tx
(
.clk(clk), .rst(rst),
.fifo_in(tx_char), .fifo_write(fifo_write), .fifo_level(), .fifo_full(fifo_full),
.clkdiv(clkdiv), .baudclk(), .tx(txd)
);
//state machine to manage control and tx uart
reg [1:0] txd_state;
localparam TXD_STATE_RECV_CHDR = 0;
localparam TXD_STATE_RECV_TIME = 1;
localparam TXD_STATE_RECV_BODY = 2;
localparam TXD_STATE_DROP_FIFO = 3;
always @(posedge clk) begin
if (rst) begin;
txd_state <= TXD_STATE_RECV_CHDR;
rxd_enable <= 1'b0;
end
if (i_tvalid && i_tready) case (txd_state)
TXD_STATE_RECV_CHDR: begin
txd_state <= (i_tdata[61])? TXD_STATE_RECV_TIME : TXD_STATE_RECV_BODY;
sid <= i_tdata[31:0];
end
TXD_STATE_RECV_TIME: begin
txd_state <= TXD_STATE_RECV_BODY;
end
TXD_STATE_RECV_BODY: begin
txd_state <= (i_tlast)? TXD_STATE_RECV_CHDR : TXD_STATE_DROP_FIFO;
clkdiv <= i_tdata[47:32];
rxd_enable <= 1'b1;
end
TXD_STATE_DROP_FIFO: begin
if (i_tlast) txd_state <= TXD_STATE_RECV_CHDR;
end
endcase //txd_state
end
assign tx_char = i_tdata[7:0];
assign fifo_write = (txd_state == TXD_STATE_RECV_BODY) && i_tvalid && i_tready;
assign i_tready = !fifo_full;
endmodule // cvita_uart
-27
View File
@@ -1,27 +0,0 @@
////////////////////////////////////////////////////////////////////////
// Copyright Ettus Research LLC
////////////////////////////////////////////////////////////////////////
module dram_2port
#(parameter DWIDTH=32,
parameter AWIDTH=9)
(input clk,
input write,
input [AWIDTH-1:0] raddr,
input [AWIDTH-1:0] waddr,
input [DWIDTH-1:0] wdata,
output [DWIDTH-1:0] rdata);
reg [DWIDTH-1:0] ram [(1<<AWIDTH)-1:0];
integer i;
initial
for(i=0;i<(1<<AWIDTH);i=i+1)
ram[i] <= {DWIDTH{1'b0}};
assign rdata = ram[raddr];
always @(posedge clk) begin
if (write) ram[waddr] <= wdata;
end
endmodule //dram_2port
-72
View File
@@ -1,72 +0,0 @@
// Discard silently packets which don't match this SID
module filter_bad_sid
(
input clk,
input reset,
input clear,
//
input [64:0] i_tdata,
input i_tvalid,
output i_tready,
//
output [64:0] o_tdata,
output o_tvalid,
input o_tready,
//
output reg [15:0] count
);
reg [1:0] state;
wire good_sid;
wire qualify_i_tvalid;
localparam IDLE = 0;
localparam ACCEPT = 1;
localparam DISCARD = 2;
always @(posedge clk)
if (reset | clear) begin
state <= IDLE;
count <= 0;
end else
case(state)
//
IDLE: begin
if (i_tvalid && i_tready)
if (good_sid)
state <= ACCEPT;
else begin
count <= count + 1;
state <= DISCARD;
end
end
//
ACCEPT: begin
if (i_tvalid && i_tready && i_tdata[64])
state <= IDLE;
end
//
DISCARD: begin
if (i_tvalid && i_tready && i_tdata[64])
state <= IDLE;
end
endcase // case(state)
assign good_sid = ((i_tdata[15:0] == 16'h00A0) || (i_tdata[15:0] == 16'h00B0));
assign qualify_i_tvalid = (state == IDLE) ? good_sid : ((state == DISCARD) ? 1'b0 : 1'b1);
//
// Buffer output, break combinatorial timing paths
//
axi_fifo_short #(.WIDTH(65)) fifo_short
(
.clk(clk), .reset(reset), .clear(clear),
.i_tdata(i_tdata), .i_tvalid(i_tvalid && qualify_i_tvalid), .i_tready(i_tready),
.o_tdata(o_tdata), .o_tvalid(o_tvalid), .o_tready(o_tready),
.space(), .occupied()
);
endmodule // axi_fast_fifo
-66
View File
@@ -1,66 +0,0 @@
//
// Copyright 2011 Ettus Research LLC
//
module gpio_atr
#(parameter BASE = 0,
parameter WIDTH = 32,
parameter default_ddr = 0,
parameter default_idle = 0)
(input clk, input reset,
input set_stb, input [7:0] set_addr, input [31:0] set_data,
input rx, input tx,
inout [WIDTH-1:0] gpio,
output reg [31:0] gpio_readback
);
wire [WIDTH-1:0] ddr, in_idle, in_tx, in_rx, in_fdx;
reg [WIDTH-1:0] rgpio, igpio;
reg [WIDTH-1:0] gpio_pipe;
setting_reg #(.my_addr(BASE+0), .width(WIDTH), .at_reset(default_idle)) reg_idle
(.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), .in(set_data),
.out(in_idle),.changed());
setting_reg #(.my_addr(BASE+1), .width(WIDTH)) reg_rx
(.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), .in(set_data),
.out(in_rx),.changed());
setting_reg #(.my_addr(BASE+2), .width(WIDTH)) reg_tx
(.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), .in(set_data),
.out(in_tx),.changed());
setting_reg #(.my_addr(BASE+3), .width(WIDTH)) reg_fdx
(.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), .in(set_data),
.out(in_fdx),.changed());
setting_reg #(.my_addr(BASE+4), .width(WIDTH), .at_reset(default_ddr)) reg_ddr
(.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), .in(set_data),
.out(ddr),.changed());
always @(posedge clk)
case({tx,rx})
2'b00: rgpio <= in_idle;
2'b01: rgpio <= in_rx;
2'b10: rgpio <= in_tx;
2'b11: rgpio <= in_fdx;
endcase // case ({tx,rx})
integer n;
always @*
for(n=0;n<WIDTH;n=n+1)
igpio[n] <= ddr[n] ? rgpio[n] : 1'bz;
assign gpio = igpio;
// Double pipeline stage for timing, first flop is in IOB, second in core logic.
always @(posedge clk) begin
gpio_pipe <= gpio;
gpio_readback <= gpio_pipe;
end
endmodule // gpio_atr
-25
View File
@@ -1,25 +0,0 @@
//
// Copyright 2013 Ettus Research LLC
//
module por_gen
(input clk,
output reset_out);
reg por_rst;
reg [7:0] por_counter = 8'h0;
always @(posedge clk)
if (por_counter != 8'h55)
begin
por_counter <= por_counter + 8'h1;
por_rst <= 1'b1;
end
else
por_rst <= 1'b0;
assign reset_out = por_rst;
endmodule // por_gen
-143
View File
@@ -1,143 +0,0 @@
// Radio Control Processor
// Accepts compressed vita extension context packets of the following form:
// { VITA Compressed Header, Stream ID }
// { Optional 64 bit time }
// { 16'h0, setting bus address [15:0], setting [31:0] }
//
// If there is a timestamp, packet is held until that time comes.
// Goes immediately if there is no timestamp or if time has passed.
// Sends out setting to setting bus, and then generates a response packet
// with the same sequence number, the src/dest swapped streamid, and the actual time
// the setting was sent.
//
// Note -- if t0 is the requested time, the actual send time on the setting bus is t0 + 1 cycle.
// Note 2 -- if t1 is the actual time the setting bus, t1+2 is the reported time.
module radio_ctrl_proc
(input clk, input reset, input clear,
input [63:0] ctrl_tdata, input ctrl_tlast, input ctrl_tvalid, output reg ctrl_tready,
output reg [63:0] resp_tdata, output reg resp_tlast, output resp_tvalid, input resp_tready,
input [63:0] vita_time,
output set_stb, output [7:0] set_addr, output [31:0] set_data,
input ready,
input [63:0] readback,
output [31:0] debug);
localparam RC_HEAD = 4'd0;
localparam RC_TIME = 4'd1;
localparam RC_DATA = 4'd2;
localparam RC_DUMP = 4'd3;
localparam RC_RESP_HEAD = 4'd4;
localparam RC_RESP_TIME = 4'd5;
localparam RC_RESP_DATA = 4'd6;
wire IS_EC = ctrl_tdata[63];
wire HAS_TIME = ctrl_tdata[61];
reg HAS_TIME_reg;
reg [3:0] rc_state;
reg [63:0] cmd_time;
wire now, late, go;
reg [11:0] seqnum;
reg [31:0] sid;
always @(posedge clk)
if(reset)
begin
rc_state <= RC_HEAD;
HAS_TIME_reg <= 1'b0;
sid <= 32'd0;
seqnum <= 12'd0;
end
else
case(rc_state)
RC_HEAD :
if(ctrl_tvalid)
begin
sid <= ctrl_tdata[31:0];
seqnum <= ctrl_tdata[59:48];
HAS_TIME_reg <= HAS_TIME;
if(IS_EC)
if(HAS_TIME)
rc_state <= RC_TIME;
else
rc_state <= RC_DATA;
else
if(~ctrl_tlast)
rc_state <= RC_DUMP;
end
RC_TIME :
if(ctrl_tvalid)
if(ctrl_tlast)
rc_state <= RC_RESP_HEAD;
else if(go)
rc_state <= RC_DATA;
RC_DATA :
if(ctrl_tvalid)
if(ready)
if(ctrl_tlast)
rc_state <= RC_RESP_HEAD;
else
rc_state <= RC_DUMP;
RC_DUMP :
if(ctrl_tvalid)
if(ctrl_tlast)
rc_state <= RC_RESP_HEAD;
RC_RESP_HEAD :
if(resp_tready)
rc_state <= RC_RESP_TIME;
RC_RESP_TIME :
if(resp_tready)
rc_state <= RC_RESP_DATA;
RC_RESP_DATA:
if(resp_tready)
rc_state <= RC_HEAD;
default :
rc_state <= RC_HEAD;
endcase // case (rc_state)
always @*
case (rc_state)
RC_HEAD : ctrl_tready <= 1'b1;
RC_TIME : ctrl_tready <= ctrl_tlast | go;
RC_DATA : ctrl_tready <= ready;
RC_DUMP : ctrl_tready <= 1'b1;
default : ctrl_tready <= 1'b0;
endcase // case (rc_state)
time_compare time_compare
(.clk(clk), .reset(reset), .time_now(vita_time), .trigger_time(ctrl_tdata), .now(now), .early(), .late(late), .too_early());
assign go = now | late;
assign set_stb = (rc_state == RC_DATA) & ready & ctrl_tvalid;
assign set_addr = ctrl_tdata[39:32];
assign set_data = ctrl_tdata[31:0];
always @*
case (rc_state)
RC_RESP_HEAD : { resp_tlast, resp_tdata } <= {1'b0, 4'hA, seqnum, 16'd24, sid[15:0], sid[31:16] };
RC_RESP_TIME : { resp_tlast, resp_tdata } <= {1'b0, vita_time};
RC_RESP_DATA : { resp_tlast, resp_tdata } <= {1'b1, readback};
default : { resp_tlast, resp_tdata } <= 65'h0;
endcase // case (rc_state)
assign resp_tvalid = (rc_state == RC_RESP_HEAD) | (rc_state == RC_RESP_TIME) | (rc_state == RC_RESP_DATA);
endmodule // radio_ctrl_proc
-104
View File
@@ -1,104 +0,0 @@
`timescale 1ns/1ps
module radio_ctrl_proc_tb();
reg clk = 0;
reg reset = 1;
always #10 clk = ~clk;
initial $dumpfile("radio_ctrl_proc_tb.vcd");
initial $dumpvars(0,radio_ctrl_proc_tb);
initial
begin
#1000 reset = 0;
#20000;
$finish;
end
reg [63:0] vita_time = 64'd0;
always @(posedge clk)
if(reset) vita_time <= 64'd0;
else vita_time <= vita_time + 64'd1;
reg [63:0] tdata;
wire [63:0] tdata_int;
reg tlast;
wire tlast_int;
reg tvalid = 1'b0;
wire tvalid_int;
wire tready, tready_int;
wire [7:0] set_addr;
wire [31:0] set_data;
wire set_stb;
wire ready = 1'b1;
task send_packet;
input ec;
input timed;
input [11:0] seqnum;
input [31:0] sid;
input [63:0] vtime;
input [15:0] addr;
input [31:0] data;
begin
// Send a packet
@(posedge clk);
tlast <= 1'b0;
tdata <= { ec, 1'b0, timed, 1'b0, seqnum, timed ? 16'd6 : 16'd4, sid };
tvalid <= 1;
@(posedge clk);
if(timed)
begin
tdata <= vtime;
@(posedge clk);
end
tlast <= 1'b1;
tdata <= { 16'h0, addr, data };
@(posedge clk);
tvalid <= 0;
@(posedge clk);
end
endtask // send_packet
initial
begin
tvalid <= 1'b0;
while(reset)
@(posedge clk);
send_packet(1'b1,1'b0,12'h5,32'hDEAD_BEEF,64'h0,16'hB,32'hF00D_1234);
send_packet(1'b1,1'b1,12'h6,32'hDEAD_6789,64'h20,16'hC,32'hABCD_4321);
send_packet(1'b1,1'b1,12'h7,32'hDEAD_6789,64'h30,16'hC,32'hABCD_4321);
//send_packet(.ec(1), .timed(0), .seqnum(5), .sid(32'hDEAD_BEEF), .vtime(0), .addr(16'hB), .data(32'hF00D_1234));
end
axi_fifo_short #(.WIDTH(65)) axi_fifo_short
(.clk(clk), .reset(reset), .clear(1'b0),
.i_tdata({tlast,tdata}), .i_tvalid(tvalid), .i_tready(tready),
.o_tdata({tlast_int,tdata_int}), .o_tvalid(tvalid_int), .o_tready(tready_int));
wire [63:0] resp_tdata;
wire resp_tlast, resp_tvalid, resp_tready;
radio_ctrl_proc radio_ctrl_proc
(.clk(clk), .reset(reset), .clear(1'b0),
.ctrl_tdata(tdata_int), .ctrl_tlast(tlast_int), .ctrl_tvalid(tvalid_int), .ctrl_tready(tready_int),
.resp_tdata(resp_tdata), .resp_tlast(resp_tlast), .resp_tvalid(resp_tvalid), .resp_tready(resp_tready),
.vita_time(vita_time), .ready(ready),
.set_stb(set_stb), .set_addr(set_addr), .set_data(set_data),
.debug()
);
assign resp_tready = 1'b1;
always @(posedge clk)
if(resp_tvalid & resp_tready)
begin
$display("%x",resp_tdata);
if(resp_tlast)
$display("TLAST");
end
endmodule // radio_ctrl_proc_tb
-49
View File
@@ -1,49 +0,0 @@
//
// Copyright 2011 Ettus Research LLC
//
module ram_2port
#(parameter DWIDTH=32,
parameter AWIDTH=9)
(input clka,
input ena,
input wea,
input [AWIDTH-1:0] addra,
input [DWIDTH-1:0] dia,
output reg [DWIDTH-1:0] doa,
input clkb,
input enb,
input web,
input [AWIDTH-1:0] addrb,
input [DWIDTH-1:0] dib,
output reg [DWIDTH-1:0] dob);
reg [DWIDTH-1:0] ram [(1<<AWIDTH)-1:0];
/*
integer i;
initial
for(i=0;i<(1<<AWIDTH);i=i+1)
ram[i] <= {DWIDTH{1'b0}};
*/
always @(posedge clka) begin
if (ena)
begin
if (wea)
ram[addra] <= dia;
doa <= ram[addra];
end
end
always @(posedge clkb) begin
if (enb)
begin
if (web)
ram[addrb] <= dib;
dob <= ram[addrb];
end
end
endmodule // ram_2port
-28
View File
@@ -1,28 +0,0 @@
//
// Copyright 2011 Ettus Research LLC
//
module reset_sync
(input clk,
input reset_in,
output reset_out);
reg reset_int;
reg reset_out_tmp;
//synthesis attribute async_reg of reset_out_tmp is "true";
//synthesis attribute async_reg of reset_int is "true";
always @(posedge clk or posedge reset_in)
if(reset_in)
{reset_out_tmp,reset_int} <= 2'b11;
else
{reset_out_tmp,reset_int} <= {reset_int,1'b0};
assign reset_out = reset_out_tmp;
endmodule // reset_sync
-121
View File
@@ -1,121 +0,0 @@
module serial_to_settings
(
input clk,
input reset,
// Serial signals (async)
input scl,
input sda,
// Settngs bus out
output reg set_stb,
output reg [7:0] set_addr,
output reg [31:0] set_data,
// Debug
output [31:0] debug
);
reg [2:0] state;
localparam SEARCH = 3'h0;
localparam ADDRESS = 3'h1;
localparam DATA = 3'h2;
localparam STOP1 = 3'h3;
localparam STOP2 = 3'h4;
reg scl_pre_reg, scl_reg, scl_reg2;
reg sda_pre_reg, sda_reg, sda_reg2;
reg [4:0] counter;
always @(posedge clk) begin
scl_reg2 <= scl_reg;
scl_reg <= scl_pre_reg;
scl_pre_reg <= scl;
sda_reg2 <= sda_reg;
sda_reg <= sda_pre_reg;
sda_pre_reg <= sda;
end
always @(posedge clk)
if (reset) begin
state <= SEARCH;
counter <= 0;
set_addr <= 0;
set_data <= 0;
set_stb <= 0;
end else begin
case(state)
//
// Search for I2C like start indication: SDA goes low whilst clock is high.
//
SEARCH: begin
set_stb <= 0;
// Look for START.
if (scl_reg && scl_reg2 && !sda_reg && sda_reg2) begin
state <= ADDRESS;
counter <= 0;
end
end
//
// Count 8 Address bits.
// Master changes SDA on falling edge of SCL, we sample on the rising edge.
//
ADDRESS: begin
if (scl_reg && !scl_reg2) begin
set_addr[7:0] <= {set_addr[6:0],sda_reg};
if (counter == 7) begin
state <= DATA;
counter <= 0;
end else
counter <= counter + 1;
end
end
//
// Count 32 data bits.
// Master changes SDA on falling edge of SCL, we sample on the rising edge.
//
DATA: begin
if (scl_reg && !scl_reg2) begin
set_data[31:0] <= {set_data[30:0],sda_reg};
if (counter == 31) begin
state <= STOP1;
counter <= 0;
end else
counter <= counter + 1;
end
end
//
// Looks for rising SCL edge before STOP bit.
//
STOP1: begin
if (scl_reg && !scl_reg2) begin
state <= STOP2;
end
end
//
// Looks for STOP bit
//
STOP2: begin
if (scl_reg && scl_reg2 && sda_reg && !sda_reg2) begin
state <= SEARCH;
counter <= 0;
set_stb <= 1;
end
end
endcase // case(state)
end // else: !if(reset)
assign debug =
{
counter[4:0],
state[2:0],
scl_reg,
sda_reg
};
endmodule // serial_to_settings
-82
View File
@@ -1,82 +0,0 @@
module serial_to_settings_tb();
reg clk;
reg reset;
wire scl;
wire sda;
wire set_stb;
wire [7:0] set_addr;
wire [31:0] set_data;
//
// These registers optionaly used
// to drive nets through procedural assignments in test bench.
// These drivers default to tri-stated.
//
reg scl_r;
reg sda_r;
assign scl = scl_r;
assign sda = sda_r;
initial
begin
scl_r <= 1'bz;
sda_r <= 1'bz;
end
serial_to_settings serial_to_settings_i
(
.clk(clk),
.reset(reset),
// Serial signals (async)
.scl(scl),
.sda(sda),
// Settngs bus out
.set_stb(set_stb),
.set_addr(set_addr),
.set_data(set_data)
);
// Nasty HAck to convert settings to wishbone crudely.
reg wb_stb;
wire wb_ack_o;
always @(posedge clk)
if (reset)
wb_stb <= 0;
else
wb_stb <= set_stb ? 1 : ((wb_ack_o) ? 0 : wb_stb);
simple_uart debug_uart
(
.clk_i(clk),
.rst_i(reset),
.we_i(wb_stb),
.stb_i(wb_stb),
.cyc_i(wb_stb),
.ack_o(wb_ack_o),
.adr_i(set_addr[2:0]),
.dat_i(set_data[31:0]),
.dat_o(),
.rx_int_o(),
.tx_int_o(),
.tx_o(txd),
.rx_i(rxd),
.baud_o()
);
//
// Bring in a simulation script here
//
`include "simulation_script.v"
endmodule
-35
View File
@@ -1,35 +0,0 @@
//
// Copyright 2011-2012 Ettus Research LLC
//
//----------------------------------------------------------------------
//-- A settings register is a peripheral for the settings register bus.
//-- When the settings register sees strobe abd a matching address,
//-- the outputs will be become registered to the given input bus.
//----------------------------------------------------------------------
module setting_reg
#(parameter my_addr = 0,
parameter awidth = 8,
parameter width = 32,
parameter at_reset=0)
(input clk, input rst, input strobe, input wire [awidth-1:0] addr,
input wire [31:0] in, output reg [width-1:0] out, output reg changed);
always @(posedge clk)
if(rst)
begin
out <= at_reset;
changed <= 1'b0;
end
else
if(strobe & (my_addr==addr))
begin
out <= in[width-1:0];
changed <= 1'b1;
end
else
changed <= 1'b0;
endmodule // setting_reg
-26
View File
@@ -1,26 +0,0 @@
//
// Copyright 2011-2012 Ettus Research LLC
//
// This module takes the settings bus on one clock domain and crosses it over to another domain
// Typically it will be used with the input settings bus on the wishbone clock, and either
// the system or dsp clock on the output side
module settings_bus_crossclock
#(parameter FLOW_CTRL=0, parameter AWIDTH=8, parameter DWIDTH=32)
(input clk_i, input rst_i, input set_stb_i, input [AWIDTH-1:0] set_addr_i, input [DWIDTH-1:0] set_data_i,
input clk_o, input rst_o, output set_stb_o, output [AWIDTH-1:0] set_addr_o, output [DWIDTH-1:0] set_data_o, input blocked);
wire nfull, nempty;
axi_fifo_2clk #(.WIDTH(AWIDTH + DWIDTH), .SIZE(0)) settings_fifo
(.reset(rst_i),
.i_aclk(clk_i), .i_tdata({set_addr_i,set_data_i}), .i_tvalid(set_stb_i), .i_tready(nfull),
.o_aclk(clk_o), .o_tdata({set_addr_o,set_data_o}), .o_tready(set_stb_o), .o_tvalid(nempty));
assign set_stb_o = nempty & (~blocked | ~FLOW_CTRL);
endmodule // settings_bus_crossclock
-104
View File
@@ -1,104 +0,0 @@
//
// Copyright 2012 Ettus Research LLC
//
// Simple I2C core
// Settings reg map:
//
// BASE+0 control register
// byte0 - control bits, data byte, or command bits, prescaler
// byte1 - what to do? (documented in cpp file)
// write prescaler lo
// write prescaler hi
// write control
// write data
// write command
// read data
// read status
//
// Readback:
//
// byte0 has readback value based on the last read command
//
module simple_i2c_core
#(
//settings register base address
parameter BASE = 0,
//i2c line level at reset
parameter ARST_LVL = 1
)
(
//clock and synchronous reset
input clock, input reset,
//32-bit settings bus inputs
input set_stb, input [7:0] set_addr, input [31:0] set_data,
//32-bit data readback
output reg [31:0] readback,
//read is high when i2c core can begin another transaction
output reg ready,
// I2C signals
// i2c clock line
input scl_pad_i, // SCL-line input
output scl_pad_o, // SCL-line output (always 1'b0)
output scl_padoen_o, // SCL-line output enable (active low)
// i2c data line
input sda_pad_i, // SDA-line input
output sda_pad_o, // SDA-line output (always 1'b0)
output sda_padoen_o, // SDA-line output enable (active low)
//optional debug output
output [31:0] debug
);
//declare command settings register
wire [7:0] sr_what, sr_data;
wire sr_changed;
setting_reg #(.my_addr(BASE+0),.width(16)) i2c_cmd_sr(
.clk(clock),.rst(reset),.strobe(set_stb),.addr(set_addr),.in(set_data),
.out({sr_what, sr_data}),.changed(sr_changed));
//declare wb interface signals
wire [2:0] wb_addr;
wire [7:0] wb_data_mosi;
wire [7:0] wb_data_miso;
wire wb_we, wb_stb, wb_cyc;
wire wb_ack;
//create wishbone-based i2c core
i2c_master_top #(.ARST_LVL(ARST_LVL)) i2c
(.wb_clk_i(clock),.wb_rst_i(reset),.arst_i(1'b0),
.wb_adr_i(wb_addr),.wb_dat_i(wb_data_mosi),.wb_dat_o(wb_data_miso),
.wb_we_i(wb_we),.wb_stb_i(wb_stb),.wb_cyc_i(wb_cyc),
.wb_ack_o(wb_ack),.wb_inta_o(),
.scl_pad_i(scl_pad_i),.scl_pad_o(scl_pad_o),.scl_padoen_o(scl_padoen_o),
.sda_pad_i(sda_pad_i),.sda_pad_o(sda_pad_o),.sda_padoen_o(sda_padoen_o) );
//not ready between setting register and wishbone ack
always @(posedge clock) begin
if (reset || wb_ack) ready <= 1;
else if (sr_changed) ready <= 0;
end
//register wishbone data on every ack
always @(posedge clock) begin
if (wb_ack) readback <= {24'b0, wb_data_miso};
end
//assign wishbone signals
assign wb_addr = sr_what[2:0];
assign wb_stb = sr_changed;
assign wb_we = wb_stb && sr_what[3];
assign wb_cyc = wb_stb;
assign wb_data_mosi = sr_data;
endmodule //simple_i2c_core
-215
View File
@@ -1,215 +0,0 @@
//
// Copyright 2012 Ettus Research LLC
//
// Simple SPI core, the simplest, yet complete spi core I can think of
// Settings register controlled.
// 2 settings regs, control and data
// 1 32-bit readback and status signal
// Settings reg map:
//
// BASE+0 divider setting
// bits [15:0] spi clock divider
//
// BASE+1 configuration input
// bits [23:0] slave select, bit0 = slave0 enabled
// bits [29:24] num bits (1 through 32)
// bit [30] data input edge = in data bit latched on rising edge of clock
// bit [31] data output edge = out data bit latched on rising edge of clock
//
// BASE+2 input data
// Writing this register begins a spi transaction.
// Bits are latched out from bit 0.
// Therefore, load this register in reverse.
//
// Readback
// Bits are latched into bit 0.
// Therefore, data will be in-order.
module simple_spi_core
#(
//settings register base address
parameter BASE = 0,
//width of serial enables (up to 24 is possible)
parameter WIDTH = 8,
//idle state of the spi clock
parameter CLK_IDLE = 0,
//idle state of the serial enables
parameter SEN_IDLE = 24'hffffff
)
(
//clock and synchronous reset
input clock, input reset,
//32-bit settings bus inputs
input set_stb, input [7:0] set_addr, input [31:0] set_data,
//32-bit data readback
output [31:0] readback,
//read is high when spi core can begin another transaction
output ready,
//spi interface, slave selects, clock, data in, data out
output reg [WIDTH-1:0] sen,
output sclk,
output reg mosi,
input miso,
//optional debug output
output [31:0] debug
);
wire [15:0] sclk_divider;
setting_reg #(.my_addr(BASE+0),.width(16)) divider_sr(
.clk(clock),.rst(reset),.strobe(set_stb),.addr(set_addr),.in(set_data),
.out(sclk_divider),.changed());
wire [23:0] slave_select;
wire [5:0] num_bits;
wire datain_edge, dataout_edge;
setting_reg #(.my_addr(BASE+1),.width(32)) config_sr(
.clk(clock),.rst(reset),.strobe(set_stb),.addr(set_addr),.in(set_data),
.out({dataout_edge, datain_edge, num_bits, slave_select}),.changed());
wire [31:0] mosi_data;
wire trigger_spi;
setting_reg #(.my_addr(BASE+2),.width(32)) data_sr(
.clk(clock),.rst(reset),.strobe(set_stb),.addr(set_addr),.in(set_data),
.out(mosi_data),.changed(trigger_spi));
localparam WAIT_TRIG = 0;
localparam PRE_IDLE = 1;
localparam CLK_REG = 2;
localparam CLK_INV = 3;
localparam POST_IDLE = 4;
localparam IDLE_SEN = 5;
reg [2:0] state;
reg ready_reg;
assign ready = ready_reg && ~trigger_spi;
//serial clock either idles or is in one of two clock states
reg sclk_reg;
assign sclk = sclk_reg;
//serial enables either idle or enabled based on state
// IJB. One pipeline stage to break critical path from register in I/O pads.
wire sen_is_idle = (state == WAIT_TRIG) || (state == IDLE_SEN);
wire [23:0] sen24 = (sen_is_idle)? SEN_IDLE : (SEN_IDLE ^ slave_select);
reg [WIDTH-1:0] sen_reg;
always @(posedge clock)
sen_reg <= sen24[WIDTH-1:0];
always @(posedge clock)
sen <= sen_reg;
//data output shift register
// IJB. One pipeline stage to break critical path from register in I/O pads.
reg [31:0] dataout_reg;
wire [31:0] dataout_next = {dataout_reg[30:0], 1'b0};
always @(posedge clock)
mosi <= dataout_reg[31];
//data input shift register
// IJB. Two pipeline stages to break critical path from register in I/O pads.
reg miso_pipe, miso_pipe2;
always @(posedge clock) begin
miso_pipe2 <= miso;
miso_pipe <= miso_pipe2;
end
reg [31:0] datain_reg;
wire [31:0] datain_next = {datain_reg[30:0], miso_pipe};
assign readback = datain_reg;
//counter for spi clock
reg [15:0] sclk_counter;
wire sclk_counter_done = (sclk_counter == sclk_divider);
wire [15:0] sclk_counter_next = (sclk_counter_done)? 0 : sclk_counter + 1;
//counter for latching bits miso/mosi
reg [6:0] bit_counter;
wire [6:0] bit_counter_next = bit_counter + 1;
wire bit_counter_done = (bit_counter_next == num_bits);
always @(posedge clock) begin
if (reset) begin
state <= WAIT_TRIG;
sclk_reg <= CLK_IDLE;
ready_reg <= 0;
end
else begin
case (state)
WAIT_TRIG: begin
if (trigger_spi) state <= PRE_IDLE;
ready_reg <= ~trigger_spi;
dataout_reg <= mosi_data;
sclk_counter <= 0;
bit_counter <= 0;
sclk_reg <= CLK_IDLE;
end
PRE_IDLE: begin
if (sclk_counter_done) state <= CLK_REG;
sclk_counter <= sclk_counter_next;
sclk_reg <= CLK_IDLE;
end
CLK_REG: begin
if (sclk_counter_done) begin
state <= CLK_INV;
if (datain_edge != CLK_IDLE) datain_reg <= datain_next;
if (dataout_edge != CLK_IDLE && bit_counter != 0) dataout_reg <= dataout_next;
sclk_reg <= ~CLK_IDLE; //transition to rising when CLK_IDLE == 0
end
sclk_counter <= sclk_counter_next;
end
CLK_INV: begin
if (sclk_counter_done) begin
state <= (bit_counter_done)? POST_IDLE : CLK_REG;
bit_counter <= bit_counter_next;
if (datain_edge == CLK_IDLE) datain_reg <= datain_next;
if (dataout_edge == CLK_IDLE && ~bit_counter_done) dataout_reg <= dataout_next;
sclk_reg <= CLK_IDLE; //transition to falling when CLK_IDLE == 0
end
sclk_counter <= sclk_counter_next;
end
POST_IDLE: begin
if (sclk_counter_done) state <= IDLE_SEN;
sclk_counter <= sclk_counter_next;
sclk_reg <= CLK_IDLE;
end
IDLE_SEN: begin
if (sclk_counter_done) state <= WAIT_TRIG;
sclk_counter <= sclk_counter_next;
sclk_reg <= CLK_IDLE;
end
default: state <= WAIT_TRIG;
endcase //state
end
end
assign debug = {
trigger_spi, state, //4
sclk, mosi, miso, ready, //4
//sen[7:0], //8
1'b0, bit_counter[6:0], //8
sclk_counter_done, bit_counter_done, //2
sclk_counter[5:0] //6
};
endmodule //simple_spi_core
-1
View File
@@ -1 +0,0 @@
coregen.log
View File
-40
View File
@@ -1,40 +0,0 @@
#
# Copyright 2013 Ettus Research LLC
#
##################################################
# DSP Sources
##################################################
DSP_SRCS = $(abspath $(addprefix $(BASE_DIR)/../lib/dsp/, \
ddc_chain_x300.v \
ddc_chain.v \
duc_chain.v \
sign_extend.v \
cordic_z24.v \
clip_reg.v \
cordic_stage.v \
clip.v \
cic_strober.v \
cic_decim.v \
cic_interp.v \
cic_dec_shifter.v \
cic_int_shifter.v \
small_hb_dec.v \
small_hb_int.v \
hb_dec.v \
hb_interp.v \
round_sd.v \
add2_and_clip_reg.v \
add2_and_clip.v \
add2.v \
add2_reg.v \
add2_and_round_reg.v \
add2_and_round.v \
round_reg.v \
round.v \
srl.v \
acc.v \
rx_frontend.v \
tx_frontend.v \
rx_dcoffset.v \
))
View File
-33
View File
@@ -1,33 +0,0 @@
//
// Copyright 2011 Ettus Research LLC
//
module acc
#(parameter IWIDTH=16, OWIDTH=30)
(input clk,
input clear,
input acc,
input [IWIDTH-1:0] in,
output reg [OWIDTH-1:0] out);
wire [OWIDTH-1:0] in_signext;
sign_extend #(.bits_in(IWIDTH),.bits_out(OWIDTH))
acc_signext (.in(in),.out(in_signext));
// CLEAR & ~ACC --> clears the accumulator
// CLEAR & ACC --> loads the accumulator
// ~CLEAR & ACC --> accumulates
// ~CLEAR & ~ACC --> hold
wire [OWIDTH-1:0] addend1 = clear ? 0 : out;
wire [OWIDTH-1:0] addend2 = ~acc ? 0 : in_signext;
wire [OWIDTH-1:0] sum_int = addend1 + addend2;
always @(posedge clk)
out <= sum_int;
endmodule // acc
-16
View File
@@ -1,16 +0,0 @@
//
// Copyright 2011 Ettus Research LLC
//
module add2
#(parameter WIDTH=16)
(input [WIDTH-1:0] in1,
input [WIDTH-1:0] in2,
output [WIDTH-1:0] sum);
wire [WIDTH:0] sum_int = {in1[WIDTH-1],in1} + {in2[WIDTH-1],in2};
assign sum = sum_int[WIDTH:1]; // Note -- will have some bias
endmodule // add2
-12
View File
@@ -1,12 +0,0 @@
module add2_and_clip
#(parameter WIDTH=16)
(input [WIDTH-1:0] in1,
input [WIDTH-1:0] in2,
output [WIDTH-1:0] sum);
wire [WIDTH:0] sum_int = {in1[WIDTH-1],in1} + {in2[WIDTH-1],in2};
clip #(.bits_in(WIDTH+1),.bits_out(WIDTH)) clip
(.in(sum_int),.out(sum));
endmodule // add2_and_clip
-25
View File
@@ -1,25 +0,0 @@
module add2_and_clip_reg
#(parameter WIDTH=16)
(input clk,
input rst,
input [WIDTH-1:0] in1,
input [WIDTH-1:0] in2,
input strobe_in,
output reg [WIDTH-1:0] sum,
output reg strobe_out);
wire [WIDTH-1:0] sum_int;
add2_and_clip #(.WIDTH(WIDTH)) add2_and_clip (.in1(in1),.in2(in2),.sum(sum_int));
always @(posedge clk)
if(rst)
sum <= 0;
else if(strobe_in)
sum <= sum_int;
always @(posedge clk)
strobe_out <= strobe_in;
endmodule // add2_and_clip_reg
-16
View File
@@ -1,16 +0,0 @@
//
// Copyright 2011 Ettus Research LLC
//
module add2_and_round
#(parameter WIDTH=16)
(input [WIDTH-1:0] in1,
input [WIDTH-1:0] in2,
output [WIDTH-1:0] sum);
wire [WIDTH:0] sum_int = {in1[WIDTH-1],in1} + {in2[WIDTH-1],in2};
assign sum = sum_int[WIDTH:1] + (sum_int[WIDTH] & sum_int[0]);
endmodule // add2_and_round
-21
View File
@@ -1,21 +0,0 @@
//
// Copyright 2011 Ettus Research LLC
//
module add2_and_round_reg
#(parameter WIDTH=16)
(input clk,
input [WIDTH-1:0] in1,
input [WIDTH-1:0] in2,
output reg [WIDTH-1:0] sum);
wire [WIDTH-1:0] sum_int;
add2_and_round #(.WIDTH(WIDTH)) add2_n_rnd (.in1(in1),.in2(in2),.sum(sum_int));
always @(posedge clk)
sum <= sum_int;
endmodule // add2_and_round_reg
-22
View File
@@ -1,22 +0,0 @@
//
// Copyright 2011 Ettus Research LLC
//
module add2_reg
#(parameter WIDTH=16)
(input clk,
input [WIDTH-1:0] in1,
input [WIDTH-1:0] in2,
output reg [WIDTH-1:0] sum);
wire [WIDTH-1:0] sum_int;
add2 #(.WIDTH(WIDTH)) add2 (.in1(in1),.in2(in2),.sum(sum_int));
always @(posedge clk)
sum <= sum_int;
endmodule // add2_reg
-94
View File
@@ -1,94 +0,0 @@
// -*- verilog -*-
//
// USRP - Universal Software Radio Peripheral
//
// Copyright (C) 2003 Matt Ettus
//
//
// NOTE This only works for N=4, max decim rate of 128
// NOTE signal "rate" is EQUAL TO the actual rate, no more -1 BS
module cic_dec_shifter(rate,signal_in,signal_out);
parameter bw = 16;
parameter maxbitgain = 28;
input [7:0] rate;
input wire [bw+maxbitgain-1:0] signal_in;
output reg [bw-1:0] signal_out;
function [4:0] bitgain;
input [7:0] rate;
case(rate)
// Exact Cases -- N*log2(rate)
8'd1 : bitgain = 0;
8'd2 : bitgain = 4;
8'd4 : bitgain = 8;
8'd8 : bitgain = 12;
8'd16 : bitgain = 16;
8'd32 : bitgain = 20;
8'd64 : bitgain = 24;
8'd128 : bitgain = 28;
// Nearest without overflow -- ceil(N*log2(rate))
8'd3 : bitgain = 7;
8'd5 : bitgain = 10;
8'd6 : bitgain = 11;
8'd7 : bitgain = 12;
8'd9 : bitgain = 13;
8'd10,8'd11 : bitgain = 14;
8'd12,8'd13 : bitgain = 15;
8'd14,8'd15 : bitgain = 16;
8'd17,8'd18,8'd19 : bitgain = 17;
8'd20,8'd21,8'd22 : bitgain = 18;
8'd23,8'd24,8'd25,8'd26 : bitgain = 19;
8'd27,8'd28,8'd29,8'd30,8'd31 : bitgain = 20;
8'd33,8'd34,8'd35,8'd36,8'd37,8'd38 : bitgain = 21;
8'd39,8'd40,8'd41,8'd42,8'd43,8'd44,8'd45 : bitgain = 22;
8'd46,8'd47,8'd48,8'd49,8'd50,8'd51,8'd52,8'd53 : bitgain = 23;
8'd54,8'd55,8'd56,8'd57,8'd58,8'd59,8'd60,8'd61,8'd62,8'd63 : bitgain = 24;
8'd65,8'd66,8'd67,8'd68,8'd69,8'd70,8'd71,8'd72,8'd73,8'd74,8'd75,8'd76 : bitgain = 25;
8'd77,8'd78,8'd79,8'd80,8'd81,8'd82,8'd83,8'd84,8'd85,8'd86,8'd87,8'd88,8'd89,8'd90 : bitgain = 26;
8'd91,8'd92,8'd93,8'd94,8'd95,8'd96,8'd97,8'd98,8'd99,8'd100,8'd101,8'd102,8'd103,8'd104,8'd105,8'd106,8'd107 : bitgain = 27;
default : bitgain = 28;
endcase // case(rate)
endfunction // bitgain
wire [4:0] shift = bitgain(rate);
// We should be able to do this, but can't ....
// assign signal_out = signal_in[shift+bw-1:shift];
always @*
case(shift)
5'd0 : signal_out = signal_in[0+bw-1:0];
5'd4 : signal_out = signal_in[4+bw-1:4];
5'd7 : signal_out = signal_in[7+bw-1:7];
5'd8 : signal_out = signal_in[8+bw-1:8];
5'd10 : signal_out = signal_in[10+bw-1:10];
5'd11 : signal_out = signal_in[11+bw-1:11];
5'd12 : signal_out = signal_in[12+bw-1:12];
5'd13 : signal_out = signal_in[13+bw-1:13];
5'd14 : signal_out = signal_in[14+bw-1:14];
5'd15 : signal_out = signal_in[15+bw-1:15];
5'd16 : signal_out = signal_in[16+bw-1:16];
5'd17 : signal_out = signal_in[17+bw-1:17];
5'd18 : signal_out = signal_in[18+bw-1:18];
5'd19 : signal_out = signal_in[19+bw-1:19];
5'd20 : signal_out = signal_in[20+bw-1:20];
5'd21 : signal_out = signal_in[21+bw-1:21];
5'd22 : signal_out = signal_in[22+bw-1:22];
5'd23 : signal_out = signal_in[23+bw-1:23];
5'd24 : signal_out = signal_in[24+bw-1:24];
5'd25 : signal_out = signal_in[25+bw-1:25];
5'd26 : signal_out = signal_in[26+bw-1:26];
5'd27 : signal_out = signal_in[27+bw-1:27];
5'd28 : signal_out = signal_in[28+bw-1:28];
default : signal_out = signal_in[28+bw-1:28];
endcase // case(shift)
endmodule // cic_dec_shifter
-76
View File
@@ -1,76 +0,0 @@
// -*- verilog -*-
//
// USRP - Universal Software Radio Peripheral
//
// Copyright (C) 2003 Matt Ettus
//
//
module cic_decim
#(parameter bw = 16, parameter N = 4, parameter log2_of_max_rate = 7)
(input clock,
input reset,
input enable,
input [7:0] rate,
input strobe_in,
input strobe_out,
input [bw-1:0] signal_in,
output reg [bw-1:0] signal_out);
localparam maxbitgain = N * log2_of_max_rate;
wire [bw+maxbitgain-1:0] signal_in_ext;
reg [bw+maxbitgain-1:0] integrator [0:N-1];
reg [bw+maxbitgain-1:0] differentiator [0:N-1];
reg [bw+maxbitgain-1:0] pipeline [0:N-1];
reg [bw+maxbitgain-1:0] sampler;
integer i;
sign_extend #(bw,bw+maxbitgain)
ext_input (.in(signal_in),.out(signal_in_ext));
always @(posedge clock)
if(~enable)
for(i=0;i<N;i=i+1)
integrator[i] <= 0;
else if (strobe_in)
begin
integrator[0] <= integrator[0] + signal_in_ext;
for(i=1;i<N;i=i+1)
integrator[i] <= integrator[i] + integrator[i-1];
end
always @(posedge clock)
if(~enable)
begin
sampler <= 0;
for(i=0;i<N;i=i+1)
begin
pipeline[i] <= 0;
differentiator[i] <= 0;
end
end
else if (strobe_out)
begin
sampler <= integrator[N-1];
differentiator[0] <= sampler;
pipeline[0] <= sampler - differentiator[0];
for(i=1;i<N;i=i+1)
begin
differentiator[i] <= pipeline[i-1];
pipeline[i] <= pipeline[i-1] - differentiator[i];
end
end // if (enable && strobe_out)
wire [bw-1:0] signal_out_unreg;
cic_dec_shifter #(bw)
cic_dec_shifter(rate,pipeline[N-1],signal_out_unreg);
always @(posedge clock)
signal_out <= signal_out_unreg;
endmodule // cic_decim
-88
View File
@@ -1,88 +0,0 @@
// -*- verilog -*-
//
// USRP - Universal Software Radio Peripheral
//
// Copyright (C) 2003 Matt Ettus
//
//
// NOTE This only works for N=4, max interp rate of 128
// NOTE signal "rate" is EQUAL TO the actual rate (no more -1 BS)
module cic_int_shifter(rate,signal_in,signal_out);
parameter bw = 16;
parameter maxbitgain = 21;
input [7:0] rate;
input wire [bw+maxbitgain-1:0] signal_in;
output reg [bw-1:0] signal_out;
function [4:0] bitgain;
input [7:0] rate;
case(rate)
// Exact Cases
8'd1 : bitgain = 0;
8'd2 : bitgain = 3;
8'd4 : bitgain = 6;
8'd8 : bitgain = 9;
8'd16 : bitgain = 12;
8'd32 : bitgain = 15;
8'd64 : bitgain = 18;
8'd128 : bitgain = 21;
// Nearest without overflow
8'd3 : bitgain = 5;
8'd5 : bitgain = 7;
8'd6 : bitgain = 8;
8'd7 : bitgain = 9;
8'd9,8'd10 : bitgain = 10;
8'd11,8'd12 : bitgain = 11;
8'd13,8'd14,8'd15 : bitgain = 12;
8'd17,8'd18,8'd19,8'd20 : bitgain = 13;
8'd21,8'd22,8'd23,8'd24,8'd25 : bitgain = 14;
8'd26,8'd27,8'd28,8'd29,8'd30,8'd31 : bitgain = 15;
8'd33,8'd34,8'd35,8'd36,8'd37,8'd38,8'd39,8'd40 : bitgain = 16;
8'd41,8'd42,8'd43,8'd44,8'd45,8'd46,8'd47,8'd48,8'd49,8'd50 : bitgain = 17;
8'd51,8'd52,8'd53,8'd54,8'd55,8'd56,8'd57,8'd58,8'd59,8'd60,8'd61,8'd62,8'd63 : bitgain = 18;
8'd65,8'd66,8'd67,8'd68,8'd69,8'd70,8'd71,8'd72,8'd73,8'd74,8'd75,8'd76,8'd77,8'd78,8'd79,8'd80 : bitgain = 19;
8'd81,8'd82,8'd83,8'd84,8'd85,8'd86,8'd87,8'd88,8'd89,8'd90,8'd91,8'd92,8'd93,8'd94,8'd95,8'd96,8'd97,8'd98,8'd99,8'd100,8'd101 : bitgain = 20;
default : bitgain = 21;
endcase // case(rate)
endfunction // bitgain
wire [4:0] shift = bitgain(rate);
// We should be able to do this, but can't ....
// assign signal_out = signal_in[shift+bw-1:shift];
always @*
case(shift)
5'd0 : signal_out = signal_in[0+bw-1:0];
5'd3 : signal_out = signal_in[3+bw-1:3];
5'd6 : signal_out = signal_in[6+bw-1:6];
5'd9 : signal_out = signal_in[9+bw-1:9];
5'd12 : signal_out = signal_in[12+bw-1:12];
5'd15 : signal_out = signal_in[15+bw-1:15];
5'd18 : signal_out = signal_in[18+bw-1:18];
5'd21 : signal_out = signal_in[21+bw-1:21];
5'd5 : signal_out = signal_in[5+bw-1:5];
5'd7 : signal_out = signal_in[7+bw-1:7];
5'd8 : signal_out = signal_in[8+bw-1:8];
5'd10 : signal_out = signal_in[10+bw-1:10];
5'd11 : signal_out = signal_in[11+bw-1:11];
5'd13 : signal_out = signal_in[13+bw-1:13];
5'd14 : signal_out = signal_in[14+bw-1:14];
5'd16 : signal_out = signal_in[16+bw-1:16];
5'd17 : signal_out = signal_in[17+bw-1:17];
5'd19 : signal_out = signal_in[19+bw-1:19];
5'd20 : signal_out = signal_in[20+bw-1:20];
default : signal_out = signal_in[21+bw-1:21];
endcase // case(shift)
endmodule // cic_int_shifter
-75
View File
@@ -1,75 +0,0 @@
// -*- verilog -*-
//
// USRP - Universal Software Radio Peripheral
//
// Copyright (C) 2003 Matt Ettus
//
//
module cic_interp
#(parameter bw = 16, parameter N = 4, parameter log2_of_max_rate = 7)
(input clock,
input reset,
input enable,
input [7:0] rate,
input strobe_in,
input strobe_out,
input [bw-1:0] signal_in,
output reg [bw-1:0] signal_out);
integer i;
localparam maxbitgain = (N-1)*log2_of_max_rate;
wire [bw+maxbitgain-1:0] signal_in_ext;
reg [bw+maxbitgain-1:0] integrator [0:N-1];
reg [bw+maxbitgain-1:0] differentiator [0:N-1];
reg [bw+maxbitgain-1:0] pipeline [0:N-1];
sign_extend #(bw,bw+maxbitgain)
ext_input (.in(signal_in),.out(signal_in_ext));
//FIXME Note that this section has pipe and diff reversed
// It still works, but is confusing
always @(posedge clock)
if(reset | ~enable)
for(i=0;i<N;i=i+1)
integrator[i] <= 0;
else if (enable & strobe_out)
begin
if(strobe_in)
integrator[0] <= integrator[0] + pipeline[N-1];
for(i=1;i<N;i=i+1)
integrator[i] <= integrator[i] + integrator[i-1];
end
always @(posedge clock)
if(reset | ~enable)
begin
for(i=0;i<N;i=i+1)
begin
differentiator[i] <= 0;
pipeline[i] <= 0;
end
end
else if (enable && strobe_in)
begin
differentiator[0] <= signal_in_ext;
pipeline[0] <= signal_in_ext - differentiator[0];
for(i=1;i<N;i=i+1)
begin
differentiator[i] <= pipeline[i-1];
pipeline[i] <= pipeline[i-1] - differentiator[i];
end
end
wire [bw-1:0] signal_out_unreg;
cic_int_shifter #(bw)
cic_int_shifter(rate,integrator[N-1],signal_out_unreg);
always @(posedge clock)
signal_out <= signal_out_unreg;
endmodule // cic_interp
-33
View File
@@ -1,33 +0,0 @@
//
// USRP2 - Universal Software Radio Peripheral Mk II
//
// Copyright (C) 2008 Matt Ettus
//
//
module cic_strober
#(parameter WIDTH=8)
( input clock,
input reset,
input enable,
input [WIDTH-1:0] rate, // Rate should EQUAL to your desired divide ratio, no more -1 BS
input strobe_fast,
output wire strobe_slow );
reg [WIDTH-1:0] counter;
wire now = (counter==1);
assign strobe_slow = now && enable && strobe_fast;
always @(posedge clock)
if(reset)
counter <= 0;
else if (~enable)
counter <= rate;
else if(strobe_fast)
if(now)
counter <= rate;
else
counter <= counter - 1;
endmodule // cic_strober
-24
View File
@@ -1,24 +0,0 @@
// -*- verilog -*-
//
// USRP - Universal Software Radio Peripheral
//
// Copyright (C) 2008 Matt Ettus
//
//
// Clipping "macro", keeps the bottom bits
module clip
#(parameter bits_in=0,
parameter bits_out=0)
(input [bits_in-1:0] in,
output [bits_out-1:0] out);
wire overflow = |in[bits_in-1:bits_out-1] & ~(&in[bits_in-1:bits_out-1]);
assign out = overflow ?
(in[bits_in-1] ? {1'b1,{(bits_out-1){1'b0}}} : {1'b0,{(bits_out-1){1'b1}}}) :
in[bits_out-1:0];
endmodule // clip
-34
View File
@@ -1,34 +0,0 @@
// -*- verilog -*-
//
// USRP - Universal Software Radio Peripheral
//
// Copyright (C) 2008 Matt Ettus
//
//
// Clipping "macro", keeps the bottom bits
module clip_reg
#(parameter bits_in=0,
parameter bits_out=0,
parameter STROBED=1'b0)
(input clk,
input [bits_in-1:0] in,
output reg [bits_out-1:0] out,
input strobe_in,
output reg strobe_out);
wire [bits_out-1:0] temp;
clip #(.bits_in(bits_in),.bits_out(bits_out)) clip (.in(in),.out(temp));
always @(posedge clk)
strobe_out <= strobe_in;
always @(posedge clk)
if(strobe_in | ~STROBED)
out <= temp;
endmodule // clip_reg
-48
View File
@@ -1,48 +0,0 @@
// -*- verilog -*-
//
// USRP - Universal Software Radio Peripheral
//
// Copyright (C) 2003 Matt Ettus
//
//
module cordic_stage( clock, reset, enable, xi,yi,zi,constant,xo,yo,zo);
parameter bitwidth = 16;
parameter zwidth = 16;
parameter shift = 1;
input clock;
input reset;
input enable;
input [bitwidth-1:0] xi,yi;
input [zwidth-1:0] zi;
input [zwidth-1:0] constant;
output [bitwidth-1:0] xo,yo;
output [zwidth-1:0] zo;
wire z_is_pos = ~zi[zwidth-1];
reg [bitwidth-1:0] xo,yo;
reg [zwidth-1:0] zo;
always @(posedge clock)
if(reset)
begin
xo <= 0;
yo <= 0;
zo <= 0;
end
else //if(enable)
begin
xo <= z_is_pos ?
xi - {{shift+1{yi[bitwidth-1]}},yi[bitwidth-2:shift]} :
xi + {{shift+1{yi[bitwidth-1]}},yi[bitwidth-2:shift]};
yo <= z_is_pos ?
yi + {{shift+1{xi[bitwidth-1]}},xi[bitwidth-2:shift]} :
yi - {{shift+1{xi[bitwidth-1]}},xi[bitwidth-2:shift]};
zo <= z_is_pos ?
zi - constant :
zi + constant;
end
endmodule
-112
View File
@@ -1,112 +0,0 @@
// -*- verilog -*-
//
// USRP - Universal Software Radio Peripheral
//
// Copyright (C) 2003, 2007 Matt Ettus
//
//
module cordic_z24(clock, reset, enable, xi, yi, zi, xo, yo, zo );
parameter bitwidth = 16;
parameter stages = 19;
localparam zwidth = 24;
input clock;
input reset;
input enable;
input [bitwidth-1:0] xi, yi;
output [bitwidth-1:0] xo, yo;
input [zwidth-1:0] zi;
output [zwidth-1:0] zo;
reg [bitwidth+1:0] x0,y0;
reg [zwidth-2:0] z0;
wire [bitwidth+1:0] x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12,x13,x14,x15,x16,x17,x18,x19,x20;
wire [bitwidth+1:0] y1,y2,y3,y4,y5,y6,y7,y8,y9,y10,y11,y12,y13,y14,y15,y16,y17,y18,y19,y20;
wire [zwidth-2:0] z1,z2,z3,z4,z5,z6,z7,z8,z9,z10,z11,z12,z13,z14,z15,z16,z17,z18,z19,z20;
wire [bitwidth+1:0] xi_ext = {{2{xi[bitwidth-1]}},xi};
wire [bitwidth+1:0] yi_ext = {{2{yi[bitwidth-1]}},yi};
// Compute consts. Would be easier if vlog had atan...
// see gen_cordic_consts.py
// constants for 24 bit wide phase
localparam c00 = 23'd2097152;
localparam c01 = 23'd1238021;
localparam c02 = 23'd654136;
localparam c03 = 23'd332050;
localparam c04 = 23'd166669;
localparam c05 = 23'd83416;
localparam c06 = 23'd41718;
localparam c07 = 23'd20860;
localparam c08 = 23'd10430;
localparam c09 = 23'd5215;
localparam c10 = 23'd2608;
localparam c11 = 23'd1304;
localparam c12 = 23'd652;
localparam c13 = 23'd326;
localparam c14 = 23'd163;
localparam c15 = 23'd81;
localparam c16 = 23'd41;
localparam c17 = 23'd20;
localparam c18 = 23'd10;
localparam c19 = 23'd5;
localparam c20 = 23'd3;
localparam c21 = 23'd1;
localparam c22 = 23'd1;
localparam c23 = 23'd0;
always @(posedge clock)
if(reset)
begin
x0 <= 0; y0 <= 0; z0 <= 0;
end
else// if(enable)
begin
z0 <= zi[zwidth-2:0];
case (zi[zwidth-1:zwidth-2])
2'b00, 2'b11 :
begin
x0 <= xi_ext;
y0 <= yi_ext;
end
2'b01, 2'b10 :
begin
x0 <= -xi_ext;
y0 <= -yi_ext;
end
endcase // case(zi[zwidth-1:zwidth-2])
end // else: !if(reset)
// FIXME need to handle variable number of stages
// This would be easier if arrays worked better in vlog...
cordic_stage #(bitwidth+2,zwidth-1,0) cordic_stage0 (clock,reset,enable,x0,y0,z0,c00,x1,y1,z1);
cordic_stage #(bitwidth+2,zwidth-1,1) cordic_stage1 (clock,reset,enable,x1,y1,z1,c01,x2,y2,z2);
cordic_stage #(bitwidth+2,zwidth-1,2) cordic_stage2 (clock,reset,enable,x2,y2,z2,c02,x3,y3,z3);
cordic_stage #(bitwidth+2,zwidth-1,3) cordic_stage3 (clock,reset,enable,x3,y3,z3,c03,x4,y4,z4);
cordic_stage #(bitwidth+2,zwidth-1,4) cordic_stage4 (clock,reset,enable,x4,y4,z4,c04,x5,y5,z5);
cordic_stage #(bitwidth+2,zwidth-1,5) cordic_stage5 (clock,reset,enable,x5,y5,z5,c05,x6,y6,z6);
cordic_stage #(bitwidth+2,zwidth-1,6) cordic_stage6 (clock,reset,enable,x6,y6,z6,c06,x7,y7,z7);
cordic_stage #(bitwidth+2,zwidth-1,7) cordic_stage7 (clock,reset,enable,x7,y7,z7,c07,x8,y8,z8);
cordic_stage #(bitwidth+2,zwidth-1,8) cordic_stage8 (clock,reset,enable,x8,y8,z8,c08,x9,y9,z9);
cordic_stage #(bitwidth+2,zwidth-1,9) cordic_stage9 (clock,reset,enable,x9,y9,z9,c09,x10,y10,z10);
cordic_stage #(bitwidth+2,zwidth-1,10) cordic_stage10 (clock,reset,enable,x10,y10,z10,c10,x11,y11,z11);
cordic_stage #(bitwidth+2,zwidth-1,11) cordic_stage11 (clock,reset,enable,x11,y11,z11,c11,x12,y12,z12);
cordic_stage #(bitwidth+2,zwidth-1,12) cordic_stage12 (clock,reset,enable,x12,y12,z12,c12,x13,y13,z13);
cordic_stage #(bitwidth+2,zwidth-1,13) cordic_stage13 (clock,reset,enable,x13,y13,z13,c13,x14,y14,z14);
cordic_stage #(bitwidth+2,zwidth-1,14) cordic_stage14 (clock,reset,enable,x14,y14,z14,c14,x15,y15,z15);
cordic_stage #(bitwidth+2,zwidth-1,15) cordic_stage15 (clock,reset,enable,x15,y15,z15,c15,x16,y16,z16);
cordic_stage #(bitwidth+2,zwidth-1,16) cordic_stage16 (clock,reset,enable,x16,y16,z16,c16,x17,y17,z17);
cordic_stage #(bitwidth+2,zwidth-1,17) cordic_stage17 (clock,reset,enable,x17,y17,z17,c17,x18,y18,z18);
cordic_stage #(bitwidth+2,zwidth-1,18) cordic_stage18 (clock,reset,enable,x18,y18,z18,c18,x19,y19,z19);
cordic_stage #(bitwidth+2,zwidth-1,19) cordic_stage19 (clock,reset,enable,x19,y19,z19,c19,x20,y20,z20);
assign xo = x20[bitwidth:1];
assign yo = y20[bitwidth:1];
assign zo = z20;
endmodule // cordic
-166
View File
@@ -1,166 +0,0 @@
//
// Copyright 2011-2014 Ettus Research LLC
//
//! The USRP digital down-conversion chain
module ddc_chain
#(
parameter BASE = 0,
parameter DSPNO = 0,
parameter WIDTH = 24
)
(input clk, input rst, input clr,
input set_stb, input [7:0] set_addr, input [31:0] set_data,
// From RX frontend
input [WIDTH-1:0] rx_fe_i,
input [WIDTH-1:0] rx_fe_q,
// To RX control
output [31:0] sample,
input run,
output strobe,
output [31:0] debug
);
localparam cwidth = 25;
localparam zwidth = 24;
wire [31:0] phase_inc;
reg [31:0] phase;
wire [17:0] scale_factor;
wire [cwidth-1:0] i_cordic, q_cordic;
wire [WIDTH-1:0] i_cordic_clip, q_cordic_clip;
wire [WIDTH-1:0] i_cic, q_cic;
wire [WIDTH-1:0] i_hb1, q_hb1;
wire [WIDTH-1:0] i_hb2, q_hb2;
wire strobe_cic, strobe_hb1, strobe_hb2;
wire enable_hb1, enable_hb2;
wire [7:0] cic_decim_rate;
reg [WIDTH-1:0] rx_fe_i_mux, rx_fe_q_mux;
wire realmode;
wire swap_iq;
wire invert_i;
wire invert_q;
setting_reg #(.my_addr(BASE+0)) sr_0
(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
.in(set_data),.out(phase_inc),.changed());
setting_reg #(.my_addr(BASE+1), .width(18)) sr_1
(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
.in(set_data),.out(scale_factor),.changed());
setting_reg #(.my_addr(BASE+2), .width(10)) sr_2
(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
.in(set_data),.out({enable_hb1, enable_hb2, cic_decim_rate}),.changed());
setting_reg #(.my_addr(BASE+3), .width(4)) sr_3
(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
.in(set_data),.out({invert_i,inver_q,realmode,swap_iq}),.changed());
// MUX so we can do realmode signals on either input
always @(posedge clk)
if(swap_iq)
begin
rx_fe_i_mux <= invert_i ? ~rx_fe_q + 1 : rx_fe_q;
rx_fe_q_mux <= realmode ? 0 : invert_q ? ~rx_fe_i + 1 : rx_fe_i;
end
else
begin
rx_fe_i_mux <= invert_i ? ~rx_fe_i + 1 : rx_fe_i;
rx_fe_q_mux <= realmode ? 0 : invert_i ? ~rx_fe_q + 1 : rx_fe_q;
end
// NCO
always @(posedge clk)
if(rst)
phase <= 0;
else if(~run)
phase <= 0;
else
phase <= phase + phase_inc;
//sign extension of cordic input
wire [cwidth-1:0] to_cordic_i, to_cordic_q;
sign_extend #(.bits_in(WIDTH), .bits_out(cwidth)) sign_extend_cordic_i (.in(rx_fe_i_mux), .out(to_cordic_i));
sign_extend #(.bits_in(WIDTH), .bits_out(cwidth)) sign_extend_cordic_q (.in(rx_fe_q_mux), .out(to_cordic_q));
// CORDIC 24-bit I/O
cordic_z24 #(.bitwidth(cwidth))
cordic(.clock(clk), .reset(rst), .enable(run),
.xi(to_cordic_i),. yi(to_cordic_q), .zi(phase[31:32-zwidth]),
.xo(i_cordic),.yo(q_cordic),.zo() );
clip_reg #(.bits_in(cwidth), .bits_out(WIDTH)) clip_i
(.clk(clk), .in(i_cordic), .strobe_in(1'b1), .out(i_cordic_clip));
clip_reg #(.bits_in(cwidth), .bits_out(WIDTH)) clip_q
(.clk(clk), .in(q_cordic), .strobe_in(1'b1), .out(q_cordic_clip));
// CIC decimator 24 bit I/O
cic_strober cic_strober(.clock(clk),.reset(rst),.enable(run),.rate(cic_decim_rate),
.strobe_fast(1),.strobe_slow(strobe_cic) );
cic_decim #(.bw(WIDTH))
decim_i (.clock(clk),.reset(rst),.enable(run),
.rate(cic_decim_rate),.strobe_in(1'b1),.strobe_out(strobe_cic),
.signal_in(i_cordic_clip),.signal_out(i_cic));
cic_decim #(.bw(WIDTH))
decim_q (.clock(clk),.reset(rst),.enable(run),
.rate(cic_decim_rate),.strobe_in(1'b1),.strobe_out(strobe_cic),
.signal_in(q_cordic_clip),.signal_out(q_cic));
// First (small) halfband 24 bit I/O
small_hb_dec #(.WIDTH(WIDTH)) small_hb_i
(.clk(clk),.rst(rst),.bypass(~enable_hb1),.run(run),
.stb_in(strobe_cic),.data_in(i_cic),.stb_out(strobe_hb1),.data_out(i_hb1));
small_hb_dec #(.WIDTH(WIDTH)) small_hb_q
(.clk(clk),.rst(rst),.bypass(~enable_hb1),.run(run),
.stb_in(strobe_cic),.data_in(q_cic),.stb_out(),.data_out(q_hb1));
// Second (large) halfband 24 bit I/O
wire [8:0] cpi_hb = enable_hb1 ? {cic_decim_rate,1'b0} : {1'b0,cic_decim_rate};
hb_dec #(.WIDTH(WIDTH)) hb_i
(.clk(clk),.rst(rst),.bypass(~enable_hb2),.run(run),.cpi(cpi_hb),
.stb_in(strobe_hb1),.data_in(i_hb1),.stb_out(strobe_hb2),.data_out(i_hb2));
hb_dec #(.WIDTH(WIDTH)) hb_q
(.clk(clk),.rst(rst),.bypass(~enable_hb2),.run(run),.cpi(cpi_hb),
.stb_in(strobe_hb1),.data_in(q_hb1),.stb_out(),.data_out(q_hb2));
//scalar operation (gain of 6 bits)
wire [35:0] prod_i, prod_q;
MULT18X18S mult_i
(.P(prod_i), .A(i_hb2[WIDTH-1:WIDTH-18]), .B(scale_factor), .C(clk), .CE(strobe_hb2), .R(rst) );
MULT18X18S mult_q
(.P(prod_q), .A(q_hb2[WIDTH-1:WIDTH-18]), .B(scale_factor), .C(clk), .CE(strobe_hb2), .R(rst) );
//pipeline for the multiplier (gain of 10 bits)
reg [WIDTH-1:0] prod_reg_i, prod_reg_q;
reg strobe_mult;
always @(posedge clk) begin
strobe_mult <= strobe_hb2;
prod_reg_i <= prod_i[33:34-WIDTH];
prod_reg_q <= prod_q[33:34-WIDTH];
end
// Round final answer to 16 bits
round_sd #(.WIDTH_IN(WIDTH),.WIDTH_OUT(16)) round_i
(.clk(clk),.reset(rst), .in(prod_reg_i),.strobe_in(strobe_mult), .out(sample[31:16]), .strobe_out(strobe));
round_sd #(.WIDTH_IN(WIDTH),.WIDTH_OUT(16)) round_q
(.clk(clk),.reset(rst), .in(prod_reg_q),.strobe_in(strobe_mult), .out(sample[15:0]), .strobe_out());
assign debug = {enable_hb1, enable_hb2, run, strobe, strobe_cic, strobe_hb1, strobe_hb2};
endmodule // ddc_chain
-262
View File
@@ -1,262 +0,0 @@
//
// Copyright 2011-2013 Ettus Research LLC
//
//! X300/X310 digital down-conversion chain
module ddc_chain_x300
#(
parameter BASE = 0,
parameter DSPNO = 0,
parameter WIDTH = 24
)
(input clk, input rst, input clr,
input set_stb, input [7:0] set_addr, input [31:0] set_data,
// From RX frontend
input [WIDTH-1:0] rx_fe_i,
input [WIDTH-1:0] rx_fe_q,
// To RX control
output [31:0] sample,
input run,
output strobe,
output [31:0] debug
);
localparam cwidth = 25;
localparam zwidth = 24;
wire [31:0] phase_inc;
reg [31:0] phase;
wire [17:0] scale_factor;
wire [cwidth-1:0] i_cordic, q_cordic;
wire [WIDTH-1:0] i_cordic_clip, q_cordic_clip;
wire [WIDTH-1:0] i_cic, q_cic;
wire [46:0] i_hb1, q_hb1;
wire [46:0] i_hb2, q_hb2;
wire [47:0] i_hb3, q_hb3;
wire strobe_cic, strobe_hb1, strobe_hb2, strobe_hb3;
wire [7:0] cic_decim_rate;
reg [WIDTH-1:0] rx_fe_i_mux, rx_fe_q_mux;
wire realmode;
wire swap_iq;
wire [1:0] hb_rate;
wire [2:0] enable_hb = { hb_rate == 2'b11, hb_rate[1] == 1'b1, hb_rate != 2'b00 };
wire reload_go, reload_we1, reload_we2, reload_we3, reload_ld1, reload_ld2, reload_ld3;
wire [17:0] coef_din;
setting_reg #(.my_addr(BASE+0)) sr_0
(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
.in(set_data),.out(phase_inc),.changed());
setting_reg #(.my_addr(BASE+1), .width(18)) sr_1
(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
.in(set_data),.out(scale_factor),.changed());
setting_reg #(.my_addr(BASE+2), .width(10)) sr_2
(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
.in(set_data),.out({hb_rate, cic_decim_rate}),.changed());
setting_reg #(.my_addr(BASE+3), .width(2)) sr_3
(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
.in(set_data),.out({realmode,swap_iq}),.changed());
setting_reg #(.my_addr(BASE+4), .width(24)) sr_4
(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
.in(set_data),.out({reload_ld3,reload_we3,reload_ld2,reload_we2,reload_ld1,reload_we1,coef_din}),.changed(reload_go));
// MUX so we can do realmode signals on either input
always @(posedge clk)
if(swap_iq)
begin
rx_fe_i_mux <= rx_fe_q;
rx_fe_q_mux <= realmode ? 0 : rx_fe_i;
end
else
begin
rx_fe_i_mux <= rx_fe_i;
rx_fe_q_mux <= realmode ? 0 : rx_fe_q;
end
// NCO
always @(posedge clk)
if(rst)
phase <= 0;
else if(~run)
phase <= 0;
else
phase <= phase + phase_inc;
//sign extension of cordic input
wire [cwidth-1:0] to_cordic_i, to_cordic_q;
sign_extend #(.bits_in(WIDTH), .bits_out(cwidth)) sign_extend_cordic_i (.in(rx_fe_i_mux), .out(to_cordic_i));
sign_extend #(.bits_in(WIDTH), .bits_out(cwidth)) sign_extend_cordic_q (.in(rx_fe_q_mux), .out(to_cordic_q));
// CORDIC 24-bit I/O
cordic_z24 #(.bitwidth(cwidth))
cordic(.clock(clk), .reset(rst), .enable(run),
.xi(to_cordic_i),. yi(to_cordic_q), .zi(phase[31:32-zwidth]),
.xo(i_cordic),.yo(q_cordic),.zo() );
clip_reg #(.bits_in(cwidth), .bits_out(WIDTH)) clip_cordic_i
(.clk(clk), .in(i_cordic), .strobe_in(1'b1), .out(i_cordic_clip));
clip_reg #(.bits_in(cwidth), .bits_out(WIDTH)) clip_cordic_q
(.clk(clk), .in(q_cordic), .strobe_in(1'b1), .out(q_cordic_clip));
// CIC decimator 24 bit I/O
cic_strober cic_strober(.clock(clk),.reset(rst),.enable(run),.rate(cic_decim_rate),
.strobe_fast(1'b1),.strobe_slow(strobe_cic) );
cic_decim #(.bw(WIDTH))
decim_i (.clock(clk),.reset(rst),.enable(run),
.rate(cic_decim_rate),.strobe_in(1'b1),.strobe_out(strobe_cic),
.signal_in(i_cordic_clip),.signal_out(i_cic));
cic_decim #(.bw(WIDTH))
decim_q (.clock(clk),.reset(rst),.enable(run),
.rate(cic_decim_rate),.strobe_in(1'b1),.strobe_out(strobe_cic),
.signal_in(q_cordic_clip),.signal_out(q_cic));
// Halfbands
wire nd1, nd2, nd3;
wire rfd1, rfd2, rfd3;
wire rdy1, rdy2, rdy3;
wire data_valid1, data_valid2, data_valid3;
localparam HB1_SCALE = 18;
localparam HB2_SCALE = 18;
localparam HB3_SCALE = 18;
assign strobe_hb1 = data_valid1;
assign strobe_hb2 = data_valid2;
assign strobe_hb3 = data_valid3;
assign nd1 = strobe_cic;
assign nd2 = strobe_hb1;
assign nd3 = strobe_hb2;
hbdec1 hbdec1
(.clk(clk), // input clk
.sclr(rst), // input sclr
.ce(enable_hb[0]), // input ce
.coef_ld(reload_go & reload_ld1), // input coef_ld
.coef_we(reload_go & reload_we1), // input coef_we
.coef_din(coef_din), // input [17 : 0] coef_din
.rfd(rfd1), // output rfd
.nd(nd1), // input nd
.din_1(i_cic), // input [23 : 0] din_1
.din_2(q_cic), // input [23 : 0] din_2
.rdy(rdy1), // output rdy
.data_valid(data_valid1), // output data_valid
.dout_1(i_hb1), // output [46 : 0] dout_1
.dout_2(q_hb1)); // output [46 : 0] dout_2
hbdec2 hbdec2
(.clk(clk), // input clk
.sclr(rst), // input sclr
.ce(enable_hb[1]), // input ce
.coef_ld(reload_go & reload_ld2), // input coef_ld
.coef_we(reload_go & reload_we2), // input coef_we
.coef_din(coef_din), // input [17 : 0] coef_din
.rfd(rfd2), // output rfd
.nd(nd2), // input nd
.din_1(i_hb1[23+HB1_SCALE:HB1_SCALE]), // input [23 : 0] din_1
.din_2(q_hb1[23+HB1_SCALE:HB1_SCALE]), // input [23 : 0] din_2
.rdy(rdy2), // output rdy
.data_valid(data_valid2), // output data_valid
.dout_1(i_hb2), // output [46 : 0] dout_1
.dout_2(q_hb2)); // output [46 : 0] dout_2
hbdec3 hbdec3
(.clk(clk), // input clk
.sclr(rst), // input sclr
.ce(enable_hb[2]), // input ce
.coef_ld(reload_go & reload_ld3), // input coef_ld
.coef_we(reload_go & reload_we3), // input coef_we
.coef_din(coef_din), // input [17 : 0] coef_din
.rfd(rfd3), // output rfd
.nd(strobe_hb2), // input nd
.din_1(i_hb2[23+HB2_SCALE:HB2_SCALE]), // input [23 : 0] din_1
.din_2(q_hb2[23+HB2_SCALE:HB2_SCALE]), // input [23 : 0] din_2
.rdy(rdy3), // output rdy
.data_valid(data_valid3), // output data_valid
.dout_1(i_hb3), // output [47 : 0] dout_1
.dout_2(q_hb3)); // output [47 : 0] dout_2
reg [23:0] i_unscaled, q_unscaled;
reg strobe_unscaled;
always @(posedge clk)
case(hb_rate)
2'd0 :
begin
strobe_unscaled <= strobe_cic;
i_unscaled <= i_cic[23:0];
q_unscaled <= q_cic[23:0];
end
2'd1 :
begin
strobe_unscaled <= strobe_hb1;
i_unscaled <= i_hb1[23+HB1_SCALE:HB1_SCALE];
q_unscaled <= q_hb1[23+HB1_SCALE:HB1_SCALE];
end
2'd2 :
begin
strobe_unscaled <= strobe_hb2;
i_unscaled <= i_hb2[23+HB2_SCALE:HB2_SCALE];
q_unscaled <= q_hb2[23+HB2_SCALE:HB2_SCALE];
end
2'd3 :
begin
strobe_unscaled <= strobe_hb3;
i_unscaled <= i_hb3[23+HB3_SCALE:HB3_SCALE];
q_unscaled <= q_hb3[23+HB3_SCALE:HB3_SCALE];
end
endcase // case (hb_rate)
wire [42:0] i_scaled, q_scaled;
wire [23:0] i_clip, q_clip;
reg strobe_scaled;
wire strobe_clip;
MULT_MACRO #(.DEVICE("7SERIES"), // Target Device: "VIRTEX5", "VIRTEX6", "SPARTAN6","7SERIES"
.LATENCY(1), // Desired clock cycle latency, 0-4
.WIDTH_A(25), // Multiplier A-input bus width, 1-25
.WIDTH_B(18)) // Multiplier B-input bus width, 1-18
SCALE_I (.P(i_scaled), // Multiplier output bus, width determined by WIDTH_P parameter
.A({i_unscaled[23],i_unscaled}), // Multiplier input A bus, width determined by WIDTH_A parameter
.B(scale_factor), // Multiplier input B bus, width determined by WIDTH_B parameter
.CE(strobe_unscaled), // 1-bit active high input clock enable
.CLK(clk), // 1-bit positive edge clock input
.RST(rst)); // 1-bit input active high reset
MULT_MACRO #(.DEVICE("7SERIES"), // Target Device: "VIRTEX5", "VIRTEX6", "SPARTAN6","7SERIES"
.LATENCY(1), // Desired clock cycle latency, 0-4
.WIDTH_A(25), // Multiplier A-input bus width, 1-25
.WIDTH_B(18)) // Multiplier B-input bus width, 1-18
SCALE_Q (.P(q_scaled), // Multiplier output bus, width determined by WIDTH_P parameter
.A({q_unscaled[23],q_unscaled}), // Multiplier input A bus, width determined by WIDTH_A parameter
.B(scale_factor), // Multiplier input B bus, width determined by WIDTH_B parameter
.CE(strobe_unscaled), // 1-bit active high input clock enable
.CLK(clk), // 1-bit positive edge clock input
.RST(rst)); // 1-bit input active high reset
always @(posedge clk) strobe_scaled <= strobe_unscaled;
clip_reg #(.bits_in(29), .bits_out(24), .STROBED(1)) clip_i
(.clk(clk), .in(i_scaled[42:14]), .strobe_in(strobe_scaled), .out(i_clip), .strobe_out(strobe_clip));
clip_reg #(.bits_in(29), .bits_out(24), .STROBED(1)) clip_q
(.clk(clk), .in(q_scaled[42:14]), .strobe_in(strobe_scaled), .out(q_clip), .strobe_out());
round_sd #(.WIDTH_IN(24), .WIDTH_OUT(16)) round_i
(.clk(clk), .reset(rst), .in(i_clip), .strobe_in(strobe_clip), .out(sample[31:16]), .strobe_out(strobe));
round_sd #(.WIDTH_IN(24), .WIDTH_OUT(16)) round_q
(.clk(clk), .reset(rst), .in(q_clip), .strobe_in(strobe_clip), .out(sample[15:0]), .strobe_out());
endmodule // ddc_chain
-58
View File
@@ -1,58 +0,0 @@
`timescale 1ns/1ps
module ddc_chain_x300_tb();
`ifdef ISIM
`else //iverilog implied.
// xlnx_glbl glbl (.GSR(),.GTS());
`endif
localparam SR_TX_DSP = 8;
reg clk = 0;
reg reset = 1;
always #10 clk = ~clk;
initial $dumpfile("ddc_chain_x300_tb.vcd");
initial $dumpvars(0,ddc_chain_x300_tb);
reg run = 0;
wire strobe;
initial
begin
#1000 reset = 0;
@(posedge clk);
set_addr <= 0; set_data <= 32'd8434349; set_stb <= 1; @(posedge clk); // CORDIC
set_addr <= 1; set_data <= 18'd19800; set_stb <= 1; @(posedge clk); // Scale factor
set_addr <= 2; set_data <= 10'h003; set_stb <= 1; @(posedge clk); // Decim control
set_addr <= 3; set_data <= 0; set_stb <= 1; @(posedge clk); // Swap iq
set_addr <= 4; set_data <= 0; set_stb <= 1; @(posedge clk); // filter taps
set_stb <= 0;
repeat(10)
@(posedge clk);
run <= 1'b1;
#30000;
$finish;
end
reg [7:0] set_addr;
reg [31:0] set_data;
reg set_stb = 1'b0;
wire [15:0] i_out, q_out;
wire [23:0] rx_fe_i, rx_fe_q;
assign rx_fe_i = 24'd8388607;
assign rx_fe_q = 24'd8388607;
//assign rx_fe_q = 0;
ddc_chain_x300 #(.BASE(0), .DSPNO(0), .WIDTH(24)) ddc_chain
(.clk(clk), .rst(reset), .clr(1'b0),
.set_stb(set_stb),.set_addr(set_addr),.set_data(set_data),
.rx_fe_i(rx_fe_i),.rx_fe_q(rx_fe_q),
.sample({i_out,q_out}), .run(run), .strobe(strobe),
.debug() );
endmodule // new_tx_tb
-146
View File
@@ -1,146 +0,0 @@
//
// Copyright 2011-2013 Ettus Research LLC
//
//! The USRP digital up-conversion chain
module duc_chain
#(
parameter BASE = 0,
parameter DSPNO = 0,
parameter WIDTH = 24
)
(input clk, input rst, input clr,
input set_stb, input [7:0] set_addr, input [31:0] set_data,
// To TX frontend
output [WIDTH-1:0] tx_fe_i,
output [WIDTH-1:0] tx_fe_q,
// From TX control
input [31:0] sample,
input run,
output strobe,
output [31:0] debug
);
wire [17:0] scale_factor;
wire [31:0] phase_inc;
reg [31:0] phase;
wire [7:0] interp_rate;
wire [3:0] tx_femux_a, tx_femux_b;
wire enable_hb1, enable_hb2;
wire rate_change;
setting_reg #(.my_addr(BASE+0)) sr_0
(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
.in(set_data),.out(phase_inc),.changed());
setting_reg #(.my_addr(BASE+1), .width(18)) sr_1
(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
.in(set_data),.out(scale_factor),.changed());
setting_reg #(.my_addr(BASE+2), .width(10)) sr_2
(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
.in(set_data),.out({enable_hb1, enable_hb2, interp_rate}),.changed(rate_change));
// Strobes are all now delayed by 1 cycle for timing reasons
wire strobe_cic_pre, strobe_hb1_pre, strobe_hb2_pre;
reg strobe_cic = 1;
reg strobe_hb1 = 1;
reg strobe_hb2 = 1;
assign strobe = strobe_hb1;
cic_strober #(.WIDTH(8))
cic_strober(.clock(clk),.reset(rst),.enable(run & ~rate_change),.rate(interp_rate),
.strobe_fast(1),.strobe_slow(strobe_cic_pre) );
cic_strober #(.WIDTH(2))
hb2_strober(.clock(clk),.reset(rst),.enable(run & ~rate_change),.rate(enable_hb2 ? 2 : 1),
.strobe_fast(strobe_cic_pre),.strobe_slow(strobe_hb2_pre) );
cic_strober #(.WIDTH(2))
hb1_strober(.clock(clk),.reset(rst),.enable(run & ~rate_change),.rate(enable_hb1 ? 2 : 1),
.strobe_fast(strobe_hb2_pre),.strobe_slow(strobe_hb1_pre) );
always @(posedge clk) strobe_hb1 <= strobe_hb1_pre;
always @(posedge clk) strobe_hb2 <= strobe_hb2_pre;
always @(posedge clk) strobe_cic <= strobe_cic_pre;
// NCO
always @(posedge clk)
if(rst)
phase <= 0;
else if(~run)
phase <= 0;
else
phase <= phase + phase_inc;
wire signed [17:0] da, db;
wire signed [35:0] prod_i, prod_q;
assign tx_fe_i = prod_i[33:34-WIDTH];
assign tx_fe_q = prod_q[33:34-WIDTH];
wire [17:0] i_interp, q_interp;
wire [17:0] hb1_i, hb1_q, hb2_i, hb2_q;
wire [7:0] cpo = enable_hb2 ? ({interp_rate,1'b0}) : interp_rate;
// Note that max CIC rate is 128, which would give an overflow on cpo if enable_hb2 is true,
// but the default case inside hb_interp handles this
hb_interp #(.IWIDTH(18),.OWIDTH(18),.ACCWIDTH(WIDTH)) hb_interp_i
(.clk(clk),.rst(rst),.bypass(~enable_hb1),.cpo(cpo),.stb_in(strobe_hb1),.data_in({sample[31:16], 2'b0}),.stb_out(strobe_hb2),.data_out(hb1_i));
hb_interp #(.IWIDTH(18),.OWIDTH(18),.ACCWIDTH(WIDTH)) hb_interp_q
(.clk(clk),.rst(rst),.bypass(~enable_hb1),.cpo(cpo),.stb_in(strobe_hb1),.data_in({sample[15:0], 2'b0}),.stb_out(strobe_hb2),.data_out(hb1_q));
small_hb_int #(.WIDTH(18)) small_hb_interp_i
(.clk(clk),.rst(rst),.bypass(~enable_hb2),.stb_in(strobe_hb2),.data_in(hb1_i),
.output_rate(interp_rate),.stb_out(strobe_cic),.data_out(hb2_i));
small_hb_int #(.WIDTH(18)) small_hb_interp_q
(.clk(clk),.rst(rst),.bypass(~enable_hb2),.stb_in(strobe_hb2),.data_in(hb1_q),
.output_rate(interp_rate),.stb_out(strobe_cic),.data_out(hb2_q));
cic_interp #(.bw(18),.N(4),.log2_of_max_rate(7))
cic_interp_i(.clock(clk),.reset(rst),.enable(run & ~rate_change),.rate(interp_rate),
.strobe_in(strobe_cic),.strobe_out(1),
.signal_in(hb2_i),.signal_out(i_interp));
cic_interp #(.bw(18),.N(4),.log2_of_max_rate(7))
cic_interp_q(.clock(clk),.reset(rst),.enable(run & ~rate_change),.rate(interp_rate),
.strobe_in(strobe_cic),.strobe_out(1),
.signal_in(hb2_q),.signal_out(q_interp));
localparam cwidth = WIDTH; // was 18
localparam zwidth = 24; // was 16
wire [cwidth-1:0] da_c, db_c;
cordic_z24 #(.bitwidth(cwidth))
cordic(.clock(clk), .reset(rst), .enable(run),
.xi({i_interp,{(cwidth-18){1'b0}}}),.yi({q_interp,{(cwidth-18){1'b0}}}),
.zi(phase[31:32-zwidth]),
.xo(da_c),.yo(db_c),.zo() );
MULT18X18S MULT18X18S_inst
(.P(prod_i), // 36-bit multiplier output
.A(da_c[cwidth-1:cwidth-18]), // 18-bit multiplier input
.B(scale_factor), // 18-bit multiplier input
.C(clk), // Clock input
.CE(1), // Clock enable input
.R(rst) // Synchronous reset input
);
MULT18X18S MULT18X18S_inst_2
(.P(prod_q), // 36-bit multiplier output
.A(db_c[cwidth-1:cwidth-18]), // 18-bit multiplier input
.B(scale_factor), // 18-bit multiplier input
.C(clk), // Clock input
.CE(1), // Clock enable input
.R(rst) // Synchronous reset input
);
assign debug = {strobe_cic, strobe_hb1, strobe_hb2,run};
endmodule // duc_chain
-177
View File
@@ -1,177 +0,0 @@
//
// Copyright 2011 Ettus Research LLC
//
// Final halfband decimator
// Implements impulse responses of the form [A 0 B 0 C .. 0 H 0.5 H 0 .. C 0 B 0 A]
// Strobe in cannot come faster than every 2nd clock cycle
// These taps designed by halfgen4 from ldoolittle
// myfilt = round(2^18 * halfgen4(.7/4,8))
module hb_dec
#(parameter WIDTH=24)
(input clk,
input rst,
input bypass,
input run,
input [8:0] cpi, // Clocks per input -- equal to the decimation ratio ahead of this block
input stb_in,
input [WIDTH-1:0] data_in,
output reg stb_out,
output reg [WIDTH-1:0] data_out);
localparam INTWIDTH = 17;
localparam ACCWIDTH = WIDTH + 3;
// Round off inputs to 17 bits because of 18 bit multipliers
wire [INTWIDTH-1:0] data_rnd;
wire stb_rnd;
round_sd #(.WIDTH_IN(WIDTH),.WIDTH_OUT(INTWIDTH)) round_in
(.clk(clk),.reset(rst),.in(data_in),.strobe_in(stb_in),.out(data_rnd),.strobe_out(stb_rnd));
// Control
reg [3:0] addr_odd_a, addr_odd_b, addr_odd_c, addr_odd_d;
wire write_odd, write_even, do_mult;
reg odd;
reg [2:0] phase, phase_d1;
reg stb_out_int;
wire clear, do_acc;
assign do_mult = 1;
always @(posedge clk)
if(rst | ~run)
odd <= 0;
else if(stb_rnd)
odd <= ~odd;
assign write_odd = stb_rnd & odd;
assign write_even = stb_rnd & ~odd;
always @(posedge clk)
if(rst | ~run)
phase <= 0;
else if(stb_rnd & odd)
phase <= 1;
else if(phase == 4)
phase <= 0;
else if(phase != 0)
phase <= phase + 1;
always @(posedge clk)
phase_d1 <= phase;
reg [15:0] stb_out_pre;
always @(posedge clk)
if(rst)
stb_out_pre <= 0;
else
stb_out_pre <= {stb_out_pre[14:0],(stb_rnd & odd)};
always @*
case(phase)
1 : begin addr_odd_a = 0; addr_odd_b = 15; end
2 : begin addr_odd_a = 1; addr_odd_b = 14; end
3 : begin addr_odd_a = 2; addr_odd_b = 13; end
4 : begin addr_odd_a = 3; addr_odd_b = 12; end
default : begin addr_odd_a = 0; addr_odd_b = 15; end
endcase // case(phase)
always @*
case(phase)
1 : begin addr_odd_c = 4; addr_odd_d = 11; end
2 : begin addr_odd_c = 5; addr_odd_d = 10; end
3 : begin addr_odd_c = 6; addr_odd_d = 9; end
4 : begin addr_odd_c = 7; addr_odd_d = 8; end
default : begin addr_odd_c = 4; addr_odd_d = 11; end
endcase // case(phase)
assign do_acc = |stb_out_pre[6:3];
assign clear = stb_out_pre[3];
// Data
wire [INTWIDTH-1:0] data_odd_a, data_odd_b, data_odd_c, data_odd_d;
reg [INTWIDTH:0] sum1, sum2; // these are 18-bit inputs to mult
reg [WIDTH:0] final_sum;
wire [WIDTH-1:0] final_sum_clip;
reg [17:0] coeff1, coeff2;
wire [35:0] prod1, prod2;
always @* // Outer coeffs
case(phase_d1)
1 : coeff1 = -107;
2 : coeff1 = 445;
3 : coeff1 = -1271;
4 : coeff1 = 2959;
default : coeff1 = -107;
endcase // case(phase)
always @* // Inner coeffs
case(phase_d1)
1 : coeff2 = -6107;
2 : coeff2 = 11953;
3 : coeff2 = -24706;
4 : coeff2 = 82359;
default : coeff2 = -6107;
endcase // case(phase)
srl #(.WIDTH(INTWIDTH)) srl_odd_a
(.clk(clk),.write(write_odd),.in(data_rnd),.addr(addr_odd_a),.out(data_odd_a));
srl #(.WIDTH(INTWIDTH)) srl_odd_b
(.clk(clk),.write(write_odd),.in(data_rnd),.addr(addr_odd_b),.out(data_odd_b));
srl #(.WIDTH(INTWIDTH)) srl_odd_c
(.clk(clk),.write(write_odd),.in(data_rnd),.addr(addr_odd_c),.out(data_odd_c));
srl #(.WIDTH(INTWIDTH)) srl_odd_d
(.clk(clk),.write(write_odd),.in(data_rnd),.addr(addr_odd_d),.out(data_odd_d));
always @(posedge clk) sum1 <= {data_odd_a[INTWIDTH-1],data_odd_a} + {data_odd_b[INTWIDTH-1],data_odd_b};
always @(posedge clk) sum2 <= {data_odd_c[INTWIDTH-1],data_odd_c} + {data_odd_d[INTWIDTH-1],data_odd_d};
wire [INTWIDTH-1:0] data_even;
reg [3:0] addr_even;
always @(posedge clk)
case(cpi)
// 1 is an error
2 : addr_even <= 9; // Maximum speed (overall decim by 4)
3, 4, 5, 6, 7 : addr_even <= 8;
default : addr_even <= 7;
endcase // case(cpi)
srl #(.WIDTH(INTWIDTH)) srl_even
(.clk(clk),.write(write_even),.in(data_rnd),.addr(addr_even),.out(data_even));
MULT18X18S mult1(.C(clk), .CE(do_mult), .R(rst), .P(prod1), .A(coeff1), .B(sum1) );
MULT18X18S mult2(.C(clk), .CE(do_mult), .R(rst), .P(prod2), .A(coeff2), .B(sum2) );
reg [35:0] sum_of_prod;
always @(posedge clk) sum_of_prod <= prod1 + prod2; // Can't overflow
wire [ACCWIDTH-1:0] acc_out;
acc #(.IWIDTH(ACCWIDTH-2),.OWIDTH(ACCWIDTH))
acc (.clk(clk),.clear(clear),.acc(do_acc),.in(sum_of_prod[35:38-ACCWIDTH]),.out(acc_out));
wire [ACCWIDTH-1:0] data_even_signext;
localparam SHIFT_FACTOR = 6;
sign_extend #(.bits_in(INTWIDTH),.bits_out(ACCWIDTH-SHIFT_FACTOR)) signext_data_even
(.in(data_even),.out(data_even_signext[ACCWIDTH-1:SHIFT_FACTOR]));
assign data_even_signext[SHIFT_FACTOR-1:0] = 0;
always @(posedge clk) final_sum <= acc_out + data_even_signext;
clip #(.bits_in(WIDTH+1), .bits_out(WIDTH)) clip (.in(final_sum), .out(final_sum_clip));
// Output MUX to allow for bypass
wire selected_stb = bypass ? stb_in : stb_out_pre[8];
always @(posedge clk)
begin
stb_out <= selected_stb;
if(selected_stb)
data_out <= bypass ? data_in : final_sum_clip;
end
endmodule // hb_dec
-165
View File
@@ -1,165 +0,0 @@
//
// Copyright 2011 Ettus Research LLC
//
// First halfband iterpolator
// Implements impulse responses of the form [A 0 B 0 C .. 0 H 0.5 H 0 .. C 0 B 0 A]
// Strobe in cannot come faster than every 4th clock cycle,
// Strobe out cannot come faster than every 2nd clock cycle
// These taps designed by halfgen4 from ldoolittle
// myfilt = round(2^18 * halfgen4(.7/4,8))
module hb_interp
#(parameter IWIDTH=18, OWIDTH=18, ACCWIDTH=24)
(input clk,
input rst,
input bypass,
input [7:0] cpo, // Clocks per output, must be at least 2
input stb_in,
input [IWIDTH-1:0] data_in,
input stb_out,
output reg [OWIDTH-1:0] data_out);
localparam MWIDTH = ACCWIDTH-2;
localparam CWIDTH = 18;
reg [CWIDTH-1:0] coeff1, coeff2;
reg [3:0] addr_a, addr_b, addr_c, addr_d, addr_e;
wire [IWIDTH-1:0] data_a, data_b, data_c, data_d, data_e, sum1, sum2;
wire [35:0] prod1, prod2;
reg [2:0] phase, phase_d1, phase_d2, phase_d3, phase_d4, phase_d5;
always @(posedge clk)
if(rst)
phase <= 0;
else
if(stb_in)
phase <= 1;
else if(phase==4)
phase <= 0;
else if(phase!=0)
phase <= phase + 1;
always @(posedge clk) phase_d1 <= phase;
always @(posedge clk) phase_d2 <= phase_d1;
always @(posedge clk) phase_d3 <= phase_d2;
always @(posedge clk) phase_d4 <= phase_d3;
always @(posedge clk) phase_d5 <= phase_d4;
srl #(.WIDTH(IWIDTH)) srl_a
(.clk(clk),.rst(rst),.write(stb_in),.in(data_in),.addr(addr_a),.out(data_a));
srl #(.WIDTH(IWIDTH)) srl_b
(.clk(clk),.rst(rst),.write(stb_in),.in(data_in),.addr(addr_b),.out(data_b));
srl #(.WIDTH(IWIDTH)) srl_c
(.clk(clk),.rst(rst),.write(stb_in),.in(data_in),.addr(addr_c),.out(data_c));
srl #(.WIDTH(IWIDTH)) srl_d
(.clk(clk),.rst(rst),.write(stb_in),.in(data_in),.addr(addr_d),.out(data_d));
srl #(.WIDTH(IWIDTH)) srl_e
(.clk(clk),.rst(rst),.write(stb_in),.in(data_in),.addr(addr_e),.out(data_e));
always @*
case(phase)
1 : begin addr_a = 0; addr_b = 15; end
2 : begin addr_a = 1; addr_b = 14; end
3 : begin addr_a = 2; addr_b = 13; end
4 : begin addr_a = 3; addr_b = 12; end
default : begin addr_a = 0; addr_b = 15; end
endcase // case(phase)
always @*
case(phase)
1 : begin addr_c = 4; addr_d = 11; end
2 : begin addr_c = 5; addr_d = 10; end
3 : begin addr_c = 6; addr_d = 9; end
4 : begin addr_c = 7; addr_d = 8; end
default : begin addr_c = 4; addr_d = 11; end
endcase // case(phase)
always @*
case(cpo)
2 : addr_e <= 9;
3,4,5,6,7,8 : addr_e <= 8;
default : addr_e <= 7; // This case works for 256, which = 0 due to overflow outside this block
endcase // case(cpo)
always @* // Outer coeffs
case(phase_d1)
1 : coeff1 = -107;
2 : coeff1 = 445;
3 : coeff1 = -1271;
4 : coeff1 = 2959;
default : coeff1 = -107;
endcase // case(phase)
always @* // Inner coeffs
case(phase_d1)
1 : coeff2 = -6107;
2 : coeff2 = 11953;
3 : coeff2 = -24706;
4 : coeff2 = 82359;
default : coeff2 = -6107;
endcase // case(phase)
add2_reg /*_and_round_reg*/ #(.WIDTH(IWIDTH)) add1 (.clk(clk),.in1(data_a),.in2(data_b),.sum(sum1));
add2_reg /*_and_round_reg*/ #(.WIDTH(IWIDTH)) add2 (.clk(clk),.in1(data_c),.in2(data_d),.sum(sum2));
// sum1, sum2 available on phase_d1
wire do_mult = 1;
MULT18X18S mult1(.C(clk), .CE(do_mult), .R(rst), .P(prod1), .A(coeff1), .B(sum1) );
MULT18X18S mult2(.C(clk), .CE(do_mult), .R(rst), .P(prod2), .A(coeff2), .B(sum2) );
// prod1, prod2 available on phase_d2
wire [MWIDTH-1:0] sum_of_prod;
add2_and_round_reg #(.WIDTH(MWIDTH))
add3 (.clk(clk),.in1(prod1[35:36-MWIDTH]),.in2(prod2[35:36-MWIDTH]),.sum(sum_of_prod));
// sum_of_prod available on phase_d3
wire [ACCWIDTH-1:0] acc_out;
wire clear = (phase_d3 == 1);
wire do_acc = (phase_d3 != 0);
acc #(.IWIDTH(MWIDTH),.OWIDTH(ACCWIDTH)) //IJB rst
acc (.clk(clk),.clear(rst|clear),.acc(do_acc),.in(sum_of_prod),.out(acc_out));
// acc_out available on phase_d4
wire [ACCWIDTH-6:0] clipped_acc;
clip #(.bits_in(ACCWIDTH),.bits_out(ACCWIDTH-5)) final_clip(.in(acc_out),.out(clipped_acc));
reg [ACCWIDTH-6:0] clipped_reg;
always @(posedge clk)
if (rst)
clipped_reg <= 0;
else if(phase_d4 == 4)
clipped_reg <= clipped_acc;
// clipped_reg available on phase_d5
wire [OWIDTH-1:0] data_out_round;
round #(.bits_in(ACCWIDTH-5),.bits_out(OWIDTH)) final_round (.in(clipped_reg),.out(data_out_round));
reg odd;
always @(posedge clk)
if(rst)
odd <= 0;
else if(stb_in)
odd <= 0;
else if(stb_out)
odd <= 1;
always @(posedge clk)
if (rst)
data_out <= 0;
else if(bypass)
data_out <= data_in;
else if(stb_out)
if(odd)
data_out <= data_e;
else
data_out <= data_out_round;
// data_out available on phase_d6
endmodule // hb_interp
-47
View File
@@ -1,47 +0,0 @@
// -*- verilog -*-
//
// USRP - Universal Software Radio Peripheral
//
// Copyright (C) 2011 Matt Ettus
//
//
// Rounding "macro"
// Keeps the topmost bits, does proper 2s comp round to zero (unbiased truncation)
module round
#(parameter bits_in=0,
parameter bits_out=0,
parameter round_to_zero=0, // original behavior
parameter round_to_nearest=1, // lowest noise
parameter trunc=0) // round to negative infinity
(input [bits_in-1:0] in,
output [bits_out-1:0] out,
output [bits_in-bits_out:0] err);
wire round_corr,round_corr_trunc,round_corr_rtz,round_corr_nearest,round_corr_nearest_safe;
assign round_corr_trunc = 0;
assign round_corr_rtz = (in[bits_in-1] & |in[bits_in-bits_out-1:0]);
assign round_corr_nearest = in[bits_in-bits_out-1];
generate
if(bits_in-bits_out > 1)
assign round_corr_nearest_safe = (~in[bits_in-1] & (&in[bits_in-2:bits_out])) ? 0 :
round_corr_nearest;
else
assign round_corr_nearest_safe = round_corr_nearest;
endgenerate
assign round_corr = round_to_nearest ? round_corr_nearest_safe :
trunc ? round_corr_trunc :
round_to_zero ? round_corr_rtz :
0; // default to trunc
assign out = in[bits_in-1:bits_in-bits_out] + round_corr;
assign err = in - {out,{(bits_in-bits_out){1'b0}}};
endmodule // round
-32
View File
@@ -1,32 +0,0 @@
// -*- verilog -*-
//
// USRP - Universal Software Radio Peripheral
//
// Copyright (C) 2008 Matt Ettus
//
//
// Rounding "macro"
// Keeps the topmost bits, does proper 2s comp rounding (round-to-zero)
module round_reg
#(parameter bits_in=0,
parameter bits_out=0)
(input clk,
input [bits_in-1:0] in,
output reg [bits_out-1:0] out,
output reg [bits_in-bits_out:0] err);
wire [bits_out-1:0] temp;
wire [bits_in-bits_out:0] err_temp;
round #(.bits_in(bits_in),.bits_out(bits_out)) round (.in(in),.out(temp), .err(err_temp));
always @(posedge clk)
out <= temp;
always @(posedge clk)
err <= err_temp;
endmodule // round_reg
-23
View File
@@ -1,23 +0,0 @@
module round_sd
#(parameter WIDTH_IN=18,
parameter WIDTH_OUT=16,
parameter DISABLE_SD=0)
(input clk, input reset,
input [WIDTH_IN-1:0] in, input strobe_in,
output [WIDTH_OUT-1:0] out, output strobe_out);
localparam ERR_WIDTH = WIDTH_IN - WIDTH_OUT + 1;
wire [ERR_WIDTH-1:0] err;
wire [WIDTH_IN-1:0] err_ext, sum;
sign_extend #(.bits_in(ERR_WIDTH),.bits_out(WIDTH_IN)) ext_err (.in(err), .out(err_ext));
add2_and_clip_reg #(.WIDTH(WIDTH_IN)) add2_and_clip_reg
(.clk(clk), .rst(reset), .in1(in), .in2((DISABLE_SD == 0) ? err_ext : 0), .strobe_in(strobe_in), .sum(sum), .strobe_out(strobe_out));
round #(.bits_in(WIDTH_IN),.bits_out(WIDTH_OUT)) round_sum (.in(sum), .out(out), .err(err));
endmodule // round_sd
-46
View File
@@ -1,46 +0,0 @@
//
// Copyright 2011 Ettus Research LLC
//
module rx_dcoffset
#(parameter WIDTH=16,
parameter ADDR=8'd0,
parameter alpha_shift=20)
(input clk, input rst,
input set_stb, input [7:0] set_addr, input [31:0] set_data,
input [WIDTH-1:0] in, output [WIDTH-1:0] out);
wire set_now = set_stb & (ADDR == set_addr);
reg fixed; // uses fixed offset
wire [WIDTH-1:0] fixed_dco;
localparam int_width = WIDTH + alpha_shift;
reg [int_width-1:0] integrator;
wire [WIDTH-1:0] quantized;
always @(posedge clk)
if(rst)
begin
fixed <= 0;
integrator <= {int_width{1'b0}};
end
else if(set_now)
begin
fixed <= set_data[31];
if(set_data[30])
integrator <= {set_data[29:0],{(int_width-30){1'b0}}};
end
else if(~fixed)
integrator <= integrator + {{(alpha_shift){out[WIDTH-1]}},out};
round_sd #(.WIDTH_IN(int_width),.WIDTH_OUT(WIDTH)) round_sd
(.clk(clk), .reset(rst), .in(integrator), .strobe_in(1'b1), .out(quantized), .strobe_out());
add2_and_clip_reg #(.WIDTH(WIDTH)) add2_and_clip_reg
(.clk(clk), .rst(rst), .in1(in), .in2(-quantized), .strobe_in(1'b1), .sum(out), .strobe_out());
endmodule // rx_dcoffset
-74
View File
@@ -1,74 +0,0 @@
module rx_frontend
#(parameter BASE = 0,
parameter IQCOMP_EN = 1)
(input clk, input rst,
input set_stb, input [7:0] set_addr, input [31:0] set_data,
input [15:0] adc_a, input adc_ovf_a,
input [15:0] adc_b, input adc_ovf_b,
output [23:0] i_out, output [23:0] q_out,
input run,
output [31:0] debug
);
reg [15:0] adc_i, adc_q;
wire [23:0] adc_i_ofs, adc_q_ofs;
wire [35:0] corr_i, corr_q;
wire [17:0] mag_corr,phase_corr;
wire swap_iq;
setting_reg #(.my_addr(BASE), .width(1)) sr_8
(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
.in(set_data),.out(swap_iq),.changed());
always @(posedge clk)
if(swap_iq) // Swap
{adc_i,adc_q} <= {adc_b,adc_a};
else
{adc_i,adc_q} <= {adc_a,adc_b};
setting_reg #(.my_addr(BASE+1),.width(18)) sr_1
(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
.in(set_data),.out(mag_corr),.changed());
setting_reg #(.my_addr(BASE+2),.width(18)) sr_2
(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
.in(set_data),.out(phase_corr),.changed());
rx_dcoffset #(.WIDTH(24),.ADDR(BASE+3)) rx_dcoffset_i
(.clk(clk),.rst(rst),.set_stb(set_stb),.set_addr(set_addr),.set_data(set_data),
.in({adc_i,8'b00}),.out(adc_i_ofs));
rx_dcoffset #(.WIDTH(24),.ADDR(BASE+4)) rx_dcoffset_q
(.clk(clk),.rst(rst),.set_stb(set_stb),.set_addr(set_addr),.set_data(set_data),
.in({adc_q,8'b00}),.out(adc_q_ofs));
generate
if(IQCOMP_EN == 1)
begin
MULT18X18S mult_mag_corr
(.P(corr_i), .A(adc_i_ofs[23:6]), .B(mag_corr), .C(clk), .CE(1), .R(rst) );
MULT18X18S mult_phase_corr
(.P(corr_q), .A(adc_i_ofs[23:6]), .B(phase_corr), .C(clk), .CE(1), .R(rst) );
add2_and_clip_reg #(.WIDTH(24)) add_clip_i
(.clk(clk), .rst(rst),
.in1(adc_i_ofs), .in2(corr_i[35:12]), .strobe_in(1'b1),
.sum(i_out), .strobe_out());
add2_and_clip_reg #(.WIDTH(24)) add_clip_q
(.clk(clk), .rst(rst),
.in1(adc_q_ofs), .in2(corr_q[35:12]), .strobe_in(1'b1),
.sum(q_out), .strobe_out());
end // if (IQCOMP_EN == 1)
else
begin
assign i_out = adc_i_ofs;
assign q_out = adc_q_ofs;
end // else: !if(IQCOMP_EN == 1)
endgenerate
endmodule // rx_frontend
-45
View File
@@ -1,45 +0,0 @@
`timescale 1ns/1ns
module rx_frontend_tb();
reg clk, rst;
initial rst = 1;
initial #1000 rst = 0;
initial clk = 0;
always #5 clk = ~clk;
initial $dumpfile("rx_frontend_tb.vcd");
initial $dumpvars(0,rx_frontend_tb);
reg [15:0] adc_in;
wire [23:0] adc_out;
always @(posedge clk)
begin
if(adc_in[15])
$write("-%d,",-adc_in);
else
$write("%d,",adc_in);
if(adc_out[23])
$write("-%d\n",-adc_out);
else
$write("%d\n",adc_out);
end
rx_frontend #(.BASE(0), .IQCOMP_EN(1)) rx_frontend
(.clk(clk),.rst(rst),
.set_stb(0),.set_addr(0),.set_data(0),
.adc_a(adc_in), .adc_ovf_a(0),
.adc_b(0), .adc_ovf_b(0),
.i_out(adc_out),.q_out(),
.run(), .debug());
always @(posedge clk)
if(rst)
adc_in <= 0;
else
adc_in <= adc_in + 4;
//adc_in <= (($random % 473) + 23)/4;
endmodule // rx_frontend_tb
-23
View File
@@ -1,23 +0,0 @@
// -*- verilog -*-
//
// USRP - Universal Software Radio Peripheral
//
// Copyright (C) 2003 Matt Ettus
//
//
// Sign extension "macro"
// bits_out should be greater than bits_in
module sign_extend (in,out);
parameter bits_in=0; // FIXME Quartus insists on a default
parameter bits_out=0;
input [bits_in-1:0] in;
output [bits_out-1:0] out;
assign out = {{(bits_out-bits_in){in[bits_in-1]}},in};
endmodule
-124
View File
@@ -1,124 +0,0 @@
//
// Copyright 2011 Ettus Research LLC
//
// Short halfband decimator (intended to be followed by another stage)
// Implements impulse responses of the form [A 0 B 0.5 B 0 A]
//
// These taps designed by halfgen4 from ldoolittle:
// 2 * 131072 * halfgen4(.75/8,2)
module small_hb_dec
#(parameter WIDTH=18)
(input clk,
input rst,
input bypass,
input run,
input stb_in,
input [WIDTH-1:0] data_in,
output reg stb_out,
output reg [WIDTH-1:0] data_out);
// Round off inputs to 17 bits because of 18 bit multipliers
localparam INTWIDTH = 17;
wire [INTWIDTH-1:0] data_rnd;
wire stb_rnd;
round_sd #(.WIDTH_IN(WIDTH),.WIDTH_OUT(INTWIDTH)) round_in
(.clk(clk),.reset(rst),.in(data_in),.strobe_in(stb_in),.out(data_rnd),.strobe_out(stb_rnd));
reg stb_rnd_d1;
reg [INTWIDTH-1:0] data_rnd_d1;
always @(posedge clk) stb_rnd_d1 <= stb_rnd;
always @(posedge clk) data_rnd_d1 <= data_rnd;
wire go;
reg phase, go_d1, go_d2, go_d3, go_d4;
always @(posedge clk)
if(rst | ~run)
phase <= 0;
else if(stb_rnd_d1)
phase <= ~phase;
assign go = stb_rnd_d1 & phase;
always @(posedge clk)
if(rst | ~run)
begin
go_d1 <= 0;
go_d2 <= 0;
go_d3 <= 0;
go_d4 <= 0;
end
else
begin
go_d1 <= go;
go_d2 <= go_d1;
go_d3 <= go_d2;
go_d4 <= go_d3;
end
wire [17:0] coeff_a = -10690;
wire [17:0] coeff_b = 75809;
reg [INTWIDTH-1:0] d1, d2, d3, d4 , d5, d6;
always @(posedge clk)
if(stb_rnd_d1 | rst)
begin
d1 <= data_rnd_d1;
d2 <= d1;
d3 <= d2;
d4 <= d3;
d5 <= d4;
d6 <= d5;
end
reg [17:0] sum_a, sum_b, middle, middle_d1;
always @(posedge clk)
if(go)
begin
sum_a <= {data_rnd_d1[INTWIDTH-1],data_rnd_d1} + {d6[INTWIDTH-1],d6};
sum_b <= {d2[INTWIDTH-1],d2} + {d4[INTWIDTH-1],d4};
//middle <= {d3[INTWIDTH-1],d3};
middle <= {d3,1'b0};
end
always @(posedge clk)
if(go_d1)
middle_d1 <= middle;
wire [17:0] sum = go_d1 ? sum_b : sum_a;
wire [17:0] coeff = go_d1 ? coeff_b : coeff_a;
wire [35:0] prod;
MULT18X18S mult(.C(clk), .CE(go_d1 | go_d2), .R(rst), .P(prod), .A(coeff), .B(sum) );
localparam ACCWIDTH = 30;
reg [ACCWIDTH-1:0] accum;
always @(posedge clk)
if(rst)
accum <= 0;
else if(go_d2)
accum <= {middle_d1[17],middle_d1[17],middle_d1,{(16+ACCWIDTH-36){1'b0}}} + {prod[35:36-ACCWIDTH]};
else if(go_d3)
accum <= accum + {prod[35:36-ACCWIDTH]};
wire [WIDTH:0] accum_rnd;
wire [WIDTH-1:0] accum_rnd_clip;
wire stb_round;
round_sd #(.WIDTH_IN(ACCWIDTH),.WIDTH_OUT(WIDTH+1)) round_acc
(.clk(clk), .reset(rst), .in(accum), .strobe_in(go_d4), .out(accum_rnd), .strobe_out(stb_round));
clip #(.bits_in(WIDTH+1),.bits_out(WIDTH)) clip (.in(accum_rnd), .out(accum_rnd_clip));
// Output
always @(posedge clk)
begin
stb_out <= bypass ? stb_in : stb_round;
data_out <= bypass ? data_in : accum_rnd_clip;
end
endmodule // small_hb_dec
-99
View File
@@ -1,99 +0,0 @@
//
// Copyright 2011 Ettus Research LLC
//
// Short halfband decimator (intended to be followed by another stage)
// Implements impulse responses of the form [A 0 B 0.5 B 0 A]
//
// These taps designed by halfgen4 from ldoolittle:
// 2 * 131072 * halfgen4(.75/8,2)
module small_hb_int
#(parameter WIDTH=18)
(input clk,
input rst,
input bypass,
input stb_in,
input [WIDTH-1:0] data_in,
input [7:0] output_rate,
input stb_out,
output reg [WIDTH-1:0] data_out);
reg [WIDTH-1:0] d1, d2, d3, d4, d5, d6;
localparam MWIDTH = 36;
wire [MWIDTH-1:0] prod;
reg [6:0] stbin_d;
always @(posedge clk)
stbin_d <= {stbin_d[5:0],stb_in};
always @(posedge clk)
if (rst)
begin
d1 <= 0;
d2 <= 0;
d3 <= 0;
d4 <= 0;
d5 <= 0;
d6 <= 0;
end
else if(stb_in)
begin
d1 <= data_in;
d2 <= d1;
d3 <= d2;
d4 <= d3;
d5 <= d4;
d6 <= d5;
end
wire [WIDTH-1:0] sum_outer, sum_inner;
add2_and_round_reg #(.WIDTH(WIDTH)) add_outer (.clk(clk),.in1(d1),.in2(d4),.sum(sum_outer));
add2_and_round_reg #(.WIDTH(WIDTH)) add_inner (.clk(clk),.in1(d2),.in2(d3),.sum(sum_inner));
wire [17:0] coeff_outer = -10690;
wire [17:0] coeff_inner = 75809;
MULT18X18S mult(.C(clk), .CE(1), .R(rst), .P(prod), .A(stbin_d[1] ? coeff_outer : coeff_inner),
.B(stbin_d[1] ? sum_outer : sum_inner) );
wire [MWIDTH:0] accum;
acc #(.IWIDTH(MWIDTH),.OWIDTH(MWIDTH+1))
acc (.clk(clk),.clear(stbin_d[2]),.acc(|stbin_d[3:2]),.in(prod),.out(accum));
wire [WIDTH+2:0] accum_rnd;
round_reg #(.bits_in(MWIDTH+1),.bits_out(WIDTH+3))
final_round (.clk(clk),.in(accum),.out(accum_rnd));
wire [WIDTH-1:0] clipped;
clip_reg #(.bits_in(WIDTH+3),.bits_out(WIDTH)) final_clip
(.clk(clk),.in(accum_rnd),.strobe_in(1'b1), .out(clipped));
reg [WIDTH-1:0] saved, saved_d3;
always @(posedge clk)
if(stbin_d[6])
saved <= clipped;
always @(posedge clk)
if(stbin_d[3])
saved_d3 <= d3;
always @(posedge clk)
if(bypass)
data_out <= data_in;
else if(stb_in & stb_out)
case(output_rate)
1 : data_out <= d6;
2 : data_out <= d4;
3, 4, 5, 6, 7 : data_out <= d3;
default : data_out <= d2;
endcase // case(output_rate)
else if(stb_out)
data_out <= saved;
endmodule // small_hb_int
-27
View File
@@ -1,27 +0,0 @@
//
// Copyright 2011 Ettus Research LLC
//
module srl
#(parameter WIDTH=18)
(input clk,
input rst,
input write,
input [WIDTH-1:0] in,
input [3:0] addr,
output [WIDTH-1:0] out);
genvar i;
generate
for (i=0;i<WIDTH;i=i+1)
begin : gen_srl
SRL16E
srl16e(.Q(out[i]),
.A0(addr[0]),.A1(addr[1]),.A2(addr[2]),.A3(addr[3]),
.CE(write|rst),.CLK(clk),.D(in[i]));
end
endgenerate
endmodule // srl
-97
View File
@@ -1,97 +0,0 @@
module tx_frontend
#(parameter BASE=0,
parameter WIDTH_OUT=16,
parameter IQCOMP_EN=1)
(input clk, input rst,
input set_stb, input [7:0] set_addr, input [31:0] set_data,
input [23:0] tx_i, input [23:0] tx_q, input run,
output reg [WIDTH_OUT-1:0] dac_a, output reg [WIDTH_OUT-1:0] dac_b
);
// IQ balance --> DC offset --> rounding --> mux
wire [23:0] i_dco, q_dco, i_ofs, q_ofs;
wire [WIDTH_OUT-1:0] i_final, q_final;
wire [7:0] mux_ctrl;
wire [35:0] corr_i, corr_q;
wire [23:0] i_bal, q_bal;
wire [17:0] mag_corr, phase_corr;
setting_reg #(.my_addr(BASE+0), .width(24)) sr_0
(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
.in(set_data),.out(i_dco),.changed());
setting_reg #(.my_addr(BASE+1), .width(24)) sr_1
(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
.in(set_data),.out(q_dco),.changed());
setting_reg #(.my_addr(BASE+2),.width(18)) sr_2
(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
.in(set_data),.out(mag_corr),.changed());
setting_reg #(.my_addr(BASE+3),.width(18)) sr_3
(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
.in(set_data),.out(phase_corr),.changed());
setting_reg #(.my_addr(BASE+4), .width(8)) sr_4
(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
.in(set_data),.out(mux_ctrl),.changed());
generate
if(IQCOMP_EN==1)
begin
// IQ Balance
MULT18X18S mult_mag_corr
(.P(corr_i), .A(tx_i[23:6]), .B(mag_corr), .C(clk), .CE(1), .R(rst) );
MULT18X18S mult_phase_corr
(.P(corr_q), .A(tx_i[23:6]), .B(phase_corr), .C(clk), .CE(1), .R(rst) );
add2_and_clip_reg #(.WIDTH(24)) add_clip_i
(.clk(clk), .rst(rst),
.in1(tx_i), .in2(corr_i[35:12]), .strobe_in(1'b1),
.sum(i_bal), .strobe_out());
add2_and_clip_reg #(.WIDTH(24)) add_clip_q
(.clk(clk), .rst(rst),
.in1(tx_q), .in2(corr_q[35:12]), .strobe_in(1'b1),
.sum(q_bal), .strobe_out());
end // if (IQCOMP_EN==1)
else
begin
assign i_bal = tx_i;
assign q_bal = tx_q;
end // else: !if(IQCOMP_EN==1)
endgenerate
// DC Offset
add2_and_clip_reg #(.WIDTH(24)) add_dco_i
(.clk(clk), .rst(rst), .in1(i_dco), .in2(i_bal), .strobe_in(1'b1), .sum(i_ofs), .strobe_out());
add2_and_clip_reg #(.WIDTH(24)) add_dco_q
(.clk(clk), .rst(rst), .in1(q_dco), .in2(q_bal), .strobe_in(1'b1), .sum(q_ofs), .strobe_out());
// Rounding
round_sd #(.WIDTH_IN(24),.WIDTH_OUT(WIDTH_OUT)) round_i
(.clk(clk), .reset(rst), .in(i_ofs),.strobe_in(1'b1), .out(i_final), .strobe_out());
round_sd #(.WIDTH_IN(24),.WIDTH_OUT(WIDTH_OUT)) round_q
(.clk(clk), .reset(rst), .in(q_ofs),.strobe_in(1'b1), .out(q_final), .strobe_out());
// Mux
always @(posedge clk)
case(mux_ctrl[3:0])
0 : dac_a <= i_final;
1 : dac_a <= q_final;
default : dac_a <= 0;
endcase // case (mux_ctrl[3:0])
always @(posedge clk)
case(mux_ctrl[7:4])
0 : dac_b <= i_final;
1 : dac_b <= q_final;
default : dac_b <= 0;
endcase // case (mux_ctrl[7:4])
endmodule // tx_frontend
-21
View File
@@ -1,21 +0,0 @@
#
# Copyright 2012-2013 Ettus Research LLC
#
##################################################
# FIFO Sources
##################################################
FIFO_SRCS = $(abspath $(addprefix $(BASE_DIR)/../lib/fifo/, \
axi_mux4.v \
axi_mux8.v \
axi_demux4.v \
axi_demux8.v \
axi_fifo_short.v \
axi_packet_gate.v \
axi_fifo.v \
axi_fifo64_to_fifo32.v \
axi_fifo32_to_fifo64.v \
axi_fifo_2clk.v \
axi_loopback.v \
axi_filter_mux4.v \
))
-77
View File
@@ -1,77 +0,0 @@
// Copyright 2012 Ettus Research LLC
// axi_demux -- takes one AXI stream, sends to one of 4 output channels
// Choice of output channel is by external logic based on first line of packet ("header" port)
// If compressed vita data, this line contains vita header and streamid.
module axi_demux4
#(parameter ACTIVE_CHAN = 4'b1111, // ACTIVE_CHAN is a map of connected outputs
parameter WIDTH = 64,
parameter BUFFER=0)
(input clk, input reset, input clear,
output [WIDTH-1:0] header, input [1:0] dest,
input [WIDTH-1:0] i_tdata, input i_tlast, input i_tvalid, output i_tready,
output [WIDTH-1:0] o0_tdata, output o0_tlast, output o0_tvalid, input o0_tready,
output [WIDTH-1:0] o1_tdata, output o1_tlast, output o1_tvalid, input o1_tready,
output [WIDTH-1:0] o2_tdata, output o2_tlast, output o2_tvalid, input o2_tready,
output [WIDTH-1:0] o3_tdata, output o3_tlast, output o3_tvalid, input o3_tready);
wire [WIDTH-1:0] i_tdata_int;
wire i_tlast_int, i_tvalid_int, i_tready_int;
generate
if(BUFFER == 0)
begin
assign i_tdata_int = i_tdata;
assign i_tlast_int = i_tlast;
assign i_tvalid_int = i_tvalid;
assign i_tready = i_tready_int;
end
else
axi_fifo_short #(.WIDTH(WIDTH+1)) axi_fifo_short
(.clk(clk), .reset(reset), .clear(clear),
.i_tdata({i_tlast,i_tdata}), .i_tvalid(i_tvalid), .i_tready(i_tready),
.o_tdata({i_tlast_int,i_tdata_int}), .o_tvalid(i_tvalid_int), .o_tready(i_tready_int),
.space(), .occupied());
endgenerate
reg [3:0] dm_state;
localparam DM_IDLE = 4'b0000;
localparam DM_0 = 4'b0001;
localparam DM_1 = 4'b0010;
localparam DM_2 = 4'b0100;
localparam DM_3 = 4'b1000;
assign header = i_tdata_int;
always @(posedge clk)
if(reset | clear)
dm_state <= DM_IDLE;
else
case (dm_state)
DM_IDLE :
if(i_tvalid_int)
case(dest)
2'b00 : dm_state <= DM_0;
2'b01 : dm_state <= DM_1;
2'b10 : dm_state <= DM_2;
2'b11 : dm_state <= DM_3;
endcase // case (i_tdata[1:0])
DM_0, DM_1, DM_2, DM_3 :
if(i_tvalid_int & i_tready_int & i_tlast_int)
dm_state <= DM_IDLE;
default :
dm_state <= DM_IDLE;
endcase // case (dm_state)
assign {o3_tvalid, o2_tvalid, o1_tvalid, o0_tvalid} = dm_state & {4{i_tvalid_int}};
assign i_tready_int = |(dm_state & ({o3_tready, o2_tready, o1_tready, o0_tready} | ~ACTIVE_CHAN));
assign {o0_tlast, o0_tdata} = {i_tlast_int, i_tdata_int};
assign {o1_tlast, o1_tdata} = {i_tlast_int, i_tdata_int};
assign {o2_tlast, o2_tdata} = {i_tlast_int, i_tdata_int};
assign {o3_tlast, o3_tdata} = {i_tlast_int, i_tdata_int};
endmodule // axi_demux4
-60
View File
@@ -1,60 +0,0 @@
// Copyright 2012 Ettus Research LLC
// axi_demux -- takes one AXI stream, sends to one of 8 output channels
// Choice of output channel is by external logic based on first line of packet ("header" port)
// If compressed vita data, this line contains vita header and streamid.
module axi_demux8 #(
parameter ACTIVE_CHAN = 8'b11111111, // ACTIVE_CHAN is a map of connected outputs
parameter WIDTH = 64,
parameter BUFFER=0
) (
input clk, input reset, input clear,
output [WIDTH-1:0] header, input [2:0] dest,
input [WIDTH-1:0] i_tdata, input i_tlast, input i_tvalid, output i_tready,
output [WIDTH-1:0] o0_tdata, output o0_tlast, output o0_tvalid, input o0_tready,
output [WIDTH-1:0] o1_tdata, output o1_tlast, output o1_tvalid, input o1_tready,
output [WIDTH-1:0] o2_tdata, output o2_tlast, output o2_tvalid, input o2_tready,
output [WIDTH-1:0] o3_tdata, output o3_tlast, output o3_tvalid, input o3_tready,
output [WIDTH-1:0] o4_tdata, output o4_tlast, output o4_tvalid, input o4_tready,
output [WIDTH-1:0] o5_tdata, output o5_tlast, output o5_tvalid, input o5_tready,
output [WIDTH-1:0] o6_tdata, output o6_tlast, output o6_tvalid, input o6_tready,
output [WIDTH-1:0] o7_tdata, output o7_tlast, output o7_tvalid, input o7_tready
);
wire [WIDTH-1:0] i_tdata_int0, i_tdata_int1;
wire i_tlast_int0, i_tlast_int1;
wire i_tvalid_int0, i_tvalid_int1;
wire i_tready_int0, i_tready_int1;
axi_demux4 #(.ACTIVE_CHAN({2'b00, (|(ACTIVE_CHAN[7:4])), (|(ACTIVE_CHAN[3:0]))}), .WIDTH(WIDTH), .BUFFER(BUFFER)) demux2 (
.clk(clk), .reset(reset), .clear(clear),
.header(header), .dest({1'b0, dest[2]}),
.i_tdata(i_tdata), .i_tlast(i_tlast), .i_tvalid(i_tvalid), .i_tready(i_tready),
.o0_tdata(i_tdata_int0), .o0_tlast(i_tlast_int0), .o0_tvalid(i_tvalid_int0), .o0_tready(i_tready_int0),
.o1_tdata(i_tdata_int1), .o1_tlast(i_tlast_int1), .o1_tvalid(i_tvalid_int1), .o1_tready(i_tready_int1),
.o2_tdata(), .o2_tlast(), .o2_tvalid(), .o2_tready(1'b0),
.o3_tdata(), .o3_tlast(), .o3_tvalid(), .o3_tready(1'b0)
);
axi_demux4 #(.ACTIVE_CHAN(ACTIVE_CHAN[3:0]), .WIDTH(WIDTH), .BUFFER(0)) demux4_int0 (
.clk(clk), .reset(reset), .clear(clear),
.header(), .dest(dest[1:0]),
.i_tdata(i_tdata_int0), .i_tlast(i_tlast_int0), .i_tvalid(i_tvalid_int0), .i_tready(i_tready_int0),
.o0_tdata(o0_tdata), .o0_tlast(o0_tlast), .o0_tvalid(o0_tvalid), .o0_tready(o0_tready),
.o1_tdata(o1_tdata), .o1_tlast(o1_tlast), .o1_tvalid(o1_tvalid), .o1_tready(o1_tready),
.o2_tdata(o2_tdata), .o2_tlast(o2_tlast), .o2_tvalid(o2_tvalid), .o2_tready(o2_tready),
.o3_tdata(o3_tdata), .o3_tlast(o3_tlast), .o3_tvalid(o3_tvalid), .o3_tready(o3_tready)
);
axi_demux4 #(.ACTIVE_CHAN(ACTIVE_CHAN[7:4]), .WIDTH(WIDTH), .BUFFER(0)) demux4_int1 (
.clk(clk), .reset(reset), .clear(clear),
.header(), .dest(dest[1:0]),
.i_tdata(i_tdata_int1), .i_tlast(i_tlast_int1), .i_tvalid(i_tvalid_int1), .i_tready(i_tready_int1),
.o0_tdata(o4_tdata), .o0_tlast(o4_tlast), .o0_tvalid(o4_tvalid), .o0_tready(o4_tready),
.o1_tdata(o5_tdata), .o1_tlast(o5_tlast), .o1_tvalid(o5_tvalid), .o1_tready(o5_tready),
.o2_tdata(o6_tdata), .o2_tlast(o6_tlast), .o2_tvalid(o6_tvalid), .o2_tready(o6_tready),
.o3_tdata(o7_tdata), .o3_tlast(o7_tlast), .o3_tvalid(o7_tvalid), .o3_tready(o7_tready)
);
endmodule // axi_demux4
-169
View File
@@ -1,169 +0,0 @@
//
// Copyright 2012-2013 Ettus Research LLC
//
// Block RAM AXI fifo
// Special case SIZE <= 5 uses a short fifo
module axi_fifo
#(parameter WIDTH=32, SIZE=9)
(input clk, input reset, input clear,
input [WIDTH-1:0] i_tdata,
input i_tvalid,
output i_tready,
output [WIDTH-1:0] o_tdata,
output o_tvalid,
input o_tready,
output reg [15:0] space,
output reg [15:0] occupied);
generate
if(SIZE<=5) begin
wire [5:0] space_short, occupied_short;
axi_fifo_short #(.WIDTH(WIDTH)) fifo_short
(
.clk(clk), .reset(reset), .clear(clear),
.i_tdata(i_tdata), .i_tvalid(i_tvalid), .i_tready(i_tready),
.o_tdata(o_tdata), .o_tvalid(o_tvalid), .o_tready(o_tready),
.space(space_short), .occupied(occupied_short)
);
always @* space <= {10'b0, space_short};
always @* occupied <= {10'b0, occupied_short};
end
else begin
wire write = i_tvalid & i_tready;
wire read = o_tvalid & o_tready;
wire full, empty;
assign i_tready = ~full;
assign o_tvalid = ~empty;
// Read side states
localparam EMPTY = 0;
localparam PRE_READ = 1;
localparam READING = 2;
reg [SIZE-1:0] wr_addr, rd_addr;
reg [1:0] read_state;
reg empty_reg, full_reg;
always @(posedge clk)
if(reset)
wr_addr <= 0;
else if(clear)
wr_addr <= 0;
else if(write)
wr_addr <= wr_addr + 1;
ram_2port #(.DWIDTH(WIDTH),.AWIDTH(SIZE))
ram (.clka(clk),
.ena(1'b1),
.wea(write),
.addra(wr_addr),
.dia(i_tdata),
.doa(),
.clkb(clk),
.enb((read_state==PRE_READ)|read),
.web(1'b0),
.addrb(rd_addr),
.dib({WIDTH{1'b1}}),
.dob(o_tdata));
always @(posedge clk)
if(reset)
begin
read_state <= EMPTY;
rd_addr <= 0;
empty_reg <= 1;
end
else
if(clear)
begin
read_state <= EMPTY;
rd_addr <= 0;
empty_reg <= 1;
end
else
case(read_state)
EMPTY :
if(write)
begin
//rd_addr <= wr_addr;
read_state <= PRE_READ;
end
PRE_READ :
begin
read_state <= READING;
empty_reg <= 0;
rd_addr <= rd_addr + 1;
end
READING :
if(read)
if(rd_addr == wr_addr)
begin
empty_reg <= 1;
if(write)
read_state <= PRE_READ;
else
read_state <= EMPTY;
end
else
rd_addr <= rd_addr + 1;
endcase // case(read_state)
wire [SIZE-1:0] dont_write_past_me = rd_addr - 2;
wire becoming_full = wr_addr == dont_write_past_me;
always @(posedge clk)
if(reset)
full_reg <= 0;
else if(clear)
full_reg <= 0;
else if(read & ~write)
full_reg <= 0;
//else if(write & ~read & (wr_addr == (rd_addr-3)))
else if(write & ~read & becoming_full)
full_reg <= 1;
//assign empty = (read_state != READING);
assign empty = empty_reg;
// assign full = ((rd_addr - 1) == wr_addr);
assign full = full_reg;
//////////////////////////////////////////////
// space and occupied are for diagnostics only
// not guaranteed exact
localparam NUMLINES = (1<<SIZE);
always @(posedge clk)
if(reset)
space <= NUMLINES;
else if(clear)
space <= NUMLINES;
else if(read & ~write)
space <= space + 16'b1;
else if(write & ~read)
space <= space - 16'b1;
always @(posedge clk)
if(reset)
occupied <= 16'b0;
else if(clear)
occupied <= 16'b0;
else if(read & ~write)
occupied <= occupied - 16'b1;
else if(write & ~read)
occupied <= occupied + 16'b1;
end
endgenerate
endmodule // fifo_long
-38
View File
@@ -1,38 +0,0 @@
module axi_fifo32_to_fifo64
(input clk, input reset, input clear,
input [31:0] i_tdata, input [1:0] i_tuser, input i_tlast, input i_tvalid, output i_tready,
output [63:0] o_tdata, output [2:0] o_tuser, output o_tlast, output o_tvalid, input o_tready
);
reg [31:0] holding;
reg state;
always @(posedge clk)
if(reset | clear)
state <= 0;
else
if(i_tvalid & i_tready)
case(state)
0 : if(~i_tlast) state <= 1'b1;
1 : state <= 1'b0;
default : state <= 1'b0;
endcase // case (state)
always @(posedge clk)
if(i_tvalid & i_tready)
holding <= i_tdata;
assign i_tready = (state == 0 && !i_tlast)? 1'b1 : o_tready;
assign o_tvalid = (state == 0 && !i_tlast)? 1'b0 : i_tvalid;
assign o_tdata = (state == 0) ? {i_tdata, 32'h0} : { holding, i_tdata };
assign o_tlast = i_tlast;
wire [2:0] occ_in = (i_tuser == 0) ? 3'd4 : {1'b0, i_tuser};
wire [2:0] occ_out = (state == 0) ? occ_in : (occ_in + 3'd4);
assign o_tuser = ~o_tlast ? 3'd0 : occ_out;
endmodule // axi_fifo32_to_fifo64
-31
View File
@@ -1,31 +0,0 @@
module axi_fifo64_to_fifo32
(input clk, input reset, input clear,
input [63:0] i_tdata, input [2:0] i_tuser, input i_tlast, input i_tvalid, output i_tready,
output [31:0] o_tdata, output [1:0] o_tuser, output o_tlast, output o_tvalid, input o_tready
);
wire short_last = i_tlast & ((i_tuser == 3'd1) | (i_tuser == 3'd2) | (i_tuser == 3'd3) | (i_tuser == 3'd4));
reg state;
always @(posedge clk)
if(reset | clear)
state <= 1'b0;
else
if(i_tvalid & o_tready)
case(state)
1'b0 :
if(~short_last)
state <= 1'b1;
1'b1 :
state <= 1'b0;
endcase // case (state)
assign o_tdata = (state == 0) ? i_tdata[63:32] : i_tdata[31:0];
assign o_tuser = o_tlast ? i_tuser[1:0] : 2'd0;
assign o_tlast = i_tlast & ((state == 1'b1) | short_last);
assign o_tvalid = i_tvalid;
assign i_tready = o_tready & ((state == 1'b1) | short_last);
endmodule // axi_fifo64_to_fifo32
-88
View File
@@ -1,88 +0,0 @@
//
// Copyright 2013 Ettus Research LLC
//
// Special case SIZE <= 5 uses a short fifo
module axi_fifo_2clk
#(parameter WIDTH=69, SIZE=9)
(input reset,
input i_aclk,
input [WIDTH-1:0] i_tdata,
input i_tvalid,
output i_tready,
input o_aclk,
output [WIDTH-1:0] o_tdata,
output o_tvalid,
input o_tready);
wire write, read, empty, full;
assign i_tready = ~full;
assign write = i_tvalid & i_tready;
wire [71:0] tdata_int;
wire tvalid_int, tready_int;
assign tvalid_int = ~empty;
assign read = tvalid_int & tready_int;
wire [71:0] wr_data;
assign wr_data[WIDTH-1:0] = i_tdata;
wire [71:0] rd_data;
assign tdata_int = rd_data[WIDTH-1:0];
generate
if(WIDTH<72) begin
assign wr_data[71:WIDTH] = 0;
end
endgenerate
generate
if(SIZE<=5)
fifo_short_2clk fifo_short_2clk
(.rst(reset),
.wr_clk(i_aclk),
.din(wr_data), // input [71 : 0] din
.wr_en(write), // input wr_en
.full(full), // output full
.wr_data_count(), // output [9 : 0] wr_data_count
.rd_clk(o_aclk), // input rd_clk
.dout(rd_data), // output [71 : 0] dout
.rd_en(read), // input rd_en
.empty(empty), // output empty
.rd_data_count() // output [9 : 0] rd_data_count
);
else
fifo_4k_2clk fifo_4k_2clk
(.rst(reset),
.wr_clk(i_aclk),
.din(wr_data), // input [71 : 0] din
.wr_en(write), // input wr_en
.full(full), // output full
.wr_data_count(), // output [9 : 0] wr_data_count
.rd_clk(o_aclk), // input rd_clk
.dout(rd_data), // output [71 : 0] dout
.rd_en(read), // input rd_en
.empty(empty), // output empty
.rd_data_count() // output [9 : 0] rd_data_count
);
endgenerate
generate
if(SIZE>9)
axi_fifo #(.WIDTH(WIDTH), .SIZE(SIZE)) fifo_1clk
(.clk(o_aclk), .reset(reset), .clear(1'b0),
.i_tdata(tdata_int), .i_tvalid(tvalid_int), .i_tready(tready_int),
.o_tdata(o_tdata), .o_tvalid(o_tvalid), .o_tready(o_tready),
.space(), .occupied());
else
begin
assign o_tdata = tdata_int;
assign o_tvalid = tvalid_int;
assign tready_int = o_tready;
end
endgenerate
endmodule // axi_fifo_2clk
-114
View File
@@ -1,114 +0,0 @@
`timescale 1ns/1ps
module axi_fifo_32_64_tb();
reg clk = 0;
reg reset = 1;
always #10 clk = ~clk;
initial $dumpfile("axi_fifo_32_64_tb.vcd");
initial $dumpvars(0,axi_fifo_32_64_tb);
task send_packet;
input [63:0] data_start;
input [2:0] user;
input [31:0] len;
begin
@(posedge clk);
{i_tuser, i_tlast, i_tdata} <= { 3'd0, 1'b0, data_start };
repeat(len-1)
begin
i_tvalid <= 1;
@(posedge clk);
i_tdata <= i_tdata + 64'h0000_0002_0000_0002;
end
i_tuser <= user;
i_tlast <= 1;
@(posedge clk);
i_tvalid <= 1'b0;
@(posedge clk);
end
endtask // send_packet
initial
begin
#1000 reset = 0;
#200000;
$finish;
end
reg [63:0] i_tdata;
reg [2:0] i_tuser;
reg i_tlast;
reg i_tvalid;
wire i_tready;
wire [63:0] i_tdata_int;
wire [2:0] i_tuser_int;
wire i_tlast_int, i_tvalid_int, i_tready_int;
wire [63:0] o_tdata;
wire [31:0] o_tdata_int, o_tdata_int2;
wire [2:0] o_tuser;
wire [1:0] o_tuser_int, o_tuser_int2;
wire o_tlast, o_tlast_int, o_tvalid, o_tvalid_int, o_tready, o_tready_int;
wire o_tlast_int2, o_tvalid_int2, o_tready_int2;
localparam RPT_COUNT = 16;
initial
begin
i_tvalid <= 0;
while(reset)
@(posedge clk);
@(posedge clk);
send_packet(64'hA0000000_A0000001, 3'd7, 4);
@(posedge clk);
end // initial begin
axi_fifo #(.WIDTH(68), .SIZE(10)) fifo
(.clk(clk), .reset(reset), .clear(1'b0),
.i_tdata({i_tlast,i_tuser,i_tdata}), .i_tvalid(i_tvalid), .i_tready(i_tready),
.o_tdata({i_tlast_int,i_tuser_int,i_tdata_int}), .o_tvalid(i_tvalid_int), .o_tready(i_tready_int));
axi_fifo64_to_fifo32 dut
(.clk(clk), .reset(reset), .clear(1'b0),
.i_tdata(i_tdata_int), .i_tuser(i_tuser_int), .i_tlast(i_tlast_int), .i_tvalid(i_tvalid_int), .i_tready(i_tready_int),
.o_tdata(o_tdata_int), .o_tuser(o_tuser_int), .o_tlast(o_tlast_int), .o_tvalid(o_tvalid_int), .o_tready(o_tready_int));
/*
axi_fifo #(.WIDTH(35), .SIZE(10)) fifo_middle
(.clk(clk), .reset(reset), .clear(1'b0),
.i_tdata({o_tlast_int,o_tuser_int,o_tdata_int}), .i_tvalid(o_tvalid_int), .i_tready(o_tready_int),
.o_tdata({o_tlast_int2,o_tuser_int2,o_tdata_int2}), .o_tvalid(o_tvalid_int2), .o_tready(o_tready_int2));
*/
assign o_tdata_int2 = o_tdata_int;
assign o_tlast_int2 = o_tlast_int;
assign o_tuser_int2 = o_tuser_int;
assign o_tvalid_int2 = o_tvalid_int;
assign o_tready_int = o_tready_int2;
axi_fifo32_to_fifo64 dut2
(.clk(clk), .reset(reset), .clear(1'b0),
.i_tdata(o_tdata_int2), .i_tuser(o_tuser_int2), .i_tlast(o_tlast_int2), .i_tvalid(o_tvalid_int2), .i_tready(o_tready_int2),
.o_tdata(o_tdata), .o_tuser(o_tuser), .o_tlast(o_tlast), .o_tvalid(o_tvalid), .o_tready(o_tready));
assign o_tready = 1'b1;
always @(posedge clk)
if(i_tvalid & i_tready)
$display("IN: TUSER %x\tTLAST %x\tTDATA %x", i_tuser, i_tlast, i_tdata);
always @(posedge clk)
if(o_tvalid_int & o_tready_int)
$display("\t\t\t\t\t\tMIDDLE: TUSER %x\tTLAST %x\tTDATA %x", o_tuser_int, o_tlast_int, o_tdata_int);
always @(posedge clk)
if(o_tvalid & o_tready)
$display("\t\t\t\t\t\t\t\t\t\t\tOUT: TUSER %x\tTLAST %x\tTDATA %x", o_tuser, o_tlast, o_tdata);
endmodule // axi_fifo_32_64_tb
-110
View File
@@ -1,110 +0,0 @@
//
// Copyright 2012 Ettus Research LLC
//
//
// 32 word FIFO with AXI4-STREAM interface.
//
// NOTE: This module uses the SRLC32E primitive explicitly and as such
// can only be used with Xilinx technology of the VIRTEX-6/SPARTAN-6/SIERIES-7 or newer.
//
module axi_fifo_short
#(parameter WIDTH=32)
(
input clk,
input reset,
input clear,
input [WIDTH-1:0] i_tdata,
input i_tvalid,
output i_tready,
output [WIDTH-1:0] o_tdata,
output o_tvalid,
input o_tready,
output reg [5:0] space,
output reg [5:0] occupied
);
reg full, empty;
wire write = i_tvalid & i_tready;
wire read = o_tready & o_tvalid;
assign i_tready = ~full;
assign o_tvalid = ~empty;
reg [4:0] a;
genvar i;
generate
for (i=0;i<WIDTH;i=i+1)
begin : gen_srlc32e
SRLC32E
srlc32e(.Q(o_tdata[i]), .Q31(),
.A(a), //.A0(a[0]),.A1(a[1]),.A2(a[2]),.A3(a[3]),.A4(a[4]),
.CE(write),.CLK(clk),.D(i_tdata[i]));
end
endgenerate
always @(posedge clk)
if(reset)
begin
a <= 0;
empty <= 1;
full <= 0;
end
else if(clear)
begin
a <= 0;
empty <= 1;
full<= 0;
end
else if(read & ~write)
begin
full <= 0;
if(a==0)
empty <= 1;
else
a <= a - 1;
end
else if(write & ~read)
begin
empty <= 0;
if(~empty)
a <= a + 1;
if(a == 30)
full <= 1;
end
// NOTE will fail if you write into a full fifo or read from an empty one
//////////////////////////////////////////////////////////////
// space and occupied are used for diagnostics, not
// guaranteed correct
//assign space = full ? 0 : empty ? 16 : 15-a;
//assign occupied = empty ? 0 : full ? 16 : a+1;
always @(posedge clk)
if(reset)
space <= 6'd32;
else if(clear)
space <= 6'd32;
else if(read & ~write)
space <= space + 6'd1;
else if(write & ~read)
space <= space - 6'd1;
always @(posedge clk)
if(reset)
occupied <= 6'd0;
else if(clear)
occupied <= 6'd0;
else if(read & ~write)
occupied <= occupied - 6'd1;
else if(write & ~read)
occupied <= occupied + 6'd1;
endmodule // axi_fifo_short
-211
View File
@@ -1,211 +0,0 @@
//
// Copyright 2012-2013 Ettus Research LLC
//
module axi_fifo_tb();
reg clk, reset;
reg read_flag, write_flag;
reg error;
reg [7:0] i_tdata, o_tdata_ref;
wire [7:0] o_tdata;
reg i_tvalid, o_tready;
wire o_tvalid, i_tready;
wire [15:0] space, occupied;
always
#100 clk = ~clk;
initial clk = 0;
axi_fifo
#(
.WIDTH(8),
.SIZE(8)
)
dut
(.clk(clk),
.reset(reset),
.clear(1'b0),
.i_tdata(i_tdata),
.i_tvalid(i_tvalid),
.i_tready(i_tready),
.o_tdata(o_tdata),
.o_tvalid(o_tvalid),
.o_tready(o_tready),
.space(space),
.occupied(occupied)
);
task write;
begin
write_flag <= 1;
i_tvalid <= 1'b1;
#1;
while (i_tready != 1'b1)
@(posedge clk);
#1;
@(posedge clk);
write_flag <= 0;
i_tvalid <= 1'b0;
i_tdata <= i_tdata + 8'h1;
end
endtask // write
task read;
begin
read_flag <= 1;
o_tready <= 1'b1;
#1;
while (o_tvalid != 1'b1)
@(posedge clk);
#1;
@(posedge clk);
read_flag <= 0;
o_tready <= 1'b0;
if (o_tdata_ref != o_tdata) begin
$display("ERROR: Expected %d, got %d, at time %d",o_tdata_ref,o_tdata,$time);
error <= 1'b1;
end else
error <= 1'b0;
o_tdata_ref = o_tdata_ref + 8'h1;
end
endtask // read
initial
begin
reset <= 1'b0;
error <= 1'b0;
i_tdata <= 8'b00;
o_tdata_ref <= 8'b00;
i_tvalid <= 1'b0;
o_tready <= 1'b0;
read_flag <= 0;
write_flag <= 0;
repeat(10) @(posedge clk);
reset <= 1'b1;
repeat(10) @(posedge clk);
reset <= 1'b0;
@(posedge clk);
@(negedge clk);
// FIFO Should be empty now, check avail space
if (space != 16'd256)
begin $display("ERROR: FIFO is empty, space should read 256 not %d at time %d",space,$time); error <= 1; end
if (occupied != 16'd0)
begin $display("ERROR: FIFO is empty, occupied should read 0 not %d at time %d",occupied,$time); error <= 1; end
if (o_tvalid == 1'b1)
begin $display("ERROR: FIFO is empty, o_tvalid should be 0 at time %d",$time); error <= 1; end
@(posedge clk);
// Push 1 item onto FIFO, check fullness updates accordingly
write();
@(posedge clk);
@(negedge clk);
if (space != 16'd255)
begin $display("ERROR: FIFO space should read 255 not %d at time %d",space,$time); error <= 1; end
if (occupied != 16'd1)
begin $display("ERROR: FIFO occupied should read 1 not %d at time %d",occupied,$time); error <= 1; end
if (o_tvalid == 1'b0)
begin $display("ERROR: FIFO is not empty, o_tvalid should be 1 at time %d",$time); error <= 1; end
// Pop FIFO once, check it goes back empty OK.
@(posedge clk);
read();
@(posedge clk);
@(negedge clk);
if (space != 16'd256)
begin $display("ERROR: FIFO is empty, space should read 256 not %d at time %d",space,$time); error <= 1; end
if (occupied != 16'd0)
begin $display("ERROR: FIFO is empty, occupied should read 0 not %d at time %d",occupied,$time); error <= 1; end
if (o_tvalid == 1'b1)
begin $display("ERROR: FIFO is empty, o_tvalid should be 0 at time %d",$time); error <= 1; end
// Push FIFO 255 times and see if it goes full incorrectly
repeat(255) begin
@(posedge clk);
write();
end
@(posedge clk);
@(negedge clk);
if (space != 16'd1)
begin $display("ERROR: FIFO is nearly full, space should read 1 not %d at time %d",space,$time); error <= 1; end
if (occupied != 16'd255)
begin $display("ERROR: FIFO is nearly full, occupied should read 255 not %d at time %d",occupied,$time); error <= 1; end
if (o_tvalid == 1'b0)
begin $display("ERROR: FIFO is nearly full, o_tvalid should be 1 at time %d",$time); error <= 1; end
if (i_tready == 1'b0)
begin $display("ERROR: FIFO is nearly full, i_tready should be 1 at time %d",$time); error <= 1; end
// Push FIFO one more time, now it should be full
@(posedge clk);
write();
@(posedge clk);
@(negedge clk);
if (space != 16'd0)
begin $display("ERROR: FIFO is full, space should read 0 not %d at time %d",space,$time); error <= 1; end
if (occupied != 16'd256)
begin $display("ERROR: FIFO is full, occupied should read 256 not %d at time %d",occupied,$time); error <= 1; end
if (o_tvalid == 1'b0)
begin $display("ERROR: FIFO is full, o_tvalid should be 1 at time %d",$time); error <= 1; end
if (i_tready == 1'b1)
begin $display("ERROR: FIFO is full, i_tready should be 0 at time %d",$time); error <= 1; end
// POP FIFO once, check it went nonfull.
@(posedge clk);
read();
@(posedge clk);
@(negedge clk);
if (space != 16'd1)
begin $display("ERROR: FIFO is nearly full, space should read 1 not %d at time %d",space,$time); error <= 1; end
if (occupied != 16'd255)
begin $display("ERROR: FIFO is nearly full, occupied should read 255 not %d at time %d",occupied,$time); error <= 1; end
if (o_tvalid == 1'b0)
begin $display("ERROR: FIFO is nearly full, o_tvalid should be 1 at time %d",$time); error <= 1; end
if (i_tready == 1'b0)
begin $display("ERROR: FIFO is nearly full, i_tready should be 1 at time %d",$time); error <= 1; end
// Take FIFO to empty state
repeat(255) begin
@(posedge clk);
read();
end
@(posedge clk);
@(negedge clk);
if (space != 16'd256)
begin $display("ERROR: FIFO is empty, space should read 256 not %d at time %d",space,$time); error <= 1; end
if (occupied != 16'd0)
begin $display("ERROR: FIFO is empty, occupied should read 0 not %d at time %d",occupied,$time); error <= 1; end
if (o_tvalid == 1'b1)
begin $display("ERROR: FIFO is empty, o_tvalid should be 0 at time %d",$time); error <= 1; end
// Push 1 item onto FIFO
@(posedge clk);
write();
@(posedge clk);
// Now write twice as fast as we read, and write 256 times, which should leave, 129 elements in FIFO.
fork
repeat(256) begin
write();
@(posedge clk);
end
repeat(128) begin
read();
@(posedge clk);
@(posedge clk);
end
join
@(posedge clk);
if (space != 16'd127)
begin $display("ERROR: FIFO space should read 127 not %d at time %d",space,$time); error <= 1; end
if (occupied != 16'd129)
begin $display("ERROR: FIFO occupied should read 129 not %d at time %d",occupied,$time); error <= 1; end
//
// END
//
repeat(10) @(posedge clk);
$finish;
end // initial begin
endmodule // axi_fifo_tb
-154
View File
@@ -1,154 +0,0 @@
// Copyright 2014 Ettus Research LLC
// axi_filter_mux -- takes 4 64-bit AXI stream of CHDR data, merges them to 1 output channel
// Round-robin if PRIO=0, priority if PRIO=1 (lower number ports get priority)
// Bubble cycles are inserted after each packet in PRIO mode, or on wraparound in Round Robin mode.
// Filter forces specific destination SID to pass per port, else dump data to /dev/null
module axi_filter_mux4
#(parameter PRIO=0,
parameter WIDTH=64,
parameter BUFFER=0,
parameter FILTER0 =0,
parameter FILTER1 =0,
parameter FILTER2 =0,
parameter FILTER3 =0
)
(input clk, input reset, input clear,
input [WIDTH-1:0] i0_tdata, input i0_tlast, input i0_tvalid, output i0_tready,
input [WIDTH-1:0] i1_tdata, input i1_tlast, input i1_tvalid, output i1_tready,
input [WIDTH-1:0] i2_tdata, input i2_tlast, input i2_tvalid, output i2_tready,
input [WIDTH-1:0] i3_tdata, input i3_tlast, input i3_tvalid, output i3_tready,
output [WIDTH-1:0] o_tdata, output o_tlast, output o_tvalid, input o_tready);
wire [WIDTH-1:0] o_tdata_int;
wire o_tlast_int, o_tvalid_int, o_tready_int;
reg [3:0] mx_state;
reg filter_packet;
localparam MX_IDLE = 4'b0000;
localparam MX_0 = 4'b0001;
localparam MX_1 = 4'b0010;
localparam MX_2 = 4'b0100;
localparam MX_3 = 4'b1000;
assign good0 = i0_tdata[15:0]==FILTER0;
assign good1 = i1_tdata[15:0]==FILTER1;
assign good2 = i2_tdata[15:0]==FILTER2;
assign good3 = i3_tdata[15:0]==FILTER3;
always @(posedge clk)
if(reset | clear)
mx_state <= MX_IDLE;
else
case (mx_state)
MX_IDLE :
if(i0_tvalid) begin
mx_state <= MX_0;
filter_packet <= !good0;
end
else if(i1_tvalid) begin
mx_state <= MX_1;
filter_packet <= !good1;
end
else if(i2_tvalid) begin
mx_state <= MX_2;
filter_packet <= !good2;
end
else if(i3_tvalid) begin
mx_state <= MX_3;
filter_packet <= !good3;
end
MX_0 :
if(o_tready_int & o_tvalid_int & o_tlast_int)
if(PRIO)
mx_state <= MX_IDLE;
else if(i1_tvalid) begin
mx_state <= MX_1;
filter_packet <= !good1;
end
else if(i2_tvalid) begin
mx_state <= MX_2;
filter_packet <= !good2;
end
else if(i3_tvalid) begin
mx_state <= MX_3;
filter_packet <= !good3;
end
else begin
mx_state <= MX_IDLE;
filter_packet <= 0;
end
MX_1 :
if(o_tready_int & o_tvalid_int & o_tlast_int)
if(PRIO)
mx_state <= MX_IDLE;
else if(i2_tvalid) begin
mx_state <= MX_2;
filter_packet <= !good2;
end
else if(i3_tvalid) begin
mx_state <= MX_3;
filter_packet <= !good3;
end
else begin
mx_state <= MX_IDLE;
filter_packet <= 0;
end
MX_2 :
if(o_tready_int & o_tvalid_int & o_tlast_int)
if(PRIO)
mx_state <= MX_IDLE;
else if(i3_tvalid) begin
mx_state <= MX_3;
filter_packet <= !good3;
end
else begin
mx_state <= MX_IDLE;
filter_packet <= 0;
end
MX_3 :
if(o_tready_int & o_tvalid_int & o_tlast_int)
begin
mx_state <= MX_IDLE;
filter_packet <= 0;
end
default :
mx_state <= MX_IDLE;
endcase // case (mx_state)
assign {i3_tready, i2_tready, i1_tready, i0_tready} = mx_state & {4{o_tready_int}};
assign o_tvalid_int = |(mx_state & ({i3_tvalid, i2_tvalid, i1_tvalid, i0_tvalid}));
assign {o_tlast_int, o_tdata_int} = mx_state[3] ? {i3_tlast, i3_tdata} :
mx_state[2] ? {i2_tlast, i2_tdata} :
mx_state[1] ? {i1_tlast, i1_tdata} :
{i0_tlast, i0_tdata};
generate
if(BUFFER == 0)
begin
assign o_tdata = o_tdata_int;
assign o_tlast = o_tlast_int;
assign o_tvalid = o_tvalid_int & !filter_packet;
assign o_tready_int = o_tready | filter_packet;
end
else
begin
wire o_tready_int_fifo;
assign o_tready_int = o_tready_int_fifo | filter_packet;
axi_fifo_short #(.WIDTH(WIDTH+1)) axi_fifo_short
(.clk(clk), .reset(reset), .clear(clear),
.i_tdata({o_tlast_int,o_tdata_int}), .i_tvalid(o_tvalid_int & !filter_packet), .i_tready(o_tready_int_fifo),
.o_tdata({o_tlast,o_tdata}), .o_tvalid(o_tvalid), .o_tready(o_tready),
.space(), .occupied());
end
endgenerate
endmodule // axi__mux4
-71
View File
@@ -1,71 +0,0 @@
// Copyright 2012 Ettus Research LLC
//
// axi_loopback.v
//
// Loopback all data assuming it's in CHDR format, and swap SRC/DST in the SID in the process
// thus reflecting it back to it's origin...in theory!
//
module axi_loopback
(
input clk,
input reset,
// Input AXIS
input [WIDTH-1:0] i_tdata,
input i_tlast,
input i_tvalid,
output i_tready,
// Output AXIS
output [WIDTH-1:0] o_tdata,
output o_tlast,
output o_tvalid,
input o_tready
);
localparam WIDTH=64;
wire [WIDTH-1:0] fifoin_tdata,fifoout_tdata,dmux_tdata;
wire fifoin_tlast,dmux_tlast;
wire fifoin_tvalid,dmux_tvalid;
wire fifoin_tready,dmux_tready;
// Since most real endpoints go via Demux4 place one in here to look for bugs.
axi_demux4 #(.ACTIVE_CHAN(4'b0001), .WIDTH(WIDTH)) demux
(.clk(clk), .reset(reset), .clear(1'b0),
.header(), .dest(2'b00),
.i_tdata(i_tdata), .i_tlast(i_tlast), .i_tvalid(i_tvalid), .i_tready(i_tready),
.o0_tdata(dmux_tdata), .o0_tlast(dmux_tlast), .o0_tvalid(dmux_tvalid), .o0_tready(dmux_tready),
.o1_tdata(), .o1_tlast(), .o1_tvalid(), .o1_tready(1'b1),
.o2_tdata(), .o2_tlast(), .o2_tvalid(), .o2_tready(1'b1),
.o3_tdata(), .o3_tlast(), .o3_tvalid(), .o3_tready(1'b1));
axi_fifo_short #(.WIDTH(WIDTH+1)) axi_fifo_short1
(.clk(clk), .reset(reset), .clear(1'b0),
.i_tdata({dmux_tlast,dmux_tdata}), .i_tvalid(dmux_tvalid), .i_tready(dmux_tready),
.o_tdata({fifoin_tlast,fifoin_tdata}), .o_tvalid(fifoin_tvalid), .o_tready(fifoin_tready),
.space(), .occupied());
reg header;
always @(posedge clk) begin
if(reset) begin
header <= 1'b1;
end else if (header) begin
if(fifoin_tvalid & fifoin_tready & ~fifoin_tlast) header <= 1'b0;
end else begin
if(fifoin_tvalid & fifoin_tready & fifoin_tlast) header <= 1'b1;
end
end
assign fifoout_tdata = header ?
{fifoin_tdata[63:32] ,fifoin_tdata[15:0],fifoin_tdata[31:16]} :
fifoin_tdata;
axi_fifo_short #(.WIDTH(WIDTH+1)) axi_fifo_short2
(.clk(clk), .reset(reset), .clear(1'b0),
.i_tdata({fifoin_tlast,fifoout_tdata}), .i_tvalid(fifoin_tvalid), .i_tready(fifoin_tready),
.o_tdata({o_tlast,o_tdata}), .o_tvalid(o_tvalid), .o_tready(o_tready),
.space(), .occupied());
endmodule // axi_loopback
-112
View File
@@ -1,112 +0,0 @@
// Copyright 2012 Ettus Research LLC
// axi_mux -- takes 4 64-bit AXI stream, merges them to 1 output channel
// Round-robin if PRIO=0, priority if PRIO=1 (lower number ports get priority)
// Bubble cycles are inserted after each packet in PRIO mode, or on wraparound in Round Robin mode
module axi_mux4
#(parameter PRIO=0,
parameter WIDTH=64,
parameter BUFFER=0)
(input clk, input reset, input clear,
input [WIDTH-1:0] i0_tdata, input i0_tlast, input i0_tvalid, output i0_tready,
input [WIDTH-1:0] i1_tdata, input i1_tlast, input i1_tvalid, output i1_tready,
input [WIDTH-1:0] i2_tdata, input i2_tlast, input i2_tvalid, output i2_tready,
input [WIDTH-1:0] i3_tdata, input i3_tlast, input i3_tvalid, output i3_tready,
output [WIDTH-1:0] o_tdata, output o_tlast, output o_tvalid, input o_tready);
wire [WIDTH-1:0] o_tdata_int;
wire o_tlast_int, o_tvalid_int, o_tready_int;
reg [3:0] mx_state;
localparam MX_IDLE = 4'b0000;
localparam MX_0 = 4'b0001;
localparam MX_1 = 4'b0010;
localparam MX_2 = 4'b0100;
localparam MX_3 = 4'b1000;
always @(posedge clk)
if(reset | clear)
mx_state <= MX_IDLE;
else
case (mx_state)
MX_IDLE :
if(i0_tvalid)
mx_state <= MX_0;
else if(i1_tvalid)
mx_state <= MX_1;
else if(i2_tvalid)
mx_state <= MX_2;
else if(i3_tvalid)
mx_state <= MX_3;
MX_0 :
if(o_tready_int & o_tvalid_int & o_tlast_int)
if(PRIO)
mx_state <= MX_IDLE;
else if(i1_tvalid)
mx_state <= MX_1;
else if(i2_tvalid)
mx_state <= MX_2;
else if(i3_tvalid)
mx_state <= MX_3;
else
mx_state <= MX_IDLE;
MX_1 :
if(o_tready_int & o_tvalid_int & o_tlast_int)
if(PRIO)
mx_state <= MX_IDLE;
else if(i2_tvalid)
mx_state <= MX_2;
else if(i3_tvalid)
mx_state <= MX_3;
else
mx_state <= MX_IDLE;
MX_2 :
if(o_tready_int & o_tvalid_int & o_tlast_int)
if(PRIO)
mx_state <= MX_IDLE;
else if(i3_tvalid)
mx_state <= MX_3;
else
mx_state <= MX_IDLE;
MX_3 :
if(o_tready_int & o_tvalid_int & o_tlast_int)
if(PRIO)
mx_state <= MX_IDLE;
else
mx_state <= MX_IDLE;
default :
mx_state <= MX_IDLE;
endcase // case (mx_state)
assign {i3_tready, i2_tready, i1_tready, i0_tready} = mx_state & {4{o_tready_int}};
assign o_tvalid_int = |(mx_state & ({i3_tvalid, i2_tvalid, i1_tvalid, i0_tvalid}));
assign {o_tlast_int, o_tdata_int} = mx_state[3] ? {i3_tlast, i3_tdata} :
mx_state[2] ? {i2_tlast, i2_tdata} :
mx_state[1] ? {i1_tlast, i1_tdata} :
{i0_tlast, i0_tdata};
generate
if(BUFFER == 0)
begin
assign o_tdata = o_tdata_int;
assign o_tlast = o_tlast_int;
assign o_tvalid = o_tvalid_int;
assign o_tready_int = o_tready;
end
else
axi_fifo_short #(.WIDTH(WIDTH+1)) axi_fifo_short
(.clk(clk), .reset(reset), .clear(clear),
.i_tdata({o_tlast_int,o_tdata_int}), .i_tvalid(o_tvalid_int), .i_tready(o_tready_int),
.o_tdata({o_tlast,o_tdata}), .o_tvalid(o_tvalid), .o_tready(o_tready),
.space(), .occupied());
endgenerate
endmodule // axi__mux4
-56
View File
@@ -1,56 +0,0 @@
// Copyright 2012 Ettus Research LLC
// axi_mux -- takes 8 64-bit AXI stream, merges them to 1 output channel
// Round-robin if PRIO=0, priority if PRIO=1 (lower number ports get priority)
// Bubble cycles are inserted after each packet in PRIO mode, or on wraparound in Round Robin mode
module axi_mux8 #(
parameter PRIO=0,
parameter WIDTH=64,
parameter BUFFER=0
) (
input clk, input reset, input clear,
input [WIDTH-1:0] i0_tdata, input i0_tlast, input i0_tvalid, output i0_tready,
input [WIDTH-1:0] i1_tdata, input i1_tlast, input i1_tvalid, output i1_tready,
input [WIDTH-1:0] i2_tdata, input i2_tlast, input i2_tvalid, output i2_tready,
input [WIDTH-1:0] i3_tdata, input i3_tlast, input i3_tvalid, output i3_tready,
input [WIDTH-1:0] i4_tdata, input i4_tlast, input i4_tvalid, output i4_tready,
input [WIDTH-1:0] i5_tdata, input i5_tlast, input i5_tvalid, output i5_tready,
input [WIDTH-1:0] i6_tdata, input i6_tlast, input i6_tvalid, output i6_tready,
input [WIDTH-1:0] i7_tdata, input i7_tlast, input i7_tvalid, output i7_tready,
output [WIDTH-1:0] o_tdata, output o_tlast, output o_tvalid, input o_tready
);
wire [WIDTH-1:0] o_tdata_int0, o_tdata_int1;
wire o_tlast_int0, o_tlast_int1;
wire o_tvalid_int0, o_tvalid_int1;
wire o_tready_int0, o_tready_int1;
axi_mux4 #(.PRIO(PRIO), .WIDTH(WIDTH), .BUFFER(0)) mux4_int0 (
.clk(clk), .reset(reset), .clear(clear),
.i0_tdata(i0_tdata), .i0_tlast(i0_tlast), .i0_tvalid(i0_tvalid), .i0_tready(i0_tready),
.i1_tdata(i1_tdata), .i1_tlast(i1_tlast), .i1_tvalid(i1_tvalid), .i1_tready(i1_tready),
.i2_tdata(i2_tdata), .i2_tlast(i2_tlast), .i2_tvalid(i2_tvalid), .i2_tready(i2_tready),
.i3_tdata(i3_tdata), .i3_tlast(i3_tlast), .i3_tvalid(i3_tvalid), .i3_tready(i3_tready),
.o_tdata(o_tdata_int0), .o_tlast(o_tlast_int0), .o_tvalid(o_tvalid_int0), .o_tready(o_tready_int0)
);
axi_mux4 #(.PRIO(PRIO), .WIDTH(WIDTH), .BUFFER(0)) mux4_int1 (
.clk(clk), .reset(reset), .clear(clear),
.i0_tdata(i4_tdata), .i0_tlast(i4_tlast), .i0_tvalid(i4_tvalid), .i0_tready(i4_tready),
.i1_tdata(i5_tdata), .i1_tlast(i5_tlast), .i1_tvalid(i5_tvalid), .i1_tready(i5_tready),
.i2_tdata(i6_tdata), .i2_tlast(i6_tlast), .i2_tvalid(i6_tvalid), .i2_tready(i6_tready),
.i3_tdata(i7_tdata), .i3_tlast(i7_tlast), .i3_tvalid(i7_tvalid), .i3_tready(i7_tready),
.o_tdata(o_tdata_int1), .o_tlast(o_tlast_int1), .o_tvalid(o_tvalid_int1), .o_tready(o_tready_int1)
);
axi_mux4 #(.PRIO(PRIO), .WIDTH(WIDTH), .BUFFER(BUFFER)) mux2 (
.clk(clk), .reset(reset), .clear(clear),
.i0_tdata(o_tdata_int0), .i0_tlast(o_tlast_int0), .i0_tvalid(o_tvalid_int0), .i0_tready(o_tready_int0),
.i1_tdata(o_tdata_int1), .i1_tlast(o_tlast_int1), .i1_tvalid(o_tvalid_int1), .i1_tready(o_tready_int1),
.i2_tdata(0), .i2_tlast(1'b0), .i2_tvalid(1'b0), .i2_tready(),
.i3_tdata(0), .i3_tlast(1'b0), .i3_tvalid(1'b0), .i3_tready(),
.o_tdata(o_tdata), .o_tlast(o_tlast), .o_tvalid(o_tvalid), .o_tready(o_tready)
);
endmodule // axi_mux8
-78
View File
@@ -1,78 +0,0 @@
//
// Copyright 2012 Ettus Research LLC
//
// Hold packets in fifo until they are complete. This prevents slowly-built packets
// from clogging up the downstream. This block will hold up to 255 packets.
// Will permanently block if a single packet is bigger than the fifo.
// Will also drop any packet with an error signalled on the last line.
// This is useful after an ethernet interface to drop packets with bad CRCs.
module axi_packet_gate
#(parameter WIDTH=68,
parameter SIZE=10)
(input clk,
input reset,
input clear,
input [WIDTH-1:0] i_tdata,
input i_tlast,
input i_terror,
input i_tvalid,
output i_tready,
output [WIDTH-1:0] o_tdata,
output o_tlast,
output o_tvalid,
input o_tready
);
reg [7:0] num_packets;
reg dump;
wire o_tvalid_int, o_tready_int, i_tvalid_int, i_tready_int;
assign i_tvalid_int = (~dump & (num_packets != 8'hFF)) ? i_tvalid : 1'b0;
assign i_tready = (~dump & (num_packets != 8'hFF)) ? i_tready_int : 1'b0;
assign o_tvalid = (num_packets != 8'h0) ? o_tvalid_int : 1'b0;
assign o_tready_int = (num_packets != 8'h0) ? o_tready : 1'b0;
wire last_in = i_tvalid_int & i_tready_int & i_tlast;
wire last_out = o_tvalid_int & o_tready_int & o_tlast;
always @(posedge clk)
if(reset | clear)
begin
num_packets <= 8'd0;
dump <= 1'b0;
end
else
if(dump)
if(num_packets != 8'd0)
if(last_out)
num_packets <= num_packets - 8'd1;
else
;
else
dump <= 1'b0;
else
if(last_in)
if(i_terror)
begin
dump <= 1'b1;
if(last_out)
num_packets <= num_packets - 8'd1;
end
else if(~last_out)
num_packets <= num_packets + 8'd1;
else
;
else if(last_out)
num_packets <= num_packets - 8'd1;
axi_fifo #(.SIZE(SIZE), .WIDTH(WIDTH+1)) axi_fifo
(.clk(clk), .reset(reset), .clear(clear | (dump & (num_packets == 8'd0))),
.i_tdata({i_tlast,i_tdata}), .i_tvalid(i_tvalid_int), .i_tready(i_tready_int),
.o_tdata({o_tlast,o_tdata}), .o_tvalid(o_tvalid_int), .o_tready(o_tready_int));
endmodule // axi_packet_gate
-106
View File
@@ -1,106 +0,0 @@
`timescale 1ns/1ps
module axi_packet_gate_tb();
reg clk = 0;
reg reset = 1;
always #10 clk = ~clk;
initial $dumpfile("axi_packet_gate_tb.vcd");
initial $dumpvars(0,axi_packet_gate_tb);
task send_packet;
input [63:0] data_start;
input [2:0] user;
input [31:0] len;
input error;
begin
// Send a packet
@(posedge clk);
{i_terror, i_tuser, i_tlast, i_tdata} <= { 1'b0, user, 1'b0, data_start };
repeat(len-1)
begin
i_tvalid <= 1;
@(posedge clk);
i_tdata <= i_tdata + 1;
end
i_tlast <= 1;
i_terror <= error;
i_tdata <= i_tdata + 1;
@(posedge clk);
i_tvalid <= 1'b0;
@(posedge clk);
end
endtask // send_packet
initial
begin
#1000 reset = 0;
#200000;
$finish;
end
wire [63:0] o_tdata;
reg [63:0] i_tdata;
wire [2:0] o_tuser;
reg [2:0] i_tuser;
reg i_tlast;
wire o_tlast;
wire o_tvalid, i_tready;
reg i_tvalid, o_tready;
reg i_terror;
localparam RPT_COUNT = 16;
initial
begin
i_tvalid <= 0;
o_tready <= 0;
while(reset)
@(posedge clk);
@(posedge clk);
send_packet(64'hA0,3'd0, 16, 0);
send_packet(64'hB0,3'd0, 16, 0);
o_tready <= 1;
send_packet(64'hC0,3'd0, 16, 1);
send_packet(64'hD0,3'd0, 16, 0);
send_packet(64'hE0,3'd0, 16, 0);
send_packet(64'hF0,3'd0, 16, 0);
@(posedge clk);
end // initial begin
wire i_terror_int, i_tlast_int, i_tready_int, i_tvalid_int;
wire [2:0] i_tuser_int;
wire [63:0] i_tdata_int;
wire o_tlast_int, o_tready_int, o_tvalid_int;
wire [2:0] o_tuser_int;
wire [63:0] o_tdata_int;
axi_fifo #(.WIDTH(69), .SIZE(10)) fifo
(.clk(clk), .reset(reset), .clear(1'b0),
.i_tdata({i_terror,i_tlast,i_tuser,i_tdata}), .i_tvalid(i_tvalid), .i_tready(i_tready),
.o_tdata({i_terror_int,i_tlast_int,i_tuser_int,i_tdata_int}), .o_tvalid(i_tvalid_int), .o_tready(i_tready_int));
axi_packet_gate #(.WIDTH(67), .SIZE(10)) dut
(.clk(clk), .reset(reset), .clear(1'b0),
.i_tdata({i_tuser_int,i_tdata_int}), .i_terror(i_terror_int), .i_tlast(i_tlast_int), .i_tvalid(i_tvalid_int), .i_tready(i_tready_int),
.o_tdata({o_tuser_int,o_tdata_int}), .o_tlast(o_tlast_int), .o_tvalid(o_tvalid_int), .o_tready(o_tready_int));
axi_fifo #(.WIDTH(68), .SIZE(10)) fifo_out
(.clk(clk), .reset(reset), .clear(1'b0),
.i_tdata({o_tlast_int,o_tuser_int,o_tdata_int}), .i_tvalid(o_tvalid_int), .i_tready(o_tready_int),
.o_tdata({o_tlast,o_tuser,o_tdata}), .o_tvalid(o_tvalid), .o_tready(o_tready));
always @(posedge clk)
if(o_tvalid & o_tready)
$display("TUSER %x\tTLAST %x\tTDATA %x",o_tuser,o_tlast, o_tdata);
endmodule // axi_packet_gate_tb
-123
View File
@@ -1,123 +0,0 @@
//
// Copyright 2012 Ettus Research LLC
//
//
// This module is instantiated in parallel with a FIFO with AXI4-STREAM interfaces.
// It tracks how many complete packets are contained within the FIFO, and also indicates
// when the first word of a packet is presented on the FIFO outputs.
//
module monitor_axi_fifo
#(
parameter COUNT_BITS=8
)
(
input clk,
input reset,
input clear,
// Monitored FIFO signals
input i_tvalid,
input i_tready,
input i_tlast,
input o_tvalid,
input o_tready,
input o_tlast,
// FIFO status outputs
output reg [COUNT_BITS-1:0] pkt_count, // Exact whole packet count
output pkt_present // Flags any whole packets present
);
localparam WAIT_SOF = 0;
localparam WAIT_EOF = 1;
reg in_state, out_state;
reg pause_tx;
//
// Count packets arriving into large FIFO
//
always @(posedge clk)
if (reset | clear) begin
in_state <= WAIT_SOF;
end else
case(in_state)
//
// After RESET or the EOF of previous packet, the first cycle with
// input valid and input ready asserted is the SOF.
//
WAIT_SOF:
if (i_tvalid && i_tready) begin
in_state <= WAIT_EOF;
end else begin
in_state <= WAIT_SOF;
end
//
// EOF is signalled by the assertion i_tlast whilst input valid and ready are asserted.
//
WAIT_EOF:
if (i_tlast && i_tvalid && i_tready) begin
in_state <= WAIT_SOF;
end else begin
in_state <= WAIT_EOF;
end
endcase // case(in_state)
//
// Count packets leaving large FIFO
//
always @(posedge clk)
if (reset | clear) begin
out_state <= WAIT_SOF;
end else
case(out_state)
//
// After RESET or the EOF of previous packet, the first cycle with
// output valid and output ready asserted is the SOF.
//
WAIT_SOF:
if (o_tvalid && o_tready) begin
out_state <= WAIT_EOF;
end else begin
out_state <= WAIT_SOF;
end
//
// EOF is signalled by o_tlast asserted whilst output valid and ready asserted.
//
WAIT_EOF:
if (o_tlast && o_tvalid && o_tready) begin
out_state <= WAIT_SOF;
end else begin
out_state <= WAIT_EOF;
end
endcase // case(in_state)
//
// Count packets in FIFO.
// No protection on counter wrap,
// unclear how to gracefully deal with it.
// Perhaps generate Error IRQ so that S/W could clean up?
// Configure so that the pkt_count is ample for the application.
//
always @(posedge clk)
if (reset | clear)
pkt_count <= 0;
else if (((out_state==WAIT_EOF) && o_tlast && o_tvalid && o_tready ) &&
((in_state==WAIT_EOF) && i_tlast && i_tvalid && i_tready))
pkt_count <= pkt_count;
else if ((out_state==WAIT_EOF) && o_tlast && o_tvalid && o_tready)
pkt_count <= pkt_count - 1;
else if ((in_state==WAIT_EOF) && i_tlast && i_tvalid && i_tready)
pkt_count <= pkt_count + 1;
// Non-zero packet count indicates packet(s) present.
assign pkt_present = |pkt_count;
endmodule // count_tx_packets
-92
View File
@@ -1,92 +0,0 @@
//
// Copyright 2011 Ettus Research LLC
//
module shortfifo
#(parameter WIDTH=32)
(input clk, input rst,
input [WIDTH-1:0] datain,
output [WIDTH-1:0] dataout,
input read,
input write,
input clear,
output reg full,
output reg empty,
output reg [4:0] space,
output reg [4:0] occupied);
reg [3:0] a;
genvar i;
generate
for (i=0;i<WIDTH;i=i+1)
begin : gen_srl16
SRL16E
srl16e(.Q(dataout[i]),
.A0(a[0]),.A1(a[1]),.A2(a[2]),.A3(a[3]),
.CE(write),.CLK(clk),.D(datain[i]));
end
endgenerate
always @(posedge clk)
if(rst)
begin
a <= 0;
empty <= 1;
full <= 0;
end
else if(clear)
begin
a <= 0;
empty <= 1;
full<= 0;
end
else if(read & ~write)
begin
full <= 0;
if(a==0)
empty <= 1;
else
a <= a - 1;
end
else if(write & ~read)
begin
empty <= 0;
if(~empty)
a <= a + 1;
if(a == 14)
full <= 1;
end
// NOTE will fail if you write into a full fifo or read from an empty one
//////////////////////////////////////////////////////////////
// space and occupied are used for diagnostics, not
// guaranteed correct
//assign space = full ? 0 : empty ? 16 : 15-a;
//assign occupied = empty ? 0 : full ? 16 : a+1;
always @(posedge clk)
if(rst)
space <= 16;
else if(clear)
space <= 16;
else if(read & ~write)
space <= space + 1;
else if(write & ~read)
space <= space - 1;
always @(posedge clk)
if(rst)
occupied <= 0;
else if(clear)
occupied <= 0;
else if(read & ~write)
occupied <= occupied - 1;
else if(write & ~read)
occupied <= occupied + 1;
endmodule // shortfifo
-13
View File
@@ -1,13 +0,0 @@
#
# Copyright 2010-2013 Ettus Research LLC
#
##################################################
# SERDES Sources
##################################################
GPIF2_SRCS = $(abspath $(addprefix $(BASE_DIR)/../lib/gpif2/, \
gpif2_slave_fifo32.v \
gpif2_to_fifo64.v \
fifo64_to_gpif2.v \
gpif2_error_checker.v \
))
-64
View File
@@ -1,64 +0,0 @@
//
// Copyright 2012-2013 Ettus Research LLC
//
module fifo64_to_gpif2
#(
parameter FIFO_SIZE = 9
)
(
//input fifo interface
input fifo_clk, input fifo_rst,
input [63:0] i_tdata,
input i_tlast,
input i_tvalid,
output i_tready,
//output interface
input gpif_clk, input gpif_rst,
output [31:0] o_tdata,
output o_tlast,
output o_tvalid,
input o_tready
);
wire [31:0] i32_tdata;
wire i32_tlast;
wire i32_tvalid, i32_tready;
axi_fifo64_to_fifo32 fifo64_to_fifo32
(
.clk(fifo_clk), .reset(fifo_rst), .clear(1'b0),
.i_tdata(i_tdata), .i_tuser(3'b0/*done care*/), .i_tlast(i_tlast), .i_tvalid(i_tvalid), .i_tready(i_tready),
.o_tdata(i32_tdata), .o_tuser(/*ignored cuz vita has len*/), .o_tlast(i32_tlast), .o_tvalid(i32_tvalid), .o_tready(i32_tready)
);
wire [31:0] gate_tdata;
wire gate_tlast;
wire gate_tvalid, gate_tready;
axi_fifo_2clk #(.WIDTH(33), .SIZE(0/*SRL*/)) cross_clock_fifo
(
.reset(fifo_rst | gpif_rst),
.i_aclk(fifo_clk), .i_tdata({i32_tlast, i32_tdata}), .i_tvalid(i32_tvalid), .i_tready(i32_tready),
.o_aclk(gpif_clk), .o_tdata({gate_tlast, gate_tdata}), .o_tvalid(gate_tvalid), .o_tready(gate_tready)
);
wire [31:0] int0_tdata; wire int0_tlast, int0_tvalid, int0_tready;
axi_packet_gate #(.WIDTH(32), .SIZE(FIFO_SIZE)) buffer_whole_pkt
(
.clk(gpif_clk), .reset(gpif_rst), .clear(1'b0),
.i_tdata(gate_tdata), .i_tlast(gate_tlast), .i_terror(1'b0), .i_tvalid(gate_tvalid), .i_tready(gate_tready),
.o_tdata(int0_tdata), .o_tlast(int0_tlast), .o_tvalid(int0_tvalid), .o_tready(int0_tready)
);
axi_fifo #(.WIDTH(33), .SIZE(0)) outgress_timing_fifo
(
.clk(gpif_clk), .reset(gpif_rst), .clear(1'b0),
.i_tdata({int0_tlast, int0_tdata}), .i_tvalid(int0_tvalid), .i_tready(int0_tready), .space(),
.o_tdata({o_tlast, o_tdata}), .o_tvalid(o_tvalid), .o_tready(o_tready), .occupied()
);
endmodule //fifo_to_gpmc16
-126
View File
@@ -1,126 +0,0 @@
// Copyright 2013 Ettus Research LLC
// inspect the input for invalid conditions
// when bad - drain input, flag error, and insert error msg packet
//
// Packets alignment errors are searched for in two different ways:
// 1) Blatently illegal values in what is assumed to be the PACKET_LENGTH field
// in the CHDR header
// (We could probably improve this by looking at other fields of the header that
// have a limited range of values)
// 2) Packet length indicating an EOF word that doesn't have TLAST set in the FIFO.
// (Upstream can howvever legally insert TLAST in the FIFO for words that are not EOF)
//
// Packet allignment recovery strategy is to wait for TLAST asserted and then decode the
// following data assuming it is the start of new CHDR headers.
//
//TODO - insert bad packet
module gpif2_error_checker
#(parameter SIZE = 9)
(input clk, input reset, input clear,
input [31:0] i_tdata, input i_tlast, input i_tvalid, output i_tready,
output [31:0] o_tdata, output o_tlast, output o_tvalid, input o_tready,
output bus_error, output [63:0] debug);
wire [31:0] gate_tdata;
wire gate_tlast, gate_terror;
wire gate_tvalid, gate_tready;
localparam STATE_HDR = 0;
localparam STATE_FWD = 1;
localparam STATE_EOF = 2;
localparam STATE_WAIT = 3;
reg [1:0] state;
reg [15:0] lines32;
reg [11:0] seq_id_ref;
reg seq_id_bad;
reg seq_id_wayoff;
wire [15:0] hdr_bytes = i_tdata[15:0] + 3; //round up to multiple of 4
wire [15:0] hdr_lines32 = {2'b0, hdr_bytes[15:2]}; //convert to lines32 count
wire [11:0] seq_id_actual = i_tdata[27:16];
wire obviously_bad_hdr = (hdr_lines32 == 16'h0) || (hdr_lines32 > (1 << SIZE));
always @(posedge clk) begin
if (reset | clear) begin
state <= STATE_HDR;
lines32 <= 16'b0;
seq_id_ref <= 12'h0;
seq_id_bad <= 0;
seq_id_wayoff <= 0;
end
else case (state)
STATE_HDR: begin //forward header and grab vita length
if (i_tvalid && i_tready) begin
if (obviously_bad_hdr) state <= STATE_WAIT;
else if (hdr_lines32 == 16'h1) state <= STATE_HDR;
else if (hdr_lines32 == 16'h2) state <= STATE_EOF;
else state <= STATE_FWD;
seq_id_bad <= (seq_id_actual != seq_id_ref);
seq_id_wayoff <= (seq_id_actual != seq_id_ref) |
(seq_id_actual != seq_id_ref+1) |
(seq_id_actual != seq_id_ref+2) |
(seq_id_actual != seq_id_ref+3);
if (seq_id_actual != seq_id_ref)
seq_id_ref <= seq_id_actual + 1;
else
seq_id_ref <= seq_id_ref + 1;
end
lines32 <= hdr_lines32;
end
STATE_FWD: begin //forward the rest of vita packet
if (i_tvalid && i_tready) begin
if (lines32 == 16'h3) state <= STATE_EOF;
lines32 <= lines32 - 1'b1;
end
end
STATE_EOF: begin //do last line of vita frame + eof
if (i_tvalid && i_tready)
if (gate_tlast) state <= STATE_HDR;
else state <= STATE_WAIT; // Try somehow to get synchronized again.
end
STATE_WAIT: begin //drop until idle
if (i_tvalid && i_tready && i_tlast) state <= STATE_HDR;
end
endcase //state
end
assign bus_error = (gate_terror && gate_tvalid && gate_tready) || ((state == STATE_HDR) && i_tvalid && i_tready && obviously_bad_hdr);
assign gate_tlast = (state == STATE_HDR)? (hdr_lines32 == 16'h1) : (state == STATE_EOF);
assign gate_tdata = i_tdata;
assign gate_tvalid = i_tvalid && ((state == STATE_HDR)? !obviously_bad_hdr : (state != STATE_WAIT));
assign i_tready = gate_tready;
axi_packet_gate #(.WIDTH(32), .SIZE(SIZE)) gate_xfer
(
.clk(clk), .reset(reset), .clear(clear),
.i_tdata(gate_tdata), .i_tlast(gate_tlast), .i_terror(1'b0), .i_tvalid(gate_tvalid), .i_tready(gate_tready),
.o_tdata(o_tdata), .o_tlast(o_tlast), .o_tvalid(o_tvalid), .o_tready(o_tready)
);
assign debug = {13'b0,
seq_id_wayoff, //[50] [114]
gate_terror, // [49] [113]
obviously_bad_hdr, // [48] [112]
seq_id_bad, // [47] [111]
seq_id_ref, // [46:35] [110:99]
i_tlast, // [34] [98]
i_tready, // [33] [97]
i_tvalid, // [32] [96]
i_tdata}; // [31:0] [95:64]
endmodule // cvita_insert_tlast
-324
View File
@@ -1,324 +0,0 @@
//
// Copyright 2011-2013 Ettus Research LLC
//
//////////////////////////////////////////////////////////////////////////////////
//this is a FIFO master interface for the FX3 in "slave fifo" mode.
module gpif2_slave_fifo32
#(
//sizes for fifo64 2 clock cascade fifos
parameter DATA_RX_FIFO_SIZE = 12, //max vita pkt size
parameter DATA_TX_FIFO_SIZE = 12, //max vita pkt size
parameter CTRL_RX_FIFO_SIZE = 5, //small resp packets
parameter CTRL_TX_FIFO_SIZE = 5, //small ctrl packets
//address constants for the endpoints
parameter ADDR_DATA_TX = 2'b00,
parameter ADDR_DATA_RX = 2'b01,
parameter ADDR_CTRL_TX = 2'b10,
parameter ADDR_CTRL_RX = 2'b11,
parameter END_WITH_COMMA = 0
)
(
// GPIF signals
input gpif_clk,
input gpif_rst,
input gpif_enb,
inout [31:0] gpif_d,
input [3:0] gpif_ctl,
output reg sloe,
output reg slrd,
output reg slwr,
output slcs,
output reg pktend,
output reg [1:0] fifoadr,
// FIFO interfaces
input fifo_clk,
input fifo_rst,
// TX Data interface to DSP
output [63:0] tx_tdata, output tx_tlast, output tx_tvalid, input tx_tready,
// RX Data interface to DSP
input [63:0] rx_tdata, input rx_tlast, input rx_tvalid, output rx_tready,
// Incomming control interface
output [63:0] ctrl_tdata, output ctrl_tlast, output ctrl_tvalid, input ctrl_tready,
// Outgoing control interface
input [63:0] resp_tdata, input resp_tlast, input resp_tvalid, output resp_tready,
// Debug Signals
output [31:0] debug
);
reg fifo_nearly_full;
wire ctrl_tx_fifo_nearly_full, data_tx_fifo_nearly_full;
wire ctrl_tx_fifo_has_space, data_tx_fifo_has_space;
assign slcs = 1'b0;
//DMA FIFO ready and watermark flags
reg EP_READY, EP_READY1, EP_WMARK, EP_WMARK1;
always @(posedge gpif_clk) EP_READY <= gpif_ctl[0];
always @(posedge gpif_clk) EP_WMARK <= gpif_ctl[1];
always @(posedge gpif_clk) EP_READY1 <= EP_READY;
always @(posedge gpif_clk) EP_WMARK1 <= EP_WMARK;
// GPIF output data lines, tristate
reg [31:0] gpif_data_in, gpif_data_out;
always @(posedge gpif_clk) gpif_data_in <= gpif_d;
assign gpif_d = sloe ? gpif_data_out[31:0] : 32'bz;
// ////////////////////////////////////////////////////////////////////
// GPIF bus master state machine
wire wr_fifo_xfer, wr_fifo_eof;
wire [31:0] wr_fifo_data;
reg read_ready_go, write_ready_go;
reg wr_one, rd_one;
reg [3:0] state; //state machine current state
localparam STATE_IDLE = 0;
localparam STATE_THINK = 1;
localparam STATE_READ = 2;
localparam STATE_WRITE = 3;
localparam STATE_WAIT = 4;
reg [2:0] idle_cycles;
reg [1:0] last_addr, next_addr;
wire local_fifo_ready;
reg slrd1, slrd2, slrd3;
always @(posedge gpif_clk)
if (gpif_rst) begin
slrd1 <= 1;
slrd2 <= 1;
slrd3 <= 1;
end else begin
slrd1 <= slrd;
slrd2 <= slrd1;
slrd3 <= slrd2;
end
wire RD_VALID = ~slrd3;
wire RD_LAST = slrd2;
wire WR_VALID = (EP_WMARK1 || !wr_one);
// //////////////////////////////////////////////////////////////
// FX2 slave FIFO bus master state machine
//
always @(posedge gpif_clk)
if(gpif_rst) begin
state <= STATE_IDLE;
sloe <= 0;
slrd <= 1;
slwr <= 1;
pktend <= 1;
gpif_data_out <= 32'b0;
idle_cycles <= 0;
fifoadr <= 0;
wr_one <= 1'b0;
rd_one <= 1'b0;
last_addr <= 2'b0;
end
else if (gpif_enb) begin
case (state)
//
// Increment fifoadr to point at next thread, set all strobes to idle,
//
STATE_IDLE: begin
sloe <= 0;
slrd <= 1;
slwr <= 1;
pktend <= 1;
gpif_data_out <= 32'b0;
fifoadr <= next_addr;
state <= STATE_WAIT;
idle_cycles <= 0;
end
//
// If the current thread we are pointing at (fifoadr) can not immediately proceed
// then quickly move to the next thread. Once we are pointing at a thread that can proceed locally
// wait for 8 clock cycles to allow fifoadr to propogate to FX3, and corresponding flag state to
// propogate back to FPGA and through resampling flops. At this point transition to STATE_THINK
// to evaluate remote flag.
//
STATE_WAIT: begin
// Current thread can proceed locally
if (local_fifo_ready) begin
idle_cycles <= idle_cycles + 1'b1;
if (idle_cycles == 3'b111) state <= STATE_THINK;
end
// ....move onto next thread.
else begin
idle_cycles <= 3'b0;
fifoadr <= fifoadr + 2'b1;
end
end
//
// If there is a read to start, assert SLRD and SLOE and transition to STATE_READ.
// If there is a write to perform, set flags that says there is the possibility to do at least
// one write (wr_one) and transition to STATE_WRITE.
// If the FX3 has nothing ready for this thread return immediately to STATE_IDLE.
//
STATE_THINK: begin
if (EP_READY1 && read_ready_go) begin
state <= STATE_READ;
slrd <= 0;
rd_one <= 0;
end
else if (EP_READY1 && write_ready_go) begin
state <= STATE_WRITE;
sloe <= 1;
wr_one <= 1'b0;
end
else begin
state <= STATE_IDLE;
end
idle_cycles <= 0;
last_addr <= fifoadr;
end
// If flag rd_one is set (armed 5 cycles after slrd goes initialy assrted) and RD_VALID has gone deasserted
// (meaning that the watermark deasserted 5 clock cycles ago) transition to STATE_IDLE.
// If watermark deasserted 2 cycles ago de-assert slrd ...read data is still traveling in the pipeline.
// Whilst RD_VALID stays asserted keep the rd_one flag armed.
STATE_READ: begin
if (rd_one && ~RD_VALID) state <= STATE_IDLE;
if (~EP_WMARK1 | fifo_nearly_full) slrd <= 1;
if (RD_VALID) rd_one <= 1'b1;
end
// If local FIFO goes empty or tlast is set then transition to STATE_IDLE
// Push local FIFO data out onto GPIF data bus.
// if local FIFO has valid data then assert slwr
// if local FIFO assertes tlast then assert pktend
// If WR_VALID asserted (because wr_one already asserted in the first cycle in this state)
// now clear wr_one (watermark will keep WR_VALID asserted from now on if this is a burst).
//
STATE_WRITE: begin
if (~wr_fifo_xfer || wr_fifo_eof) state <= STATE_IDLE;
gpif_data_out <= wr_fifo_data;
slwr <= ~wr_fifo_xfer;
pktend <= ~wr_fifo_eof;
if (WR_VALID) wr_one <= 1'b1;
end
default: state <= STATE_IDLE;
endcase
end
// ///////////////////////////////////////////////////////////////////
// fifo signal assignments and enables
//output from fifos - ready to xfer
wire data_tx_tready, ctrl_tx_tready;
wire ctrl_rx_tvalid, data_rx_tvalid;
//Priority encoding for the the next address to service:
//The next address to service is based on the readiness
//of the internal fifos and last serviced fairness metric.
/* -----\/----- EXCLUDED -----\/-----
always @(posedge gpif_clk) next_addr <=
((ctrl_rx_tvalid && (last_addr != ADDR_CTRL_RX))? ADDR_CTRL_RX :
((ctrl_tx_fifo_has_space && (last_addr != ADDR_CTRL_TX))? ADDR_CTRL_TX :
((data_rx_tvalid && (last_addr != ADDR_DATA_RX))? ADDR_DATA_RX :
((data_tx_fifo_has_space && (last_addr != ADDR_DATA_TX))? ADDR_DATA_TX :
(fifoadr + 2'b1)
))));
-----/\----- EXCLUDED -----/\----- */
always @(posedge gpif_clk) next_addr <= (fifoadr + 2'b1);
//Help the FPGA search to only look for addrs that the FPGA is ready for
assign local_fifo_ready =
(ctrl_rx_tvalid && (fifoadr == ADDR_CTRL_RX)) ||
(ctrl_tx_fifo_has_space && (fifoadr == ADDR_CTRL_TX)) ||
(data_rx_tvalid && (fifoadr == ADDR_DATA_RX)) ||
(data_tx_fifo_has_space && (fifoadr == ADDR_DATA_TX));
always @(posedge gpif_clk) fifo_nearly_full <=
(ctrl_tx_fifo_nearly_full && (fifoadr == ADDR_CTRL_TX)) ||
(data_tx_fifo_nearly_full && (fifoadr == ADDR_DATA_TX));
always @(posedge gpif_clk) read_ready_go <=
(ctrl_tx_fifo_has_space && (fifoadr == ADDR_CTRL_TX)) ||
(data_tx_fifo_has_space && (fifoadr == ADDR_DATA_TX));
always @(posedge gpif_clk) write_ready_go <=
(ctrl_rx_tvalid && (fifoadr == ADDR_CTRL_RX)) ||
(data_rx_tvalid && (fifoadr == ADDR_DATA_RX));
//fifo xfer enable
wire data_rx_tready = (state == STATE_WRITE) && (fifoadr == ADDR_DATA_RX) && WR_VALID;
wire ctrl_rx_tready = (state == STATE_WRITE) && (fifoadr == ADDR_CTRL_RX) && WR_VALID;
wire data_tx_tvalid = (state == STATE_READ) && (fifoadr == ADDR_DATA_TX) && RD_VALID;
wire ctrl_tx_tvalid = (state == STATE_READ) && (fifoadr == ADDR_CTRL_TX) && RD_VALID;
//outputs from rx fifo paths
wire ctrl_rx_tlast, data_rx_tlast;
wire [31:0] ctrl_rx_tdata, data_rx_tdata;
//mux rx outputs for gpif state machine
assign wr_fifo_xfer = (fifoadr == ADDR_CTRL_RX)? (ctrl_rx_tvalid && ctrl_rx_tready) : (data_rx_tvalid && data_rx_tready);
assign wr_fifo_eof = wr_fifo_xfer && ((fifoadr == ADDR_CTRL_RX)? ctrl_rx_tlast : data_rx_tlast);
assign wr_fifo_data = (fifoadr == ADDR_CTRL_RX)? ctrl_rx_tdata : data_rx_tdata;
wire ctrl_bus_error, tx_bus_error;
// ////////////////////////////////////////////////////////////////////
// TX Data Path
gpif2_to_fifo64 #(.FIFO_SIZE(DATA_TX_FIFO_SIZE)) gpif2_to_fifo64_tx(
.gpif_clk(gpif_clk), .gpif_rst(gpif_rst),
.i_tdata(gpif_data_in), .i_tlast(RD_LAST), .i_tvalid(data_tx_tvalid), .i_tready(data_tx_tready),
.fifo_clk(fifo_clk), .fifo_rst(fifo_rst),
.fifo_nearly_full(data_tx_fifo_nearly_full), .fifo_has_space(data_tx_fifo_has_space),
.o_tdata(tx_tdata), .o_tlast(tx_tlast), .o_tvalid(tx_tvalid), .o_tready(tx_tready),
.bus_error(tx_bus_error), .debug()
);
// ////////////////////////////////////////////
// RX Data Path
fifo64_to_gpif2 #(.FIFO_SIZE(DATA_RX_FIFO_SIZE)) fifo64_to_gpif2_rx(
.fifo_clk(fifo_clk), .fifo_rst(fifo_rst),
.i_tdata(rx_tdata), .i_tlast(rx_tlast), .i_tvalid(rx_tvalid), .i_tready(rx_tready),
.gpif_clk(gpif_clk), .gpif_rst(gpif_rst),
.o_tdata(data_rx_tdata), .o_tlast(data_rx_tlast), .o_tvalid(data_rx_tvalid), .o_tready(data_rx_tready)
);
// ////////////////////////////////////////////////////////////////////
// CTRL path
gpif2_to_fifo64 #(.FIFO_SIZE(CTRL_TX_FIFO_SIZE)) gpif2_to_fifo64_ctrl(
.gpif_clk(gpif_clk), .gpif_rst(gpif_rst),
.i_tdata(gpif_data_in), .i_tlast(RD_LAST), .i_tvalid(ctrl_tx_tvalid), .i_tready(ctrl_tx_tready),
.fifo_clk(fifo_clk), .fifo_rst(fifo_rst),
.fifo_nearly_full(ctrl_tx_fifo_nearly_full), .fifo_has_space(ctrl_tx_fifo_has_space),
.o_tdata(ctrl_tdata), .o_tlast(ctrl_tlast), .o_tvalid(ctrl_tvalid), .o_tready(ctrl_tready),
.bus_error(ctrl_bus_error), .debug()
);
// ////////////////////////////////////////////////////////////////////
// RESP path
fifo64_to_gpif2 #(.FIFO_SIZE(CTRL_RX_FIFO_SIZE)) fifo64_to_gpif2_resp(
.fifo_clk(fifo_clk), .fifo_rst(fifo_rst),
.i_tdata(resp_tdata), .i_tlast(resp_tlast), .i_tvalid(resp_tvalid), .i_tready(resp_tready),
.gpif_clk(gpif_clk), .gpif_rst(gpif_rst),
.o_tdata(ctrl_rx_tdata), .o_tlast(ctrl_rx_tlast), .o_tvalid(ctrl_rx_tvalid), .o_tready(ctrl_rx_tready)
);
// ////////////////////////////////////////////
// DEBUG
endmodule // gpif2_slave_fifo32
-124
View File
@@ -1,124 +0,0 @@
//
// Copyright 2012-2013 Ettus Research LLC
//
module gpif2_to_fifo64
#(
parameter FIFO_SIZE = 9
)
(
//input interface
input gpif_clk,
input gpif_rst,
input [31:0] i_tdata,
input i_tlast,
input i_tvalid,
output i_tready,
output fifo_has_space,
output fifo_nearly_full,
//output fifo interface
input fifo_clk,
input fifo_rst,
output [63:0] o_tdata,
output o_tlast,
output o_tvalid,
input o_tready,
output bus_error,
output [31:0] debug
);
wire [31:0] int_tdata;
wire int_tlast;
wire int_tvalid, int_tready;
wire [31:0] int0_tdata;
wire int0_tlast, int0_tvalid, int0_tready;
//
// Generate flags that show if initial FIFO's can accept a maximum sized burst from the FX3
// or if the FIFO is about to fill.
//
localparam BURST_SIZE = (FIFO_SIZE < 8)? FIFO_SIZE : 8;
wire [15:0] space;
assign fifo_has_space = space >= (1 << BURST_SIZE);
assign fifo_nearly_full = (space < 6); // 5 spaces left.
//
// This FIFO is provdied purely to easy FPGA timing closure as data is comming from I/O pins.
//
axi_fifo #(.WIDTH(33), .SIZE(0)) ingress_timing_fifo
(
.clk(gpif_clk), .reset(gpif_rst), .clear(1'b0),
.i_tdata({i_tlast, i_tdata}), .i_tvalid(i_tvalid), .i_tready(i_tready), .space(),
.o_tdata({int0_tlast, int0_tdata}), .o_tvalid(int0_tvalid), .o_tready(int0_tready), .occupied()
);
//
// This FIFO provides space to accept a single burst from FX3 and it's fullness drives flags to GPIF2 logic
//
axi_fifo #(.WIDTH(33), .SIZE(BURST_SIZE)) min_read_buff
(
.clk(gpif_clk), .reset(gpif_rst), .clear(1'b0),
.i_tdata({int0_tlast, int0_tdata}), .i_tvalid(int0_tvalid), .i_tready(int0_tready), .space(space),
.o_tdata({int_tlast, int_tdata}), .o_tvalid(int_tvalid), .o_tready(int_tready), .occupied()
);
//
// This logic allows signals to cross from the GPIF2 clock domain to the BUS clock domain.
// It may now be obselete if bus_clk and gpif_clk are merged
//
wire [31:0] chk_tdata;
wire chk_tlast;
wire chk_tvalid, chk_tready;
axi_fifo_2clk #(.WIDTH(33), .SIZE(0/*SRL*/)) cross_clock_fifo
(
.reset(fifo_rst | gpif_rst),
.i_aclk(gpif_clk), .i_tdata({int_tlast, int_tdata}), .i_tvalid(int_tvalid), .i_tready(int_tready),
.o_aclk(fifo_clk), .o_tdata({chk_tlast, chk_tdata}), .o_tvalid(chk_tvalid), .o_tready(chk_tready)
);
//
// Performs basic tests on incomming packets such as testing if size on the wire patches
// the internal size field. Uses axi_packet_gate internally so can back pressure upstream if
// packet needs to be dropped.
//
wire [31:0] o32_tdata;
wire o32_tlast;
wire o32_tvalid, o32_tready;
gpif2_error_checker #(.SIZE(FIFO_SIZE)) checker
(
.clk(fifo_clk), .reset(fifo_rst), .clear(1'b0),
.i_tdata(chk_tdata), .i_tlast(chk_tlast), .i_tvalid(chk_tvalid), .i_tready(chk_tready),
.o_tdata(o32_tdata), .o_tlast(o32_tlast), .o_tvalid(o32_tvalid), .o_tready(o32_tready),
.bus_error(bus_error), .debug()
);
//assign o32_tdata = chk_tdata;
//assign o32_tlast = chk_tlast;
//assign o32_tvalid = chk_tvalid;
//assign chk_tready = o32_tready;
//
// Convert 32bit AXIS bus to 64bit
//
axi_fifo32_to_fifo64 fifo32_to_fifo64
(
.clk(fifo_clk), .reset(fifo_rst), .clear(1'b0),
.i_tdata(o32_tdata), .i_tuser(2'b0/*always 32 bits*/), .i_tlast(o32_tlast), .i_tvalid(o32_tvalid), .i_tready(o32_tready),
.o_tdata(o_tdata), .o_tuser(/*ignored cuz vita has len*/), .o_tlast(o_tlast), .o_tvalid(o_tvalid), .o_tready(o_tready)
);
/////////////////////////////////////////////
//
// Debug logic only
//
/////////////////////////////////////////////
endmodule //fifo_to_gpif2
-1
View File
@@ -1 +0,0 @@
/build

Some files were not shown because too many files have changed in this diff Show More