mirror of
				https://github.com/fairwaves/UHD-Fairwaves.git
				synced 2025-11-04 05:53:17 +00:00 
			
		
		
		
	umtrx: updated many cores and top level, dsp still needs proper strobes
This commit is contained in:
		@@ -1,5 +1,5 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright 2010 Ettus Research LLC
 | 
			
		||||
# Copyright 2010-2012 Ettus Research LLC
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
##################################################
 | 
			
		||||
@@ -55,4 +55,8 @@ settings_bus_16LE.v \
 | 
			
		||||
atr_controller16.v \
 | 
			
		||||
fifo_to_wb.v \
 | 
			
		||||
gpio_atr.v \
 | 
			
		||||
user_settings.v \
 | 
			
		||||
settings_fifo_ctrl.v \
 | 
			
		||||
simple_spi_core.v \
 | 
			
		||||
simple_i2c_core.v \
 | 
			
		||||
))
 | 
			
		||||
 
 | 
			
		||||
@@ -27,7 +27,7 @@ module double_buffer_tb();
 | 
			
		||||
   reg src_rdy_i = 0;
 | 
			
		||||
   wire dst_rdy_o;
 | 
			
		||||
   
 | 
			
		||||
   wire dst_rdy_i = 1;
 | 
			
		||||
   wire dst_rdy_i = 0;
 | 
			
		||||
   wire [35:0] data_o;
 | 
			
		||||
   reg [35:0]  data_i;
 | 
			
		||||
 | 
			
		||||
@@ -46,9 +46,9 @@ module double_buffer_tb();
 | 
			
		||||
      .data_i(data_i), .src_rdy_i(src_rdy_i), .dst_rdy_o(dst_rdy_o),
 | 
			
		||||
      .data_o(data_o), .src_rdy_o(src_rdy_o), .dst_rdy_i(dst_rdy_i));
 | 
			
		||||
 | 
			
		||||
   dspengine_16to8 dspengine_16to8
 | 
			
		||||
   dspengine_8to16 #(.HEADER_OFFSET(1)) dspengine_8to16
 | 
			
		||||
     (.clk(clk),.reset(rst),.clear(0),
 | 
			
		||||
      .set_stb(set_stb), .set_addr(0), .set_data({13'h0,1'b1,18'h00400}),
 | 
			
		||||
      .set_stb(set_stb), .set_addr(0), .set_data(1),
 | 
			
		||||
      .access_we(access_we), .access_stb(access_stb), .access_ok(access_ok), .access_done(access_done), 
 | 
			
		||||
      .access_skip_read(access_skip_read), .access_adr(access_adr), .access_len(access_len), 
 | 
			
		||||
      .access_dat_i(buf_to_dsp), .access_dat_o(dsp_to_buf));
 | 
			
		||||
@@ -69,11 +69,13 @@ module double_buffer_tb();
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
	// Passthrough
 | 
			
		||||
	$display("Passthrough");
 | 
			
		||||
	src_rdy_i <= 1;
 | 
			
		||||
	data_i <= { 2'b00,1'b0,1'b1,32'hFFFFFFFF};
 | 
			
		||||
	data_i <= { 2'b00,1'b0,1'b1,32'h01234567};
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
	data_i <= { 2'b00,1'b0,1'b0,32'hFFFFFFFF};
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
	data_i <= { 2'b00,1'b0,1'b0,32'h04050607};
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
@@ -86,16 +88,18 @@ module double_buffer_tb();
 | 
			
		||||
 | 
			
		||||
	repeat (5)
 | 
			
		||||
	  @(posedge clk);
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
	$display("Enabled");
 | 
			
		||||
	set_stb <= 1;
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
	set_stb <= 0;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
	$display("Non-IF Data Passthrough");
 | 
			
		||||
	src_rdy_i <= 1;
 | 
			
		||||
	data_i <= { 2'b00,1'b0,1'b1,32'hC0000000};
 | 
			
		||||
	data_i <= { 2'b00,1'b0,1'b1,32'h89acdef0};
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
	data_i <= { 2'b00,1'b0,1'b0,32'hC0000000};
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
	data_i <= { 2'b00,1'b0,1'b0,32'h14151617};
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
@@ -111,7 +115,9 @@ module double_buffer_tb();
 | 
			
		||||
	
 | 
			
		||||
	$display("No StreamID, No Trailer, Even");
 | 
			
		||||
	src_rdy_i <= 1;
 | 
			
		||||
  	data_i <= { 2'b00,1'b0,1'b1,32'h0000FFFF};
 | 
			
		||||
  	data_i <= { 2'b00,1'b0,1'b1,32'hAAAAAAAA};
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
  	data_i <= { 2'b00,1'b0,1'b0,32'h0000FFFF};
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
	data_i <= { 2'b00,1'b0,1'b0,32'h01000200};
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
@@ -139,7 +145,9 @@ module double_buffer_tb();
 | 
			
		||||
 | 
			
		||||
	$display("No StreamID, No Trailer, Odd");
 | 
			
		||||
	src_rdy_i <= 1;
 | 
			
		||||
  	data_i <= { 2'b00,1'b0,1'b1,32'h0000FFFF};
 | 
			
		||||
  	data_i <= { 2'b00,1'b0,1'b1,32'hBBBBBBBB};
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
  	data_i <= { 2'b00,1'b0,1'b0,32'h0000FFFF};
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
	data_i <= { 2'b00,1'b0,1'b0,32'h11001200};
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
@@ -159,30 +167,59 @@ module double_buffer_tb();
 | 
			
		||||
 | 
			
		||||
	while(~dst_rdy_o)
 | 
			
		||||
	  @(posedge clk);
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
   /*
 | 
			
		||||
	$display("No StreamID, Trailer, Even");
 | 
			
		||||
	src_rdy_i <= 1;
 | 
			
		||||
  	data_i <= { 2'b00,1'b0,1'b1,32'h0400FFFF};
 | 
			
		||||
  	data_i <= { 2'b00,1'b0,1'b1,32'hCCCCCCCC};
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
	data_i <= { 2'b00,1'b0,1'b0,32'h21002200};
 | 
			
		||||
  	data_i <= { 2'b00,1'b0,1'b0,32'h0400FFFF};
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
	data_i <= { 2'b00,1'b0,1'b0,32'h23002400};
 | 
			
		||||
	data_i <= { 2'b00,1'b0,1'b0,32'h21222324};
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
	data_i <= { 2'b00,1'b0,1'b0,32'h25262728};
 | 
			
		||||
	src_rdy_i <= 0;
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
	src_rdy_i <= 1;
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
	data_i <= { 2'b00,1'b0,1'b0,32'h25002600};
 | 
			
		||||
	data_i <= { 2'b00,1'b0,1'b0,32'h292a2b2c};
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
	data_i <= { 2'b00,1'b0,1'b0,32'h27002800};
 | 
			
		||||
	data_i <= { 2'b00,1'b0,1'b0,32'h2d2e2f30};
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
	data_i <= { 2'b00,1'b1,1'b0,32'h29002a00};
 | 
			
		||||
	data_i <= { 2'b00,1'b1,1'b0,32'hDEADBEEF};
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
	src_rdy_i <= 0;
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
	while(~dst_rdy_o)
 | 
			
		||||
	  @(posedge clk);
 | 
			
		||||
/*
 | 
			
		||||
	$display("No StreamID, Trailer, Odd");
 | 
			
		||||
	src_rdy_i <= 1;
 | 
			
		||||
  	data_i <= { 2'b00,1'b0,1'b1,32'hDDDDDDDD};
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
  	data_i <= { 2'b00,1'b0,1'b0,32'h0400FFFF};
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
	data_i <= { 2'b00,1'b0,1'b0,32'h21222324};
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
	data_i <= { 2'b00,1'b0,1'b0,32'h25262728};
 | 
			
		||||
	src_rdy_i <= 0;
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
	src_rdy_i <= 1;
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
	data_i <= { 2'b00,1'b0,1'b0,32'h292a2b2c};
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
	data_i <= { 2'b00,1'b0,1'b0,32'h2d2e2f30};
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
	data_i <= { 2'b00,1'b1,1'b0,32'hDEBDBF0D};
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
	src_rdy_i <= 0;
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
*/
 | 
			
		||||
	while(~dst_rdy_o)
 | 
			
		||||
	  @(posedge clk);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
	$display("No StreamID, Trailer, Odd");
 | 
			
		||||
	src_rdy_i <= 1;
 | 
			
		||||
  	data_i <= { 2'b00,1'b0,1'b1,32'h0400FFFF};
 | 
			
		||||
@@ -226,23 +263,45 @@ module double_buffer_tb();
 | 
			
		||||
 | 
			
		||||
	while(~dst_rdy_o)
 | 
			
		||||
	  @(posedge clk);
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
	$display("StreamID, Trailer, Odd");
 | 
			
		||||
	src_rdy_i <= 1;
 | 
			
		||||
  	data_i <= { 2'b00,1'b0,1'b1,32'h1400FFFF};
 | 
			
		||||
  	data_i <= { 2'b00,1'b0,1'b1,32'hABCDEF98};
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
	data_i <= { 2'b00,1'b0,1'b0,32'ha100a200};
 | 
			
		||||
  	data_i <= { 2'b00,1'b0,1'b0,32'h1c034567};
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
	data_i <= { 2'b00,1'b0,1'b0,32'ha0a1a2a3};
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
	data_i <= { 2'b00,1'b0,1'b0,32'ha4a5a6a7};
 | 
			
		||||
//	src_rdy_i <= 0;
 | 
			
		||||
//	@(posedge clk);
 | 
			
		||||
//	src_rdy_i <= 1;
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
	data_i <= { 2'b00,1'b0,1'b0,32'ha8a9aaab};
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
	data_i <= { 2'b00,1'b0,1'b0,32'hacadaeaf};
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
	data_i <= { 2'b00,1'b1,1'b0,32'hdeadbeef};
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
	data_i <= { 2'b00,1'b0,1'b0,32'ha300a400};
 | 
			
		||||
	src_rdy_i <= 0;
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
	src_rdy_i <= 1;
 | 
			
		||||
  	data_i <= { 2'b00,1'b0,1'b1,32'hABCDEF98};
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
	data_i <= { 2'b00,1'b0,1'b0,32'ha500a600};
 | 
			
		||||
  	data_i <= { 2'b00,1'b0,1'b0,32'h1c034567};
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
	data_i <= { 2'b00,1'b0,1'b0,32'ha700a800};
 | 
			
		||||
	data_i <= { 2'b00,1'b0,1'b0,32'ha0a1a2a3};
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
	data_i <= { 2'b00,1'b1,1'b0,32'hbbb0bbb0};
 | 
			
		||||
	data_i <= { 2'b00,1'b0,1'b0,32'ha4a5a6a7};
 | 
			
		||||
//	src_rdy_i <= 0;
 | 
			
		||||
//	@(posedge clk);
 | 
			
		||||
//	src_rdy_i <= 1;
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
	data_i <= { 2'b00,1'b0,1'b0,32'ha8a9aaab};
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
	data_i <= { 2'b00,1'b0,1'b0,32'hacadaeaf};
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
	data_i <= { 2'b00,1'b1,1'b0,32'hdeadbeef};
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
	src_rdy_i <= 0;
 | 
			
		||||
	@(posedge clk);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2011 Ettus Research LLC
 | 
			
		||||
// Copyright 2011-2012 Ettus Research LLC
 | 
			
		||||
//
 | 
			
		||||
// This program is free software: you can redistribute it and/or modify
 | 
			
		||||
// it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -22,16 +22,17 @@
 | 
			
		||||
// the system or dsp clock on the output side
 | 
			
		||||
 | 
			
		||||
module settings_bus_crossclock
 | 
			
		||||
  #(parameter FLOW_CTRL=0)
 | 
			
		||||
  (input clk_i, input rst_i, input set_stb_i, input [7:0] set_addr_i, input [31:0] set_data_i,
 | 
			
		||||
   input clk_o, input rst_o, output set_stb_o, output [7:0] set_addr_o, output [31:0] set_data_o);
 | 
			
		||||
   input clk_o, input rst_o, output set_stb_o, output [7:0] set_addr_o, output [31:0] set_data_o, input blocked);
 | 
			
		||||
 | 
			
		||||
   wire  full, empty;
 | 
			
		||||
   
 | 
			
		||||
   fifo_xlnx_16x40_2clk settings_fifo
 | 
			
		||||
     (.rst(rst_i),
 | 
			
		||||
      .wr_clk(clk_i), .din({set_addr_i,set_data_i}), .wr_en(set_stb_i & ~full), .full(full),
 | 
			
		||||
      .rd_clk(clk_o), .dout({set_addr_o,set_data_o}), .rd_en(~empty), .empty(empty));
 | 
			
		||||
      .rd_clk(clk_o), .dout({set_addr_o,set_data_o}), .rd_en(set_stb_o), .empty(empty));
 | 
			
		||||
 | 
			
		||||
   assign set_stb_o = ~empty;
 | 
			
		||||
   assign set_stb_o = ~empty & (~blocked | ~FLOW_CTRL);
 | 
			
		||||
 | 
			
		||||
endmodule // settings_bus_crossclock
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										395
									
								
								fpga/control_lib/settings_fifo_ctrl.v
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										395
									
								
								fpga/control_lib/settings_fifo_ctrl.v
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,395 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2012 Ettus Research LLC
 | 
			
		||||
//
 | 
			
		||||
// This program is free software: you can redistribute it and/or modify
 | 
			
		||||
// it under the terms of the GNU General Public License as published by
 | 
			
		||||
// the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
// (at your option) any later version.
 | 
			
		||||
//
 | 
			
		||||
// This program is distributed in the hope that it will be useful,
 | 
			
		||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
// GNU General Public License for more details.
 | 
			
		||||
//
 | 
			
		||||
// You should have received a copy of the GNU General Public License
 | 
			
		||||
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
// A settings and readback bus controlled via fifo36 interface
 | 
			
		||||
 | 
			
		||||
module settings_fifo_ctrl
 | 
			
		||||
    #(
 | 
			
		||||
        parameter XPORT_HDR = 1, //extra transport hdr line
 | 
			
		||||
        parameter PROT_DEST = 0, //protocol framer destination
 | 
			
		||||
        parameter PROT_HDR = 1, //needs a protocol header?
 | 
			
		||||
        parameter ACK_SID = 0 //stream ID for packet ACK
 | 
			
		||||
    )
 | 
			
		||||
    (
 | 
			
		||||
        //clock and synchronous reset for all interfaces
 | 
			
		||||
        input clock, input reset, input clear,
 | 
			
		||||
 | 
			
		||||
        //current system time
 | 
			
		||||
        input [63:0] vita_time,
 | 
			
		||||
 | 
			
		||||
        //ready signal for multiple peripherals
 | 
			
		||||
        input perfs_ready,
 | 
			
		||||
 | 
			
		||||
        //input fifo36 interface control
 | 
			
		||||
        input [35:0] in_data, input in_valid, output in_ready,
 | 
			
		||||
 | 
			
		||||
        //output fifo36 interface status
 | 
			
		||||
        output [35:0] out_data, output out_valid, input out_ready,
 | 
			
		||||
 | 
			
		||||
        //32-bit settings bus outputs
 | 
			
		||||
        output strobe, output [7:0] addr, output [31:0] data,
 | 
			
		||||
 | 
			
		||||
        //16X 32-bit inputs for readback
 | 
			
		||||
        input [31:0] word00,
 | 
			
		||||
        input [31:0] word01,
 | 
			
		||||
        input [31:0] word02,
 | 
			
		||||
        input [31:0] word03,
 | 
			
		||||
        input [31:0] word04,
 | 
			
		||||
        input [31:0] word05,
 | 
			
		||||
        input [31:0] word06,
 | 
			
		||||
        input [31:0] word07,
 | 
			
		||||
        input [31:0] word08,
 | 
			
		||||
        input [31:0] word09,
 | 
			
		||||
        input [31:0] word10,
 | 
			
		||||
        input [31:0] word11,
 | 
			
		||||
        input [31:0] word12,
 | 
			
		||||
        input [31:0] word13,
 | 
			
		||||
        input [31:0] word14,
 | 
			
		||||
        input [31:0] word15,
 | 
			
		||||
 | 
			
		||||
        //debug output
 | 
			
		||||
        output [31:0] debug
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    wire reading = in_valid && in_ready;
 | 
			
		||||
    wire writing = out_valid && out_ready;
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------
 | 
			
		||||
    //-- The command fifo:
 | 
			
		||||
    //-- Stores an individual register access command per line.
 | 
			
		||||
    //------------------------------------------------------------------
 | 
			
		||||
    wire [63:0] in_command_ticks, out_command_ticks;
 | 
			
		||||
    wire [31:0] in_command_hdr, out_command_hdr;
 | 
			
		||||
    wire [31:0] in_command_data, out_command_data;
 | 
			
		||||
    wire in_command_has_time, out_command_has_time;
 | 
			
		||||
    wire command_fifo_full, command_fifo_empty;
 | 
			
		||||
    wire command_fifo_read, command_fifo_write;
 | 
			
		||||
 | 
			
		||||
    shortfifo #(.WIDTH(129)) command_fifo (
 | 
			
		||||
        .clk(clock), .rst(reset), .clear(clear),
 | 
			
		||||
        .datain({in_command_ticks, in_command_hdr, in_command_data, in_command_has_time}),
 | 
			
		||||
        .dataout({out_command_ticks, out_command_hdr, out_command_data, out_command_has_time}),
 | 
			
		||||
        .write(command_fifo_write), .full(command_fifo_full), //input interface
 | 
			
		||||
        .empty(command_fifo_empty), .read(command_fifo_read)  //output interface
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------
 | 
			
		||||
    //-- The result fifo:
 | 
			
		||||
    //-- Stores an individual result of a command per line.
 | 
			
		||||
    //------------------------------------------------------------------
 | 
			
		||||
    wire [31:0] in_result_hdr, out_result_hdr;
 | 
			
		||||
    wire [31:0] in_result_data, out_result_data;
 | 
			
		||||
    wire result_fifo_full, result_fifo_empty;
 | 
			
		||||
    wire result_fifo_read, result_fifo_write;
 | 
			
		||||
 | 
			
		||||
    shortfifo #(.WIDTH(64)) result_fifo (
 | 
			
		||||
        .clk(clock), .rst(reset), .clear(clear),
 | 
			
		||||
        .datain({in_result_hdr, in_result_data}),
 | 
			
		||||
        .dataout({out_result_hdr, out_result_data}),
 | 
			
		||||
        .write(result_fifo_write), .full(result_fifo_full), //input interface
 | 
			
		||||
        .empty(result_fifo_empty), .read(result_fifo_read)  //output interface
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------
 | 
			
		||||
    //-- Input state machine:
 | 
			
		||||
    //-- Read input packet and fill a command fifo entry.
 | 
			
		||||
    //------------------------------------------------------------------
 | 
			
		||||
    localparam READ_LINE0     = 0;
 | 
			
		||||
    localparam VITA_HDR       = 1;
 | 
			
		||||
    localparam VITA_SID       = 2;
 | 
			
		||||
    localparam VITA_CID0      = 3;
 | 
			
		||||
    localparam VITA_CID1      = 4;
 | 
			
		||||
    localparam VITA_TSI       = 5;
 | 
			
		||||
    localparam VITA_TSF0      = 6;
 | 
			
		||||
    localparam VITA_TSF1      = 7;
 | 
			
		||||
    localparam READ_HDR       = 8;
 | 
			
		||||
    localparam READ_DATA      = 9;
 | 
			
		||||
    localparam WAIT_EOF       = 10;
 | 
			
		||||
    localparam STORE_CMD      = 11;
 | 
			
		||||
 | 
			
		||||
    localparam START_STATE = (XPORT_HDR)? READ_LINE0 : VITA_HDR;
 | 
			
		||||
 | 
			
		||||
    reg [4:0] in_state;
 | 
			
		||||
 | 
			
		||||
    //holdover from current read inputs
 | 
			
		||||
    reg [31:0] in_data_reg, in_hdr_reg;
 | 
			
		||||
    reg [63:0] in_ticks_reg;
 | 
			
		||||
    wire has_sid = in_data[28];
 | 
			
		||||
    wire has_cid = in_data[27];
 | 
			
		||||
    wire has_tsi = in_data[23:22] != 0;
 | 
			
		||||
    wire has_tsf = in_data[21:20] != 0;
 | 
			
		||||
    reg has_sid_reg, has_cid_reg, has_tsi_reg, has_tsf_reg;
 | 
			
		||||
 | 
			
		||||
    assign in_ready = (in_state < STORE_CMD);
 | 
			
		||||
    assign command_fifo_write  = (in_state == STORE_CMD);
 | 
			
		||||
    assign in_command_ticks    = in_ticks_reg;
 | 
			
		||||
    assign in_command_data     = in_data_reg;
 | 
			
		||||
    assign in_command_hdr      = in_hdr_reg;
 | 
			
		||||
    assign in_command_has_time = has_tsf_reg;
 | 
			
		||||
 | 
			
		||||
    always @(posedge clock) begin
 | 
			
		||||
        if (reset) begin
 | 
			
		||||
            in_state <= START_STATE;
 | 
			
		||||
        end
 | 
			
		||||
        else begin
 | 
			
		||||
            case (in_state)
 | 
			
		||||
 | 
			
		||||
            READ_LINE0: begin
 | 
			
		||||
                if (reading) in_state <= VITA_HDR;
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            VITA_HDR: begin
 | 
			
		||||
                if (reading) begin
 | 
			
		||||
                    if      (has_sid) in_state <= VITA_SID;
 | 
			
		||||
                    else if (has_cid) in_state <= VITA_CID0;
 | 
			
		||||
                    else if (has_tsi) in_state <= VITA_TSI;
 | 
			
		||||
                    else if (has_tsf) in_state <= VITA_TSF0;
 | 
			
		||||
                    else              in_state <= READ_HDR;
 | 
			
		||||
                end
 | 
			
		||||
                has_sid_reg <= has_sid;
 | 
			
		||||
                has_cid_reg <= has_cid;
 | 
			
		||||
                has_tsi_reg <= has_tsi;
 | 
			
		||||
                has_tsf_reg <= has_tsf;
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            VITA_SID: begin
 | 
			
		||||
                if (reading) begin
 | 
			
		||||
                    if      (has_cid_reg) in_state <= VITA_CID0;
 | 
			
		||||
                    else if (has_tsi_reg) in_state <= VITA_TSI;
 | 
			
		||||
                    else if (has_tsf_reg) in_state <= VITA_TSF0;
 | 
			
		||||
                    else                  in_state <= READ_HDR;
 | 
			
		||||
                end
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            VITA_CID0: begin
 | 
			
		||||
                if (reading) in_state <= VITA_CID1;
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            VITA_CID1: begin
 | 
			
		||||
                if (reading) begin
 | 
			
		||||
                    if      (has_tsi_reg) in_state <= VITA_TSI;
 | 
			
		||||
                    else if (has_tsf_reg) in_state <= VITA_TSF0;
 | 
			
		||||
                    else                  in_state <= READ_HDR;
 | 
			
		||||
                end
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            VITA_TSI: begin
 | 
			
		||||
                if (reading) begin
 | 
			
		||||
                    if (has_tsf_reg) in_state <= VITA_TSF0;
 | 
			
		||||
                    else             in_state <= READ_HDR;
 | 
			
		||||
                end
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            VITA_TSF0: begin
 | 
			
		||||
                if (reading) in_state <= VITA_TSF1;
 | 
			
		||||
                in_ticks_reg[63:32] <= in_data;
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            VITA_TSF1: begin
 | 
			
		||||
                if (reading) in_state <= READ_HDR;
 | 
			
		||||
                in_ticks_reg[31:0] <= in_data;
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            READ_HDR: begin
 | 
			
		||||
                if (reading) in_state <= READ_DATA;
 | 
			
		||||
                in_hdr_reg <= in_data[31:0];
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            READ_DATA: begin
 | 
			
		||||
                if (reading) in_state <= (in_data[33])? STORE_CMD : WAIT_EOF;
 | 
			
		||||
                in_data_reg <= in_data[31:0];
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            WAIT_EOF: begin
 | 
			
		||||
                if (reading && in_data[33]) in_state <= STORE_CMD;
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            STORE_CMD: begin
 | 
			
		||||
                if (~command_fifo_full) in_state <= START_STATE;
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            endcase //in_state
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------
 | 
			
		||||
    //-- Command state machine:
 | 
			
		||||
    //-- Read a command fifo entry, act on it, produce result.
 | 
			
		||||
    //------------------------------------------------------------------
 | 
			
		||||
    localparam LOAD_CMD    = 0;
 | 
			
		||||
    localparam EVENT_CMD   = 1;
 | 
			
		||||
 | 
			
		||||
    reg cmd_state;
 | 
			
		||||
    reg [31:0] rb_data;
 | 
			
		||||
 | 
			
		||||
    reg [63:0] command_ticks_reg;
 | 
			
		||||
    reg [31:0] command_hdr_reg;
 | 
			
		||||
    reg [31:0] command_data_reg;
 | 
			
		||||
 | 
			
		||||
    reg [63:0] vita_time_reg;
 | 
			
		||||
    always @(posedge clock)
 | 
			
		||||
        vita_time_reg <= vita_time;
 | 
			
		||||
 | 
			
		||||
    wire late;
 | 
			
		||||
    `ifndef FIFO_CTRL_NO_TIME
 | 
			
		||||
    time_compare time_compare(
 | 
			
		||||
        .time_now(vita_time_reg), .trigger_time(command_ticks_reg), .late(late));
 | 
			
		||||
    `else
 | 
			
		||||
    assign late = 1;
 | 
			
		||||
    `endif
 | 
			
		||||
 | 
			
		||||
    //action occurs in the event state and when there is fifo space (should always be true)
 | 
			
		||||
    //the third condition is that all peripherals in the perfs signal are ready/active high
 | 
			
		||||
    //the fourth condition is that is an event time has been set, action is delayed until that time
 | 
			
		||||
    wire time_ready = (out_command_has_time)? late : 1;
 | 
			
		||||
    wire action = (cmd_state == EVENT_CMD) && ~result_fifo_full && perfs_ready && time_ready;
 | 
			
		||||
 | 
			
		||||
    assign command_fifo_read = action;
 | 
			
		||||
    assign result_fifo_write = action;
 | 
			
		||||
    assign in_result_hdr = command_hdr_reg;
 | 
			
		||||
    assign in_result_data = rb_data;
 | 
			
		||||
 | 
			
		||||
    always @(posedge clock) begin
 | 
			
		||||
        if (reset) begin
 | 
			
		||||
            cmd_state <= LOAD_CMD;
 | 
			
		||||
        end
 | 
			
		||||
        else begin
 | 
			
		||||
            case (cmd_state)
 | 
			
		||||
 | 
			
		||||
            LOAD_CMD: begin
 | 
			
		||||
                if (~command_fifo_empty) cmd_state <= EVENT_CMD;
 | 
			
		||||
                command_ticks_reg <= out_command_ticks;
 | 
			
		||||
                command_hdr_reg <= out_command_hdr;
 | 
			
		||||
                command_data_reg <= out_command_data;
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            EVENT_CMD: begin // poking and peeking happens here!
 | 
			
		||||
                if (action || clear) cmd_state <= LOAD_CMD;
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            endcase //cmd_state
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------
 | 
			
		||||
    //-- assign to settings bus interface
 | 
			
		||||
    //------------------------------------------------------------------
 | 
			
		||||
    reg strobe_reg;
 | 
			
		||||
    assign strobe = strobe_reg;
 | 
			
		||||
    assign data = command_data_reg;
 | 
			
		||||
    assign addr = command_hdr_reg[7:0];
 | 
			
		||||
    wire poke = command_hdr_reg[8];
 | 
			
		||||
 | 
			
		||||
    always @(posedge clock) begin
 | 
			
		||||
        if (reset || clear) strobe_reg <= 0;
 | 
			
		||||
        else                strobe_reg <= action && poke;
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------
 | 
			
		||||
    //-- readback mux
 | 
			
		||||
    //------------------------------------------------------------------
 | 
			
		||||
    always @(posedge clock) begin
 | 
			
		||||
        case (out_command_hdr[3:0])
 | 
			
		||||
            0 : rb_data <= word00;
 | 
			
		||||
            1 : rb_data <= word01;
 | 
			
		||||
            2 : rb_data <= word02;
 | 
			
		||||
            3 : rb_data <= word03;
 | 
			
		||||
            4 : rb_data <= word04;
 | 
			
		||||
            5 : rb_data <= word05;
 | 
			
		||||
            6 : rb_data <= word06;
 | 
			
		||||
            7 : rb_data <= word07;
 | 
			
		||||
            8 : rb_data <= word08;
 | 
			
		||||
            9 : rb_data <= word09;
 | 
			
		||||
            10: rb_data <= word10;
 | 
			
		||||
            11: rb_data <= word11;
 | 
			
		||||
            12: rb_data <= word12;
 | 
			
		||||
            13: rb_data <= word13;
 | 
			
		||||
            14: rb_data <= word14;
 | 
			
		||||
            15: rb_data <= word15;
 | 
			
		||||
        endcase // case(addr_reg[3:0])
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------
 | 
			
		||||
    //-- Output state machine:
 | 
			
		||||
    //-- Read a command fifo entry, act on it, produce ack packet.
 | 
			
		||||
    //------------------------------------------------------------------
 | 
			
		||||
    localparam WRITE_PROT_HDR = 0;
 | 
			
		||||
    localparam WRITE_VRT_HDR  = 1;
 | 
			
		||||
    localparam WRITE_VRT_SID  = 2;
 | 
			
		||||
    localparam WRITE_RB_HDR   = 3;
 | 
			
		||||
    localparam WRITE_RB_DATA  = 4;
 | 
			
		||||
 | 
			
		||||
    //the state for the start of packet condition
 | 
			
		||||
    localparam WRITE_PKT_HDR = (PROT_HDR)? WRITE_PROT_HDR : WRITE_VRT_HDR;
 | 
			
		||||
 | 
			
		||||
    reg [2:0] out_state;
 | 
			
		||||
 | 
			
		||||
    assign out_valid = ~result_fifo_empty;
 | 
			
		||||
    assign result_fifo_read = out_data[33] && writing;
 | 
			
		||||
 | 
			
		||||
    always @(posedge clock) begin
 | 
			
		||||
        if (reset) begin
 | 
			
		||||
            out_state <= WRITE_PKT_HDR;
 | 
			
		||||
        end
 | 
			
		||||
        else if (writing && out_data[33]) begin
 | 
			
		||||
            out_state <= WRITE_PKT_HDR;
 | 
			
		||||
        end
 | 
			
		||||
        else if (writing) begin
 | 
			
		||||
            out_state <= out_state + 1;
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------
 | 
			
		||||
    //-- assign to output fifo interface
 | 
			
		||||
    //------------------------------------------------------------------
 | 
			
		||||
    wire [31:0] prot_hdr;
 | 
			
		||||
    assign prot_hdr[15:0] = 16; //bytes in proceeding vita packet
 | 
			
		||||
    assign prot_hdr[16] = 1; //yes frame
 | 
			
		||||
    assign prot_hdr[18:17] = PROT_DEST;
 | 
			
		||||
    assign prot_hdr[31:19] = 0; //nothing
 | 
			
		||||
 | 
			
		||||
    reg [31:0] out_data_int;
 | 
			
		||||
    always @* begin
 | 
			
		||||
        case (out_state)
 | 
			
		||||
            WRITE_PROT_HDR: out_data_int <= prot_hdr;
 | 
			
		||||
            WRITE_VRT_HDR:  out_data_int <= {12'b010100000000, out_result_hdr[19:16], 2'b0, prot_hdr[15:2]};
 | 
			
		||||
            WRITE_VRT_SID:  out_data_int <= ACK_SID;
 | 
			
		||||
            WRITE_RB_HDR:   out_data_int <= out_result_hdr;
 | 
			
		||||
            WRITE_RB_DATA:  out_data_int <= out_result_data;
 | 
			
		||||
            default:        out_data_int <= 0;
 | 
			
		||||
        endcase //state
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    assign out_data[35:34] = 2'b0;
 | 
			
		||||
    assign out_data[33] = (out_state == WRITE_RB_DATA);
 | 
			
		||||
    assign out_data[32] = (out_state == WRITE_PKT_HDR);
 | 
			
		||||
    assign out_data[31:0] = out_data_int;
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------
 | 
			
		||||
    //-- debug outputs
 | 
			
		||||
    //------------------------------------------------------------------
 | 
			
		||||
    assign debug = {
 | 
			
		||||
        in_state, out_state, //8
 | 
			
		||||
        in_valid, in_ready, in_data[33:32], //4
 | 
			
		||||
        out_valid, out_ready, out_data[33:32], //4
 | 
			
		||||
        command_fifo_empty, command_fifo_full, //2
 | 
			
		||||
        command_fifo_read, command_fifo_write, //2
 | 
			
		||||
        addr, //8
 | 
			
		||||
        strobe_reg, strobe, poke, out_command_has_time //4
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
endmodule //settings_fifo_ctrl
 | 
			
		||||
							
								
								
									
										116
									
								
								fpga/control_lib/simple_i2c_core.v
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								fpga/control_lib/simple_i2c_core.v
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,116 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2012 Ettus Research LLC
 | 
			
		||||
//
 | 
			
		||||
// This program is free software: you can redistribute it and/or modify
 | 
			
		||||
// it under the terms of the GNU General Public License as published by
 | 
			
		||||
// the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
// (at your option) any later version.
 | 
			
		||||
//
 | 
			
		||||
// This program is distributed in the hope that it will be useful,
 | 
			
		||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
// GNU General Public License for more details.
 | 
			
		||||
//
 | 
			
		||||
// You should have received a copy of the GNU General Public License
 | 
			
		||||
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
							
								
								
									
										214
									
								
								fpga/control_lib/simple_spi_core.v
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										214
									
								
								fpga/control_lib/simple_spi_core.v
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,214 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2012 Ettus Research LLC
 | 
			
		||||
//
 | 
			
		||||
// This program is free software: you can redistribute it and/or modify
 | 
			
		||||
// it under the terms of the GNU General Public License as published by
 | 
			
		||||
// the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
// (at your option) any later version.
 | 
			
		||||
//
 | 
			
		||||
// This program is distributed in the hope that it will be useful,
 | 
			
		||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
// GNU General Public License for more details.
 | 
			
		||||
//
 | 
			
		||||
// You should have received a copy of the GNU General Public License
 | 
			
		||||
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
// 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 [WIDTH-1:0] sen,
 | 
			
		||||
        output sclk,
 | 
			
		||||
        output 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
 | 
			
		||||
    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];
 | 
			
		||||
    assign sen = sen_reg;
 | 
			
		||||
 | 
			
		||||
    //data output shift register
 | 
			
		||||
    reg [31:0] dataout_reg;
 | 
			
		||||
    wire [31:0] dataout_next = {dataout_reg[30:0], 1'b0};
 | 
			
		||||
    assign mosi = dataout_reg[31];
 | 
			
		||||
 | 
			
		||||
    //data input shift register
 | 
			
		||||
    reg [31:0] datain_reg;
 | 
			
		||||
    wire [31:0] datain_next = {datain_reg[30:0], miso};
 | 
			
		||||
    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
 | 
			
		||||
							
								
								
									
										63
									
								
								fpga/control_lib/user_settings.v
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								fpga/control_lib/user_settings.v
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,63 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2012 Ettus Research LLC
 | 
			
		||||
//
 | 
			
		||||
// This program is free software: you can redistribute it and/or modify
 | 
			
		||||
// it under the terms of the GNU General Public License as published by
 | 
			
		||||
// the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
// (at your option) any later version.
 | 
			
		||||
//
 | 
			
		||||
// This program is distributed in the hope that it will be useful,
 | 
			
		||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
// GNU General Public License for more details.
 | 
			
		||||
//
 | 
			
		||||
// You should have received a copy of the GNU General Public License
 | 
			
		||||
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
// User settings bus
 | 
			
		||||
//
 | 
			
		||||
// Provides 8-bit address, 32-bit data write only bus for user settings, consumes to addresses in
 | 
			
		||||
// normal settings bus.
 | 
			
		||||
//
 | 
			
		||||
// Write user address to BASE
 | 
			
		||||
// Write user data to BASE+1
 | 
			
		||||
//
 | 
			
		||||
// The user_set_stb will strobe after data write, must write new address even if same as previous one.
 | 
			
		||||
 | 
			
		||||
module user_settings
 | 
			
		||||
  #(parameter BASE=0)
 | 
			
		||||
  (input clk,
 | 
			
		||||
   input rst,
 | 
			
		||||
 | 
			
		||||
   input         set_stb,
 | 
			
		||||
   input [7:0]   set_addr,
 | 
			
		||||
   input [31:0]  set_data,
 | 
			
		||||
 | 
			
		||||
   output        set_stb_user,
 | 
			
		||||
   output [7:0]  set_addr_user,
 | 
			
		||||
   output [31:0] set_data_user
 | 
			
		||||
   );
 | 
			
		||||
 | 
			
		||||
   wire 	 addr_changed, data_changed;
 | 
			
		||||
   reg 		 stb_int;
 | 
			
		||||
   
 | 
			
		||||
   setting_reg #(.my_addr(BASE+0),.width(8)) sr_0
 | 
			
		||||
     (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
 | 
			
		||||
      .in(set_data),.out(set_addr_user),.changed(addr_changed) );
 | 
			
		||||
   
 | 
			
		||||
   setting_reg #(.my_addr(BASE+1)) sr_1
 | 
			
		||||
     (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
 | 
			
		||||
      .in(set_data),.out(set_data_user),.changed(data_changed) );
 | 
			
		||||
   
 | 
			
		||||
   always @(posedge clk)
 | 
			
		||||
     if (rst|set_stb_user)
 | 
			
		||||
       stb_int <= 0;
 | 
			
		||||
     else
 | 
			
		||||
       if (addr_changed)
 | 
			
		||||
         stb_int <= 1;
 | 
			
		||||
   
 | 
			
		||||
   assign set_stb_user = stb_int & data_changed;
 | 
			
		||||
   
 | 
			
		||||
endmodule // user_settings
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										316
									
								
								fpga/fifo/packet_dispatcher36_x4.v
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										316
									
								
								fpga/fifo/packet_dispatcher36_x4.v
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,316 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2011-2012 Ettus Research LLC
 | 
			
		||||
//
 | 
			
		||||
// Packet dispatcher with fifo36 interface and 4 outputs.
 | 
			
		||||
//
 | 
			
		||||
// The packet dispatcher expects 2-byte padded ethernet frames.
 | 
			
		||||
// The frames will be inspected at ethernet, IPv4, UDP, and VRT layers.
 | 
			
		||||
// Packets are dispatched into the following streams:
 | 
			
		||||
//   * tx dsp stream
 | 
			
		||||
//   * tx control stream
 | 
			
		||||
//   * to cpu stream
 | 
			
		||||
//   * to external stream
 | 
			
		||||
//   * to both cpu and external
 | 
			
		||||
//
 | 
			
		||||
// The following registers are used for dispatcher control:
 | 
			
		||||
//   * base + 0 = this ipv4 address (32 bits)
 | 
			
		||||
//   * base + 1 = udp control port (upper 16 bits), udp dsp port (lower 16 bits)
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
module packet_dispatcher36_x4
 | 
			
		||||
    #(
 | 
			
		||||
        parameter BASE = 0
 | 
			
		||||
    )
 | 
			
		||||
    (
 | 
			
		||||
        //clocking and reset interface:
 | 
			
		||||
        input clk, input rst, input clr,
 | 
			
		||||
 | 
			
		||||
        //setting register interface:
 | 
			
		||||
        input set_stb, input [7:0] set_addr, input [31:0] set_data,
 | 
			
		||||
 | 
			
		||||
        //input stream interfaces:
 | 
			
		||||
        input [35:0] com_inp_data, input com_inp_valid, output com_inp_ready,
 | 
			
		||||
 | 
			
		||||
        //output stream interfaces:
 | 
			
		||||
        output [35:0] ext_out_data, output ext_out_valid, input ext_out_ready,
 | 
			
		||||
        output [35:0] dsp_out_data, output dsp_out_valid, input dsp_out_ready,
 | 
			
		||||
        output [35:0] ctl_out_data, output ctl_out_valid, input ctl_out_ready,
 | 
			
		||||
        output [35:0] cpu_out_data, output cpu_out_valid, input cpu_out_ready
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    //setting register to program the IP address
 | 
			
		||||
    wire [31:0] my_ip_addr;
 | 
			
		||||
    setting_reg #(.my_addr(BASE+0)) sreg_ip_addr(
 | 
			
		||||
        .clk(clk),.rst(rst),
 | 
			
		||||
        .strobe(set_stb),.addr(set_addr),.in(set_data),
 | 
			
		||||
        .out(my_ip_addr),.changed()
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    //setting register to program the UDP DSP port
 | 
			
		||||
    wire [15:0] dsp_udp_port, ctl_udp_port;
 | 
			
		||||
    setting_reg #(.my_addr(BASE+1), .width(32)) sreg_data_port(
 | 
			
		||||
        .clk(clk),.rst(rst),
 | 
			
		||||
        .strobe(set_stb),.addr(set_addr),.in(set_data),
 | 
			
		||||
        .out({ctl_udp_port, dsp_udp_port}),.changed()
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    ////////////////////////////////////////////////////////////////////
 | 
			
		||||
    // Communication input inspector
 | 
			
		||||
    //   - inspect com input and send it to DSP, EXT, CPU, or BOTH
 | 
			
		||||
    ////////////////////////////////////////////////////////////////////
 | 
			
		||||
    localparam PD_STATE_READ_COM_PRE = 0;
 | 
			
		||||
    localparam PD_STATE_READ_COM = 1;
 | 
			
		||||
    localparam PD_STATE_WRITE_REGS = 2;
 | 
			
		||||
    localparam PD_STATE_WRITE_LIVE = 3;
 | 
			
		||||
 | 
			
		||||
    localparam PD_DEST_DSP = 0;
 | 
			
		||||
    localparam PD_DEST_EXT = 1;
 | 
			
		||||
    localparam PD_DEST_CPU = 2;
 | 
			
		||||
    localparam PD_DEST_BOF = 3;
 | 
			
		||||
    localparam PD_DEST_CTL = 4;
 | 
			
		||||
 | 
			
		||||
    localparam PD_MAX_NUM_DREGS = 13; //padded_eth + ip + udp + seq + vrt_hdr
 | 
			
		||||
    localparam PD_DREGS_DSP_OFFSET = 11; //offset to start dsp at
 | 
			
		||||
 | 
			
		||||
    //output inspector interfaces
 | 
			
		||||
    wire [35:0] pd_out_dsp_data;
 | 
			
		||||
    wire        pd_out_dsp_valid;
 | 
			
		||||
    wire        pd_out_dsp_ready;
 | 
			
		||||
 | 
			
		||||
    wire [35:0] pd_out_ext_data;
 | 
			
		||||
    wire        pd_out_ext_valid;
 | 
			
		||||
    wire        pd_out_ext_ready;
 | 
			
		||||
 | 
			
		||||
    wire [35:0] pd_out_cpu_data;
 | 
			
		||||
    wire        pd_out_cpu_valid;
 | 
			
		||||
    wire        pd_out_cpu_ready;
 | 
			
		||||
 | 
			
		||||
    wire [35:0] pd_out_bof_data;
 | 
			
		||||
    wire        pd_out_bof_valid;
 | 
			
		||||
    wire        pd_out_bof_ready;
 | 
			
		||||
 | 
			
		||||
    wire [35:0] pd_out_ctl_data;
 | 
			
		||||
    wire        pd_out_ctl_valid;
 | 
			
		||||
    wire        pd_out_ctl_ready;
 | 
			
		||||
 | 
			
		||||
    reg [1:0] pd_state;
 | 
			
		||||
    reg [2:0] pd_dest;
 | 
			
		||||
    reg [3:0] pd_dreg_count; //data registers to buffer headers
 | 
			
		||||
    wire [3:0] pd_dreg_count_next = pd_dreg_count + 1'b1;
 | 
			
		||||
    wire pd_dreg_counter_done = (pd_dreg_count_next == PD_MAX_NUM_DREGS)? 1'b1 : 1'b0;
 | 
			
		||||
    reg [35:0] pd_dregs [PD_MAX_NUM_DREGS-1:0];
 | 
			
		||||
 | 
			
		||||
    reg is_eth_dst_mac_bcast;
 | 
			
		||||
    reg is_eth_type_ipv4;
 | 
			
		||||
    reg is_eth_ipv4_proto_udp;
 | 
			
		||||
    reg is_eth_ipv4_dst_addr_here;
 | 
			
		||||
    reg is_eth_udp_dsp_port_here;
 | 
			
		||||
    reg is_eth_udp_ctl_port_here;
 | 
			
		||||
    wire is_vrt_size_zero = (com_inp_data[15:0] == 16'h0); //needed on the same cycle, so it cant be registered
 | 
			
		||||
 | 
			
		||||
    //Inspector output flags special case:
 | 
			
		||||
    //Inject SOF into flags at first DSP line.
 | 
			
		||||
    wire [3:0] pd_out_flags = (
 | 
			
		||||
        (pd_dreg_count == PD_DREGS_DSP_OFFSET) &&
 | 
			
		||||
        (pd_dest == PD_DEST_DSP)
 | 
			
		||||
    )? 4'b0001 : pd_dregs[pd_dreg_count][35:32];
 | 
			
		||||
 | 
			
		||||
    //The communication inspector ouput data and valid signals:
 | 
			
		||||
    //Mux between com input and data registers based on the state.
 | 
			
		||||
    wire [35:0] pd_out_data = (pd_state == PD_STATE_WRITE_REGS)?
 | 
			
		||||
        {pd_out_flags, pd_dregs[pd_dreg_count][31:0]} : com_inp_data
 | 
			
		||||
    ;
 | 
			
		||||
    wire pd_out_valid =
 | 
			
		||||
        (pd_state == PD_STATE_WRITE_REGS)? 1'b1          : (
 | 
			
		||||
        (pd_state == PD_STATE_WRITE_LIVE)? com_inp_valid : (
 | 
			
		||||
    1'b0));
 | 
			
		||||
 | 
			
		||||
    //The communication inspector ouput ready signal:
 | 
			
		||||
    //Mux between the various destination ready signals.
 | 
			
		||||
    wire pd_out_ready =
 | 
			
		||||
        (pd_dest == PD_DEST_DSP)? pd_out_dsp_ready : (
 | 
			
		||||
        (pd_dest == PD_DEST_EXT)? pd_out_ext_ready : (
 | 
			
		||||
        (pd_dest == PD_DEST_CPU)? pd_out_cpu_ready : (
 | 
			
		||||
        (pd_dest == PD_DEST_BOF)? pd_out_bof_ready : (
 | 
			
		||||
        (pd_dest == PD_DEST_CTL)? pd_out_ctl_ready : (
 | 
			
		||||
    1'b0)))));
 | 
			
		||||
 | 
			
		||||
    //Always connected output data lines.
 | 
			
		||||
    assign pd_out_dsp_data = pd_out_data;
 | 
			
		||||
    assign pd_out_ext_data = pd_out_data;
 | 
			
		||||
    assign pd_out_cpu_data = pd_out_data;
 | 
			
		||||
    assign pd_out_bof_data = pd_out_data;
 | 
			
		||||
    assign pd_out_ctl_data = pd_out_data;
 | 
			
		||||
 | 
			
		||||
    //Destination output valid signals:
 | 
			
		||||
    //Comes from inspector valid when destination is selected, and otherwise low.
 | 
			
		||||
    assign pd_out_dsp_valid = (pd_dest == PD_DEST_DSP)? pd_out_valid : 1'b0;
 | 
			
		||||
    assign pd_out_ext_valid = (pd_dest == PD_DEST_EXT)? pd_out_valid : 1'b0;
 | 
			
		||||
    assign pd_out_cpu_valid = (pd_dest == PD_DEST_CPU)? pd_out_valid : 1'b0;
 | 
			
		||||
    assign pd_out_bof_valid = (pd_dest == PD_DEST_BOF)? pd_out_valid : 1'b0;
 | 
			
		||||
    assign pd_out_ctl_valid = (pd_dest == PD_DEST_CTL)? pd_out_valid : 1'b0;
 | 
			
		||||
 | 
			
		||||
    //The communication inspector ouput ready signal:
 | 
			
		||||
    //Always ready when storing to data registers,
 | 
			
		||||
    //comes from inspector ready output when live,
 | 
			
		||||
    //and otherwise low.
 | 
			
		||||
    assign com_inp_ready =
 | 
			
		||||
        (pd_state == PD_STATE_READ_COM_PRE)  ? 1'b1         : (
 | 
			
		||||
        (pd_state == PD_STATE_READ_COM)      ? 1'b1         : (
 | 
			
		||||
        (pd_state == PD_STATE_WRITE_LIVE)    ? pd_out_ready : (
 | 
			
		||||
    1'b0)));
 | 
			
		||||
 | 
			
		||||
    //inspect the incoming data and mark register booleans
 | 
			
		||||
    always @(posedge clk)
 | 
			
		||||
    if (com_inp_ready & com_inp_valid) begin
 | 
			
		||||
        case(pd_dreg_count)
 | 
			
		||||
        0: begin
 | 
			
		||||
            is_eth_dst_mac_bcast <= (com_inp_data[15:0] == 16'hffff);
 | 
			
		||||
        end
 | 
			
		||||
        1: begin
 | 
			
		||||
            is_eth_dst_mac_bcast <= is_eth_dst_mac_bcast && (com_inp_data[31:0] == 32'hffffffff);
 | 
			
		||||
        end
 | 
			
		||||
        3: begin
 | 
			
		||||
            is_eth_type_ipv4 <= (com_inp_data[15:0] == 16'h800);
 | 
			
		||||
        end
 | 
			
		||||
        6: begin
 | 
			
		||||
            is_eth_ipv4_proto_udp <= (com_inp_data[23:16] == 8'h11);
 | 
			
		||||
        end
 | 
			
		||||
        8: begin
 | 
			
		||||
            is_eth_ipv4_dst_addr_here <= (com_inp_data[31:0] == my_ip_addr);
 | 
			
		||||
        end
 | 
			
		||||
        9: begin
 | 
			
		||||
            is_eth_udp_dsp_port_here <= (com_inp_data[15:0] == dsp_udp_port);
 | 
			
		||||
            is_eth_udp_ctl_port_here <= (com_inp_data[15:0] == ctl_udp_port);
 | 
			
		||||
        end
 | 
			
		||||
        endcase //pd_dreg_count
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    always @(posedge clk)
 | 
			
		||||
    if(rst | clr) begin
 | 
			
		||||
        pd_state <= PD_STATE_READ_COM_PRE;
 | 
			
		||||
        pd_dreg_count <= 0;
 | 
			
		||||
    end
 | 
			
		||||
    else begin
 | 
			
		||||
        case(pd_state)
 | 
			
		||||
        PD_STATE_READ_COM_PRE: begin
 | 
			
		||||
            if (com_inp_ready & com_inp_valid & com_inp_data[32]) begin
 | 
			
		||||
                pd_state <= PD_STATE_READ_COM;
 | 
			
		||||
                pd_dreg_count <= pd_dreg_count_next;
 | 
			
		||||
                pd_dregs[pd_dreg_count] <= com_inp_data;
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        PD_STATE_READ_COM: begin
 | 
			
		||||
            if (com_inp_ready & com_inp_valid) begin
 | 
			
		||||
                pd_dregs[pd_dreg_count] <= com_inp_data;
 | 
			
		||||
                if (pd_dreg_counter_done | com_inp_data[33]) begin
 | 
			
		||||
                    pd_state <= PD_STATE_WRITE_REGS;
 | 
			
		||||
                    pd_dreg_count <= 0;
 | 
			
		||||
 | 
			
		||||
                    //---------- begin inspection decision -----------//
 | 
			
		||||
                    //EOF or bcast or not IPv4 or not UDP:
 | 
			
		||||
                    if (
 | 
			
		||||
                        com_inp_data[33] || is_eth_dst_mac_bcast ||
 | 
			
		||||
                        ~is_eth_type_ipv4 || ~is_eth_ipv4_proto_udp
 | 
			
		||||
                    ) begin
 | 
			
		||||
                        pd_dest <= PD_DEST_BOF;
 | 
			
		||||
                    end
 | 
			
		||||
 | 
			
		||||
                    //not my IP address:
 | 
			
		||||
                    else if (~is_eth_ipv4_dst_addr_here) begin
 | 
			
		||||
                        pd_dest <= PD_DEST_EXT;
 | 
			
		||||
                    end
 | 
			
		||||
 | 
			
		||||
                    //UDP control port and VRT:
 | 
			
		||||
                    else if (is_eth_udp_ctl_port_here && ~is_vrt_size_zero) begin
 | 
			
		||||
                        pd_dest <= PD_DEST_CTL;
 | 
			
		||||
                        pd_dreg_count <= PD_DREGS_DSP_OFFSET;
 | 
			
		||||
                    end
 | 
			
		||||
 | 
			
		||||
                    //UDP data port and VRT:
 | 
			
		||||
                    else if (is_eth_udp_dsp_port_here && ~is_vrt_size_zero) begin
 | 
			
		||||
                        pd_dest <= PD_DEST_DSP;
 | 
			
		||||
                        pd_dreg_count <= PD_DREGS_DSP_OFFSET;
 | 
			
		||||
                    end
 | 
			
		||||
 | 
			
		||||
                    //other:
 | 
			
		||||
                    else begin
 | 
			
		||||
                        pd_dest <= PD_DEST_CPU;
 | 
			
		||||
                    end
 | 
			
		||||
                    //---------- end inspection decision -------------//
 | 
			
		||||
 | 
			
		||||
                end
 | 
			
		||||
                else begin
 | 
			
		||||
                    pd_dreg_count <= pd_dreg_count_next;
 | 
			
		||||
                end
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        PD_STATE_WRITE_REGS: begin
 | 
			
		||||
            if (pd_out_ready & pd_out_valid) begin
 | 
			
		||||
                if (pd_out_data[33]) begin
 | 
			
		||||
                    pd_state <= PD_STATE_READ_COM_PRE;
 | 
			
		||||
                    pd_dreg_count <= 0;
 | 
			
		||||
                end
 | 
			
		||||
                else if (pd_dreg_counter_done) begin
 | 
			
		||||
                    pd_state <= PD_STATE_WRITE_LIVE;
 | 
			
		||||
                    pd_dreg_count <= 0;
 | 
			
		||||
                end
 | 
			
		||||
                else begin
 | 
			
		||||
                    pd_dreg_count <= pd_dreg_count_next;
 | 
			
		||||
                end
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        PD_STATE_WRITE_LIVE: begin
 | 
			
		||||
            if (pd_out_ready & pd_out_valid & pd_out_data[33]) begin
 | 
			
		||||
                pd_state <= PD_STATE_READ_COM_PRE;
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        endcase //pd_state
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    //connect this fast-path signals directly to the DSP out
 | 
			
		||||
    assign dsp_out_data = pd_out_dsp_data;
 | 
			
		||||
    assign dsp_out_valid = pd_out_dsp_valid;
 | 
			
		||||
    assign pd_out_dsp_ready = dsp_out_ready;
 | 
			
		||||
 | 
			
		||||
    assign ctl_out_data = pd_out_ctl_data;
 | 
			
		||||
    assign ctl_out_valid = pd_out_ctl_valid;
 | 
			
		||||
    assign pd_out_ctl_ready = ctl_out_ready;
 | 
			
		||||
 | 
			
		||||
    ////////////////////////////////////////////////////////////////////
 | 
			
		||||
    // Splitter and output muxes for the bof packets
 | 
			
		||||
    //   - split the bof packets into two streams
 | 
			
		||||
    //   - mux split packets into cpu out and ext out
 | 
			
		||||
    ////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
    //dummy signals to join the the splitter and muxes below
 | 
			
		||||
    wire [35:0] _split_to_ext_data,  _split_to_cpu_data;
 | 
			
		||||
    wire        _split_to_ext_valid, _split_to_cpu_valid;
 | 
			
		||||
    wire        _split_to_ext_ready, _split_to_cpu_ready;
 | 
			
		||||
 | 
			
		||||
    splitter36 bof_out_splitter(
 | 
			
		||||
        .clk(clk), .rst(rst), .clr(clr),
 | 
			
		||||
        .inp_data(pd_out_bof_data), .inp_valid(pd_out_bof_valid), .inp_ready(pd_out_bof_ready),
 | 
			
		||||
        .out0_data(_split_to_ext_data), .out0_valid(_split_to_ext_valid), .out0_ready(_split_to_ext_ready),
 | 
			
		||||
        .out1_data(_split_to_cpu_data), .out1_valid(_split_to_cpu_valid), .out1_ready(_split_to_cpu_ready)
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    fifo36_mux ext_out_mux(
 | 
			
		||||
        .clk(clk), .reset(rst), .clear(clr),
 | 
			
		||||
        .data0_i(pd_out_ext_data), .src0_rdy_i(pd_out_ext_valid), .dst0_rdy_o(pd_out_ext_ready),
 | 
			
		||||
        .data1_i(_split_to_ext_data), .src1_rdy_i(_split_to_ext_valid), .dst1_rdy_o(_split_to_ext_ready),
 | 
			
		||||
        .data_o(ext_out_data), .src_rdy_o(ext_out_valid), .dst_rdy_i(ext_out_ready)
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    fifo36_mux cpu_out_mux(
 | 
			
		||||
        .clk(clk), .reset(rst), .clear(clr),
 | 
			
		||||
        .data0_i(pd_out_cpu_data), .src0_rdy_i(pd_out_cpu_valid), .dst0_rdy_o(pd_out_cpu_ready),
 | 
			
		||||
        .data1_i(_split_to_cpu_data), .src1_rdy_i(_split_to_cpu_valid), .dst1_rdy_o(_split_to_cpu_ready),
 | 
			
		||||
        .data_o(cpu_out_data), .src_rdy_o(cpu_out_valid), .dst_rdy_i(cpu_out_ready)
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
endmodule // packet_dispatcher36_x3
 | 
			
		||||
							
								
								
									
										155
									
								
								fpga/fifo/packet_padder36.v
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										155
									
								
								fpga/fifo/packet_padder36.v
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,155 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2011-2012 Ettus Research LLC
 | 
			
		||||
//
 | 
			
		||||
// This program is free software: you can redistribute it and/or modify
 | 
			
		||||
// it under the terms of the GNU General Public License as published by
 | 
			
		||||
// the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
// (at your option) any later version.
 | 
			
		||||
//
 | 
			
		||||
// This program is distributed in the hope that it will be useful,
 | 
			
		||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
// GNU General Public License for more details.
 | 
			
		||||
//
 | 
			
		||||
// You should have received a copy of the GNU General Public License
 | 
			
		||||
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
// The packet padder 36 for use with RX VITA stream output.
 | 
			
		||||
// Packet padder understands the concept of USB LUTs,
 | 
			
		||||
// and will forward packets through the interface,
 | 
			
		||||
// adding zero padding as needed to properly flush.
 | 
			
		||||
// The padder will never write a packet across a LUT boundary.
 | 
			
		||||
// When flushing, padder writes out zeros until the LUT boundary.
 | 
			
		||||
// Requires that the input line0 be a VITA header, and SOF set.
 | 
			
		||||
// Flush when the LUT is partially filled and timeout is reached,
 | 
			
		||||
// or when the LUT is partially filled and the DSP is inactive.
 | 
			
		||||
 | 
			
		||||
module packet_padder36
 | 
			
		||||
#(
 | 
			
		||||
    parameter BASE = 0,
 | 
			
		||||
 | 
			
		||||
    //default is 16K LUT
 | 
			
		||||
    parameter DEFAULT_LINES32 = 4096,
 | 
			
		||||
 | 
			
		||||
    //default about 1ms at 64MHz clock
 | 
			
		||||
    parameter DEFAULT_IDLE_CYC = 65536
 | 
			
		||||
)
 | 
			
		||||
(
 | 
			
		||||
    input clk, input reset,
 | 
			
		||||
 | 
			
		||||
    //setting bus
 | 
			
		||||
    input set_stb, input [7:0] set_addr, input [31:0] set_data,
 | 
			
		||||
 | 
			
		||||
    //input interface
 | 
			
		||||
    input [35:0] data_i,
 | 
			
		||||
    input src_rdy_i,
 | 
			
		||||
    output dst_rdy_o,
 | 
			
		||||
 | 
			
		||||
    //output interface
 | 
			
		||||
    output [35:0] data_o,
 | 
			
		||||
    output src_rdy_o,
 | 
			
		||||
    input dst_rdy_i,
 | 
			
		||||
 | 
			
		||||
    input always_flush
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
    wire lut_lines_changed;
 | 
			
		||||
    wire [15:0] max_lut_lines32;
 | 
			
		||||
    setting_reg #(.my_addr(BASE+0),.width(16),.at_reset(DEFAULT_LINES32)) sr_num_lines(
 | 
			
		||||
        .clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr),.in(set_data),
 | 
			
		||||
        .out(max_lut_lines32),.changed(lut_lines_changed));
 | 
			
		||||
 | 
			
		||||
    wire idle_cyc_changed;
 | 
			
		||||
    wire [17:0] idle_flush_cycles;
 | 
			
		||||
    setting_reg #(.my_addr(BASE+1),.width(18),.at_reset(DEFAULT_IDLE_CYC)) sr_flush_cyc(
 | 
			
		||||
        .clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr),.in(set_data),
 | 
			
		||||
        .out(idle_flush_cycles),.changed(idle_cyc_changed));
 | 
			
		||||
 | 
			
		||||
    //state machine definitions
 | 
			
		||||
    localparam STATE_READ_HDR = 0;
 | 
			
		||||
    localparam STATE_WRITE_HDR = 1;
 | 
			
		||||
    localparam STATE_FORWARD = 2;
 | 
			
		||||
    localparam STATE_WRITE_PAD = 3;
 | 
			
		||||
    reg [1:0] state;
 | 
			
		||||
 | 
			
		||||
    //keep track of the outgoing lines
 | 
			
		||||
    reg [15:0] line_count;
 | 
			
		||||
    wire line_count_done = line_count == 1;
 | 
			
		||||
    wire lut_is_empty = line_count == max_lut_lines32;
 | 
			
		||||
    always @(posedge clk) begin
 | 
			
		||||
        if (reset || lut_lines_changed) begin
 | 
			
		||||
            line_count <= max_lut_lines32;
 | 
			
		||||
        end
 | 
			
		||||
        else if (src_rdy_o && dst_rdy_i) begin
 | 
			
		||||
            line_count <= (line_count_done)? max_lut_lines32 : line_count - 1;
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    //count the number of cycles since RX data so we can force a flush
 | 
			
		||||
    reg [17:0] non_rx_cycles;
 | 
			
		||||
    wire idle_timeout = (non_rx_cycles == idle_flush_cycles);
 | 
			
		||||
    always @(posedge clk) begin
 | 
			
		||||
        if(reset || state != STATE_READ_HDR || idle_cyc_changed) begin
 | 
			
		||||
            non_rx_cycles <= 0;
 | 
			
		||||
        end
 | 
			
		||||
        else if (~idle_timeout) begin
 | 
			
		||||
            non_rx_cycles <= non_rx_cycles + 1;
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    //flush when we have written data to a LUT and either idle or non active DSP
 | 
			
		||||
    wire force_flush = ~lut_is_empty && (idle_timeout || always_flush);
 | 
			
		||||
 | 
			
		||||
    //the padding state machine
 | 
			
		||||
    reg [31:0] vita_hdr;
 | 
			
		||||
    reg has_vita_hdr;
 | 
			
		||||
    always @(posedge clk) begin
 | 
			
		||||
        if (reset) begin
 | 
			
		||||
            state <= STATE_READ_HDR;
 | 
			
		||||
        end
 | 
			
		||||
        else case(state)
 | 
			
		||||
 | 
			
		||||
        STATE_READ_HDR: begin
 | 
			
		||||
            if (src_rdy_i && dst_rdy_o && data_i[32]) begin
 | 
			
		||||
                vita_hdr <= data_i[31:0];
 | 
			
		||||
                has_vita_hdr <= 1;
 | 
			
		||||
                state <= (data_i[15:0] > line_count)? STATE_WRITE_PAD : STATE_WRITE_HDR;
 | 
			
		||||
            end
 | 
			
		||||
            else if (force_flush) begin
 | 
			
		||||
                has_vita_hdr <= 0;
 | 
			
		||||
                state <= STATE_WRITE_PAD;
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        STATE_WRITE_HDR: begin
 | 
			
		||||
            if (src_rdy_o && dst_rdy_i) begin
 | 
			
		||||
                state <= STATE_FORWARD;
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        STATE_FORWARD: begin
 | 
			
		||||
            if (src_rdy_i && dst_rdy_o && data_i[33]) begin
 | 
			
		||||
                state <= STATE_READ_HDR;
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        STATE_WRITE_PAD: begin
 | 
			
		||||
            if (src_rdy_o && dst_rdy_i && line_count_done) begin
 | 
			
		||||
                state <= (has_vita_hdr)? STATE_WRITE_HDR : STATE_READ_HDR;
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        endcase //state
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    //assign outgoing signals
 | 
			
		||||
    assign dst_rdy_o = (state == STATE_READ_HDR)? 1 : ((state == STATE_FORWARD)? dst_rdy_i : 0);
 | 
			
		||||
    assign src_rdy_o = (state == STATE_WRITE_HDR || state == STATE_WRITE_PAD)? 1 : ((state == STATE_FORWARD )? src_rdy_i : 0);
 | 
			
		||||
    assign data_o = (state == STATE_WRITE_HDR)? {4'b0001, vita_hdr} : ((state == STATE_FORWARD)? data_i : 0);
 | 
			
		||||
 | 
			
		||||
endmodule // packet_padder36
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										88
									
								
								fpga/fifo/resp_packet_padder36.v
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								fpga/fifo/resp_packet_padder36.v
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,88 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2011-2012 Ettus Research LLC
 | 
			
		||||
//
 | 
			
		||||
// This program is free software: you can redistribute it and/or modify
 | 
			
		||||
// it under the terms of the GNU General Public License as published by
 | 
			
		||||
// the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
// (at your option) any later version.
 | 
			
		||||
//
 | 
			
		||||
// This program is distributed in the hope that it will be useful,
 | 
			
		||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
// GNU General Public License for more details.
 | 
			
		||||
//
 | 
			
		||||
// You should have received a copy of the GNU General Public License
 | 
			
		||||
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
// PAD to NUM LINES
 | 
			
		||||
 | 
			
		||||
module resp_packet_padder36
 | 
			
		||||
#(
 | 
			
		||||
    parameter NUM_LINES32 = 128
 | 
			
		||||
)
 | 
			
		||||
(
 | 
			
		||||
    input clk, input reset,
 | 
			
		||||
 | 
			
		||||
    //input interface
 | 
			
		||||
    input [35:0] data_i,
 | 
			
		||||
    input src_rdy_i,
 | 
			
		||||
    output dst_rdy_o,
 | 
			
		||||
 | 
			
		||||
    //output interface
 | 
			
		||||
    output [35:0] data_o,
 | 
			
		||||
    output src_rdy_o,
 | 
			
		||||
    input dst_rdy_i
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
    localparam STATE_FWD = 0;
 | 
			
		||||
    localparam STATE_PAD = 1;
 | 
			
		||||
    reg state;
 | 
			
		||||
 | 
			
		||||
    reg [15:0] counter;
 | 
			
		||||
 | 
			
		||||
    always @(posedge clk) begin
 | 
			
		||||
        if (reset) begin
 | 
			
		||||
            counter <= 0;
 | 
			
		||||
        end
 | 
			
		||||
        else if (src_rdy_o && dst_rdy_i) begin
 | 
			
		||||
            if (data_o[33]) counter <= 0;
 | 
			
		||||
            else counter <= counter + 1;
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    always @(posedge clk) begin
 | 
			
		||||
        if (reset) begin
 | 
			
		||||
            state <= STATE_FWD;
 | 
			
		||||
        end
 | 
			
		||||
        else case(state)
 | 
			
		||||
 | 
			
		||||
        STATE_FWD: begin
 | 
			
		||||
            if (src_rdy_i && dst_rdy_o && data_i[33] && ~data_o[33]) begin
 | 
			
		||||
                state <= STATE_PAD;
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        STATE_PAD: begin
 | 
			
		||||
            if (src_rdy_o && dst_rdy_i && data_o[33]) begin
 | 
			
		||||
                state <= STATE_FWD;
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        endcase //state
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    //assign data out
 | 
			
		||||
    assign data_o[31:0] = (state == STATE_FWD)? data_i[31:0] : {32'b0};
 | 
			
		||||
    wire eof = (counter == (NUM_LINES32-1));
 | 
			
		||||
    assign data_o[35:32] = {data_i[35:34], eof, data_i[32]};
 | 
			
		||||
 | 
			
		||||
    //assign ready
 | 
			
		||||
    assign src_rdy_o = (state == STATE_FWD)? src_rdy_i : 1'b1;
 | 
			
		||||
    assign dst_rdy_o = (state == STATE_FWD)? dst_rdy_i : 1'b0;
 | 
			
		||||
 | 
			
		||||
endmodule // resp_packet_padder36
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -1,14 +0,0 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright 2010 Ettus Research LLC
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
##################################################
 | 
			
		||||
# SERDES Sources
 | 
			
		||||
##################################################
 | 
			
		||||
GPIF_SRCS = $(abspath $(addprefix $(BASE_DIR)/../gpif/, \
 | 
			
		||||
gpif.v \
 | 
			
		||||
gpif_wr.v \
 | 
			
		||||
gpif_rd.v \
 | 
			
		||||
packet_reframer.v \
 | 
			
		||||
packet_splitter.v \
 | 
			
		||||
))
 | 
			
		||||
							
								
								
									
										185
									
								
								fpga/gpif/gpif.v
									
									
									
									
									
								
							
							
						
						
									
										185
									
								
								fpga/gpif/gpif.v
									
									
									
									
									
								
							@@ -1,185 +0,0 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2011 Ettus Research LLC
 | 
			
		||||
//
 | 
			
		||||
// This program is free software: you can redistribute it and/or modify
 | 
			
		||||
// it under the terms of the GNU General Public License as published by
 | 
			
		||||
// the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
// (at your option) any later version.
 | 
			
		||||
//
 | 
			
		||||
// This program is distributed in the hope that it will be useful,
 | 
			
		||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
// GNU General Public License for more details.
 | 
			
		||||
//
 | 
			
		||||
// You should have received a copy of the GNU General Public License
 | 
			
		||||
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
//////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
module gpif
 | 
			
		||||
  #(parameter TXFIFOSIZE = 11, parameter RXFIFOSIZE = 11)
 | 
			
		||||
   (// GPIF signals
 | 
			
		||||
    input gpif_clk, input gpif_rst,
 | 
			
		||||
    inout [15:0] gpif_d, input [3:0] gpif_ctl, output [3:0] gpif_rdy,
 | 
			
		||||
    output [2:0] gpif_misc,
 | 
			
		||||
    
 | 
			
		||||
    // Wishbone signals
 | 
			
		||||
    input wb_clk, input wb_rst,
 | 
			
		||||
    output [15:0] wb_adr_o, output [15:0] wb_dat_mosi, input [15:0] wb_dat_miso,
 | 
			
		||||
    output [1:0] wb_sel_o, output wb_cyc_o, output wb_stb_o, output wb_we_o, input wb_ack_i,
 | 
			
		||||
    input [7:0] triggers,
 | 
			
		||||
    
 | 
			
		||||
    // FIFO interface
 | 
			
		||||
    input fifo_clk, input fifo_rst, input clear_tx, input clear_rx,
 | 
			
		||||
    output [35:0] tx_data_o, output tx_src_rdy_o, input tx_dst_rdy_i,
 | 
			
		||||
    input [35:0] rx_data_i, input rx_src_rdy_i, output rx_dst_rdy_o,
 | 
			
		||||
    input [35:0] tx_err_data_i, input tx_err_src_rdy_i, output tx_err_dst_rdy_o,
 | 
			
		||||
    
 | 
			
		||||
    output tx_underrun, output rx_overrun,
 | 
			
		||||
    input [7:0] frames_per_packet,
 | 
			
		||||
    output [31:0] debug0, output [31:0] debug1
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
   assign tx_underrun = 0;
 | 
			
		||||
   assign rx_overrun = 0;
 | 
			
		||||
   
 | 
			
		||||
   wire 	  WR = gpif_ctl[0];
 | 
			
		||||
   wire 	  RD = gpif_ctl[1];
 | 
			
		||||
   wire 	  OE = gpif_ctl[2];
 | 
			
		||||
   wire 	  EP = gpif_ctl[3];
 | 
			
		||||
 | 
			
		||||
   wire 	  CF, CE, DF, DE;
 | 
			
		||||
   
 | 
			
		||||
   assign gpif_rdy = { CF, CE, DF, DE };
 | 
			
		||||
   
 | 
			
		||||
   wire [15:0] 	  gpif_d_out;
 | 
			
		||||
   assign gpif_d = OE ? gpif_d_out : 16'bz;
 | 
			
		||||
 | 
			
		||||
   wire [15:0] 	  gpif_d_copy = gpif_d;
 | 
			
		||||
 | 
			
		||||
   wire [31:0] 	  debug_rd, debug_wr, debug_split0, debug_split1;
 | 
			
		||||
   
 | 
			
		||||
   // ////////////////////////////////////////////////////////////////////
 | 
			
		||||
   // TX Data Path
 | 
			
		||||
 | 
			
		||||
   wire [18:0] 	  tx19_data;
 | 
			
		||||
   wire 	  tx19_src_rdy, tx19_dst_rdy;
 | 
			
		||||
   wire [35:0] 	  tx36_data;
 | 
			
		||||
   wire 	  tx36_src_rdy, tx36_dst_rdy;
 | 
			
		||||
 | 
			
		||||
   wire [18:0] 	  ctrl_data;
 | 
			
		||||
   wire 	  ctrl_src_rdy, ctrl_dst_rdy;
 | 
			
		||||
   
 | 
			
		||||
   gpif_wr gpif_wr
 | 
			
		||||
     (.gpif_clk(gpif_clk), .gpif_rst(gpif_rst), 
 | 
			
		||||
      .gpif_data(gpif_d), .gpif_wr(WR), .gpif_ep(EP),
 | 
			
		||||
      .gpif_full_d(DF), .gpif_full_c(CF),
 | 
			
		||||
      
 | 
			
		||||
      .sys_clk(fifo_clk), .sys_rst(fifo_rst),
 | 
			
		||||
      .data_o(tx19_data), .src_rdy_o(tx19_src_rdy), .dst_rdy_i(tx19_dst_rdy),
 | 
			
		||||
      .ctrl_o(ctrl_data), .ctrl_src_rdy_o(ctrl_src_rdy), .ctrl_dst_rdy_i(ctrl_dst_rdy),
 | 
			
		||||
      .debug(debug_wr) );
 | 
			
		||||
 | 
			
		||||
   // join vita packets which are longer than one frame, drop frame padding
 | 
			
		||||
   wire [18:0] 	  refr_data;
 | 
			
		||||
   wire 	  refr_src_rdy, refr_dst_rdy;
 | 
			
		||||
   
 | 
			
		||||
   packet_reframer tx_packet_reframer 
 | 
			
		||||
     (.clk(fifo_clk), .reset(fifo_rst), .clear(clear_tx),
 | 
			
		||||
      .data_i(tx19_data), .src_rdy_i(tx19_src_rdy), .dst_rdy_o(tx19_dst_rdy),
 | 
			
		||||
      .data_o(refr_data), .src_rdy_o(refr_src_rdy), .dst_rdy_i(refr_dst_rdy));
 | 
			
		||||
 | 
			
		||||
   fifo19_to_fifo36 #(.LE(1)) f19_to_f36
 | 
			
		||||
     (.clk(fifo_clk), .reset(fifo_rst), .clear(0),
 | 
			
		||||
      .f19_datain(refr_data), .f19_src_rdy_i(refr_src_rdy), .f19_dst_rdy_o(refr_dst_rdy),
 | 
			
		||||
      .f36_dataout(tx36_data), .f36_src_rdy_o(tx36_src_rdy), .f36_dst_rdy_i(tx36_dst_rdy));
 | 
			
		||||
   
 | 
			
		||||
   fifo_cascade #(.WIDTH(36), .SIZE(TXFIFOSIZE)) tx_fifo36
 | 
			
		||||
     (.clk(fifo_clk), .reset(fifo_rst), .clear(clear_tx),
 | 
			
		||||
      .datain(tx36_data), .src_rdy_i(tx36_src_rdy), .dst_rdy_o(tx36_dst_rdy),
 | 
			
		||||
      .dataout(tx_data_o), .src_rdy_o(tx_src_rdy_o), .dst_rdy_i(tx_dst_rdy_i));
 | 
			
		||||
 | 
			
		||||
   // ////////////////////////////////////////////
 | 
			
		||||
   // RX Data Path
 | 
			
		||||
 | 
			
		||||
   wire [35:0] 	  rx36_data;
 | 
			
		||||
   wire 	  rx36_src_rdy, rx36_dst_rdy;
 | 
			
		||||
   wire [18:0] 	  rx19_data, splt_data;
 | 
			
		||||
   wire 	  rx19_src_rdy, rx19_dst_rdy, splt_src_rdy, splt_dst_rdy;
 | 
			
		||||
   wire [18:0] 	  resp_data, resp_int1, resp_int2;
 | 
			
		||||
   wire 	  resp_src_rdy, resp_dst_rdy;
 | 
			
		||||
   wire 	  resp_src_rdy_int1, resp_dst_rdy_int1, resp_src_rdy_int2, resp_dst_rdy_int2;
 | 
			
		||||
   
 | 
			
		||||
   fifo_cascade #(.WIDTH(36), .SIZE(RXFIFOSIZE)) rx_fifo36
 | 
			
		||||
     (.clk(fifo_clk), .reset(fifo_rst), .clear(clear_rx),
 | 
			
		||||
      .datain(rx_data_i), .src_rdy_i(rx_src_rdy_i), .dst_rdy_o(rx_dst_rdy_o),
 | 
			
		||||
      .dataout(rx36_data), .src_rdy_o(rx36_src_rdy), .dst_rdy_i(rx36_dst_rdy));
 | 
			
		||||
 | 
			
		||||
   fifo36_to_fifo19 #(.LE(1)) f36_to_f19
 | 
			
		||||
     (.clk(fifo_clk), .reset(fifo_rst), .clear(clear_rx),
 | 
			
		||||
      .f36_datain(rx36_data), .f36_src_rdy_i(rx36_src_rdy), .f36_dst_rdy_o(rx36_dst_rdy),
 | 
			
		||||
      .f19_dataout(rx19_data), .f19_src_rdy_o(rx19_src_rdy), .f19_dst_rdy_i(rx19_dst_rdy) );
 | 
			
		||||
 | 
			
		||||
   packet_splitter #(.FRAME_LEN(256)) packet_splitter
 | 
			
		||||
     (.clk(fifo_clk), .reset(fifo_rst), .clear(clear_rx),
 | 
			
		||||
      .frames_per_packet(frames_per_packet),
 | 
			
		||||
      .data_i(rx19_data), .src_rdy_i(rx19_src_rdy), .dst_rdy_o(rx19_dst_rdy),
 | 
			
		||||
      .data_o(splt_data), .src_rdy_o(splt_src_rdy), .dst_rdy_i(splt_dst_rdy),
 | 
			
		||||
      .debug0(debug_split0), .debug1(debug_split1));
 | 
			
		||||
     
 | 
			
		||||
   gpif_rd gpif_rd
 | 
			
		||||
     (.gpif_clk(gpif_clk), .gpif_rst(gpif_rst),
 | 
			
		||||
      .gpif_data(gpif_d_out), .gpif_rd(RD), .gpif_ep(EP),
 | 
			
		||||
      .gpif_empty_d(DE), .gpif_empty_c(CE), .gpif_flush(gpif_misc[0]),
 | 
			
		||||
      
 | 
			
		||||
      .sys_clk(fifo_clk), .sys_rst(fifo_rst),
 | 
			
		||||
      .data_i(splt_data), .src_rdy_i(splt_src_rdy), .dst_rdy_o(splt_dst_rdy),
 | 
			
		||||
      .resp_i(resp_data), .resp_src_rdy_i(resp_src_rdy), .resp_dst_rdy_o(resp_dst_rdy),
 | 
			
		||||
      .debug(debug_rd) );
 | 
			
		||||
 | 
			
		||||
   // ////////////////////////////////////////////////////////////////////
 | 
			
		||||
   // FIFO to Wishbone interface
 | 
			
		||||
 | 
			
		||||
   fifo_to_wb fifo_to_wb
 | 
			
		||||
     (.clk(fifo_clk), .reset(fifo_rst), .clear(0),
 | 
			
		||||
      .data_i(ctrl_data), .src_rdy_i(ctrl_src_rdy), .dst_rdy_o(ctrl_dst_rdy),
 | 
			
		||||
      .data_o(resp_int1), .src_rdy_o(resp_src_rdy_int1), .dst_rdy_i(resp_dst_rdy_int1),
 | 
			
		||||
      .wb_adr_o(wb_adr_o), .wb_dat_mosi(wb_dat_mosi), .wb_dat_miso(wb_dat_miso), .wb_sel_o(wb_sel_o), 
 | 
			
		||||
      .wb_cyc_o(wb_cyc_o), .wb_stb_o(wb_stb_o), .wb_we_o(wb_we_o), .wb_ack_i(wb_ack_i),
 | 
			
		||||
      .triggers(triggers),
 | 
			
		||||
      .debug0(), .debug1());
 | 
			
		||||
 | 
			
		||||
   wire [18:0] 	  tx_err19_data;
 | 
			
		||||
   wire 	  tx_err19_src_rdy, tx_err19_dst_rdy;
 | 
			
		||||
   
 | 
			
		||||
   fifo36_to_fifo19 #(.LE(1)) f36_to_f19_txerr
 | 
			
		||||
     (.clk(fifo_clk), .reset(fifo_rst), .clear(clear_rx),
 | 
			
		||||
      .f36_datain(tx_err_data_i), .f36_src_rdy_i(tx_err_src_rdy_i), .f36_dst_rdy_o(tx_err_dst_rdy_o),
 | 
			
		||||
      .f19_dataout(tx_err19_data), .f19_src_rdy_o(tx_err19_src_rdy), .f19_dst_rdy_i(tx_err19_dst_rdy) );
 | 
			
		||||
 | 
			
		||||
   fifo19_mux #(.prio(0)) mux_err_stream
 | 
			
		||||
     (.clk(wb_clk), .reset(wb_rst), .clear(0),
 | 
			
		||||
      .data0_i(resp_int1), .src0_rdy_i(resp_src_rdy_int1), .dst0_rdy_o(resp_dst_rdy_int1),
 | 
			
		||||
      .data1_i(tx_err19_data), .src1_rdy_i(tx_err19_src_rdy), .dst1_rdy_o(tx_err19_dst_rdy),
 | 
			
		||||
      .data_o(resp_int2), .src_rdy_o(resp_src_rdy_int2), .dst_rdy_i(resp_dst_rdy_int2));
 | 
			
		||||
									
 | 
			
		||||
   fifo19_pad #(.LENGTH(16)) fifo19_pad
 | 
			
		||||
     (.clk(fifo_clk), .reset(fifo_rst), .clear(0),
 | 
			
		||||
      .data_i(resp_int2), .src_rdy_i(resp_src_rdy_int2), .dst_rdy_o(resp_dst_rdy_int2),
 | 
			
		||||
      .data_o(resp_data), .src_rdy_o(resp_src_rdy), .dst_rdy_i(resp_dst_rdy));
 | 
			
		||||
        
 | 
			
		||||
   // ////////////////////////////////////////////
 | 
			
		||||
   //    DEBUG
 | 
			
		||||
   
 | 
			
		||||
   //assign debug0 = { rx19_src_rdy, rx19_dst_rdy, resp_src_rdy, resp_dst_rdy, gpif_ctl[3:0], gpif_rdy[3:0], 
 | 
			
		||||
	//	     gpif_d_copy[15:0] };
 | 
			
		||||
   
 | 
			
		||||
   //assign debug1 = { { debug_rd[15:8] },
 | 
			
		||||
	//	     { debug_rd[7:0] },
 | 
			
		||||
		//     { rx_src_rdy_i, rx_dst_rdy_o, rx36_src_rdy, rx36_dst_rdy, rx19_src_rdy, rx19_dst_rdy, resp_src_rdy, resp_dst_rdy},
 | 
			
		||||
		  //   { tx_src_rdy_o, tx_dst_rdy_i, tx19_src_rdy, tx19_dst_rdy, tx36_src_rdy, tx36_dst_rdy, ctrl_src_rdy, ctrl_dst_rdy} };
 | 
			
		||||
   
 | 
			
		||||
   assign debug0 = { gpif_ctl[3:0], gpif_rdy[3:0], debug_split0[23:0] };
 | 
			
		||||
   assign debug1 = { gpif_misc[0], debug_rd[14:0], debug_split1[15:8], debug_split1[7:0] };
 | 
			
		||||
endmodule // gpif
 | 
			
		||||
@@ -1,111 +0,0 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2011 Ettus Research LLC
 | 
			
		||||
//
 | 
			
		||||
// This program is free software: you can redistribute it and/or modify
 | 
			
		||||
// it under the terms of the GNU General Public License as published by
 | 
			
		||||
// the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
// (at your option) any later version.
 | 
			
		||||
//
 | 
			
		||||
// This program is distributed in the hope that it will be useful,
 | 
			
		||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
// GNU General Public License for more details.
 | 
			
		||||
//
 | 
			
		||||
// You should have received a copy of the GNU General Public License
 | 
			
		||||
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
module gpif_rd
 | 
			
		||||
  (input gpif_clk, input gpif_rst,
 | 
			
		||||
   output [15:0] gpif_data, input gpif_rd, input gpif_ep,
 | 
			
		||||
   output reg gpif_empty_d, output reg gpif_empty_c,
 | 
			
		||||
   output reg gpif_flush,
 | 
			
		||||
   
 | 
			
		||||
   input sys_clk, input sys_rst,
 | 
			
		||||
   input [18:0] data_i, input src_rdy_i, output dst_rdy_o,
 | 
			
		||||
   input [18:0] resp_i, input resp_src_rdy_i, output resp_dst_rdy_o,
 | 
			
		||||
   output [31:0] debug
 | 
			
		||||
   );
 | 
			
		||||
   
 | 
			
		||||
   wire [18:0] 	 data_o; // occ bit indicates flush
 | 
			
		||||
   wire [17:0] 	 resp_o; // no occ bit
 | 
			
		||||
   wire 	 final_rdy_data, final_rdy_resp;
 | 
			
		||||
   
 | 
			
		||||
   // 33/257 Bug Fix
 | 
			
		||||
   reg [8:0] 	read_count;
 | 
			
		||||
   always @(negedge gpif_clk)
 | 
			
		||||
     if(gpif_rst)
 | 
			
		||||
       read_count <= 0;
 | 
			
		||||
     else if(gpif_rd)
 | 
			
		||||
       read_count <= read_count + 1;
 | 
			
		||||
     else
 | 
			
		||||
       read_count <= 0;
 | 
			
		||||
 | 
			
		||||
   // Data Path
 | 
			
		||||
   wire [18:0] 	data_int;
 | 
			
		||||
   wire 	src_rdy_int, dst_rdy_int;
 | 
			
		||||
   fifo_2clock_cascade #(.WIDTH(19), .SIZE(4)) rd_fifo_2clk
 | 
			
		||||
     (.wclk(sys_clk), .datain(data_i[18:0]), .src_rdy_i(src_rdy_i), .dst_rdy_o(dst_rdy_o), .space(),
 | 
			
		||||
      .rclk(~gpif_clk), .dataout(data_int), .src_rdy_o(src_rdy_int), .dst_rdy_i(dst_rdy_int), .occupied(),
 | 
			
		||||
      .arst(sys_rst));
 | 
			
		||||
 | 
			
		||||
   reg [7:0] 	packet_count;
 | 
			
		||||
   wire 	consume_data_line = gpif_rd & ~gpif_ep & ~read_count[8];
 | 
			
		||||
   wire 	produce_eop = src_rdy_int & dst_rdy_int & data_int[17];
 | 
			
		||||
   wire 	consume_sop = consume_data_line & final_rdy_data & data_o[16];
 | 
			
		||||
   wire 	consume_eop = consume_data_line & final_rdy_data & data_o[17];
 | 
			
		||||
   
 | 
			
		||||
   fifo_cascade #(.WIDTH(19), .SIZE(10)) rd_fifo
 | 
			
		||||
     (.clk(~gpif_clk), .reset(gpif_rst), .clear(0),
 | 
			
		||||
      .datain(data_int), .src_rdy_i(src_rdy_int), .dst_rdy_o(dst_rdy_int), .space(),
 | 
			
		||||
      .dataout(data_o), .src_rdy_o(final_rdy_data), .dst_rdy_i(consume_data_line), .occupied());
 | 
			
		||||
 | 
			
		||||
   always @(negedge gpif_clk)
 | 
			
		||||
     if(gpif_rst)
 | 
			
		||||
       packet_count <= 0;
 | 
			
		||||
     else
 | 
			
		||||
       if(produce_eop & ~consume_sop)
 | 
			
		||||
	 packet_count <= packet_count + 1;
 | 
			
		||||
       else if(consume_sop & ~produce_eop)
 | 
			
		||||
	 packet_count <= packet_count - 1;
 | 
			
		||||
 | 
			
		||||
   always @(negedge gpif_clk)
 | 
			
		||||
     if(gpif_rst)
 | 
			
		||||
       gpif_empty_d <= 1;
 | 
			
		||||
     else
 | 
			
		||||
       gpif_empty_d <= ~|packet_count;
 | 
			
		||||
 | 
			
		||||
   // Use occ bit to signal a gpif flush
 | 
			
		||||
   always @(negedge gpif_clk)
 | 
			
		||||
     if(gpif_rst)
 | 
			
		||||
       gpif_flush <= 0;
 | 
			
		||||
     else if(consume_eop & data_o[18])
 | 
			
		||||
       gpif_flush <= ~gpif_flush;
 | 
			
		||||
   
 | 
			
		||||
   // Response Path
 | 
			
		||||
   wire [15:0] 	resp_fifolevel;
 | 
			
		||||
   wire 	consume_resp_line = gpif_rd & gpif_ep & ~read_count[4];
 | 
			
		||||
 | 
			
		||||
   fifo_2clock_cascade #(.WIDTH(18), .SIZE(4)) resp_fifo_2clk
 | 
			
		||||
     (.wclk(sys_clk), .datain(resp_i[17:0]), .src_rdy_i(resp_src_rdy_i), .dst_rdy_o(resp_dst_rdy_o), .space(),
 | 
			
		||||
      .rclk(~gpif_clk), .dataout(resp_o), 
 | 
			
		||||
      .src_rdy_o(final_rdy_resp), .dst_rdy_i(consume_resp_line), .occupied(resp_fifolevel),
 | 
			
		||||
      .arst(sys_rst));
 | 
			
		||||
 | 
			
		||||
   // FIXME -- handle short packets
 | 
			
		||||
   
 | 
			
		||||
   always @(negedge gpif_clk)
 | 
			
		||||
     if(gpif_rst)
 | 
			
		||||
       gpif_empty_c <= 1;
 | 
			
		||||
     else
 | 
			
		||||
       gpif_empty_c <= resp_fifolevel < 16;
 | 
			
		||||
   
 | 
			
		||||
   // Output Mux
 | 
			
		||||
   assign gpif_data = gpif_ep ? resp_o[15:0] : data_o[15:0];
 | 
			
		||||
 | 
			
		||||
   assign debug = { { 16'd0 },
 | 
			
		||||
		    { data_int[17:16], data_o[17:16], packet_count[3:0] },
 | 
			
		||||
		    { consume_sop, consume_eop, final_rdy_data, data_o[18], consume_data_line, consume_resp_line, src_rdy_int, dst_rdy_int} };
 | 
			
		||||
   
 | 
			
		||||
endmodule // gpif_rd
 | 
			
		||||
@@ -1,142 +0,0 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2011 Ettus Research LLC
 | 
			
		||||
//
 | 
			
		||||
// This program is free software: you can redistribute it and/or modify
 | 
			
		||||
// it under the terms of the GNU General Public License as published by
 | 
			
		||||
// the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
// (at your option) any later version.
 | 
			
		||||
//
 | 
			
		||||
// This program is distributed in the hope that it will be useful,
 | 
			
		||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
// GNU General Public License for more details.
 | 
			
		||||
//
 | 
			
		||||
// You should have received a copy of the GNU General Public License
 | 
			
		||||
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
module gpif_tb();
 | 
			
		||||
   
 | 
			
		||||
   reg sys_clk = 0;
 | 
			
		||||
   reg sys_rst = 1;
 | 
			
		||||
   reg gpif_clk = 0;
 | 
			
		||||
   reg gpif_rst = 1;
 | 
			
		||||
      
 | 
			
		||||
   reg [15:0] gpif_data;
 | 
			
		||||
   reg 	      WR = 0, EP = 0;
 | 
			
		||||
 | 
			
		||||
   wire       CF, DF;
 | 
			
		||||
   
 | 
			
		||||
   wire       gpif_full_d, gpif_full_c;
 | 
			
		||||
   wire [18:0] data_o, ctrl_o, data_splt;
 | 
			
		||||
   wire        src_rdy, dst_rdy, src_rdy_splt, dst_rdy_splt;
 | 
			
		||||
   wire        ctrl_src_rdy, ctrl_dst_rdy;
 | 
			
		||||
 | 
			
		||||
   assign ctrl_dst_rdy = 1;
 | 
			
		||||
   
 | 
			
		||||
   initial $dumpfile("gpif_tb.vcd");
 | 
			
		||||
   initial $dumpvars(0,gpif_tb);
 | 
			
		||||
 | 
			
		||||
   initial #1000 gpif_rst = 0;
 | 
			
		||||
   initial #1000 sys_rst = 0;
 | 
			
		||||
   always #64 gpif_clk <= ~gpif_clk;
 | 
			
		||||
   always #47.9 sys_clk <= ~sys_clk;
 | 
			
		||||
 | 
			
		||||
   wire [18:0] data_int;
 | 
			
		||||
   wire        src_rdy_int, dst_rdy_int;
 | 
			
		||||
 | 
			
		||||
   assign dst_rdy_splt = 1;
 | 
			
		||||
   
 | 
			
		||||
   gpif_wr gpif_write
 | 
			
		||||
     (.gpif_clk(gpif_clk), .gpif_rst(gpif_rst), 
 | 
			
		||||
      .gpif_data(gpif_data), .gpif_wr(WR), .gpif_ep(EP),
 | 
			
		||||
      .gpif_full_d(DF), .gpif_full_c(CF),
 | 
			
		||||
      
 | 
			
		||||
      .sys_clk(sys_clk), .sys_rst(sys_rst),
 | 
			
		||||
      .data_o(data_int), .src_rdy_o(src_rdy_int), .dst_rdy_i(dst_rdy_int),
 | 
			
		||||
      .ctrl_o(ctrl_o), .ctrl_src_rdy_o(ctrl_src_rdy), .ctrl_dst_rdy_i(ctrl_dst_rdy) );
 | 
			
		||||
 | 
			
		||||
   packet_reframer tx_packet_reframer 
 | 
			
		||||
     (.clk(sys_clk), .reset(sys_rst), .clear(0),
 | 
			
		||||
      .data_i(data_int), .src_rdy_i(src_rdy_int), .dst_rdy_o(dst_rdy_int),
 | 
			
		||||
      .data_o(data_o), .src_rdy_o(src_rdy), .dst_rdy_i(dst_rdy));
 | 
			
		||||
 | 
			
		||||
   packet_splitter #(.FRAME_LEN(256)) rx_packet_splitter
 | 
			
		||||
     (.clk(sys_clk), .reset(sys_rst), .clear(0),
 | 
			
		||||
      .frames_per_packet(2),
 | 
			
		||||
      .data_i(data_o), .src_rdy_i(src_rdy), .dst_rdy_o(dst_rdy),
 | 
			
		||||
      .data_o(data_splt), .src_rdy_o(src_rdy_splt), .dst_rdy_i(dst_rdy_splt));
 | 
			
		||||
 | 
			
		||||
   always @(posedge sys_clk)
 | 
			
		||||
     if(ctrl_src_rdy & ctrl_dst_rdy)
 | 
			
		||||
       $display("CTRL: %x",ctrl_o);
 | 
			
		||||
 | 
			
		||||
   always @(posedge sys_clk)
 | 
			
		||||
     if(src_rdy_splt & dst_rdy_splt)
 | 
			
		||||
       begin
 | 
			
		||||
	  if(data_splt[16])
 | 
			
		||||
	    $display("<-------- DATA SOF--------->");
 | 
			
		||||
	  $display("DATA: %x",data_splt);
 | 
			
		||||
	  if(data_splt[17])
 | 
			
		||||
	    $display("<-------- DATA EOF--------->");
 | 
			
		||||
       end
 | 
			
		||||
   
 | 
			
		||||
   initial
 | 
			
		||||
     begin
 | 
			
		||||
	#10000;
 | 
			
		||||
	repeat (1)
 | 
			
		||||
	  begin
 | 
			
		||||
	     @(posedge gpif_clk);
 | 
			
		||||
	     
 | 
			
		||||
	     WR <= 1;
 | 
			
		||||
	     gpif_data <= 256;  // Length
 | 
			
		||||
	     @(posedge gpif_clk);
 | 
			
		||||
	     gpif_data <= 16'h00;
 | 
			
		||||
	     @(posedge gpif_clk);
 | 
			
		||||
	     repeat(254)
 | 
			
		||||
	       begin
 | 
			
		||||
		  gpif_data <= gpif_data + 1;
 | 
			
		||||
		  @(posedge gpif_clk);
 | 
			
		||||
	       end
 | 
			
		||||
	     WR <= 0;
 | 
			
		||||
 | 
			
		||||
	     while(DF)
 | 
			
		||||
	       @(posedge gpif_clk);
 | 
			
		||||
	     repeat (16)
 | 
			
		||||
	       @(posedge gpif_clk);
 | 
			
		||||
	     
 | 
			
		||||
	     WR <= 1;
 | 
			
		||||
	     repeat(256)
 | 
			
		||||
	       begin
 | 
			
		||||
		  gpif_data <= gpif_data - 1;
 | 
			
		||||
		  @(posedge gpif_clk);
 | 
			
		||||
	       end
 | 
			
		||||
	     WR <= 0;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
	     while(DF)
 | 
			
		||||
	       @(posedge gpif_clk);
 | 
			
		||||
	     	     
 | 
			
		||||
	     repeat (20)
 | 
			
		||||
	       @(posedge gpif_clk);
 | 
			
		||||
	     WR <= 1;
 | 
			
		||||
	     gpif_data <= 16'h5;
 | 
			
		||||
	     @(posedge gpif_clk);
 | 
			
		||||
	     gpif_data <= 16'h00;
 | 
			
		||||
	     @(posedge gpif_clk);
 | 
			
		||||
	     repeat(254)
 | 
			
		||||
	       begin
 | 
			
		||||
		  gpif_data <= gpif_data - 1;
 | 
			
		||||
		  @(posedge gpif_clk);
 | 
			
		||||
	       end
 | 
			
		||||
	     WR <= 0;
 | 
			
		||||
 */
 | 
			
		||||
	  end
 | 
			
		||||
     end // initial begin
 | 
			
		||||
   
 | 
			
		||||
   initial #200000 $finish;
 | 
			
		||||
   
 | 
			
		||||
     
 | 
			
		||||
endmodule // gpif_tb
 | 
			
		||||
@@ -1,95 +0,0 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2011 Ettus Research LLC
 | 
			
		||||
//
 | 
			
		||||
// This program is free software: you can redistribute it and/or modify
 | 
			
		||||
// it under the terms of the GNU General Public License as published by
 | 
			
		||||
// the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
// (at your option) any later version.
 | 
			
		||||
//
 | 
			
		||||
// This program is distributed in the hope that it will be useful,
 | 
			
		||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
// GNU General Public License for more details.
 | 
			
		||||
//
 | 
			
		||||
// You should have received a copy of the GNU General Public License
 | 
			
		||||
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
module gpif_wr
 | 
			
		||||
  (input gpif_clk, input gpif_rst,
 | 
			
		||||
   input [15:0] gpif_data, input gpif_wr, input gpif_ep,
 | 
			
		||||
   output reg gpif_full_d, output reg gpif_full_c,
 | 
			
		||||
 | 
			
		||||
   input sys_clk, input sys_rst,
 | 
			
		||||
   output [18:0] data_o, output src_rdy_o, input dst_rdy_i,
 | 
			
		||||
   output [18:0] ctrl_o, output ctrl_src_rdy_o, input ctrl_dst_rdy_i,
 | 
			
		||||
   output [31:0] debug );
 | 
			
		||||
 | 
			
		||||
   reg 		 wr_reg, ep_reg;
 | 
			
		||||
   reg [15:0] 	 gpif_data_reg;
 | 
			
		||||
   
 | 
			
		||||
   always @(posedge gpif_clk)
 | 
			
		||||
     begin
 | 
			
		||||
	ep_reg <= gpif_ep;
 | 
			
		||||
	wr_reg <= gpif_wr;
 | 
			
		||||
	gpif_data_reg <= gpif_data;
 | 
			
		||||
     end
 | 
			
		||||
 | 
			
		||||
   reg [9:0] write_count;
 | 
			
		||||
   
 | 
			
		||||
   always @(posedge gpif_clk)
 | 
			
		||||
     if(gpif_rst)
 | 
			
		||||
       write_count <= 0;
 | 
			
		||||
     else if(wr_reg)
 | 
			
		||||
       write_count <= write_count + 1;
 | 
			
		||||
     else
 | 
			
		||||
       write_count <= 0;
 | 
			
		||||
 | 
			
		||||
   reg 	     sop;
 | 
			
		||||
   wire      eop = (write_count == 255);
 | 
			
		||||
   wire      eop_ctrl = (write_count == 15);
 | 
			
		||||
   
 | 
			
		||||
   always @(posedge gpif_clk)
 | 
			
		||||
     sop <= gpif_wr & ~wr_reg;
 | 
			
		||||
 | 
			
		||||
   // Data Path
 | 
			
		||||
   wire [15:0] fifo_space;
 | 
			
		||||
   always @(posedge gpif_clk)
 | 
			
		||||
     if(gpif_rst)
 | 
			
		||||
       gpif_full_d <= 1;
 | 
			
		||||
     else
 | 
			
		||||
       gpif_full_d <= fifo_space < 256;
 | 
			
		||||
 | 
			
		||||
   wire [17:0] data_int;
 | 
			
		||||
   wire        src_rdy_int, dst_rdy_int;
 | 
			
		||||
 | 
			
		||||
   fifo_cascade #(.WIDTH(18), .SIZE(10)) wr_fifo
 | 
			
		||||
     (.clk(gpif_clk), .reset(gpif_rst), .clear(0),
 | 
			
		||||
      .datain({eop,sop,gpif_data_reg}), .src_rdy_i(~ep_reg & wr_reg & ~write_count[8]), .dst_rdy_o(), .space(fifo_space),
 | 
			
		||||
      .dataout(data_int), .src_rdy_o(src_rdy_int), .dst_rdy_i(dst_rdy_int), .occupied());
 | 
			
		||||
   
 | 
			
		||||
   fifo_2clock_cascade #(.WIDTH(18), .SIZE(4)) wr_fifo_2clk
 | 
			
		||||
     (.wclk(gpif_clk), .datain(data_int), .src_rdy_i(src_rdy_int), .dst_rdy_o(dst_rdy_int), .space(),
 | 
			
		||||
      .rclk(sys_clk), .dataout(data_o[17:0]), .src_rdy_o(src_rdy_o), .dst_rdy_i(dst_rdy_i), .occupied(),
 | 
			
		||||
      .arst(sys_rst));
 | 
			
		||||
   assign data_o[18] = 1'b0;
 | 
			
		||||
   
 | 
			
		||||
   // Control Path
 | 
			
		||||
   wire [15:0] ctrl_fifo_space;
 | 
			
		||||
   always @(posedge gpif_clk)
 | 
			
		||||
     if(gpif_rst)
 | 
			
		||||
       gpif_full_c <= 1;
 | 
			
		||||
     else
 | 
			
		||||
       gpif_full_c <= ctrl_fifo_space < 16;
 | 
			
		||||
   
 | 
			
		||||
   fifo_2clock_cascade #(.WIDTH(19), .SIZE(4)) ctrl_fifo_2clk
 | 
			
		||||
     (.wclk(gpif_clk), .datain({1'b0,eop_ctrl,sop,gpif_data_reg}), 
 | 
			
		||||
      .src_rdy_i(ep_reg & wr_reg & ~write_count[4]), .dst_rdy_o(), .space(ctrl_fifo_space),
 | 
			
		||||
      .rclk(sys_clk), .dataout(ctrl_o[18:0]), 
 | 
			
		||||
      .src_rdy_o(ctrl_src_rdy_o), .dst_rdy_i(ctrl_dst_rdy_i), .occupied(),
 | 
			
		||||
      .arst(sys_rst));
 | 
			
		||||
 | 
			
		||||
   assign debug = { 16'd0, ep_reg, wr_reg, eop, sop, (~ep_reg & wr_reg & ~write_count[8]), src_rdy_int, dst_rdy_int, write_count[8:0]};
 | 
			
		||||
   
 | 
			
		||||
endmodule // gpif_wr
 | 
			
		||||
@@ -1,110 +0,0 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2011 Ettus Research LLC
 | 
			
		||||
//
 | 
			
		||||
// This program is free software: you can redistribute it and/or modify
 | 
			
		||||
// it under the terms of the GNU General Public License as published by
 | 
			
		||||
// the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
// (at your option) any later version.
 | 
			
		||||
//
 | 
			
		||||
// This program is distributed in the hope that it will be useful,
 | 
			
		||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
// GNU General Public License for more details.
 | 
			
		||||
//
 | 
			
		||||
// You should have received a copy of the GNU General Public License
 | 
			
		||||
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
module gpif_wr_tb();
 | 
			
		||||
   
 | 
			
		||||
   reg sys_clk = 0;
 | 
			
		||||
   reg sys_rst = 1;
 | 
			
		||||
   reg gpif_clk = 0;
 | 
			
		||||
   reg gpif_rst = 1;
 | 
			
		||||
      
 | 
			
		||||
   reg [15:0] gpif_data;
 | 
			
		||||
   reg 	      WR = 0, EP = 0;
 | 
			
		||||
 | 
			
		||||
   wire       CF, DF;
 | 
			
		||||
   
 | 
			
		||||
   wire       gpif_full_d, gpif_full_c;
 | 
			
		||||
   wire [18:0] data_o, ctrl_o;
 | 
			
		||||
   wire        src_rdy, dst_rdy;
 | 
			
		||||
   wire        ctrl_src_rdy, ctrl_dst_rdy;
 | 
			
		||||
 | 
			
		||||
   assign ctrl_dst_rdy = 1;
 | 
			
		||||
   assign dst_rdy = 1;
 | 
			
		||||
   
 | 
			
		||||
   initial $dumpfile("gpif_wr_tb.vcd");
 | 
			
		||||
   initial $dumpvars(0,gpif_wr_tb);
 | 
			
		||||
 | 
			
		||||
   initial #1000 gpif_rst = 0;
 | 
			
		||||
   initial #1000 sys_rst = 0;
 | 
			
		||||
   always #64 gpif_clk <= ~gpif_clk;
 | 
			
		||||
   always #47.9 sys_clk <= ~sys_clk;
 | 
			
		||||
 | 
			
		||||
   wire [18:0] data_int;
 | 
			
		||||
   wire        src_rdy_int, dst_rdy_int;
 | 
			
		||||
   
 | 
			
		||||
   gpif_wr gpif_write
 | 
			
		||||
     (.gpif_clk(gpif_clk), .gpif_rst(gpif_rst), 
 | 
			
		||||
      .gpif_data(gpif_data), .gpif_wr(WR), .gpif_ep(EP),
 | 
			
		||||
      .gpif_full_d(DF), .gpif_full_c(CF),
 | 
			
		||||
      
 | 
			
		||||
      .sys_clk(sys_clk), .sys_rst(sys_rst),
 | 
			
		||||
      .data_o(data_int), .src_rdy_o(src_rdy_int), .dst_rdy_i(dst_rdy_int),
 | 
			
		||||
      .ctrl_o(ctrl_o), .ctrl_src_rdy_o(ctrl_src_rdy), .ctrl_dst_rdy_i(ctrl_dst_rdy) );
 | 
			
		||||
 | 
			
		||||
   packet_reframer tx_packet_reframer 
 | 
			
		||||
     (.clk(sys_clk), .reset(sys_rst), .clear(0),
 | 
			
		||||
      .data_i(data_int), .src_rdy_i(src_rdy_int), .dst_rdy_o(dst_rdy_int),
 | 
			
		||||
      .data_o(data_o), .src_rdy_o(src_rdy), .dst_rdy_i(dst_rdy));
 | 
			
		||||
 | 
			
		||||
   always @(posedge sys_clk)
 | 
			
		||||
     if(ctrl_src_rdy & ctrl_dst_rdy)
 | 
			
		||||
       $display("CTRL: %x",ctrl_o);
 | 
			
		||||
 | 
			
		||||
   always @(posedge sys_clk)
 | 
			
		||||
     if(src_rdy & dst_rdy)
 | 
			
		||||
       begin
 | 
			
		||||
	  if(data_o[16])
 | 
			
		||||
	    $display("<-------- DATA SOF--------->");
 | 
			
		||||
	  $display("DATA: %x",data_o);
 | 
			
		||||
	  if(data_o[17])
 | 
			
		||||
	    $display("<-------- DATA EOF--------->");
 | 
			
		||||
       end
 | 
			
		||||
   
 | 
			
		||||
   initial
 | 
			
		||||
     begin
 | 
			
		||||
	#10000;
 | 
			
		||||
	repeat (1)
 | 
			
		||||
	  begin
 | 
			
		||||
	     WR <= 1;
 | 
			
		||||
	     gpif_data <= 10;  // Length
 | 
			
		||||
	     @(posedge gpif_clk);
 | 
			
		||||
	     gpif_data <= 16'h00;
 | 
			
		||||
	     @(posedge gpif_clk);
 | 
			
		||||
	     repeat(254)
 | 
			
		||||
	       begin
 | 
			
		||||
		  gpif_data <= gpif_data + 1;
 | 
			
		||||
		  @(posedge gpif_clk);
 | 
			
		||||
	       end
 | 
			
		||||
	     WR <= 0;
 | 
			
		||||
	     repeat (20)
 | 
			
		||||
	       @(posedge gpif_clk);
 | 
			
		||||
	     WR <= 1;
 | 
			
		||||
	     gpif_data <= 16'h5;
 | 
			
		||||
	     @(posedge gpif_clk);
 | 
			
		||||
	     repeat(254)
 | 
			
		||||
	       begin
 | 
			
		||||
		  gpif_data <= gpif_data - 1;
 | 
			
		||||
		  @(posedge gpif_clk);
 | 
			
		||||
	       end
 | 
			
		||||
	  end
 | 
			
		||||
     end // initial begin
 | 
			
		||||
   
 | 
			
		||||
   initial #100000 $finish;
 | 
			
		||||
   
 | 
			
		||||
     
 | 
			
		||||
endmodule // gpif_wr_tb
 | 
			
		||||
@@ -1,2 +0,0 @@
 | 
			
		||||
iverilog -Wall -y . -y ../fifo/ -y ../control_lib/ -y ../models/ -y ../coregen/ -y ../simple_gemac/ -y ../sdr_lib/ -y ../vrt/ gpif.v 2>&1 | grep -v coregen | grep -v models
 | 
			
		||||
 | 
			
		||||
@@ -1,79 +0,0 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2011 Ettus Research LLC
 | 
			
		||||
//
 | 
			
		||||
// This program is free software: you can redistribute it and/or modify
 | 
			
		||||
// it under the terms of the GNU General Public License as published by
 | 
			
		||||
// the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
// (at your option) any later version.
 | 
			
		||||
//
 | 
			
		||||
// This program is distributed in the hope that it will be useful,
 | 
			
		||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
// GNU General Public License for more details.
 | 
			
		||||
//
 | 
			
		||||
// You should have received a copy of the GNU General Public License
 | 
			
		||||
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Join vita packets longer than one GPIF frame, drop padding on short frames
 | 
			
		||||
 | 
			
		||||
module packet_reframer
 | 
			
		||||
  (input clk, input reset, input clear,
 | 
			
		||||
   input [18:0] data_i,
 | 
			
		||||
   input src_rdy_i,
 | 
			
		||||
   output dst_rdy_o,
 | 
			
		||||
   output [18:0] data_o,
 | 
			
		||||
   output src_rdy_o,
 | 
			
		||||
   input dst_rdy_i);
 | 
			
		||||
 | 
			
		||||
   reg [1:0] state;
 | 
			
		||||
   reg [15:0] length;
 | 
			
		||||
   
 | 
			
		||||
   localparam RF_IDLE = 0;
 | 
			
		||||
   localparam RF_PKT = 1;
 | 
			
		||||
   localparam RF_DUMP = 2;
 | 
			
		||||
   
 | 
			
		||||
   always @(posedge clk)
 | 
			
		||||
     if(reset | clear)
 | 
			
		||||
       state <= 0;
 | 
			
		||||
     else
 | 
			
		||||
       if(src_rdy_i & dst_rdy_i)
 | 
			
		||||
	 case(state)
 | 
			
		||||
	   RF_IDLE :
 | 
			
		||||
	     begin
 | 
			
		||||
		length <= {data_i[14:0],1'b0};
 | 
			
		||||
		state <= RF_PKT;
 | 
			
		||||
	     end
 | 
			
		||||
	   RF_PKT :
 | 
			
		||||
	     begin
 | 
			
		||||
		if(length == 2)
 | 
			
		||||
		  if(data_i[17])
 | 
			
		||||
		    state <= RF_IDLE;
 | 
			
		||||
		  else
 | 
			
		||||
		    state <= RF_DUMP;
 | 
			
		||||
		else
 | 
			
		||||
		  length <= length - 1;
 | 
			
		||||
	     end
 | 
			
		||||
	   RF_DUMP :
 | 
			
		||||
	     if(data_i[17])
 | 
			
		||||
	       state <= RF_IDLE;
 | 
			
		||||
	   default :
 | 
			
		||||
	     state<= RF_IDLE;
 | 
			
		||||
	 endcase // case (state)
 | 
			
		||||
   
 | 
			
		||||
   assign dst_rdy_o = dst_rdy_i; // this is a little pessimistic but ok
 | 
			
		||||
   assign src_rdy_o = src_rdy_i & (state != RF_DUMP);
 | 
			
		||||
   
 | 
			
		||||
   wire occ_out = 0;
 | 
			
		||||
   wire eof_out = (state == RF_PKT) & (length == 2);
 | 
			
		||||
   wire sof_out = (state == RF_IDLE);
 | 
			
		||||
   wire [15:0] data_out = data_i[15:0];
 | 
			
		||||
   assign data_o = {occ_out, eof_out, sof_out, data_out};
 | 
			
		||||
   
 | 
			
		||||
      
 | 
			
		||||
endmodule // packet_reframer
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -1,123 +0,0 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2011 Ettus Research LLC
 | 
			
		||||
//
 | 
			
		||||
// This program is free software: you can redistribute it and/or modify
 | 
			
		||||
// it under the terms of the GNU General Public License as published by
 | 
			
		||||
// the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
// (at your option) any later version.
 | 
			
		||||
//
 | 
			
		||||
// This program is distributed in the hope that it will be useful,
 | 
			
		||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
// GNU General Public License for more details.
 | 
			
		||||
//
 | 
			
		||||
// You should have received a copy of the GNU General Public License
 | 
			
		||||
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Split vita packets longer than one GPIF frame, add padding on short frames
 | 
			
		||||
 | 
			
		||||
module packet_splitter
 | 
			
		||||
  #(parameter FRAME_LEN=256)
 | 
			
		||||
   (input clk, input reset, input clear,
 | 
			
		||||
    input  [7:0] frames_per_packet,
 | 
			
		||||
    input [18:0] data_i,
 | 
			
		||||
    input src_rdy_i,
 | 
			
		||||
    output dst_rdy_o,
 | 
			
		||||
    output [18:0] data_o,
 | 
			
		||||
    output src_rdy_o,
 | 
			
		||||
    input dst_rdy_i,
 | 
			
		||||
    output [31:0] debug0,
 | 
			
		||||
    output [31:0] debug1);
 | 
			
		||||
   
 | 
			
		||||
   reg [1:0] state;
 | 
			
		||||
   reg [15:0] length;
 | 
			
		||||
   reg [15:0] frame_len;
 | 
			
		||||
   reg [7:0]  frame_count;
 | 
			
		||||
   
 | 
			
		||||
   localparam PS_IDLE = 0;
 | 
			
		||||
   localparam PS_FRAME = 1;
 | 
			
		||||
   localparam PS_NEW_FRAME = 2;
 | 
			
		||||
   localparam PS_PAD = 3;
 | 
			
		||||
 | 
			
		||||
   wire       eof_i = data_i[17];
 | 
			
		||||
   
 | 
			
		||||
   always @(posedge clk)
 | 
			
		||||
     if(reset | clear)
 | 
			
		||||
       begin
 | 
			
		||||
	  state <= PS_IDLE;
 | 
			
		||||
	  frame_count <= 0;
 | 
			
		||||
       end
 | 
			
		||||
     else
 | 
			
		||||
       case(state)
 | 
			
		||||
	 PS_IDLE :
 | 
			
		||||
	   if(src_rdy_i & dst_rdy_i)
 | 
			
		||||
	     begin
 | 
			
		||||
		length <= { data_i[14:0],1'b0};
 | 
			
		||||
		frame_len <= FRAME_LEN;
 | 
			
		||||
		state <= PS_FRAME;
 | 
			
		||||
		frame_count <= 1;
 | 
			
		||||
	     end
 | 
			
		||||
	 PS_FRAME :
 | 
			
		||||
	   if(src_rdy_i & dst_rdy_i)
 | 
			
		||||
	     if((frame_len == 2) & ((length == 2) | eof_i))
 | 
			
		||||
	       state <= PS_IDLE;
 | 
			
		||||
	     else if(frame_len == 2)
 | 
			
		||||
	       begin
 | 
			
		||||
		  length <= length - 1;
 | 
			
		||||
		  state <= PS_NEW_FRAME;
 | 
			
		||||
		  frame_count <= frame_count + 1;
 | 
			
		||||
	       end
 | 
			
		||||
	     else if((length == 2)|eof_i)
 | 
			
		||||
	       begin
 | 
			
		||||
		  frame_len <= frame_len - 1;
 | 
			
		||||
		  state <= PS_PAD;
 | 
			
		||||
	       end
 | 
			
		||||
	     else
 | 
			
		||||
	       begin
 | 
			
		||||
		  frame_len <= frame_len - 1;
 | 
			
		||||
		  length <= length - 1;
 | 
			
		||||
	       end
 | 
			
		||||
	 PS_NEW_FRAME :
 | 
			
		||||
	   if(src_rdy_i & dst_rdy_i)
 | 
			
		||||
	     begin
 | 
			
		||||
		frame_len <= FRAME_LEN;
 | 
			
		||||
		if((length == 2)|eof_i)
 | 
			
		||||
		  state <= PS_PAD;
 | 
			
		||||
		else
 | 
			
		||||
		  begin
 | 
			
		||||
		     state <= PS_FRAME;
 | 
			
		||||
		     length <= length - 1;
 | 
			
		||||
		  end // else: !if((length == 2)|eof_i)
 | 
			
		||||
	     end // if (src_rdy_i & dst_rdy_i)
 | 
			
		||||
	 
 | 
			
		||||
	 PS_PAD :
 | 
			
		||||
	   if(dst_rdy_i)
 | 
			
		||||
	     if(frame_len == 2)
 | 
			
		||||
	       state <= PS_IDLE;
 | 
			
		||||
	     else
 | 
			
		||||
	       frame_len <= frame_len - 1;
 | 
			
		||||
 | 
			
		||||
       endcase // case (state)
 | 
			
		||||
 | 
			
		||||
   wire next_state_is_idle = dst_rdy_i & (frame_len==2) & 
 | 
			
		||||
	( (state==PS_PAD) | ( (state==PS_FRAME) & src_rdy_i & ((length==2)|eof_i) ) );
 | 
			
		||||
	  
 | 
			
		||||
	 
 | 
			
		||||
	
 | 
			
		||||
   
 | 
			
		||||
   assign dst_rdy_o = dst_rdy_i & (state != PS_PAD);
 | 
			
		||||
   assign src_rdy_o = src_rdy_i | (state == PS_PAD);
 | 
			
		||||
   
 | 
			
		||||
   wire eof_out = (frame_len == 2) & (state != PS_IDLE) & (state != PS_NEW_FRAME);
 | 
			
		||||
   wire sof_out = (state == PS_IDLE) | (state == PS_NEW_FRAME);
 | 
			
		||||
   wire occ_out = eof_out & next_state_is_idle & (frames_per_packet != frame_count);
 | 
			
		||||
   
 | 
			
		||||
   wire [15:0] data_out = data_i[15:0];
 | 
			
		||||
   assign data_o = {occ_out, eof_out, sof_out, data_out};
 | 
			
		||||
   
 | 
			
		||||
   assign debug0 = { 8'd0, dst_rdy_o, src_rdy_o, next_state_is_idle, eof_out, sof_out, occ_out, state[1:0], frame_count[7:0], frames_per_packet[7:0] };
 | 
			
		||||
   assign debug1 = { length[15:0], frame_len[15:0] };
 | 
			
		||||
   
 | 
			
		||||
endmodule // packet_splitter
 | 
			
		||||
@@ -1,137 +0,0 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2011 Ettus Research LLC
 | 
			
		||||
//
 | 
			
		||||
// This program is free software: you can redistribute it and/or modify
 | 
			
		||||
// it under the terms of the GNU General Public License as published by
 | 
			
		||||
// the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
// (at your option) any later version.
 | 
			
		||||
//
 | 
			
		||||
// This program is distributed in the hope that it will be useful,
 | 
			
		||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
// GNU General Public License for more details.
 | 
			
		||||
//
 | 
			
		||||
// You should have received a copy of the GNU General Public License
 | 
			
		||||
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
module packet_splitter_tb();
 | 
			
		||||
   
 | 
			
		||||
   reg sys_clk = 0;
 | 
			
		||||
   reg sys_rst = 1;
 | 
			
		||||
   reg gpif_clk = 0;
 | 
			
		||||
   reg gpif_rst = 1;
 | 
			
		||||
      
 | 
			
		||||
   reg [15:0] gpif_data;
 | 
			
		||||
   reg 	      WR = 0, EP = 0;
 | 
			
		||||
 | 
			
		||||
   wire       CF, DF;
 | 
			
		||||
   
 | 
			
		||||
   wire       gpif_full_d, gpif_full_c;
 | 
			
		||||
   wire [18:0] data_o, ctrl_o, data_splt;
 | 
			
		||||
   wire        src_rdy, dst_rdy, src_rdy_splt, dst_rdy_splt;
 | 
			
		||||
   wire        ctrl_src_rdy, ctrl_dst_rdy;
 | 
			
		||||
 | 
			
		||||
   assign ctrl_dst_rdy = 1;
 | 
			
		||||
   
 | 
			
		||||
   initial $dumpfile("packet_splitter_tb.vcd");
 | 
			
		||||
   initial $dumpvars(0,packet_splitter_tb);
 | 
			
		||||
 | 
			
		||||
   initial #1000 gpif_rst = 0;
 | 
			
		||||
   initial #1000 sys_rst = 0;
 | 
			
		||||
   always #64 gpif_clk <= ~gpif_clk;
 | 
			
		||||
   always #47.9 sys_clk <= ~sys_clk;
 | 
			
		||||
 | 
			
		||||
   wire [35:0] data_int;
 | 
			
		||||
   wire        src_rdy_int, dst_rdy_int;
 | 
			
		||||
 | 
			
		||||
   assign dst_rdy_splt = 1;
 | 
			
		||||
 | 
			
		||||
   vita_pkt_gen vita_pkt_gen
 | 
			
		||||
     (.clk(sys_clk), .reset(sys_rst) , .clear(0),
 | 
			
		||||
      .len(512),.data_o(data_int), .src_rdy_o(src_rdy_int), .dst_rdy_i(dst_rdy_int));
 | 
			
		||||
 | 
			
		||||
   fifo36_to_fifo19 #(.LE(1)) f36_to_f19
 | 
			
		||||
     (.clk(sys_clk), .reset(sys_rst), .clear(0),
 | 
			
		||||
      .f36_datain(data_int), .f36_src_rdy_i(src_rdy_int), .f36_dst_rdy_o(dst_rdy_int),
 | 
			
		||||
      .f19_dataout(data_o), .f19_src_rdy_o(src_rdy), .f19_dst_rdy_i(dst_rdy));
 | 
			
		||||
   		 
 | 
			
		||||
   packet_splitter #(.FRAME_LEN(13)) rx_packet_splitter
 | 
			
		||||
     (.clk(sys_clk), .reset(sys_rst), .clear(0),
 | 
			
		||||
      .frames_per_packet(4),
 | 
			
		||||
      .data_i(data_o), .src_rdy_i(src_rdy), .dst_rdy_o(dst_rdy),
 | 
			
		||||
      .data_o(data_splt), .src_rdy_o(src_rdy_splt), .dst_rdy_i(dst_rdy_splt));
 | 
			
		||||
 | 
			
		||||
   always @(posedge sys_clk)
 | 
			
		||||
     if(ctrl_src_rdy & ctrl_dst_rdy)
 | 
			
		||||
       $display("CTRL: %x",ctrl_o);
 | 
			
		||||
 | 
			
		||||
   always @(posedge sys_clk)
 | 
			
		||||
     if(src_rdy_splt & dst_rdy_splt)
 | 
			
		||||
       begin
 | 
			
		||||
	  if(data_splt[16])
 | 
			
		||||
	    $display("<-------- DATA SOF--------->");
 | 
			
		||||
	  $display("DATA: %x",data_splt);
 | 
			
		||||
	  if(data_splt[17])
 | 
			
		||||
	    $display("<-------- DATA EOF--------->");
 | 
			
		||||
       end
 | 
			
		||||
   
 | 
			
		||||
   initial
 | 
			
		||||
     begin
 | 
			
		||||
	#10000;
 | 
			
		||||
	repeat (1)
 | 
			
		||||
	  begin
 | 
			
		||||
	     @(posedge gpif_clk);
 | 
			
		||||
	     
 | 
			
		||||
	     WR <= 1;
 | 
			
		||||
	     gpif_data <= 256;  // Length
 | 
			
		||||
	     @(posedge gpif_clk);
 | 
			
		||||
	     gpif_data <= 16'h00;
 | 
			
		||||
	     @(posedge gpif_clk);
 | 
			
		||||
	     repeat(254)
 | 
			
		||||
	       begin
 | 
			
		||||
		  gpif_data <= gpif_data + 1;
 | 
			
		||||
		  @(posedge gpif_clk);
 | 
			
		||||
	       end
 | 
			
		||||
	     WR <= 0;
 | 
			
		||||
 | 
			
		||||
	     while(DF)
 | 
			
		||||
	       @(posedge gpif_clk);
 | 
			
		||||
	     repeat (16)
 | 
			
		||||
	       @(posedge gpif_clk);
 | 
			
		||||
	     
 | 
			
		||||
	     WR <= 1;
 | 
			
		||||
	     repeat(256)
 | 
			
		||||
	       begin
 | 
			
		||||
		  gpif_data <= gpif_data - 1;
 | 
			
		||||
		  @(posedge gpif_clk);
 | 
			
		||||
	       end
 | 
			
		||||
	     WR <= 0;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
	     while(DF)
 | 
			
		||||
	       @(posedge gpif_clk);
 | 
			
		||||
	     	     
 | 
			
		||||
	     repeat (20)
 | 
			
		||||
	       @(posedge gpif_clk);
 | 
			
		||||
	     WR <= 1;
 | 
			
		||||
	     gpif_data <= 16'h5;
 | 
			
		||||
	     @(posedge gpif_clk);
 | 
			
		||||
	     gpif_data <= 16'h00;
 | 
			
		||||
	     @(posedge gpif_clk);
 | 
			
		||||
	     repeat(254)
 | 
			
		||||
	       begin
 | 
			
		||||
		  gpif_data <= gpif_data - 1;
 | 
			
		||||
		  @(posedge gpif_clk);
 | 
			
		||||
	       end
 | 
			
		||||
	     WR <= 0;
 | 
			
		||||
 */
 | 
			
		||||
	  end
 | 
			
		||||
     end // initial begin
 | 
			
		||||
   
 | 
			
		||||
   initial #200000 $finish;
 | 
			
		||||
   
 | 
			
		||||
     
 | 
			
		||||
endmodule // packet_splitter_tb
 | 
			
		||||
							
								
								
									
										2
									
								
								fpga/gpmc/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								fpga/gpmc/.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,2 +0,0 @@
 | 
			
		||||
*.gif
 | 
			
		||||
 | 
			
		||||
@@ -1,14 +0,0 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright 2010-2011 Ettus Research LLC
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
##################################################
 | 
			
		||||
# GPMC Sources
 | 
			
		||||
##################################################
 | 
			
		||||
GPMC_SRCS = $(abspath $(addprefix $(BASE_DIR)/../gpmc/, \
 | 
			
		||||
cross_clock_reader.v \
 | 
			
		||||
fifo_to_gpmc.v \
 | 
			
		||||
gpmc.v \
 | 
			
		||||
gpmc_to_fifo.v \
 | 
			
		||||
gpmc_wb.v \
 | 
			
		||||
))
 | 
			
		||||
@@ -1,42 +0,0 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2011 Ettus Research LLC
 | 
			
		||||
//
 | 
			
		||||
// This program is free software: you can redistribute it and/or modify
 | 
			
		||||
// it under the terms of the GNU General Public License as published by
 | 
			
		||||
// the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
// (at your option) any later version.
 | 
			
		||||
//
 | 
			
		||||
// This program is distributed in the hope that it will be useful,
 | 
			
		||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
// GNU General Public License for more details.
 | 
			
		||||
//
 | 
			
		||||
// You should have received a copy of the GNU General Public License
 | 
			
		||||
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
module cross_clock_reader
 | 
			
		||||
    #(
 | 
			
		||||
        parameter WIDTH = 1,
 | 
			
		||||
        parameter DEFAULT = 0
 | 
			
		||||
    )
 | 
			
		||||
    (
 | 
			
		||||
        input clk, input rst,
 | 
			
		||||
        input [WIDTH-1:0] in,
 | 
			
		||||
        output reg [WIDTH-1:0] out
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    reg [WIDTH-1:0] shadow;
 | 
			
		||||
 | 
			
		||||
    always @(posedge clk) begin
 | 
			
		||||
        if (rst) begin
 | 
			
		||||
            out <= DEFAULT;
 | 
			
		||||
            shadow <= DEFAULT;
 | 
			
		||||
        end
 | 
			
		||||
        else if (shadow == in) begin
 | 
			
		||||
            out <= shadow;
 | 
			
		||||
        end
 | 
			
		||||
        shadow <= in;
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
endmodule //cross_clock_reader
 | 
			
		||||
@@ -1,159 +0,0 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2011 Ettus Research LLC
 | 
			
		||||
//
 | 
			
		||||
// This program is free software: you can redistribute it and/or modify
 | 
			
		||||
// it under the terms of the GNU General Public License as published by
 | 
			
		||||
// the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
// (at your option) any later version.
 | 
			
		||||
//
 | 
			
		||||
// This program is distributed in the hope that it will be useful,
 | 
			
		||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
// GNU General Public License for more details.
 | 
			
		||||
//
 | 
			
		||||
// You should have received a copy of the GNU General Public License
 | 
			
		||||
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// FIFO to GPMC
 | 
			
		||||
//
 | 
			
		||||
// Reads frames from FIFO interface and writes them into BRAM pages.
 | 
			
		||||
// The GPMC is asynchronously alerted when a BRAM page has been filled.
 | 
			
		||||
//
 | 
			
		||||
// EM_CLK:
 | 
			
		||||
// A GPMC read transaction consists of two EM_CLK cycles (idle low).
 | 
			
		||||
//
 | 
			
		||||
// EM_OE:
 | 
			
		||||
// Output enable is actually the combination of ~NOE & ~NCS.
 | 
			
		||||
// The output enable is only active for the second rising edge,
 | 
			
		||||
// to ensure one edge per transaction to transition on.
 | 
			
		||||
//
 | 
			
		||||
// EM_D:
 | 
			
		||||
// The BRAM performs a read on the first rising edge into EM_D.
 | 
			
		||||
// Then, data will then be read on the next rising edge by GPMC.
 | 
			
		||||
//
 | 
			
		||||
// EM_A:
 | 
			
		||||
// On the first rising edge of EM_CLK, the address is held.
 | 
			
		||||
// On the second rising edge, the address is set for the next transaction.
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
module fifo_to_gpmc
 | 
			
		||||
  #(parameter PTR_WIDTH = 2, parameter ADDR_WIDTH = 10)
 | 
			
		||||
  (input clk, input reset, input clear, input arst,
 | 
			
		||||
   input [17:0] data_i, input src_rdy_i, output dst_rdy_o,
 | 
			
		||||
   output [15:0] EM_D, input [ADDR_WIDTH:1] EM_A, input EM_CLK, input EM_OE,
 | 
			
		||||
   output reg data_available);
 | 
			
		||||
 | 
			
		||||
    //states for the GPMC side of things
 | 
			
		||||
    wire [17:0] data_o;
 | 
			
		||||
    reg gpmc_state;
 | 
			
		||||
    reg [ADDR_WIDTH:1] addr;
 | 
			
		||||
    reg [PTR_WIDTH:0] gpmc_ptr, next_gpmc_ptr;
 | 
			
		||||
    localparam GPMC_STATE_START = 0;
 | 
			
		||||
    localparam GPMC_STATE_EMPTY = 1;
 | 
			
		||||
 | 
			
		||||
    //states for the FIFO side of things
 | 
			
		||||
    reg fifo_state;
 | 
			
		||||
    reg [ADDR_WIDTH-1:0] counter;
 | 
			
		||||
    reg [PTR_WIDTH:0] fifo_ptr;
 | 
			
		||||
    localparam FIFO_STATE_CLAIM = 0;
 | 
			
		||||
    localparam FIFO_STATE_FILL = 1;
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------
 | 
			
		||||
    // State machine to control the data from GPMC to BRAM
 | 
			
		||||
    //------------------------------------------------------------------
 | 
			
		||||
    always @(posedge EM_CLK or posedge arst) begin
 | 
			
		||||
        if (arst) begin
 | 
			
		||||
            gpmc_state <= GPMC_STATE_START;
 | 
			
		||||
            gpmc_ptr <= 0;
 | 
			
		||||
            next_gpmc_ptr <= 0;
 | 
			
		||||
            addr <= 0;
 | 
			
		||||
        end
 | 
			
		||||
        else if (EM_OE) begin
 | 
			
		||||
            addr <= EM_A + 1;
 | 
			
		||||
            case(gpmc_state)
 | 
			
		||||
 | 
			
		||||
            GPMC_STATE_START: begin
 | 
			
		||||
                if (EM_A == 0) begin
 | 
			
		||||
                    gpmc_state <= GPMC_STATE_EMPTY;
 | 
			
		||||
                    next_gpmc_ptr <= gpmc_ptr + 1;
 | 
			
		||||
                end
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            GPMC_STATE_EMPTY: begin
 | 
			
		||||
                if (EM_A == 10'h3ff) begin
 | 
			
		||||
                    gpmc_state <= GPMC_STATE_START;
 | 
			
		||||
                    gpmc_ptr <= next_gpmc_ptr;
 | 
			
		||||
                end
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            endcase //gpmc_state
 | 
			
		||||
        end //EM_WE
 | 
			
		||||
    end //always
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------
 | 
			
		||||
    // High when the gpmc pointer has not caught up to the fifo pointer.
 | 
			
		||||
    //------------------------------------------------------------------
 | 
			
		||||
    wire [PTR_WIDTH:0] safe_gpmc_ptr;
 | 
			
		||||
    cross_clock_reader #(.WIDTH(PTR_WIDTH+1)) read_gpmc_ptr
 | 
			
		||||
        (.clk(clk), .rst(reset | clear), .in(gpmc_ptr), .out(safe_gpmc_ptr));
 | 
			
		||||
 | 
			
		||||
    wire bram_available_to_fill = (fifo_ptr ^ (1 << PTR_WIDTH)) != safe_gpmc_ptr;
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------
 | 
			
		||||
    // Glich free generation of data available signal:
 | 
			
		||||
    // Data is available when the pointers dont match.
 | 
			
		||||
    //------------------------------------------------------------------
 | 
			
		||||
    wire [PTR_WIDTH:0] safe_next_gpmc_ptr;
 | 
			
		||||
    cross_clock_reader #(.WIDTH(PTR_WIDTH+1)) read_next_gpmc_ptr
 | 
			
		||||
        (.clk(clk), .rst(reset | clear), .in(next_gpmc_ptr), .out(safe_next_gpmc_ptr));
 | 
			
		||||
 | 
			
		||||
    always @(posedge clk)
 | 
			
		||||
        if (reset | clear) data_available <= 0;
 | 
			
		||||
        else               data_available <= safe_next_gpmc_ptr != fifo_ptr;
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------
 | 
			
		||||
    // State machine to control the data from BRAM to FIFO
 | 
			
		||||
    //------------------------------------------------------------------
 | 
			
		||||
    always @(posedge clk) begin
 | 
			
		||||
        if (reset | clear) begin
 | 
			
		||||
            fifo_state <= FIFO_STATE_CLAIM;
 | 
			
		||||
            fifo_ptr <= 0;
 | 
			
		||||
            counter <= 0;
 | 
			
		||||
        end
 | 
			
		||||
        else begin
 | 
			
		||||
            case(fifo_state)
 | 
			
		||||
 | 
			
		||||
            FIFO_STATE_CLAIM: begin
 | 
			
		||||
                if (bram_available_to_fill) fifo_state <= FIFO_STATE_FILL;
 | 
			
		||||
                counter <= 0;
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            FIFO_STATE_FILL: begin
 | 
			
		||||
                if (src_rdy_i && dst_rdy_o && data_i[17]) begin
 | 
			
		||||
                    fifo_state <= FIFO_STATE_CLAIM;
 | 
			
		||||
                    fifo_ptr <= fifo_ptr + 1;
 | 
			
		||||
                end
 | 
			
		||||
                if (src_rdy_i && dst_rdy_o) begin
 | 
			
		||||
                    counter <= counter + 1;
 | 
			
		||||
                end
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            endcase //fifo_state
 | 
			
		||||
        end
 | 
			
		||||
    end //always
 | 
			
		||||
 | 
			
		||||
    assign dst_rdy_o = fifo_state == FIFO_STATE_FILL;
 | 
			
		||||
 | 
			
		||||
    //assign data from bram output
 | 
			
		||||
    assign EM_D = data_o[15:0];
 | 
			
		||||
 | 
			
		||||
    //instantiate dual ported bram for async read + write
 | 
			
		||||
    ram_2port #(.DWIDTH(18),.AWIDTH(PTR_WIDTH + ADDR_WIDTH)) async_fifo_bram
 | 
			
		||||
     (.clka(clk),.ena(1'b1),.wea(src_rdy_i && dst_rdy_o),
 | 
			
		||||
      .addra({fifo_ptr[PTR_WIDTH-1:0], counter}),.dia(data_i),.doa(),
 | 
			
		||||
      .clkb(EM_CLK),.enb(1'b1),.web(1'b0),
 | 
			
		||||
      .addrb({gpmc_ptr[PTR_WIDTH-1:0], addr}),.dib(18'h3ffff),.dob(data_o));
 | 
			
		||||
 | 
			
		||||
endmodule // fifo_to_gpmc
 | 
			
		||||
							
								
								
									
										159
									
								
								fpga/gpmc/gpmc.v
									
									
									
									
									
								
							
							
						
						
									
										159
									
								
								fpga/gpmc/gpmc.v
									
									
									
									
									
								
							@@ -1,159 +0,0 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2011 Ettus Research LLC
 | 
			
		||||
//
 | 
			
		||||
// This program is free software: you can redistribute it and/or modify
 | 
			
		||||
// it under the terms of the GNU General Public License as published by
 | 
			
		||||
// the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
// (at your option) any later version.
 | 
			
		||||
//
 | 
			
		||||
// This program is distributed in the hope that it will be useful,
 | 
			
		||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
// GNU General Public License for more details.
 | 
			
		||||
//
 | 
			
		||||
// You should have received a copy of the GNU General Public License
 | 
			
		||||
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
//////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
module gpmc
 | 
			
		||||
  #(parameter TXFIFOSIZE = 11, 
 | 
			
		||||
    parameter RXFIFOSIZE = 11,
 | 
			
		||||
    parameter ADDR_WIDTH = 10,
 | 
			
		||||
    parameter BUSDEBUG = 1)
 | 
			
		||||
   (// GPMC signals
 | 
			
		||||
    input arst,
 | 
			
		||||
    input EM_CLK, inout [15:0] EM_D, input [ADDR_WIDTH:1] EM_A, input [1:0] EM_NBE,
 | 
			
		||||
    input EM_WAIT0, input EM_NCS4, input EM_NCS6, input EM_NWE, input EM_NOE,
 | 
			
		||||
    
 | 
			
		||||
    // GPIOs for FIFO signalling
 | 
			
		||||
    output rx_have_data, output tx_have_space,
 | 
			
		||||
    
 | 
			
		||||
    // Wishbone signals
 | 
			
		||||
    input wb_clk, input wb_rst,
 | 
			
		||||
    output [ADDR_WIDTH:0] wb_adr_o, output [15:0] wb_dat_mosi, input [15:0] wb_dat_miso,
 | 
			
		||||
    output [1:0] wb_sel_o, output wb_cyc_o, output wb_stb_o, output wb_we_o, input wb_ack_i,
 | 
			
		||||
    
 | 
			
		||||
    // FIFO interface
 | 
			
		||||
    input fifo_clk, input fifo_rst, input clear_tx, input clear_rx,
 | 
			
		||||
    output [35:0] tx_data_o, output tx_src_rdy_o, input tx_dst_rdy_i,
 | 
			
		||||
    input [35:0] rx_data_i, input rx_src_rdy_i, output rx_dst_rdy_o,
 | 
			
		||||
 | 
			
		||||
    output tx_underrun, output rx_overrun,
 | 
			
		||||
    input [7:0] test_rate, input [3:0] test_ctrl,
 | 
			
		||||
    output [31:0] debug
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
   wire 	  EM_output_enable = (~EM_NOE & (~EM_NCS4 | ~EM_NCS6));
 | 
			
		||||
   wire [15:0] 	  EM_D_fifo;
 | 
			
		||||
   wire [15:0] 	  EM_D_wb;
 | 
			
		||||
 | 
			
		||||
   assign EM_D = ~EM_output_enable ? 16'bz : ~EM_NCS4 ? EM_D_fifo : EM_D_wb;
 | 
			
		||||
 | 
			
		||||
   // CS4 is RAM_2PORT for DATA PATH (high-speed data)
 | 
			
		||||
   //    Writes go into one RAM, reads come from the other
 | 
			
		||||
   // CS6 is for CONTROL PATH (wishbone)
 | 
			
		||||
 | 
			
		||||
   // ////////////////////////////////////////////
 | 
			
		||||
   // TX Data Path
 | 
			
		||||
 | 
			
		||||
   wire [17:0] 	  tx18_data;
 | 
			
		||||
   wire 	  tx18_src_rdy, tx18_dst_rdy;
 | 
			
		||||
   wire [35:0] 	  tx_data, txb_data;
 | 
			
		||||
   wire 	  tx_src_rdy, tx_dst_rdy;
 | 
			
		||||
   wire 	  txb_src_rdy, txb_dst_rdy;
 | 
			
		||||
 | 
			
		||||
   gpmc_to_fifo #(.ADDR_WIDTH(ADDR_WIDTH)) gpmc_to_fifo
 | 
			
		||||
     (.EM_D(EM_D), .EM_A(EM_A), .EM_CLK(EM_CLK), .EM_WE(~EM_NCS4 & ~EM_NWE),
 | 
			
		||||
      .clk(fifo_clk), .reset(fifo_rst), .clear(clear_tx), .arst(fifo_rst | clear_tx | arst),
 | 
			
		||||
      .data_o(tx18_data), .src_rdy_o(tx18_src_rdy), .dst_rdy_i(tx18_dst_rdy),
 | 
			
		||||
      .have_space(tx_have_space));
 | 
			
		||||
 | 
			
		||||
   fifo19_to_fifo36 #(.LE(1)) f19_to_f36   // Little endian because ARM is LE
 | 
			
		||||
     (.clk(fifo_clk), .reset(fifo_rst), .clear(clear_tx),
 | 
			
		||||
      .f19_datain({1'b0,tx18_data}), .f19_src_rdy_i(tx18_src_rdy), .f19_dst_rdy_o(tx18_dst_rdy),
 | 
			
		||||
      .f36_dataout(txb_data), .f36_src_rdy_o(txb_src_rdy), .f36_dst_rdy_i(txb_dst_rdy));
 | 
			
		||||
 | 
			
		||||
   fifo_cascade #(.WIDTH(36), .SIZE(TXFIFOSIZE)) tx_buffering(
 | 
			
		||||
        .clk(fifo_clk), .reset(fifo_rst), .clear(clear_tx),
 | 
			
		||||
        .datain(txb_data), .src_rdy_i(txb_src_rdy), .dst_rdy_o(txb_dst_rdy),
 | 
			
		||||
        .dataout(tx_data), .src_rdy_o(tx_src_rdy), .dst_rdy_i(tx_dst_rdy)
 | 
			
		||||
   );
 | 
			
		||||
 | 
			
		||||
   // ////////////////////////////////////////////
 | 
			
		||||
   // RX Data Path
 | 
			
		||||
   
 | 
			
		||||
   wire [17:0] 	  rx18_data;
 | 
			
		||||
   wire 	  rx18_src_rdy, rx18_dst_rdy;
 | 
			
		||||
   wire [35:0] 	  rx_data, rxb_data;
 | 
			
		||||
   wire 	  rx_src_rdy, rx_dst_rdy;
 | 
			
		||||
   wire 	  rxb_src_rdy, rxb_dst_rdy;
 | 
			
		||||
   wire 	  dummy;
 | 
			
		||||
 | 
			
		||||
   fifo_cascade #(.WIDTH(36), .SIZE(RXFIFOSIZE)) rx_buffering(
 | 
			
		||||
        .clk(fifo_clk), .reset(fifo_rst), .clear(clear_rx),
 | 
			
		||||
        .datain(rx_data), .src_rdy_i(rx_src_rdy), .dst_rdy_o(rx_dst_rdy),
 | 
			
		||||
        .dataout(rxb_data), .src_rdy_o(rxb_src_rdy), .dst_rdy_i(rxb_dst_rdy)
 | 
			
		||||
   );
 | 
			
		||||
 | 
			
		||||
   fifo36_to_fifo19 #(.LE(1)) f36_to_f19   // Little endian because ARM is LE
 | 
			
		||||
     (.clk(fifo_clk), .reset(fifo_rst), .clear(clear_rx),
 | 
			
		||||
      .f36_datain(rxb_data), .f36_src_rdy_i(rxb_src_rdy), .f36_dst_rdy_o(rxb_dst_rdy),
 | 
			
		||||
      .f19_dataout({dummy,rx18_data}), .f19_src_rdy_o(rx18_src_rdy), .f19_dst_rdy_i(rx18_dst_rdy) );
 | 
			
		||||
 | 
			
		||||
   fifo_to_gpmc #(.ADDR_WIDTH(ADDR_WIDTH)) fifo_to_gpmc
 | 
			
		||||
     (.clk(fifo_clk), .reset(fifo_rst), .clear(clear_rx), .arst(fifo_rst | clear_rx | arst),
 | 
			
		||||
      .data_i(rx18_data), .src_rdy_i(rx18_src_rdy), .dst_rdy_o(rx18_dst_rdy),
 | 
			
		||||
      .EM_D(EM_D_fifo), .EM_A(EM_A), .EM_CLK(EM_CLK), .EM_OE(~EM_NCS4 & ~EM_NOE),
 | 
			
		||||
      .data_available(rx_have_data));
 | 
			
		||||
 | 
			
		||||
   // ////////////////////////////////////////////
 | 
			
		||||
   // Control path on CS6
 | 
			
		||||
   
 | 
			
		||||
   gpmc_wb gpmc_wb
 | 
			
		||||
     (.EM_CLK(EM_CLK), .EM_D_in(EM_D), .EM_D_out(EM_D_wb), .EM_A(EM_A), .EM_NBE(EM_NBE),
 | 
			
		||||
      .EM_WE(~EM_NCS6 & ~EM_NWE), .EM_OE(~EM_NCS6 & ~EM_NOE),
 | 
			
		||||
      .wb_clk(wb_clk), .wb_rst(wb_rst),
 | 
			
		||||
      .wb_adr_o(wb_adr_o), .wb_dat_mosi(wb_dat_mosi), .wb_dat_miso(wb_dat_miso),
 | 
			
		||||
      .wb_sel_o(wb_sel_o), .wb_cyc_o(wb_cyc_o), .wb_stb_o(wb_stb_o), .wb_we_o(wb_we_o),
 | 
			
		||||
      .wb_ack_i(wb_ack_i) );
 | 
			
		||||
 | 
			
		||||
   // ////////////////////////////////////////////
 | 
			
		||||
   // Test support, traffic generator, loopback, etc.
 | 
			
		||||
 | 
			
		||||
   // RX side muxes test data into the same stream
 | 
			
		||||
   wire [35:0] loopbackrx_data, testrx_data;
 | 
			
		||||
   wire [35:0] loopbacktx_data, testtx_data;
 | 
			
		||||
   wire        loopbackrx_src_rdy, loopbackrx_dst_rdy;
 | 
			
		||||
   wire        loopbacktx_src_rdy, loopbacktx_dst_rdy;
 | 
			
		||||
   wire        sel_testtx = test_ctrl[0];
 | 
			
		||||
 | 
			
		||||
   fifo36_mux rx_test_mux_lvl_2
 | 
			
		||||
     (.clk(fifo_clk), .reset(fifo_rst), .clear(clear_rx),
 | 
			
		||||
      .data0_i(loopbackrx_data), .src0_rdy_i(loopbackrx_src_rdy), .dst0_rdy_o(loopbackrx_dst_rdy),
 | 
			
		||||
      .data1_i(rx_data_i), .src1_rdy_i(rx_src_rdy_i), .dst1_rdy_o(rx_dst_rdy_o),
 | 
			
		||||
      .data_o(rx_data), .src_rdy_o(rx_src_rdy), .dst_rdy_i(rx_dst_rdy));
 | 
			
		||||
 | 
			
		||||
   fifo_short #(.WIDTH(36)) loopback_fifo
 | 
			
		||||
     (.clk(fifo_clk), .reset(fifo_rst), .clear(clear_tx | clear_rx),
 | 
			
		||||
      .datain(loopbacktx_data), .src_rdy_i(loopbacktx_src_rdy), .dst_rdy_o(loopbacktx_dst_rdy),
 | 
			
		||||
      .dataout(loopbackrx_data), .src_rdy_o(loopbackrx_src_rdy), .dst_rdy_i(loopbackrx_dst_rdy));
 | 
			
		||||
 | 
			
		||||
   // Crossbar used as a demux for switching TX stream to main DSP or to test logic
 | 
			
		||||
   crossbar36 tx_crossbar_lvl_1
 | 
			
		||||
     (.clk(fifo_clk), .reset(fifo_rst), .clear(clear_tx),
 | 
			
		||||
      .cross(sel_testtx),
 | 
			
		||||
      .data0_i(tx_data), .src0_rdy_i(tx_src_rdy), .dst0_rdy_o(tx_dst_rdy),
 | 
			
		||||
      .data1_i(tx_data), .src1_rdy_i(1'b0), .dst1_rdy_o(),  // No 2nd input
 | 
			
		||||
      .data0_o(tx_data_o), .src0_rdy_o(tx_src_rdy_o), .dst0_rdy_i(tx_dst_rdy_i),
 | 
			
		||||
      .data1_o(loopbacktx_data), .src1_rdy_o(loopbacktx_src_rdy), .dst1_rdy_i(loopbacktx_dst_rdy) );
 | 
			
		||||
 | 
			
		||||
   assign debug = {
 | 
			
		||||
        EM_D, //16
 | 
			
		||||
        EM_A, //10
 | 
			
		||||
        EM_CLK, EM_NCS4, EM_NWE, EM_NOE, //4
 | 
			
		||||
        EM_NCS6, wb_ack_i
 | 
			
		||||
   };
 | 
			
		||||
 | 
			
		||||
endmodule // gpmc
 | 
			
		||||
@@ -1,157 +0,0 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2011 Ettus Research LLC
 | 
			
		||||
//
 | 
			
		||||
// This program is free software: you can redistribute it and/or modify
 | 
			
		||||
// it under the terms of the GNU General Public License as published by
 | 
			
		||||
// the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
// (at your option) any later version.
 | 
			
		||||
//
 | 
			
		||||
// This program is distributed in the hope that it will be useful,
 | 
			
		||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
// GNU General Public License for more details.
 | 
			
		||||
//
 | 
			
		||||
// You should have received a copy of the GNU General Public License
 | 
			
		||||
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// GPMC to FIFO
 | 
			
		||||
//
 | 
			
		||||
// Reads frames from BRAM pages and writes them into FIFO interface.
 | 
			
		||||
// The GPMC is asynchronously alerted when a BRAM page is available.
 | 
			
		||||
//
 | 
			
		||||
// EM_CLK:
 | 
			
		||||
// A GPMC read transaction consists of one EM_CLK cycle (idle low).
 | 
			
		||||
//
 | 
			
		||||
// EM_WE:
 | 
			
		||||
// Write enable is actually the combination of ~NWE & ~NCS.
 | 
			
		||||
// The write enable is active for the entire transaction.
 | 
			
		||||
//
 | 
			
		||||
// EM_D:
 | 
			
		||||
// Data is set on the rising edge and written into BRAM on the falling edge.
 | 
			
		||||
//
 | 
			
		||||
// EM_A:
 | 
			
		||||
// Address is set on the rising edge and read by BRAM on the falling edge.
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
module gpmc_to_fifo
 | 
			
		||||
  #(parameter PTR_WIDTH = 2, parameter ADDR_WIDTH = 10)
 | 
			
		||||
  (input [15:0] EM_D, input [ADDR_WIDTH:1] EM_A, input EM_CLK, input EM_WE,
 | 
			
		||||
   input clk, input reset, input clear, input arst,
 | 
			
		||||
   output [17:0] data_o, output src_rdy_o, input dst_rdy_i,
 | 
			
		||||
   output reg have_space);
 | 
			
		||||
 | 
			
		||||
    //states for the GPMC side of things
 | 
			
		||||
    wire [17:0] data_i;
 | 
			
		||||
    reg gpmc_state;
 | 
			
		||||
    reg [ADDR_WIDTH:1] last_addr;
 | 
			
		||||
    reg [PTR_WIDTH:0] gpmc_ptr, next_gpmc_ptr;
 | 
			
		||||
    localparam GPMC_STATE_START = 0;
 | 
			
		||||
    localparam GPMC_STATE_FILL = 1;
 | 
			
		||||
 | 
			
		||||
    //states for the FIFO side of things
 | 
			
		||||
    reg fifo_state;
 | 
			
		||||
    reg [ADDR_WIDTH-1:0] counter;
 | 
			
		||||
    reg [PTR_WIDTH:0] fifo_ptr;
 | 
			
		||||
    localparam FIFO_STATE_CLAIM = 0;
 | 
			
		||||
    localparam FIFO_STATE_EMPTY = 1;
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------
 | 
			
		||||
    // State machine to control the data from GPMC to BRAM
 | 
			
		||||
    //------------------------------------------------------------------
 | 
			
		||||
    always @(negedge EM_CLK or posedge arst) begin
 | 
			
		||||
        if (arst) begin
 | 
			
		||||
            gpmc_state <= GPMC_STATE_START;
 | 
			
		||||
            gpmc_ptr <= 0;
 | 
			
		||||
            next_gpmc_ptr <= 0;
 | 
			
		||||
        end
 | 
			
		||||
        else if (EM_WE) begin
 | 
			
		||||
            case(gpmc_state)
 | 
			
		||||
 | 
			
		||||
            GPMC_STATE_START: begin
 | 
			
		||||
                if (EM_A == 0) begin
 | 
			
		||||
                    gpmc_state <= GPMC_STATE_FILL;
 | 
			
		||||
                    last_addr <= {EM_D[ADDR_WIDTH-2:0], 1'b0} - 1'b1;
 | 
			
		||||
                    next_gpmc_ptr <= gpmc_ptr + 1;
 | 
			
		||||
                end
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            GPMC_STATE_FILL: begin
 | 
			
		||||
                if (data_i[17]) begin
 | 
			
		||||
                    gpmc_state <= GPMC_STATE_START;
 | 
			
		||||
                    gpmc_ptr <= next_gpmc_ptr;
 | 
			
		||||
                end
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            endcase //gpmc_state
 | 
			
		||||
        end //EM_WE
 | 
			
		||||
    end //always
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------
 | 
			
		||||
    // A block ram is available to empty when the pointers dont match.
 | 
			
		||||
    //------------------------------------------------------------------
 | 
			
		||||
    wire [PTR_WIDTH:0] safe_gpmc_ptr;
 | 
			
		||||
    cross_clock_reader #(.WIDTH(PTR_WIDTH+1)) read_gpmc_ptr
 | 
			
		||||
        (.clk(clk), .rst(reset | clear), .in(gpmc_ptr), .out(safe_gpmc_ptr));
 | 
			
		||||
 | 
			
		||||
    wire bram_available_to_empty = safe_gpmc_ptr != fifo_ptr;
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------
 | 
			
		||||
    // Glich free generation of have space signal:
 | 
			
		||||
    // High when the fifo pointer has not caught up to the gpmc pointer.
 | 
			
		||||
    //------------------------------------------------------------------
 | 
			
		||||
    wire [PTR_WIDTH:0] safe_next_gpmc_ptr;
 | 
			
		||||
    cross_clock_reader #(.WIDTH(PTR_WIDTH+1)) read_next_gpmc_ptr
 | 
			
		||||
        (.clk(clk), .rst(reset | clear), .in(next_gpmc_ptr), .out(safe_next_gpmc_ptr));
 | 
			
		||||
 | 
			
		||||
    always @(posedge clk)
 | 
			
		||||
        if (reset | clear) have_space <= 0;
 | 
			
		||||
        else               have_space <= (fifo_ptr ^ (1 << PTR_WIDTH)) != safe_next_gpmc_ptr;
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------
 | 
			
		||||
    // State machine to control the data from BRAM to FIFO
 | 
			
		||||
    //------------------------------------------------------------------
 | 
			
		||||
    always @(posedge clk) begin
 | 
			
		||||
        if (reset | clear) begin
 | 
			
		||||
            fifo_state <= FIFO_STATE_CLAIM;
 | 
			
		||||
            fifo_ptr <= 0;
 | 
			
		||||
            counter <= 0;
 | 
			
		||||
        end
 | 
			
		||||
        else begin
 | 
			
		||||
            case(fifo_state)
 | 
			
		||||
 | 
			
		||||
            FIFO_STATE_CLAIM: begin
 | 
			
		||||
                if (bram_available_to_empty) fifo_state <= FIFO_STATE_EMPTY;
 | 
			
		||||
                counter <= 0;
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            FIFO_STATE_EMPTY: begin
 | 
			
		||||
                if (src_rdy_o && dst_rdy_i && data_o[17]) begin
 | 
			
		||||
                    fifo_state <= FIFO_STATE_CLAIM;
 | 
			
		||||
                    fifo_ptr <= fifo_ptr + 1;
 | 
			
		||||
                end
 | 
			
		||||
                if (src_rdy_o && dst_rdy_i) begin
 | 
			
		||||
                    counter <= counter + 1;
 | 
			
		||||
                end
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            endcase //fifo_state
 | 
			
		||||
        end
 | 
			
		||||
    end //always
 | 
			
		||||
 | 
			
		||||
    assign src_rdy_o = fifo_state == FIFO_STATE_EMPTY;
 | 
			
		||||
 | 
			
		||||
    //assign data and frame bits to bram input
 | 
			
		||||
    assign data_i[15:0] = EM_D;
 | 
			
		||||
    assign data_i[16] = (gpmc_state == GPMC_STATE_START);
 | 
			
		||||
    assign data_i[17] = (EM_A == last_addr);
 | 
			
		||||
 | 
			
		||||
    //instantiate dual ported bram for async read + write
 | 
			
		||||
    ram_2port #(.DWIDTH(18),.AWIDTH(PTR_WIDTH + ADDR_WIDTH)) async_fifo_bram
 | 
			
		||||
     (.clka(~EM_CLK),.ena(1'b1),.wea(EM_WE),
 | 
			
		||||
      .addra({gpmc_ptr[PTR_WIDTH-1:0], EM_A}),.dia(data_i),.doa(),
 | 
			
		||||
      .clkb(~clk),.enb(1'b1),.web(1'b0),
 | 
			
		||||
      .addrb({fifo_ptr[PTR_WIDTH-1:0], counter}),.dib(18'h3ffff),.dob(data_o));
 | 
			
		||||
 | 
			
		||||
endmodule // gpmc_to_fifo
 | 
			
		||||
@@ -1,79 +0,0 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2011 Ettus Research LLC
 | 
			
		||||
//
 | 
			
		||||
// This program is free software: you can redistribute it and/or modify
 | 
			
		||||
// it under the terms of the GNU General Public License as published by
 | 
			
		||||
// the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
// (at your option) any later version.
 | 
			
		||||
//
 | 
			
		||||
// This program is distributed in the hope that it will be useful,
 | 
			
		||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
// GNU General Public License for more details.
 | 
			
		||||
//
 | 
			
		||||
// You should have received a copy of the GNU General Public License
 | 
			
		||||
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
module gpmc_wb
 | 
			
		||||
  (input EM_CLK, input [15:0] EM_D_in, output [15:0] EM_D_out, input [10:1] EM_A, input [1:0] EM_NBE,
 | 
			
		||||
   input EM_WE, input EM_OE,
 | 
			
		||||
 | 
			
		||||
   input wb_clk, input wb_rst,
 | 
			
		||||
   output reg [10:0] wb_adr_o, output reg [15:0] wb_dat_mosi, input [15:0] wb_dat_miso,
 | 
			
		||||
   output reg [1:0] wb_sel_o, output wb_cyc_o, output reg wb_stb_o, output reg wb_we_o, input wb_ack_i);
 | 
			
		||||
   
 | 
			
		||||
   // ////////////////////////////////////////////
 | 
			
		||||
   // Control Path, Wishbone bus bridge (wb master)
 | 
			
		||||
   reg [1:0] we_del, oe_del;
 | 
			
		||||
 | 
			
		||||
   // Synchronize the async control signals
 | 
			
		||||
   always @(posedge wb_clk)
 | 
			
		||||
     if (wb_rst) begin
 | 
			
		||||
        we_del <= 2'b0;
 | 
			
		||||
        oe_del <= 2'b0;
 | 
			
		||||
     end
 | 
			
		||||
     else begin
 | 
			
		||||
        we_del <= { we_del[0], EM_WE };
 | 
			
		||||
        oe_del <= { oe_del[0], EM_OE };
 | 
			
		||||
     end
 | 
			
		||||
 | 
			
		||||
    wire writing = we_del == 2'b01;
 | 
			
		||||
    wire reading = oe_del == 2'b01;
 | 
			
		||||
 | 
			
		||||
   always @(posedge wb_clk)
 | 
			
		||||
     if(writing || reading)
 | 
			
		||||
       wb_adr_o <= { EM_A, 1'b0 };
 | 
			
		||||
 | 
			
		||||
   always @(posedge wb_clk)
 | 
			
		||||
     if(writing)
 | 
			
		||||
       begin
 | 
			
		||||
          wb_dat_mosi <= EM_D_in;
 | 
			
		||||
          wb_sel_o <= ~EM_NBE;
 | 
			
		||||
       end
 | 
			
		||||
 | 
			
		||||
   reg [15:0] EM_D_hold;
 | 
			
		||||
   
 | 
			
		||||
   always @(posedge wb_clk)
 | 
			
		||||
     if(wb_ack_i)
 | 
			
		||||
       EM_D_hold <= wb_dat_miso;
 | 
			
		||||
 | 
			
		||||
   assign EM_D_out = wb_ack_i ? wb_dat_miso : EM_D_hold;
 | 
			
		||||
   
 | 
			
		||||
   assign wb_cyc_o = wb_stb_o;
 | 
			
		||||
 | 
			
		||||
   always @(posedge wb_clk)
 | 
			
		||||
     if(writing)
 | 
			
		||||
       wb_we_o <= 1;
 | 
			
		||||
     else if(wb_ack_i)  // Turn off we when done.  Could also use we_del[0], others...
 | 
			
		||||
       wb_we_o <= 0;
 | 
			
		||||
 | 
			
		||||
   always @(posedge wb_clk)
 | 
			
		||||
     if(writing || reading)
 | 
			
		||||
       wb_stb_o <= 1;
 | 
			
		||||
     else if(wb_ack_i)
 | 
			
		||||
       wb_stb_o <= 0;
 | 
			
		||||
   
 | 
			
		||||
endmodule // gpmc_wb
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright 2010 Ettus Research LLC
 | 
			
		||||
# Copyright 2010-2012 Ettus Research LLC
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
##################################################
 | 
			
		||||
@@ -23,10 +23,10 @@ clip_reg.v \
 | 
			
		||||
cordic.v \
 | 
			
		||||
cordic_z24.v \
 | 
			
		||||
cordic_stage.v \
 | 
			
		||||
dsp_core_rx.v \
 | 
			
		||||
dsp_core_tx.v \
 | 
			
		||||
ddc_chain.v \
 | 
			
		||||
duc_chain.v \
 | 
			
		||||
dspengine_16to8.v \
 | 
			
		||||
frontend_sw.v \
 | 
			
		||||
dspengine_8to16.v \
 | 
			
		||||
hb_dec.v \
 | 
			
		||||
hb_interp.v \
 | 
			
		||||
pipectrl.v \
 | 
			
		||||
@@ -40,4 +40,7 @@ sign_extend.v \
 | 
			
		||||
small_hb_dec.v \
 | 
			
		||||
small_hb_int.v \
 | 
			
		||||
tx_frontend.v \
 | 
			
		||||
dsp_tx_glue.v \
 | 
			
		||||
dsp_rx_glue.v \
 | 
			
		||||
frontend_sw.v \
 | 
			
		||||
))
 | 
			
		||||
 
 | 
			
		||||
@@ -119,8 +119,6 @@ module cordic_z24(clock, reset, enable, xi, yi, zi, xo, yo, zo );
 | 
			
		||||
   assign xo = x20[bitwidth:1];  
 | 
			
		||||
   assign yo = y20[bitwidth:1];
 | 
			
		||||
   assign zo = z20;		  
 | 
			
		||||
   //assign xo = x20[bitwidth+1:2];  // CORDIC gain is ~1.6, plus gain from rotating vectors
 | 
			
		||||
   //assign yo = y20[bitwidth+1:2];
 | 
			
		||||
 | 
			
		||||
endmodule // cordic
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										190
									
								
								fpga/sdr_lib/ddc_chain.v
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										190
									
								
								fpga/sdr_lib/ddc_chain.v
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,190 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2011-2012 Ettus Research LLC
 | 
			
		||||
//
 | 
			
		||||
// This program is free software: you can redistribute it and/or modify
 | 
			
		||||
// it under the terms of the GNU General Public License as published by
 | 
			
		||||
// the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
// (at your option) any later version.
 | 
			
		||||
//
 | 
			
		||||
// This program is distributed in the hope that it will be useful,
 | 
			
		||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
// GNU General Public License for more details.
 | 
			
		||||
//
 | 
			
		||||
// You should have received a copy of the GNU General Public License
 | 
			
		||||
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
//! 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,
 | 
			
		||||
   input set_stb_user, input [7:0] set_addr_user, input [31:0] set_data_user,
 | 
			
		||||
 | 
			
		||||
   // 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 ddc_enb;
 | 
			
		||||
   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;
 | 
			
		||||
   
 | 
			
		||||
   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(2)) sr_3
 | 
			
		||||
     (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
 | 
			
		||||
      .in(set_data),.out({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 <= 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(~ddc_enb)
 | 
			
		||||
       phase <= 0;
 | 
			
		||||
     else
 | 
			
		||||
       phase <= phase + phase_inc;
 | 
			
		||||
 | 
			
		||||
   //sign extension of cordic input
 | 
			
		||||
   wire [WIDTH-1:0] to_ddc_chain_i, to_ddc_chain_q;
 | 
			
		||||
   wire [cwidth-1:0] to_cordic_i, to_cordic_q;
 | 
			
		||||
   sign_extend #(.bits_in(WIDTH), .bits_out(cwidth)) sign_extend_cordic_i (.in(to_ddc_chain_i), .out(to_cordic_i));
 | 
			
		||||
   sign_extend #(.bits_in(WIDTH), .bits_out(cwidth)) sign_extend_cordic_q (.in(to_ddc_chain_q), .out(to_cordic_q));
 | 
			
		||||
 | 
			
		||||
   // CORDIC  24-bit I/O
 | 
			
		||||
   cordic_z24 #(.bitwidth(cwidth))
 | 
			
		||||
     cordic(.clock(clk), .reset(rst), .enable(ddc_enb),
 | 
			
		||||
	    .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(ddc_enb),.rate(cic_decim_rate),
 | 
			
		||||
			   .strobe_fast(1),.strobe_slow(strobe_cic) );
 | 
			
		||||
 | 
			
		||||
   cic_decim #(.bw(WIDTH))
 | 
			
		||||
     decim_i (.clock(clk),.reset(rst),.enable(ddc_enb),
 | 
			
		||||
	      .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(ddc_enb),
 | 
			
		||||
	      .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(ddc_enb),
 | 
			
		||||
      .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(ddc_enb),
 | 
			
		||||
      .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(ddc_enb),.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(ddc_enb),.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
 | 
			
		||||
   wire [31:0] ddc_chain_out;
 | 
			
		||||
   wire ddc_chain_stb;
 | 
			
		||||
 | 
			
		||||
   round_sd #(.WIDTH_IN(WIDTH),.WIDTH_OUT(16)) round_i
 | 
			
		||||
     (.clk(clk),.reset(rst), .in(prod_reg_i),.strobe_in(strobe_mult), .out(ddc_chain_out[31:16]), .strobe_out(ddc_chain_stb));
 | 
			
		||||
 | 
			
		||||
   round_sd #(.WIDTH_IN(WIDTH),.WIDTH_OUT(16)) round_q
 | 
			
		||||
     (.clk(clk),.reset(rst), .in(prod_reg_q),.strobe_in(strobe_mult), .out(ddc_chain_out[15:0]), .strobe_out());
 | 
			
		||||
 | 
			
		||||
   dsp_rx_glue #(.DSPNO(DSPNO), .WIDTH(WIDTH)) custom(
 | 
			
		||||
    .clock(clk), .reset(rst), .clear(clr), .enable(run),
 | 
			
		||||
    .set_stb(set_stb_user), .set_addr(set_addr_user), .set_data(set_data_user),
 | 
			
		||||
    .frontend_i(rx_fe_i_mux), .frontend_q(rx_fe_q_mux),
 | 
			
		||||
    .ddc_in_i(to_ddc_chain_i), .ddc_in_q(to_ddc_chain_q),
 | 
			
		||||
    .ddc_out_sample(ddc_chain_out), .ddc_out_strobe(ddc_chain_stb), .ddc_out_enable(ddc_enb),
 | 
			
		||||
    .bb_sample(sample), .bb_strobe(strobe));
 | 
			
		||||
 | 
			
		||||
   assign      debug = {enable_hb1, enable_hb2, run, strobe, strobe_cic, strobe_hb1, strobe_hb2};
 | 
			
		||||
   
 | 
			
		||||
endmodule // ddc_chain
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
 | 
			
		||||
`timescale 1ns/1ns
 | 
			
		||||
module dsp_core_rx_tb();
 | 
			
		||||
module ddc_chain_tb();
 | 
			
		||||
   
 | 
			
		||||
   reg clk, rst;
 | 
			
		||||
 | 
			
		||||
@@ -9,8 +9,8 @@ module dsp_core_rx_tb();
 | 
			
		||||
   initial clk = 0;
 | 
			
		||||
   always #5 clk = ~clk;
 | 
			
		||||
   
 | 
			
		||||
   initial $dumpfile("dsp_core_rx_tb.vcd");
 | 
			
		||||
   initial $dumpvars(0,dsp_core_rx_tb);
 | 
			
		||||
   initial $dumpfile("ddc_chain_tb.vcd");
 | 
			
		||||
   initial $dumpvars(0,ddc_chain_tb);
 | 
			
		||||
   
 | 
			
		||||
   reg signed [23:0] adc_in;
 | 
			
		||||
   wire signed [15:0] adc_out_i, adc_out_q;
 | 
			
		||||
@@ -27,7 +27,7 @@ module dsp_core_rx_tb();
 | 
			
		||||
   reg [7:0] set_addr;
 | 
			
		||||
   reg [31:0] set_data;
 | 
			
		||||
   
 | 
			
		||||
   dsp_core_rx #(.BASE(0)) dsp_core_rx
 | 
			
		||||
   ddc_chain #(.BASE(0)) ddc_chain
 | 
			
		||||
     (.clk(clk),.rst(rst),
 | 
			
		||||
      .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data),
 | 
			
		||||
      .adc_i(adc_in), .adc_ovf_i(0),
 | 
			
		||||
@@ -70,4 +70,4 @@ module dsp_core_rx_tb();
 | 
			
		||||
       adc_in <= adc_in + 4;
 | 
			
		||||
   //adc_in <= (($random % 473) + 23)/4;
 | 
			
		||||
*/   
 | 
			
		||||
endmodule // dsp_core_rx_tb
 | 
			
		||||
endmodule // ddc_chain_tb
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										98
									
								
								fpga/sdr_lib/dsp_rx_glue.v
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								fpga/sdr_lib/dsp_rx_glue.v
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,98 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2012 Ettus Research LLC
 | 
			
		||||
//
 | 
			
		||||
// This program is free software: you can redistribute it and/or modify
 | 
			
		||||
// it under the terms of the GNU General Public License as published by
 | 
			
		||||
// the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
// (at your option) any later version.
 | 
			
		||||
//
 | 
			
		||||
// This program is distributed in the hope that it will be useful,
 | 
			
		||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
// GNU General Public License for more details.
 | 
			
		||||
//
 | 
			
		||||
// You should have received a copy of the GNU General Public License
 | 
			
		||||
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
//The following module effects the IO of the DDC chain.
 | 
			
		||||
//By default, this entire module is a simple pass-through.
 | 
			
		||||
 | 
			
		||||
module dsp_rx_glue
 | 
			
		||||
#(
 | 
			
		||||
    //the dsp unit number: 0, 1, 2...
 | 
			
		||||
    parameter DSPNO = 0,
 | 
			
		||||
 | 
			
		||||
    //frontend bus width
 | 
			
		||||
    parameter WIDTH = 24
 | 
			
		||||
)
 | 
			
		||||
(
 | 
			
		||||
    //control signals
 | 
			
		||||
    input clock, input reset, input clear, input enable,
 | 
			
		||||
 | 
			
		||||
    //user settings bus, controlled through user setting regs API
 | 
			
		||||
    input set_stb, input [7:0] set_addr, input [31:0] set_data,
 | 
			
		||||
 | 
			
		||||
    //full rate inputs directly from the RX frontend
 | 
			
		||||
    input [WIDTH-1:0] frontend_i,
 | 
			
		||||
    input [WIDTH-1:0] frontend_q,
 | 
			
		||||
 | 
			
		||||
    //full rate outputs directly to the DDC chain
 | 
			
		||||
    output [WIDTH-1:0] ddc_in_i,
 | 
			
		||||
    output [WIDTH-1:0] ddc_in_q,
 | 
			
		||||
 | 
			
		||||
    //strobed samples {I16,Q16} from the RX DDC chain
 | 
			
		||||
    input [31:0] ddc_out_sample,
 | 
			
		||||
    input ddc_out_strobe, //high on valid sample
 | 
			
		||||
    output ddc_out_enable, //enables DDC module
 | 
			
		||||
 | 
			
		||||
    //strobbed baseband samples {I16,Q16} from this module
 | 
			
		||||
    output [31:0] bb_sample,
 | 
			
		||||
    output bb_strobe, //high on valid sample
 | 
			
		||||
 | 
			
		||||
    //debug output (optional)
 | 
			
		||||
    output [31:0] debug
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
    generate
 | 
			
		||||
        if (DSPNO==0) begin
 | 
			
		||||
            `ifndef RX_DSP0_MODULE
 | 
			
		||||
            assign ddc_in_i = frontend_i;
 | 
			
		||||
            assign ddc_in_q = frontend_q;
 | 
			
		||||
            assign bb_sample = ddc_out_sample;
 | 
			
		||||
            assign bb_strobe = ddc_out_strobe;
 | 
			
		||||
            assign ddc_out_enable = enable;
 | 
			
		||||
            `else
 | 
			
		||||
            `RX_DSP0_MODULE #(.WIDTH(WIDTH)) rx_dsp0_custom
 | 
			
		||||
            (
 | 
			
		||||
                .clock(clock), .reset(reset), .clear(clear), .enable(enable),
 | 
			
		||||
                .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data),
 | 
			
		||||
                .frontend_i(frontend_i), .frontend_q(frontend_q),
 | 
			
		||||
                .ddc_in_i(ddc_in_i), .ddc_in_q(ddc_in_q),
 | 
			
		||||
                .ddc_out_sample(ddc_out_sample), .ddc_out_strobe(ddc_out_strobe), .ddc_out_enable(ddc_out_enable),
 | 
			
		||||
                .bb_sample(bb_sample), .bb_strobe(bb_strobe)
 | 
			
		||||
            );
 | 
			
		||||
            `endif
 | 
			
		||||
        end
 | 
			
		||||
        else begin
 | 
			
		||||
            `ifndef RX_DSP1_MODULE
 | 
			
		||||
            assign ddc_in_i = frontend_i;
 | 
			
		||||
            assign ddc_in_q = frontend_q;
 | 
			
		||||
            assign bb_sample = ddc_out_sample;
 | 
			
		||||
            assign bb_strobe = ddc_out_strobe;
 | 
			
		||||
            assign ddc_out_enable = enable;
 | 
			
		||||
            `else
 | 
			
		||||
            `RX_DSP1_MODULE #(.WIDTH(WIDTH)) rx_dsp1_custom
 | 
			
		||||
            (
 | 
			
		||||
                .clock(clock), .reset(reset), .clear(clear), .enable(enable),
 | 
			
		||||
                .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data),
 | 
			
		||||
                .frontend_i(frontend_i), .frontend_q(frontend_q),
 | 
			
		||||
                .ddc_in_i(ddc_in_i), .ddc_in_q(ddc_in_q),
 | 
			
		||||
                .ddc_out_sample(ddc_out_sample), .ddc_out_strobe(ddc_out_strobe), .ddc_out_enable(ddc_out_enable),
 | 
			
		||||
                .bb_sample(bb_sample), .bb_strobe(bb_strobe)
 | 
			
		||||
            );
 | 
			
		||||
            `endif
 | 
			
		||||
        end
 | 
			
		||||
    endgenerate
 | 
			
		||||
 | 
			
		||||
endmodule //dsp_rx_glue
 | 
			
		||||
							
								
								
									
										98
									
								
								fpga/sdr_lib/dsp_tx_glue.v
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								fpga/sdr_lib/dsp_tx_glue.v
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,98 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2012 Ettus Research LLC
 | 
			
		||||
//
 | 
			
		||||
// This program is free software: you can redistribute it and/or modify
 | 
			
		||||
// it under the terms of the GNU General Public License as published by
 | 
			
		||||
// the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
// (at your option) any later version.
 | 
			
		||||
//
 | 
			
		||||
// This program is distributed in the hope that it will be useful,
 | 
			
		||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
// GNU General Public License for more details.
 | 
			
		||||
//
 | 
			
		||||
// You should have received a copy of the GNU General Public License
 | 
			
		||||
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
//The following module effects the IO of the DUC chain.
 | 
			
		||||
//By default, this entire module is a simple pass-through.
 | 
			
		||||
 | 
			
		||||
module dsp_tx_glue
 | 
			
		||||
#(
 | 
			
		||||
    //the dsp unit number: 0, 1, 2...
 | 
			
		||||
    parameter DSPNO = 0,
 | 
			
		||||
 | 
			
		||||
    //frontend bus width
 | 
			
		||||
    parameter WIDTH = 24
 | 
			
		||||
)
 | 
			
		||||
(
 | 
			
		||||
    //control signals
 | 
			
		||||
    input clock, input reset, input clear, input enable,
 | 
			
		||||
 | 
			
		||||
    //user settings bus, controlled through user setting regs API
 | 
			
		||||
    input set_stb, input [7:0] set_addr, input [31:0] set_data,
 | 
			
		||||
 | 
			
		||||
    //full rate outputs directly to the TX frontend
 | 
			
		||||
    output [WIDTH-1:0] frontend_i,
 | 
			
		||||
    output [WIDTH-1:0] frontend_q,
 | 
			
		||||
 | 
			
		||||
    //full rate outputs directly from the DUC chain
 | 
			
		||||
    input [WIDTH-1:0] duc_out_i,
 | 
			
		||||
    input [WIDTH-1:0] duc_out_q,
 | 
			
		||||
 | 
			
		||||
    //strobed samples {I16,Q16} to the TX DUC chain
 | 
			
		||||
    output [31:0] duc_in_sample,
 | 
			
		||||
    input duc_in_strobe, //this is a backpressure signal
 | 
			
		||||
    output duc_in_enable, //enables DUC module
 | 
			
		||||
 | 
			
		||||
    //strobbed baseband samples {I16,Q16} to this module
 | 
			
		||||
    input [31:0] bb_sample,
 | 
			
		||||
    output bb_strobe, //this is a backpressure signal
 | 
			
		||||
 | 
			
		||||
    //debug output (optional)
 | 
			
		||||
    output [31:0] debug
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
    generate
 | 
			
		||||
        if (DSPNO==0) begin
 | 
			
		||||
            `ifndef TX_DSP0_MODULE
 | 
			
		||||
            assign frontend_i = duc_out_i;
 | 
			
		||||
            assign frontend_q = duc_out_q;
 | 
			
		||||
            assign duc_in_sample = bb_sample;
 | 
			
		||||
            assign bb_strobe = duc_in_strobe;
 | 
			
		||||
            assign duc_in_enable = enable;
 | 
			
		||||
            `else
 | 
			
		||||
            `TX_DSP0_MODULE #(.WIDTH(WIDTH)) tx_dsp0_custom
 | 
			
		||||
            (
 | 
			
		||||
                .clock(clock), .reset(reset), .clear(clear), .enable(enable),
 | 
			
		||||
                .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data),
 | 
			
		||||
                .frontend_i(frontend_i), .frontend_q(frontend_q),
 | 
			
		||||
                .duc_out_i(duc_out_i), .duc_out_q(duc_out_q),
 | 
			
		||||
                .duc_in_sample(duc_in_sample), .duc_in_strobe(duc_in_strobe), .duc_in_enable(duc_in_enable),
 | 
			
		||||
                .bb_sample(bb_sample), .bb_strobe(bb_strobe)
 | 
			
		||||
            );
 | 
			
		||||
            `endif
 | 
			
		||||
        end
 | 
			
		||||
        else begin
 | 
			
		||||
            `ifndef TX_DSP1_MODULE
 | 
			
		||||
            assign frontend_i = duc_out_i;
 | 
			
		||||
            assign frontend_q = duc_out_q;
 | 
			
		||||
            assign duc_in_sample = bb_sample;
 | 
			
		||||
            assign bb_strobe = duc_in_strobe;
 | 
			
		||||
            assign duc_in_enable = enable;
 | 
			
		||||
            `else
 | 
			
		||||
            `TX_DSP1_MODULE #(.WIDTH(WIDTH)) tx_dsp1_custom
 | 
			
		||||
            (
 | 
			
		||||
                .clock(clock), .reset(reset), .clear(clear), .enable(enable),
 | 
			
		||||
                .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data),
 | 
			
		||||
                .frontend_i(frontend_i), .frontend_q(frontend_q),
 | 
			
		||||
                .duc_out_i(duc_out_i), .duc_out_q(duc_out_q),
 | 
			
		||||
                .duc_in_sample(duc_in_sample), .duc_in_strobe(duc_in_strobe), .duc_in_enable(duc_in_enable),
 | 
			
		||||
                .bb_sample(bb_sample), .bb_strobe(bb_strobe)
 | 
			
		||||
            );
 | 
			
		||||
            `endif
 | 
			
		||||
        end
 | 
			
		||||
    endgenerate
 | 
			
		||||
 | 
			
		||||
endmodule //dsp_tx_glue
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
 | 
			
		||||
// Copyright 2011 Ettus Research LLC
 | 
			
		||||
// Copyright 2011-2013 Ettus Research LLC
 | 
			
		||||
//
 | 
			
		||||
// This program is free software: you can redistribute it and/or modify
 | 
			
		||||
// it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -32,13 +32,11 @@ module dspengine_16to8
 | 
			
		||||
    input [35:0] access_dat_i
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
   wire 	 convert;
 | 
			
		||||
   wire [17:0] 	 scale_factor;
 | 
			
		||||
   
 | 
			
		||||
   setting_reg #(.my_addr(BASE),.width(19)) sr_16to8
 | 
			
		||||
   wire convert;
 | 
			
		||||
   setting_reg #(.my_addr(BASE),.width(1)) sr_16to8
 | 
			
		||||
     (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr),
 | 
			
		||||
      .in(set_data),.out({convert,scale_factor}),.changed());
 | 
			
		||||
   
 | 
			
		||||
      .in(set_data),.out(convert),.changed());
 | 
			
		||||
 | 
			
		||||
   reg [2:0] 	 dsp_state;
 | 
			
		||||
   localparam DSP_IDLE = 0;
 | 
			
		||||
   localparam DSP_PARSE_HEADER = 1;
 | 
			
		||||
@@ -63,7 +61,7 @@ module dspengine_16to8
 | 
			
		||||
   wire [15:0] 	 scaled_i, scaled_q;
 | 
			
		||||
   wire [7:0] 	 i8, q8;
 | 
			
		||||
   reg [7:0] 	 i8_reg, q8_reg;
 | 
			
		||||
   wire 	 stb_read, stb_mult, stb_clip, stb_round, val_read, val_mult, val_clip, val_round;
 | 
			
		||||
   wire 	 stb_read, stb_clip, val_read, val_clip;
 | 
			
		||||
   wire 	 stb_out, stb_reg;
 | 
			
		||||
   reg 		 even;
 | 
			
		||||
   
 | 
			
		||||
@@ -183,8 +181,8 @@ module dspengine_16to8
 | 
			
		||||
 | 
			
		||||
   assign access_dat_o = (dsp_state == DSP_WRITE_HEADER) ? { 4'h1, new_header } :
 | 
			
		||||
			 (dsp_state == DSP_WRITE_TRAILER) ? { 4'h2, new_trailer } :
 | 
			
		||||
			 (last_o&~even_o) ? {4'h0, 16'd0, i8, q8 } : 
 | 
			
		||||
			 {4'h0, i8, q8, i8_reg, q8_reg };
 | 
			
		||||
			 (last_o&~even_o) ? {4'h0, i8, q8, 16'd0 } :
 | 
			
		||||
			 {4'h0, i8_reg, q8_reg, i8, q8 };
 | 
			
		||||
   
 | 
			
		||||
   assign access_adr = (stb_write|(dsp_state == DSP_WRITE_HEADER)|(dsp_state == DSP_WRITE_TRAILER)) ? write_adr : read_adr;
 | 
			
		||||
      
 | 
			
		||||
@@ -193,29 +191,21 @@ module dspengine_16to8
 | 
			
		||||
   wire [15:0] i16 = access_dat_i[31:16];
 | 
			
		||||
   wire [15:0] q16 = access_dat_i[15:0];
 | 
			
		||||
 | 
			
		||||
   pipectrl #(.STAGES(4), .TAGWIDTH(2)) pipectrl 
 | 
			
		||||
   pipectrl #(.STAGES(2), .TAGWIDTH(2)) pipectrl
 | 
			
		||||
     (.clk(clk), .reset(reset),
 | 
			
		||||
      .src_rdy_i(send_to_pipe), .dst_rdy_o(), // dst_rdy_o will always be 1 since dst_rdy_i is 1, below
 | 
			
		||||
      .src_rdy_o(stb_out), .dst_rdy_i(1),   // always accept output of chain
 | 
			
		||||
      .strobes({stb_round,stb_clip,stb_mult,stb_read}), .valids({val_round,val_clip,val_mult,val_read}),
 | 
			
		||||
      .strobes({stb_clip,stb_read}), .valids({val_clip,val_read}),
 | 
			
		||||
      .tag_i({last,even}), .tag_o({last_o,even_o}));
 | 
			
		||||
 | 
			
		||||
   always @(posedge clk)
 | 
			
		||||
     if(stb_out & ~even_o)
 | 
			
		||||
       {i8_reg,q8_reg} <= {i8,q8};
 | 
			
		||||
   
 | 
			
		||||
   MULT18X18S mult_i 
 | 
			
		||||
     (.P(prod_i), .A(scale_factor), .B({i16,2'b00}), .C(clk), .CE(stb_mult), .R(reset) ); 
 | 
			
		||||
   clip_reg #(.bits_in(24),.bits_out(16),.STROBED(1)) clip_i 
 | 
			
		||||
     (.clk(clk), .in(prod_i[35:12]), .out(scaled_i), .strobe_in(stb_clip), .strobe_out());
 | 
			
		||||
   round_sd #(.WIDTH_IN(16),.WIDTH_OUT(8),.DISABLE_SD(1)) round_i
 | 
			
		||||
     (.clk(clk), .reset(reset), .in(scaled_i), .strobe_in(stb_round), .out(i8), .strobe_out());
 | 
			
		||||
 | 
			
		||||
   MULT18X18S mult_q 
 | 
			
		||||
     (.P(prod_q), .A(scale_factor), .B({q16,2'b00}), .C(clk), .CE(stb_mult), .R(reset) ); 
 | 
			
		||||
   clip_reg #(.bits_in(24),.bits_out(16),.STROBED(1)) clip_q 
 | 
			
		||||
     (.clk(clk), .in(prod_q[35:12]), .out(scaled_q), .strobe_in(stb_clip), .strobe_out());
 | 
			
		||||
   round_sd #(.WIDTH_IN(16),.WIDTH_OUT(8),.DISABLE_SD(1)) round_q
 | 
			
		||||
     (.clk(clk), .reset(reset), .in(scaled_q), .strobe_in(stb_round), .out(q8), .strobe_out());
 | 
			
		||||
   clip_reg #(.bits_in(16),.bits_out(8),.STROBED(1)) clip_i
 | 
			
		||||
     (.clk(clk), .in(i16), .out(i8), .strobe_in(stb_clip), .strobe_out());
 | 
			
		||||
 | 
			
		||||
   clip_reg #(.bits_in(16),.bits_out(8),.STROBED(1)) clip_q
 | 
			
		||||
     (.clk(clk), .in(q16), .out(q8), .strobe_in(stb_clip), .strobe_out());
 | 
			
		||||
 | 
			
		||||
endmodule // dspengine_16to8
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										203
									
								
								fpga/sdr_lib/dspengine_8to16.v
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										203
									
								
								fpga/sdr_lib/dspengine_8to16.v
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,203 @@
 | 
			
		||||
 | 
			
		||||
// Copyright 2012-2013 Ettus Research LLC
 | 
			
		||||
//
 | 
			
		||||
// This program is free software: you can redistribute it and/or modify
 | 
			
		||||
// it under the terms of the GNU General Public License as published by
 | 
			
		||||
// the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
// (at your option) any later version.
 | 
			
		||||
//
 | 
			
		||||
// This program is distributed in the hope that it will be useful,
 | 
			
		||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
// GNU General Public License for more details.
 | 
			
		||||
//
 | 
			
		||||
// You should have received a copy of the GNU General Public License
 | 
			
		||||
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
module dspengine_8to16
 | 
			
		||||
  #(parameter BASE = 0,
 | 
			
		||||
    parameter BUF_SIZE = 9,
 | 
			
		||||
    parameter HEADER_OFFSET = 0)
 | 
			
		||||
   (input clk, input reset, input clear,
 | 
			
		||||
    input set_stb, input [7:0] set_addr, input [31:0] set_data,
 | 
			
		||||
 | 
			
		||||
    output access_we,
 | 
			
		||||
    output access_stb,
 | 
			
		||||
    input access_ok,
 | 
			
		||||
    output access_done,
 | 
			
		||||
    output access_skip_read,
 | 
			
		||||
    output [BUF_SIZE-1:0] access_adr,
 | 
			
		||||
    input [BUF_SIZE-1:0] access_len,
 | 
			
		||||
    output [35:0] access_dat_o,
 | 
			
		||||
    input [35:0] access_dat_i
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
   wire 	 convert;
 | 
			
		||||
   
 | 
			
		||||
   setting_reg #(.my_addr(BASE),.width(1)) sr_8to16
 | 
			
		||||
     (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr),
 | 
			
		||||
      .in(set_data),.out(convert),.changed());
 | 
			
		||||
   
 | 
			
		||||
   reg [3:0] 	 dsp_state;
 | 
			
		||||
   localparam DSP_IDLE = 0;
 | 
			
		||||
   localparam DSP_IDLE_RD = 1;
 | 
			
		||||
   localparam DSP_PARSE_HEADER = 2;
 | 
			
		||||
   localparam DSP_READ = 3;
 | 
			
		||||
   localparam DSP_READ_WAIT = 4;
 | 
			
		||||
   localparam DSP_WRITE_1 = 5;
 | 
			
		||||
   localparam DSP_WRITE_0 = 6;
 | 
			
		||||
   localparam DSP_READ_TRAILER = 7;
 | 
			
		||||
   localparam DSP_WRITE_TRAILER = 8;
 | 
			
		||||
   localparam DSP_WRITE_HEADER = 9;
 | 
			
		||||
   localparam DSP_DONE = 10;
 | 
			
		||||
   
 | 
			
		||||
   // Parse VITA header
 | 
			
		||||
   wire 	 is_if_data = (access_dat_i[31:29] == 3'b000);
 | 
			
		||||
   wire 	 has_streamid = access_dat_i[28];
 | 
			
		||||
   wire 	 has_classid = access_dat_i[27];
 | 
			
		||||
   wire 	 has_trailer = access_dat_i[26];
 | 
			
		||||
   // 25:24 reserved, aka SOB/EOB
 | 
			
		||||
   wire 	 has_secs = |access_dat_i[23:22];
 | 
			
		||||
   wire 	 has_tics = |access_dat_i[21:20];
 | 
			
		||||
   wire [3:0] 	 hdr_length = 1 + has_streamid + has_classid + has_classid + has_secs + has_tics + has_tics;
 | 
			
		||||
   reg [15:0] 	 hdr_length_reg;
 | 
			
		||||
 	 
 | 
			
		||||
   reg 		 odd;
 | 
			
		||||
   
 | 
			
		||||
   reg [BUF_SIZE-1:0] read_adr, write_adr;
 | 
			
		||||
   reg 		      has_trailer_reg;
 | 
			
		||||
   
 | 
			
		||||
   reg [31:0] 	      new_header, new_trailer, trailer_mask;
 | 
			
		||||
   reg 		      wait_for_trailer;
 | 
			
		||||
   reg [15:0] 	      data_in_len;
 | 
			
		||||
   wire       	      is_odd = access_dat_i[22] & access_dat_i[10];
 | 
			
		||||
   wire [15:0] 	      data_in_lenx2 = {data_in_len[14:0], 1'b0} - is_odd;
 | 
			
		||||
 | 
			
		||||
   reg [7:0] 	      i8_0, q8_0;
 | 
			
		||||
   wire [7:0] 	      i8_1 = access_dat_i[15:8];
 | 
			
		||||
   wire [7:0] 	      q8_1 = access_dat_i[7:0];
 | 
			
		||||
   reg 		      skip;
 | 
			
		||||
   
 | 
			
		||||
 | 
			
		||||
   always @(posedge clk)
 | 
			
		||||
     { i8_0, q8_0 } <= access_dat_i[31:16];
 | 
			
		||||
   
 | 
			
		||||
   always @(posedge clk)
 | 
			
		||||
     if(reset | clear)
 | 
			
		||||
       dsp_state <= DSP_IDLE;
 | 
			
		||||
     else
 | 
			
		||||
       case(dsp_state)
 | 
			
		||||
	 DSP_IDLE :
 | 
			
		||||
	   begin
 | 
			
		||||
	      read_adr <= HEADER_OFFSET;
 | 
			
		||||
	      write_adr <= HEADER_OFFSET;
 | 
			
		||||
	      if(access_ok)
 | 
			
		||||
		dsp_state <= DSP_IDLE_RD;
 | 
			
		||||
	   end
 | 
			
		||||
 | 
			
		||||
	 DSP_IDLE_RD: //extra idle state for read to become valid
 | 
			
		||||
		dsp_state <= DSP_PARSE_HEADER;
 | 
			
		||||
 | 
			
		||||
	 DSP_PARSE_HEADER :
 | 
			
		||||
	   begin
 | 
			
		||||
	      has_trailer_reg <= has_trailer;
 | 
			
		||||
	      new_header[31:0] <= access_dat_i[31:0];
 | 
			
		||||
	      hdr_length_reg <= hdr_length;
 | 
			
		||||
	      if(~is_if_data | ~convert | ~has_trailer)
 | 
			
		||||
		// ~convert is valid (16 bit mode) but both ~trailer and ~is_if_data are both
 | 
			
		||||
		// really error conditions on the TX side.  We shouldn't ever see them in the TX chain
 | 
			
		||||
		dsp_state <= DSP_WRITE_HEADER;  
 | 
			
		||||
	      else
 | 
			
		||||
		begin
 | 
			
		||||
		   read_adr <= access_dat_i[15:0] + HEADER_OFFSET - 1; // point to trailer
 | 
			
		||||
		   dsp_state <= DSP_READ_TRAILER;
 | 
			
		||||
		   wait_for_trailer <= 0;
 | 
			
		||||
		   data_in_len <= access_dat_i[15:0] - hdr_length - 1 /*trailer*/;
 | 
			
		||||
		end
 | 
			
		||||
	   end
 | 
			
		||||
	 
 | 
			
		||||
	 DSP_READ_TRAILER :
 | 
			
		||||
	   begin
 | 
			
		||||
	      wait_for_trailer <= 1;
 | 
			
		||||
	      if(wait_for_trailer)
 | 
			
		||||
		dsp_state <= DSP_WRITE_TRAILER;
 | 
			
		||||
	      new_trailer <= access_dat_i[31:0]; // Leave trailer unchanged
 | 
			
		||||
	      odd <= is_odd;
 | 
			
		||||
	      write_adr <= hdr_length_reg + data_in_lenx2 + HEADER_OFFSET;
 | 
			
		||||
	   end
 | 
			
		||||
 | 
			
		||||
	 DSP_WRITE_TRAILER :
 | 
			
		||||
	   begin
 | 
			
		||||
	      dsp_state <= DSP_READ;
 | 
			
		||||
	      write_adr <= write_adr - 1;
 | 
			
		||||
	      read_adr <= read_adr - 1;
 | 
			
		||||
	      new_header[15:0] <= write_adr + (1 - HEADER_OFFSET); // length = addr of trailer + 1
 | 
			
		||||
	   end
 | 
			
		||||
 | 
			
		||||
	 DSP_READ :
 | 
			
		||||
	   begin
 | 
			
		||||
	      read_adr <= read_adr - 1;
 | 
			
		||||
	      if(odd)
 | 
			
		||||
		dsp_state <= DSP_READ_WAIT;
 | 
			
		||||
	      else
 | 
			
		||||
		dsp_state <= DSP_WRITE_1;
 | 
			
		||||
	      odd <= 0;
 | 
			
		||||
	   end
 | 
			
		||||
 | 
			
		||||
	 DSP_READ_WAIT :
 | 
			
		||||
	   dsp_state <= DSP_WRITE_0;
 | 
			
		||||
	 
 | 
			
		||||
	 DSP_WRITE_1 :
 | 
			
		||||
	   begin
 | 
			
		||||
	      write_adr <= write_adr - 1;
 | 
			
		||||
	      if(write_adr == (hdr_length_reg+HEADER_OFFSET))
 | 
			
		||||
		begin
 | 
			
		||||
		   write_adr <= HEADER_OFFSET;
 | 
			
		||||
		   dsp_state <= DSP_WRITE_HEADER;
 | 
			
		||||
		end
 | 
			
		||||
	      dsp_state <= DSP_WRITE_0;
 | 
			
		||||
	   end
 | 
			
		||||
 | 
			
		||||
	 DSP_WRITE_0 :
 | 
			
		||||
	   begin
 | 
			
		||||
	      write_adr <= write_adr - 1;
 | 
			
		||||
	      if(write_adr == (hdr_length_reg+HEADER_OFFSET))
 | 
			
		||||
		begin
 | 
			
		||||
		   write_adr <= HEADER_OFFSET;
 | 
			
		||||
		   dsp_state <= DSP_WRITE_HEADER;
 | 
			
		||||
		end
 | 
			
		||||
	      else
 | 
			
		||||
		dsp_state <= DSP_READ;
 | 
			
		||||
	   end
 | 
			
		||||
 | 
			
		||||
	 DSP_WRITE_HEADER :
 | 
			
		||||
	   dsp_state <= DSP_DONE;
 | 
			
		||||
 | 
			
		||||
	 DSP_DONE :
 | 
			
		||||
	   begin
 | 
			
		||||
	      read_adr <= HEADER_OFFSET;
 | 
			
		||||
	      write_adr <= HEADER_OFFSET;
 | 
			
		||||
	      dsp_state <= DSP_IDLE;
 | 
			
		||||
	   end
 | 
			
		||||
       endcase // case (dsp_state)
 | 
			
		||||
 | 
			
		||||
   assign access_skip_read = 0;
 | 
			
		||||
   assign access_done = (dsp_state == DSP_DONE);
 | 
			
		||||
 | 
			
		||||
   assign access_stb = 1;
 | 
			
		||||
 | 
			
		||||
   assign access_we = (dsp_state == DSP_WRITE_HEADER) | 
 | 
			
		||||
		      (dsp_state == DSP_WRITE_TRAILER) |
 | 
			
		||||
		      (dsp_state == DSP_WRITE_0) |
 | 
			
		||||
		      (dsp_state == DSP_WRITE_1);
 | 
			
		||||
   
 | 
			
		||||
   assign access_dat_o = (dsp_state == DSP_WRITE_HEADER) ? { 4'h0, new_header } :
 | 
			
		||||
			 (dsp_state == DSP_WRITE_TRAILER) ? { 4'h2, new_trailer } :
 | 
			
		||||
			 (dsp_state == DSP_WRITE_0) ? { 4'h0, i8_0, 8'd0, q8_0, 8'd0 } :
 | 
			
		||||
			 (dsp_state == DSP_WRITE_1) ? { 4'h0, i8_1, 8'd0, q8_1, 8'd0 } :
 | 
			
		||||
			 34'h0DEADBEEF;
 | 
			
		||||
         
 | 
			
		||||
   assign access_adr = access_we ? write_adr : read_adr;
 | 
			
		||||
      
 | 
			
		||||
endmodule // dspengine_16to8
 | 
			
		||||
							
								
								
									
										165
									
								
								fpga/sdr_lib/duc_chain.v
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								fpga/sdr_lib/duc_chain.v
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,165 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2011-2012 Ettus Research LLC
 | 
			
		||||
//
 | 
			
		||||
// This program is free software: you can redistribute it and/or modify
 | 
			
		||||
// it under the terms of the GNU General Public License as published by
 | 
			
		||||
// the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
// (at your option) any later version.
 | 
			
		||||
//
 | 
			
		||||
// This program is distributed in the hope that it will be useful,
 | 
			
		||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
// GNU General Public License for more details.
 | 
			
		||||
//
 | 
			
		||||
// You should have received a copy of the GNU General Public License
 | 
			
		||||
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
//! 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,
 | 
			
		||||
   input set_stb_user, input [7:0] set_addr_user, input [31:0] set_data_user,
 | 
			
		||||
 | 
			
		||||
   // 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 duc_enb;
 | 
			
		||||
   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;
 | 
			
		||||
   
 | 
			
		||||
   cic_strober #(.WIDTH(8))
 | 
			
		||||
     cic_strober(.clock(clk),.reset(rst),.enable(duc_enb & ~rate_change),.rate(interp_rate),
 | 
			
		||||
		 .strobe_fast(1),.strobe_slow(strobe_cic_pre) );
 | 
			
		||||
   cic_strober #(.WIDTH(2))
 | 
			
		||||
     hb2_strober(.clock(clk),.reset(rst),.enable(duc_enb & ~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(duc_enb & ~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(~duc_enb)
 | 
			
		||||
       phase <= 0;
 | 
			
		||||
     else
 | 
			
		||||
       phase <= phase + phase_inc;
 | 
			
		||||
   
 | 
			
		||||
   wire        signed [17:0] da, db;
 | 
			
		||||
   wire        signed [35:0] prod_i, prod_q;
 | 
			
		||||
 | 
			
		||||
   wire [15:0] bb_i;
 | 
			
		||||
   wire [15:0] bb_q;
 | 
			
		||||
   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({bb_i, 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({bb_q, 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(duc_enb & ~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(duc_enb & ~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(duc_enb),
 | 
			
		||||
	    .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
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
   dsp_tx_glue #(.DSPNO(DSPNO), .WIDTH(WIDTH)) dsp_tx_glue(
 | 
			
		||||
    .clock(clk), .reset(rst), .clear(clr), .enable(run),
 | 
			
		||||
    .set_stb(set_stb_user), .set_addr(set_addr_user), .set_data(set_data_user),
 | 
			
		||||
    .frontend_i(tx_fe_i), .frontend_q(tx_fe_q),
 | 
			
		||||
    .duc_out_i(prod_i[33:34-WIDTH]), .duc_out_q(prod_q[33:34-WIDTH]),
 | 
			
		||||
    .duc_in_sample({bb_i, bb_q}), .duc_in_strobe(strobe_hb1), .duc_in_enable(duc_enb),
 | 
			
		||||
    .bb_sample(sample), .bb_strobe(strobe));
 | 
			
		||||
 | 
			
		||||
   assign      debug = {strobe_cic, strobe_hb1, strobe_hb2,run};
 | 
			
		||||
 | 
			
		||||
endmodule // dsp_core
 | 
			
		||||
@@ -76,4 +76,4 @@ module dummy_rx
 | 
			
		||||
       q_out <= q_out + 1;
 | 
			
		||||
       
 | 
			
		||||
   
 | 
			
		||||
endmodule // dsp_core_rx
 | 
			
		||||
endmodule // ddc_chain
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,6 @@ module rx_frontend
 | 
			
		||||
  #(parameter BASE = 0,
 | 
			
		||||
    parameter IQCOMP_EN = 1)
 | 
			
		||||
   (input clk, input rst,
 | 
			
		||||
    input adc_clk,
 | 
			
		||||
    input set_stb, input [7:0] set_addr, input [31:0] set_data,
 | 
			
		||||
 | 
			
		||||
    input [15:0] adc_a, input adc_ovf_a,
 | 
			
		||||
@@ -23,7 +22,7 @@ module rx_frontend
 | 
			
		||||
     (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
 | 
			
		||||
      .in(set_data),.out(swap_iq),.changed());
 | 
			
		||||
 | 
			
		||||
   always @(posedge adc_clk)
 | 
			
		||||
   always @(posedge clk)
 | 
			
		||||
     if(swap_iq) // Swap
 | 
			
		||||
       {adc_i,adc_q} <= {adc_b,adc_a};
 | 
			
		||||
     else
 | 
			
		||||
@@ -41,37 +40,37 @@ module rx_frontend
 | 
			
		||||
      if(IQCOMP_EN == 1)
 | 
			
		||||
	begin
 | 
			
		||||
	   rx_dcoffset #(.WIDTH(18),.ADDR(BASE+3)) rx_dcoffset_i
 | 
			
		||||
	     (.clk(adc_clk),.rst(rst),.set_stb(set_stb),.set_addr(set_addr),.set_data(set_data),
 | 
			
		||||
	     (.clk(clk),.rst(rst),.set_stb(set_stb),.set_addr(set_addr),.set_data(set_data),
 | 
			
		||||
	      .in({adc_i,2'b00}),.out(adc_i_ofs));
 | 
			
		||||
	   
 | 
			
		||||
	   rx_dcoffset #(.WIDTH(18),.ADDR(BASE+4)) rx_dcoffset_q
 | 
			
		||||
	     (.clk(adc_clk),.rst(rst),.set_stb(set_stb),.set_addr(set_addr),.set_data(set_data),
 | 
			
		||||
	     (.clk(clk),.rst(rst),.set_stb(set_stb),.set_addr(set_addr),.set_data(set_data),
 | 
			
		||||
	      .in({adc_q,2'b00}),.out(adc_q_ofs));
 | 
			
		||||
	   
 | 
			
		||||
	   MULT18X18S mult_mag_corr
 | 
			
		||||
	     (.P(corr_i), .A(adc_i_ofs), .B(mag_corr), .C(adc_clk), .CE(1), .R(rst) );
 | 
			
		||||
	     (.P(corr_i), .A(adc_i_ofs), .B(mag_corr), .C(clk), .CE(1), .R(rst) ); 
 | 
			
		||||
	   
 | 
			
		||||
	   MULT18X18S mult_phase_corr
 | 
			
		||||
	     (.P(corr_q), .A(adc_i_ofs), .B(phase_corr), .C(adc_clk), .CE(1), .R(rst) );
 | 
			
		||||
	     (.P(corr_q), .A(adc_i_ofs), .B(phase_corr), .C(clk), .CE(1), .R(rst) );
 | 
			
		||||
	   
 | 
			
		||||
	   add2_and_clip_reg #(.WIDTH(24)) add_clip_i
 | 
			
		||||
	     (.clk(adc_clk), .rst(rst),
 | 
			
		||||
	     (.clk(clk), .rst(rst), 
 | 
			
		||||
	      .in1({adc_i_ofs,6'd0}), .in2(corr_i[35:12]), .strobe_in(1'b1),
 | 
			
		||||
	      .sum(i_out), .strobe_out());
 | 
			
		||||
	   
 | 
			
		||||
	   add2_and_clip_reg #(.WIDTH(24)) add_clip_q
 | 
			
		||||
	     (.clk(adc_clk), .rst(rst),
 | 
			
		||||
	     (.clk(clk), .rst(rst), 
 | 
			
		||||
	      .in1({adc_q_ofs,6'd0}), .in2(corr_q[35:12]), .strobe_in(1'b1),
 | 
			
		||||
	      .sum(q_out), .strobe_out());
 | 
			
		||||
	end // if (IQCOMP_EN == 1)
 | 
			
		||||
      else
 | 
			
		||||
	begin
 | 
			
		||||
	   rx_dcoffset #(.WIDTH(24),.ADDR(BASE+3)) rx_dcoffset_i
 | 
			
		||||
	     (.clk(adc_clk),.rst(rst),.set_stb(set_stb),.set_addr(set_addr),.set_data(set_data),
 | 
			
		||||
	     (.clk(clk),.rst(rst),.set_stb(set_stb),.set_addr(set_addr),.set_data(set_data),
 | 
			
		||||
	      .in({adc_i,8'b00}),.out(i_out));
 | 
			
		||||
	   
 | 
			
		||||
	   rx_dcoffset #(.WIDTH(24),.ADDR(BASE+4)) rx_dcoffset_q
 | 
			
		||||
	     (.clk(adc_clk),.rst(rst),.set_stb(set_stb),.set_addr(set_addr),.set_data(set_data),
 | 
			
		||||
	     (.clk(clk),.rst(rst),.set_stb(set_stb),.set_addr(set_addr),.set_data(set_data),
 | 
			
		||||
	      .in({adc_q,8'b00}),.out(q_out));
 | 
			
		||||
	end // else: !if(IQCOMP_EN == 1)
 | 
			
		||||
      endgenerate
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,7 @@
 | 
			
		||||
 | 
			
		||||
module tx_frontend
 | 
			
		||||
  #(parameter BASE=0,
 | 
			
		||||
`ifndef LMS602D_FRONTEND
 | 
			
		||||
    parameter WIDTH_OUT=16,
 | 
			
		||||
`else
 | 
			
		||||
    parameter WIDTH_OUT=12,
 | 
			
		||||
`endif // !`ifndef LMS602D_FRONTEND
 | 
			
		||||
    parameter IQCOMP_EN=1)
 | 
			
		||||
   (input clk, input rst,
 | 
			
		||||
    input set_stb, input [7:0] set_addr, input [31:0] set_data,
 | 
			
		||||
@@ -47,18 +43,18 @@ module tx_frontend
 | 
			
		||||
	begin
 | 
			
		||||
	   // IQ Balance
 | 
			
		||||
	   MULT18X18S mult_mag_corr
 | 
			
		||||
	     (.P(corr_i), .A(tx_i[23:6]), .B(mag_corr), .C(clk), .CE(1), .R(rst) );
 | 
			
		||||
	     (.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),
 | 
			
		||||
	     (.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),
 | 
			
		||||
	     (.clk(clk), .rst(rst), 
 | 
			
		||||
	      .in1(tx_q), .in2(corr_q[35:12]), .strobe_in(1'b1),
 | 
			
		||||
	      .sum(q_bal), .strobe_out());
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -168,14 +168,14 @@ module u2plus_core
 | 
			
		||||
   
 | 
			
		||||
   // FIFO Sizes, 9 = 512 lines, 10 = 1024, 11 = 2048
 | 
			
		||||
   // all (most?) are 36 bits wide, so 9 is 1 BRAM, 10 is 2, 11 is 4 BRAMs
 | 
			
		||||
   // localparam DSP_TX_FIFOSIZE = 9;  unused -- DSPTX uses extram fifo
 | 
			
		||||
   localparam DSP_RX_FIFOSIZE = 10;
 | 
			
		||||
   localparam DSP_TX_FIFOSIZE = 10;
 | 
			
		||||
   localparam ETH_TX_FIFOSIZE = 9;
 | 
			
		||||
   localparam ETH_RX_FIFOSIZE = 11;
 | 
			
		||||
   
 | 
			
		||||
   wire [7:0] 	set_addr, set_addr_dsp, set_addr_sys;
 | 
			
		||||
   wire [31:0] 	set_data, set_data_dsp, set_data_sys;
 | 
			
		||||
   wire 	set_stb, set_stb_dsp, set_stb_sys;
 | 
			
		||||
   wire [7:0] 	set_addr, set_addr_dsp, set_addr_sys, set_addr_user;
 | 
			
		||||
   wire [31:0] 	set_data, set_data_dsp, set_data_sys, set_data_user;
 | 
			
		||||
   wire 	set_stb, set_stb_dsp, set_stb_sys, set_stb_user;
 | 
			
		||||
   
 | 
			
		||||
   reg 		wb_rst;
 | 
			
		||||
   wire 	dsp_rst, sys_rst;
 | 
			
		||||
@@ -619,7 +619,6 @@ module u2plus_core
 | 
			
		||||
   
 | 
			
		||||
   rx_frontend #(.BASE(SR_RX_FRONT0)) rx_frontend0
 | 
			
		||||
     (.clk(dsp_clk),.rst(dsp_rst),
 | 
			
		||||
     .adc_clk(dsp_clk),
 | 
			
		||||
      .set_stb(set_stb_dsp),.set_addr(set_addr_dsp),.set_data(set_data_dsp),
 | 
			
		||||
      .adc_a({adc0_a,4'b00}),.adc_ovf_a(adc_ovf_i_0_mux),
 | 
			
		||||
      .adc_b({adc0_b,4'b00}),.adc_ovf_b(adc_ovf_q_0_mux),
 | 
			
		||||
@@ -627,7 +626,6 @@ module u2plus_core
 | 
			
		||||
 | 
			
		||||
   rx_frontend #(.BASE(SR_RX_FRONT1)) rx_frontend1
 | 
			
		||||
     (.clk(dsp_clk),.rst(dsp_rst),
 | 
			
		||||
     .adc_clk(dsp_clk),
 | 
			
		||||
      .set_stb(set_stb_dsp),.set_addr(set_addr_dsp),.set_data(set_data_dsp),
 | 
			
		||||
      .adc_a({adc1_a,4'b00}),.adc_ovf_a(adc_ovf_i_1_mux),
 | 
			
		||||
      .adc_b({adc1_b,4'b00}),.adc_ovf_b(adc_ovf_q_1_mux),
 | 
			
		||||
@@ -650,77 +648,68 @@ module u2plus_core
 | 
			
		||||
   
 | 
			
		||||
   // /////////////////////////////////////////////////////////////////////////
 | 
			
		||||
   // DSP RX 0
 | 
			
		||||
   wire [31:0] 	 sample_rx0;
 | 
			
		||||
   wire 	 clear_rx0, strobe_rx0;
 | 
			
		||||
 | 
			
		||||
    wire [31:0] 	 sample_rx0;
 | 
			
		||||
    wire 	 strobe_rx0, clear_rx0;
 | 
			
		||||
    wire [35:0] rx0_vita_data;
 | 
			
		||||
    wire rx0_vita1_valid, rx0_vita1_ready;
 | 
			
		||||
    wire rx0_vita_valid, rx0_vita_ready;
 | 
			
		||||
 | 
			
		||||
   always @(posedge dsp_clk)
 | 
			
		||||
    always @(posedge dsp_clk)
 | 
			
		||||
     run_rx0_d1 <= run_rx0;
 | 
			
		||||
   
 | 
			
		||||
   dsp_core_rx #(.BASE(SR_RX_DSP0)) dsp_core_rx0
 | 
			
		||||
     (.clk(dsp_clk),.rst(dsp_rst),
 | 
			
		||||
     .adc_clk(dsp_clk),
 | 
			
		||||
 | 
			
		||||
    ddc_chain #(.BASE(SR_RX_DSP0), .DSPNO(0)) ddc_chain0
 | 
			
		||||
     (.clk(dsp_clk), .rst(dsp_rst), .clr(clear_rx0),
 | 
			
		||||
      .set_stb(set_stb_dsp),.set_addr(set_addr_dsp),.set_data(set_data_dsp),
 | 
			
		||||
      .adc_i(i_0_mux),.adc_ovf_i(adc_ovf_i_0_mux),.adc_q(q_0_mux),.adc_ovf_q(adc_ovf_q_0_mux),
 | 
			
		||||
      .set_stb_user(set_stb_user), .set_addr_user(set_addr_user), .set_data_user(set_data_user),
 | 
			
		||||
      .rx_fe_i(i_0_mux),.rx_fe_q(q_0_mux),
 | 
			
		||||
      .sample(sample_rx0), .run(run_rx0_d1), .strobe(strobe_rx0),
 | 
			
		||||
      .debug() );
 | 
			
		||||
 | 
			
		||||
   setting_reg #(.my_addr(SR_RX_CTRL0+3)) sr_clear_rx0
 | 
			
		||||
     (.clk(dsp_clk),.rst(dsp_rst),
 | 
			
		||||
      .strobe(set_stb_dsp),.addr(set_addr_dsp),.in(set_data_dsp),
 | 
			
		||||
      .out(),.changed(clear_rx0));
 | 
			
		||||
 | 
			
		||||
   vita_rx_chain #(.BASE(SR_RX_CTRL0),.UNIT(0),.FIFOSIZE(DSP_RX_FIFOSIZE)) vita_rx_chain0
 | 
			
		||||
     (.clk(dsp_clk), .reset(dsp_rst), .clear(clear_rx0),
 | 
			
		||||
    vita_rx_chain #(.BASE(SR_RX_CTRL0),.UNIT(0),.FIFOSIZE(DSP_RX_FIFOSIZE), .DSP_NUMBER(0)) vita_rx_chain0
 | 
			
		||||
     (.clk(dsp_clk), .reset(dsp_rst),
 | 
			
		||||
      .set_stb(set_stb_dsp),.set_addr(set_addr_dsp),.set_data(set_data_dsp),
 | 
			
		||||
      .set_stb_user(set_stb_user), .set_addr_user(set_addr_user), .set_data_user(set_data_user),
 | 
			
		||||
      .vita_time(vita_time), .overrun(overrun0),
 | 
			
		||||
      .sample(sample_rx0), .run(run_rx0), .strobe(strobe_rx0),
 | 
			
		||||
      .rx_data_o(rx0_vita_data), .rx_src_rdy_o(rx0_vita1_valid), .rx_dst_rdy_i(rx0_vita1_ready),
 | 
			
		||||
      .sample(sample_rx0), .run(run_rx0), .strobe(strobe_rx0), .clear_o(clear_rx0),
 | 
			
		||||
      .rx_data_o(rx0_vita_data), .rx_src_rdy_o(rx0_vita_valid), .rx_dst_rdy_i(rx0_vita_ready),
 | 
			
		||||
      .debug() );
 | 
			
		||||
 | 
			
		||||
    fifo_2clock #(.WIDTH(36)) fifo_2clock_rx0
 | 
			
		||||
    (
 | 
			
		||||
        .wclk(dsp_clk), .datain(rx0_vita_data), .src_rdy_i(rx0_vita1_valid), .dst_rdy_o(rx0_vita1_ready),
 | 
			
		||||
        .wclk(dsp_clk), .datain(rx0_vita_data), .src_rdy_i(rx0_vita_valid), .dst_rdy_o(rx0_vita_ready),
 | 
			
		||||
        .rclk(sys_clk), .dataout(wr1_dat), .src_rdy_o(wr1_ready_i), .dst_rdy_i(wr1_ready_o),
 | 
			
		||||
        .arst(dsp_rst | sys_rst)
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
   // /////////////////////////////////////////////////////////////////////////
 | 
			
		||||
   // DSP RX 1
 | 
			
		||||
   wire [31:0] 	 sample_rx1;
 | 
			
		||||
   wire 	 clear_rx1, strobe_rx1;
 | 
			
		||||
 | 
			
		||||
    wire [31:0] 	 sample_rx1;
 | 
			
		||||
    wire 	 strobe_rx1, clear_rx1;
 | 
			
		||||
    wire [35:0] rx1_vita_data;
 | 
			
		||||
    wire rx1_vita1_valid, rx1_vita1_ready;
 | 
			
		||||
    wire rx1_vita_valid, rx1_vita_ready;
 | 
			
		||||
 | 
			
		||||
   always @(posedge dsp_clk)
 | 
			
		||||
    always @(posedge dsp_clk)
 | 
			
		||||
     run_rx1_d1 <= run_rx1;
 | 
			
		||||
   
 | 
			
		||||
   dsp_core_rx #(.BASE(SR_RX_DSP1)) dsp_core_rx1
 | 
			
		||||
     (.clk(dsp_clk),.rst(dsp_rst),
 | 
			
		||||
     .adc_clk(dsp_clk),
 | 
			
		||||
 | 
			
		||||
    ddc_chain #(.BASE(SR_RX_DSP1), .DSPNO(1)) ddc_chain1
 | 
			
		||||
     (.clk(dsp_clk), .rst(dsp_rst), .clr(clear_rx1),
 | 
			
		||||
      .set_stb(set_stb_dsp),.set_addr(set_addr_dsp),.set_data(set_data_dsp),
 | 
			
		||||
      .adc_i(i_1_mux),.adc_ovf_i(adc_ovf_i_1_mux),.adc_q(q_1_mux),.adc_ovf_q(adc_ovf_q_1_mux),
 | 
			
		||||
      .set_stb_user(set_stb_user), .set_addr_user(set_addr_user), .set_data_user(set_data_user),
 | 
			
		||||
      .rx_fe_i(i_1_mux),.rx_fe_q(q_1_mux),
 | 
			
		||||
      .sample(sample_rx1), .run(run_rx1_d1), .strobe(strobe_rx1),
 | 
			
		||||
      .debug() );
 | 
			
		||||
 | 
			
		||||
   setting_reg #(.my_addr(SR_RX_CTRL1+3)) sr_clear_rx1
 | 
			
		||||
     (.clk(dsp_clk),.rst(dsp_rst),
 | 
			
		||||
      .strobe(set_stb_dsp),.addr(set_addr_dsp),.in(set_data_dsp),
 | 
			
		||||
      .out(),.changed(clear_rx1));
 | 
			
		||||
   vita_rx_chain #(.BASE(SR_RX_CTRL1),.UNIT(2),.FIFOSIZE(DSP_RX_FIFOSIZE)) vita_rx_chain1
 | 
			
		||||
     (.clk(dsp_clk), .reset(dsp_rst), .clear(clear_rx1),
 | 
			
		||||
    vita_rx_chain #(.BASE(SR_RX_CTRL1),.UNIT(2),.FIFOSIZE(DSP_RX_FIFOSIZE), .DSP_NUMBER(1)) vita_rx_chain1
 | 
			
		||||
     (.clk(dsp_clk), .reset(dsp_rst),
 | 
			
		||||
      .set_stb(set_stb_dsp),.set_addr(set_addr_dsp),.set_data(set_data_dsp),
 | 
			
		||||
      .set_stb_user(set_stb_user), .set_addr_user(set_addr_user), .set_data_user(set_data_user),
 | 
			
		||||
      .vita_time(vita_time), .overrun(overrun1),
 | 
			
		||||
      .sample(sample_rx1), .run(run_rx1), .strobe(strobe_rx1),
 | 
			
		||||
      .rx_data_o(rx1_vita_data), .rx_src_rdy_o(rx1_vita1_valid), .rx_dst_rdy_i(rx1_vita1_ready),
 | 
			
		||||
      .sample(sample_rx1), .run(run_rx1), .strobe(strobe_rx1), .clear_o(clear_rx1),
 | 
			
		||||
      .rx_data_o(rx1_vita_data), .rx_src_rdy_o(rx1_vita_valid), .rx_dst_rdy_i(rx1_vita_ready),
 | 
			
		||||
      .debug() );
 | 
			
		||||
 | 
			
		||||
    fifo_2clock #(.WIDTH(36)) fifo_2clock_rx1
 | 
			
		||||
    (
 | 
			
		||||
        .wclk(dsp_clk), .datain(rx1_vita_data), .src_rdy_i(rx1_vita1_valid), .dst_rdy_o(rx1_vita1_ready),
 | 
			
		||||
        .wclk(dsp_clk), .datain(rx1_vita_data), .src_rdy_i(rx1_vita_valid), .dst_rdy_o(rx1_vita_ready),
 | 
			
		||||
        .rclk(sys_clk), .dataout(wr3_dat), .src_rdy_o(wr3_ready_i), .dst_rdy_i(wr3_ready_o),
 | 
			
		||||
        .arst(dsp_rst | sys_rst)
 | 
			
		||||
    );
 | 
			
		||||
@@ -732,12 +721,8 @@ module u2plus_core
 | 
			
		||||
   wire 	 tx_src_rdy, tx_dst_rdy;
 | 
			
		||||
   wire [35:0] 	 tx_data_1;
 | 
			
		||||
   wire 	 tx_src_rdy_1, tx_dst_rdy_1;
 | 
			
		||||
   wire [31:0] 	 debug_vt;
 | 
			
		||||
   wire 	 clear_tx;
 | 
			
		||||
 | 
			
		||||
   setting_reg #(.my_addr(SR_TX_CTRL+1)) sr_clear_tx
 | 
			
		||||
     (.clk(dsp_clk),.rst(dsp_rst),.strobe(set_stb_dsp),.addr(set_addr_dsp),
 | 
			
		||||
      .in(set_data_dsp),.out(),.changed(clear_tx));
 | 
			
		||||
   wire 	 clear_tx1;
 | 
			
		||||
 | 
			
		||||
`ifndef NO_EXT_FIFO
 | 
			
		||||
   assign 	 RAM_A[20:19] = 2'b0;
 | 
			
		||||
@@ -747,7 +732,7 @@ module u2plus_core
 | 
			
		||||
     ext_fifo_i1
 | 
			
		||||
       (.int_clk(sys_clk),
 | 
			
		||||
	.ext_clk(sys_clk),
 | 
			
		||||
	.rst(sys_rst | clear_tx),
 | 
			
		||||
	.rst(sys_rst | clear_tx | clear_tx1),
 | 
			
		||||
`ifndef NO_EXT_FIFO
 | 
			
		||||
	.RAM_D_pi(RAM_D_pi),
 | 
			
		||||
	.RAM_D_po(RAM_D_po),
 | 
			
		||||
@@ -784,37 +769,12 @@ module u2plus_core
 | 
			
		||||
	.debug2(debug_extfifo2) );
 | 
			
		||||
 | 
			
		||||
   // /////////////////////////////////////////////////////////////////////////
 | 
			
		||||
   // DSP TX 0
 | 
			
		||||
   // DAC Frontend
 | 
			
		||||
   wire [23:0] 	 tx_i, tx_q;
 | 
			
		||||
   wire [23:0] 	 tx1_i, tx1_q;
 | 
			
		||||
   wire [23:0] 	 front_i_0, front_q_0;
 | 
			
		||||
   wire [23:0] 	 front_i_1, front_q_1;
 | 
			
		||||
 | 
			
		||||
    wire [35:0] tx0_vita_data;
 | 
			
		||||
    wire tx0_vita1_valid, tx0_vita1_ready;
 | 
			
		||||
 | 
			
		||||
    fifo_2clock #(.WIDTH(36)) fifo_2clock_tx0
 | 
			
		||||
    (
 | 
			
		||||
        .wclk(sys_clk), .datain(tx_data), .src_rdy_i(tx_src_rdy), .dst_rdy_o(tx_dst_rdy),
 | 
			
		||||
        .rclk(dsp_clk), .dataout(tx0_vita_data), .src_rdy_o(tx1_vita0_valid), .dst_rdy_i(tx0_vita1_ready),
 | 
			
		||||
        .arst(dsp_rst | sys_rst)
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
   vita_tx_chain #(.BASE_CTRL(SR_TX_CTRL), .BASE_DSP(SR_TX_DSP), 
 | 
			
		||||
		   .REPORT_ERROR(1), .DO_FLOW_CONTROL(1),
 | 
			
		||||
		   .PROT_ENG_FLAGS(1), .USE_TRANS_HEADER(1),
 | 
			
		||||
		   .DSP_NUMBER(0))
 | 
			
		||||
   vita_tx_chain
 | 
			
		||||
     (.clk(dsp_clk), .reset(dsp_rst),
 | 
			
		||||
     .dac_clk(dsp_clk),
 | 
			
		||||
      .set_stb(set_stb_dsp),.set_addr(set_addr_dsp),.set_data(set_data_dsp),
 | 
			
		||||
      .vita_time(vita_time),
 | 
			
		||||
      .tx_data_i(tx0_vita_data), .tx_src_rdy_i(tx1_vita0_valid), .tx_dst_rdy_o(tx0_vita1_ready),
 | 
			
		||||
      .err_data_o(tx_err_data), .err_src_rdy_o(tx_err_src_rdy), .err_dst_rdy_i(tx_err_dst_rdy),
 | 
			
		||||
      .tx_i(tx_i),.tx_q(tx_q),
 | 
			
		||||
      .underrun(underrun), .run(run_tx),
 | 
			
		||||
      .debug(debug_vt));
 | 
			
		||||
 | 
			
		||||
   frontend_sw #(.BASE(SR_TX_FRONT_SW)) tx_frontend_sw
 | 
			
		||||
     (
 | 
			
		||||
      .clk(dsp_clk), .rst(dsp_rst),
 | 
			
		||||
@@ -837,34 +797,6 @@ module u2plus_core
 | 
			
		||||
      .tx_i(front_i_0), .tx_q(front_q_0), .run(1'b1),
 | 
			
		||||
      .dac_a(dac0_a), .dac_b(dac0_b));
 | 
			
		||||
 | 
			
		||||
   // /////////////////////////////////////////////////////////////////////////
 | 
			
		||||
   // DSP TX 1
 | 
			
		||||
 | 
			
		||||
    wire [35:0] tx1_vita_data;
 | 
			
		||||
    wire tx1_vita1_valid, tx1_vita1_ready;
 | 
			
		||||
 | 
			
		||||
    fifo_2clock #(.WIDTH(36)) fifo_2clock_tx1
 | 
			
		||||
    (
 | 
			
		||||
        .wclk(sys_clk), .datain(tx_data_1), .src_rdy_i(tx_src_rdy_1), .dst_rdy_o(tx_dst_rdy_1),
 | 
			
		||||
        .rclk(dsp_clk), .dataout(tx1_vita_data), .src_rdy_o(tx1_vita1_valid), .dst_rdy_i(tx1_vita1_ready),
 | 
			
		||||
        .arst(dsp_rst | sys_rst)
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
   vita_tx_chain #(.BASE_CTRL(SR_TX1_CTRL), .BASE_DSP(SR_TX1_DSP), 
 | 
			
		||||
		   .REPORT_ERROR(1), .DO_FLOW_CONTROL(1),
 | 
			
		||||
		   .PROT_ENG_FLAGS(1), .USE_TRANS_HEADER(1),
 | 
			
		||||
		   .DSP_NUMBER(1))
 | 
			
		||||
   vita_tx1_chain
 | 
			
		||||
     (.clk(dsp_clk), .reset(dsp_rst),
 | 
			
		||||
     .dac_clk(dsp_clk),
 | 
			
		||||
      .set_stb(set_stb_dsp),.set_addr(set_addr_dsp),.set_data(set_data_dsp),
 | 
			
		||||
      .vita_time(vita_time),
 | 
			
		||||
      .tx_data_i(tx1_vita_data), .tx_src_rdy_i(tx1_vita_data), .tx_dst_rdy_o(tx1_vita1_ready),
 | 
			
		||||
      .err_data_o(tx1_err_data), .err_src_rdy_o(tx1_err_src_rdy), .err_dst_rdy_i(tx1_err_dst_rdy),
 | 
			
		||||
      .tx_i(tx1_i),.tx_q(tx1_q),
 | 
			
		||||
      .underrun(underrun1), .run(run_tx1),
 | 
			
		||||
      .debug());
 | 
			
		||||
 | 
			
		||||
   tx_frontend #(.BASE(SR_TX1_FRONT)) tx1_frontend
 | 
			
		||||
     (
 | 
			
		||||
     .clk(dsp_clk), .rst(dsp_rst),
 | 
			
		||||
@@ -872,6 +804,80 @@ module u2plus_core
 | 
			
		||||
      .tx_i(front_i_1), .tx_q(front_q_1), .run(1'b1),
 | 
			
		||||
      .dac_a(dac1_a), .dac_b(dac1_b));
 | 
			
		||||
 | 
			
		||||
   // /////////////////////////////////////////////////////////////////////////
 | 
			
		||||
   // DSP TX 0
 | 
			
		||||
    wire [31:0]   sample_tx0;
 | 
			
		||||
    wire strobe_tx0;
 | 
			
		||||
    wire [35:0] tx0_vita_data;
 | 
			
		||||
    wire tx0_vita_valid, tx0_vita_ready;
 | 
			
		||||
 | 
			
		||||
    fifo_2clock #(.WIDTH(36)) fifo_2clock_tx0
 | 
			
		||||
    (
 | 
			
		||||
        .wclk(sys_clk), .datain(tx_data), .src_rdy_i(tx_src_rdy), .dst_rdy_o(tx_dst_rdy),
 | 
			
		||||
        .rclk(dsp_clk), .dataout(tx0_vita_data), .src_rdy_o(tx1_vita0_valid), .dst_rdy_i(tx0_vita_ready),
 | 
			
		||||
        .arst(dsp_rst | sys_rst)
 | 
			
		||||
    );
 | 
			
		||||
   
 | 
			
		||||
    vita_tx_chain #(.BASE(SR_TX_CTRL), .FIFOSIZE(DSP_TX_FIFOSIZE),
 | 
			
		||||
		   .REPORT_ERROR(1), .DO_FLOW_CONTROL(1),
 | 
			
		||||
		   .PROT_ENG_FLAGS(1), .USE_TRANS_HEADER(1),
 | 
			
		||||
		   .DSP_NUMBER(0))
 | 
			
		||||
    vita_tx_chain
 | 
			
		||||
     (.clk(dsp_clk), .reset(dsp_rst),
 | 
			
		||||
      .set_stb(set_stb_dsp),.set_addr(set_addr_dsp),.set_data(set_data_dsp),
 | 
			
		||||
      .set_stb_user(set_stb_user), .set_addr_user(set_addr_user), .set_data_user(set_data_user),
 | 
			
		||||
      .vita_time(vita_time),
 | 
			
		||||
      .tx_data_i(tx0_vita_data), .tx_src_rdy_i(tx1_vita0_valid), .tx_dst_rdy_o(tx0_vita_ready),
 | 
			
		||||
      .err_data_o(tx_err_data), .err_src_rdy_o(tx_err_src_rdy), .err_dst_rdy_i(tx_err_dst_rdy),
 | 
			
		||||
      .sample(sample_tx0), .strobe(strobe_tx0),
 | 
			
		||||
      .underrun(underrun), .run(run_tx), .clear_o(clear_tx),
 | 
			
		||||
      .debug());
 | 
			
		||||
 | 
			
		||||
    duc_chain #(.BASE(SR_TX_DSP), .DSPNO(0)) duc_chain
 | 
			
		||||
     (.clk(dsp_clk),.rst(dsp_rst), .clr(clear_tx),
 | 
			
		||||
      .set_stb(set_stb_dsp),.set_addr(set_addr_dsp),.set_data(set_data_dsp),
 | 
			
		||||
      .set_stb_user(set_stb_user), .set_addr_user(set_addr_user), .set_data_user(set_data_user),
 | 
			
		||||
      .tx_fe_i(tx_i),.tx_fe_q(tx_q),
 | 
			
		||||
      .sample(sample_tx0), .run(run_tx0), .strobe(strobe_tx0),
 | 
			
		||||
      .debug() );
 | 
			
		||||
 | 
			
		||||
   // /////////////////////////////////////////////////////////////////////////
 | 
			
		||||
   // DSP TX 1
 | 
			
		||||
    wire [31:0]   sample_tx1;
 | 
			
		||||
    wire strobe_tx1;
 | 
			
		||||
    wire [35:0] tx1_vita_data;
 | 
			
		||||
    wire tx1_vita_valid, tx1_vita_ready;
 | 
			
		||||
 | 
			
		||||
    fifo_2clock #(.WIDTH(36)) fifo_2clock_tx1
 | 
			
		||||
    (
 | 
			
		||||
        .wclk(sys_clk), .datain(tx_data_1), .src_rdy_i(tx_src_rdy_1), .dst_rdy_o(tx_dst_rdy_1),
 | 
			
		||||
        .rclk(dsp_clk), .dataout(tx1_vita_data), .src_rdy_o(tx1_vita_valid), .dst_rdy_i(tx1_vita_ready),
 | 
			
		||||
        .arst(dsp_rst | sys_rst)
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    vita_tx_chain #(.BASE(SR_TX1_CTRL), .FIFOSIZE(DSP_TX_FIFOSIZE),
 | 
			
		||||
		   .REPORT_ERROR(1), .DO_FLOW_CONTROL(1),
 | 
			
		||||
		   .PROT_ENG_FLAGS(1), .USE_TRANS_HEADER(1),
 | 
			
		||||
		   .DSP_NUMBER(1))
 | 
			
		||||
    vita_tx_chain1
 | 
			
		||||
     (.clk(dsp_clk), .reset(dsp_rst),
 | 
			
		||||
      .set_stb(set_stb_dsp),.set_addr(set_addr_dsp),.set_data(set_data_dsp),
 | 
			
		||||
      .set_stb_user(set_stb_user), .set_addr_user(set_addr_user), .set_data_user(set_data_user),
 | 
			
		||||
      .vita_time(vita_time),
 | 
			
		||||
      .tx_data_i(tx1_vita_data), .tx_src_rdy_i(tx1_vita_valid), .tx_dst_rdy_o(tx1_vita_ready),
 | 
			
		||||
      .err_data_o(tx1_err_data), .err_src_rdy_o(tx1_err_src_rdy), .err_dst_rdy_i(tx1_err_dst_rdy),
 | 
			
		||||
      .sample(sample_tx1), .strobe(strobe_tx1),
 | 
			
		||||
      .underrun(underrun1), .run(run_tx1), .clear_o(clear_tx1),
 | 
			
		||||
      .debug());
 | 
			
		||||
 | 
			
		||||
    duc_chain #(.BASE(SR_TX1_DSP), .DSPNO(1)) duc_chain1
 | 
			
		||||
     (.clk(dsp_clk),.rst(dsp_rst), .clr(clear_tx1),
 | 
			
		||||
      .set_stb(set_stb_dsp),.set_addr(set_addr_dsp),.set_data(set_data_dsp),
 | 
			
		||||
      .set_stb_user(set_stb_user), .set_addr_user(set_addr_user), .set_data_user(set_data_user),
 | 
			
		||||
      .tx_fe_i(tx1_i),.tx_fe_q(tx1_q),
 | 
			
		||||
      .sample(sample_tx1), .run(run_tx1), .strobe(strobe_tx1),
 | 
			
		||||
      .debug() );
 | 
			
		||||
 | 
			
		||||
   // ///////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
   // SERDES
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -191,13 +191,13 @@ wire DivSw1, DivSw2;
 | 
			
		||||
            TX2D_reg <= dac2_b; //DAC_Q signal
 | 
			
		||||
 | 
			
		||||
        TX1IQSEL_reg <= ~dac1_strobe;
 | 
			
		||||
        TX2IQSEL_reg <= ~dac0_strobe;
 | 
			
		||||
        TX2IQSEL_reg <= ~dac2_strobe;
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    reg dsp_clk_div2_tx=0; // DSP clock signal devided by 2
 | 
			
		||||
    always @(negedge lms_clk) dsp_clk_div2_tx = ~dsp_clk_div2_tx;
 | 
			
		||||
    assign dac1_strobe = dsp_clk_div2_tx;
 | 
			
		||||
    assign dac0_strobe = dsp_clk_div2_tx;
 | 
			
		||||
    assign dac2_strobe = dsp_clk_div2_tx;
 | 
			
		||||
 | 
			
		||||
   // Handle Clocks
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -15,4 +15,6 @@ vita_tx_chain.v \
 | 
			
		||||
gen_context_pkt.v \
 | 
			
		||||
trigger_context_pkt.v \
 | 
			
		||||
vita_pkt_gen.v \
 | 
			
		||||
vita_rx_engine_glue.v \
 | 
			
		||||
vita_tx_engine_glue.v \
 | 
			
		||||
))
 | 
			
		||||
 
 | 
			
		||||
@@ -32,12 +32,11 @@ module gen_context_pkt
 | 
			
		||||
   localparam CTXT_PROT_ENG = 1;
 | 
			
		||||
   localparam CTXT_HEADER = 2;
 | 
			
		||||
   localparam CTXT_STREAMID = 3;
 | 
			
		||||
   localparam CTXT_SECS = 4;
 | 
			
		||||
   localparam CTXT_TICS = 5;
 | 
			
		||||
   localparam CTXT_TICS2 = 6;
 | 
			
		||||
   localparam CTXT_MESSAGE = 7;
 | 
			
		||||
   localparam CTXT_FLOWCTRL = 8;
 | 
			
		||||
   localparam CTXT_DONE = 9;
 | 
			
		||||
   localparam CTXT_TICS = 4;
 | 
			
		||||
   localparam CTXT_TICS2 = 5;
 | 
			
		||||
   localparam CTXT_MESSAGE = 6;
 | 
			
		||||
   localparam CTXT_FLOWCTRL = 7;
 | 
			
		||||
   localparam CTXT_DONE = 8;
 | 
			
		||||
 | 
			
		||||
   reg [33:0] 	 data_int;
 | 
			
		||||
   wire 	 src_rdy_int, dst_rdy_int;
 | 
			
		||||
@@ -88,11 +87,10 @@ module gen_context_pkt
 | 
			
		||||
 | 
			
		||||
   always @*
 | 
			
		||||
     case(ctxt_state)
 | 
			
		||||
       CTXT_PROT_ENG : data_int <= { 2'b01, 13'b0, DSP_NUMBER[0], 1'b1, 1'b1, 16'd28 }; // UDP port 1 or 3
 | 
			
		||||
       CTXT_HEADER : data_int <= { 1'b0, (PROT_ENG_FLAGS ? 1'b0 : 1'b1), 12'b010100001101, seqno, 16'd7 };
 | 
			
		||||
       CTXT_PROT_ENG : data_int <= { 2'b01, 13'b0, DSP_NUMBER[0], 1'b1, 1'b1, 16'd24 }; // UDP port 1 or 3
 | 
			
		||||
       CTXT_HEADER : data_int <= { 1'b0, (PROT_ENG_FLAGS ? 1'b0 : 1'b1), 12'b010100000001, seqno, 16'd6 };
 | 
			
		||||
       CTXT_STREAMID : data_int <= { 2'b00, streamid };
 | 
			
		||||
       CTXT_SECS : data_int <= { 2'b00, err_time[63:32] };
 | 
			
		||||
       CTXT_TICS : data_int <= { 2'b00, 32'd0 };
 | 
			
		||||
       CTXT_TICS : data_int <= { 2'b00, err_time[63:32] };
 | 
			
		||||
       CTXT_TICS2 : data_int <= { 2'b00, err_time[31:0] };
 | 
			
		||||
       CTXT_MESSAGE : data_int <= { 2'b00, message };
 | 
			
		||||
       CTXT_FLOWCTRL : data_int <= { 2'b10, seqnum };
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										102
									
								
								fpga/vrt/vita_packet_demux36.v
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								fpga/vrt/vita_packet_demux36.v
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,102 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2012 Ettus Research LLC
 | 
			
		||||
//
 | 
			
		||||
// This program is free software: you can redistribute it and/or modify
 | 
			
		||||
// it under the terms of the GNU General Public License as published by
 | 
			
		||||
// the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
// (at your option) any later version.
 | 
			
		||||
//
 | 
			
		||||
// This program is distributed in the hope that it will be useful,
 | 
			
		||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
// GNU General Public License for more details.
 | 
			
		||||
//
 | 
			
		||||
// You should have received a copy of the GNU General Public License
 | 
			
		||||
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
//demux an input stream based on the SID
 | 
			
		||||
//output packet has SID removed from header
 | 
			
		||||
 | 
			
		||||
module vita_packet_demux36
 | 
			
		||||
#(
 | 
			
		||||
    parameter NUMCHAN = 1,
 | 
			
		||||
    parameter SID_BASE = 0
 | 
			
		||||
)
 | 
			
		||||
(
 | 
			
		||||
    input clk, input rst,
 | 
			
		||||
 | 
			
		||||
    input [35:0] in_data,
 | 
			
		||||
    input in_src_rdy,
 | 
			
		||||
    output in_dst_rdy,
 | 
			
		||||
 | 
			
		||||
    output [35:0] out_data,
 | 
			
		||||
    output [NUMCHAN-1:0] out_src_rdy,
 | 
			
		||||
    input [NUMCHAN-1:0] out_dst_rdy
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
    reg [1:0] state;
 | 
			
		||||
    localparam STATE_WAIT_HDR = 0;
 | 
			
		||||
    localparam STATE_PROC_SID = 1;
 | 
			
		||||
    localparam STATE_WRITE_HDR = 2;
 | 
			
		||||
    localparam STATE_FORWARD = 3;
 | 
			
		||||
 | 
			
		||||
    reg [31:0] hdr;
 | 
			
		||||
    reg [NUMCHAN-1:0] sid;
 | 
			
		||||
    wire has_sid = in_data[28];
 | 
			
		||||
    reg has_sid_reg;
 | 
			
		||||
 | 
			
		||||
    wire my_out_dst_rdy = out_dst_rdy[sid];
 | 
			
		||||
    wire my_out_src_rdy = out_src_rdy[sid];
 | 
			
		||||
 | 
			
		||||
    always @(posedge clk) begin
 | 
			
		||||
        if (rst) begin
 | 
			
		||||
            state <= STATE_WAIT_HDR;
 | 
			
		||||
        end
 | 
			
		||||
        else case(state)
 | 
			
		||||
 | 
			
		||||
        STATE_WAIT_HDR: begin
 | 
			
		||||
            if (in_src_rdy && in_dst_rdy && in_data[32]) begin
 | 
			
		||||
                state <= (has_sid)? STATE_PROC_SID : STATE_WRITE_HDR;
 | 
			
		||||
            end
 | 
			
		||||
            sid <= 0;
 | 
			
		||||
            hdr <= in_data[31:0];
 | 
			
		||||
            has_sid_reg <= has_sid;
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        STATE_PROC_SID: begin
 | 
			
		||||
            if (in_src_rdy && in_dst_rdy) begin
 | 
			
		||||
                state <= STATE_WRITE_HDR;
 | 
			
		||||
                sid <= in_data[31:0] - SID_BASE;
 | 
			
		||||
                hdr[28] <= 1'b0; //clear has sid
 | 
			
		||||
                hdr[15:0] <= hdr[15:0] - 1'b1; //subtract a line
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        STATE_WRITE_HDR: begin
 | 
			
		||||
            if (my_out_src_rdy && my_out_dst_rdy) begin
 | 
			
		||||
                state <= STATE_FORWARD;
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        STATE_FORWARD: begin
 | 
			
		||||
            if (my_out_src_rdy && my_out_dst_rdy && out_data[33]) begin
 | 
			
		||||
                state <= STATE_WAIT_HDR;
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        endcase //state
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    assign out_data = (state == STATE_WRITE_HDR)? {4'b0001, hdr} : in_data;
 | 
			
		||||
    wire out_src_rdy_i = (state == STATE_WRITE_HDR)? 1'b1 : ((state == STATE_FORWARD)? in_src_rdy : 1'b0);
 | 
			
		||||
    assign in_dst_rdy = (state == STATE_WAIT_HDR || state == STATE_PROC_SID)? 1'b1 : ((state == STATE_FORWARD)? my_out_dst_rdy : 1'b0);
 | 
			
		||||
 | 
			
		||||
    genvar i;
 | 
			
		||||
    generate
 | 
			
		||||
    for(i = 0; i < NUMCHAN; i = i + 1) begin:valid_assign
 | 
			
		||||
        assign out_src_rdy[i] = (i == sid)? out_src_rdy_i : 1'b0;
 | 
			
		||||
    end
 | 
			
		||||
    endgenerate
 | 
			
		||||
 | 
			
		||||
endmodule //vita_packet_demux36
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2011 Ettus Research LLC
 | 
			
		||||
// Copyright 2011-2012 Ettus Research LLC
 | 
			
		||||
//
 | 
			
		||||
// This program is free software: you can redistribute it and/or modify
 | 
			
		||||
// it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -20,21 +20,31 @@ module vita_rx_chain
 | 
			
		||||
  #(parameter BASE=0,
 | 
			
		||||
    parameter UNIT=0,
 | 
			
		||||
    parameter FIFOSIZE=10,
 | 
			
		||||
    parameter PROT_ENG_FLAGS=1)
 | 
			
		||||
   (input clk, input reset, input clear,
 | 
			
		||||
    parameter PROT_ENG_FLAGS=1,
 | 
			
		||||
    parameter DSP_NUMBER=0)
 | 
			
		||||
   (input clk, input reset,
 | 
			
		||||
    input set_stb, input [7:0] set_addr, input [31:0] set_data,
 | 
			
		||||
    input [63:0] vita_time, output overrun,
 | 
			
		||||
    input [31:0] sample, output run, input strobe,
 | 
			
		||||
    input set_stb_user, input [7:0] set_addr_user, input [31:0] set_data_user,
 | 
			
		||||
    input [63:0] vita_time,
 | 
			
		||||
    input [31:0] sample, input strobe,
 | 
			
		||||
    output [35:0] rx_data_o, output rx_src_rdy_o, input rx_dst_rdy_i,
 | 
			
		||||
    output overrun, output run, output clear_o,
 | 
			
		||||
    output [31:0] debug );
 | 
			
		||||
       
 | 
			
		||||
 | 
			
		||||
   wire [100:0] sample_data;
 | 
			
		||||
   wire 	sample_dst_rdy, sample_src_rdy;
 | 
			
		||||
   wire [31:0] 	vrc_debug, vrf_debug;
 | 
			
		||||
 | 
			
		||||
   wire [35:0] 	rx_data_int;
 | 
			
		||||
   wire 	rx_src_rdy_int, rx_dst_rdy_int;
 | 
			
		||||
   
 | 
			
		||||
 | 
			
		||||
   wire clear;
 | 
			
		||||
   assign clear_o = clear;
 | 
			
		||||
   wire clear_int;
 | 
			
		||||
   setting_reg #(.my_addr(BASE+8)) sr
 | 
			
		||||
     (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr),
 | 
			
		||||
      .in(set_data),.out(),.changed(clear_int));
 | 
			
		||||
 | 
			
		||||
   vita_rx_control #(.BASE(BASE), .WIDTH(32)) vita_rx_control
 | 
			
		||||
     (.clk(clk), .reset(reset), .clear(clear),
 | 
			
		||||
      .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data),
 | 
			
		||||
@@ -65,9 +75,10 @@ module vita_rx_chain
 | 
			
		||||
      .data_i(rx_data_int), .src_rdy_i(rx_src_rdy_int), .dst_rdy_o(rx_dst_rdy_int),
 | 
			
		||||
      .data_o(rx_data_int2), .src_rdy_o(rx_src_rdy_int2), .dst_rdy_i(rx_dst_rdy_int2));
 | 
			
		||||
 | 
			
		||||
   dspengine_16to8 #(.BASE(BASE+9), .BUF_SIZE(FIFOSIZE)) dspengine_16to8
 | 
			
		||||
     (.clk(clk),.reset(reset),.clear(clear),
 | 
			
		||||
      .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data),
 | 
			
		||||
   vita_rx_engine_glue #(.DSPNO(DSP_NUMBER), .MAIN_SETTINGS_BASE(BASE+3), .BUF_SIZE(FIFOSIZE)) dspengine_rx
 | 
			
		||||
     (.clock(clk),.reset(reset),.clear(clear),
 | 
			
		||||
      .set_stb_main(set_stb), .set_addr_main(set_addr), .set_data_main(set_data),
 | 
			
		||||
      .set_stb_user(set_stb_user), .set_addr_user(set_addr_user), .set_data_user(set_data_user),
 | 
			
		||||
      .access_we(access_we), .access_stb(access_stb), .access_ok(access_ok), .access_done(access_done), 
 | 
			
		||||
      .access_skip_read(access_skip_read), .access_adr(access_adr), .access_len(access_len), 
 | 
			
		||||
      .access_dat_i(buf_to_dsp), .access_dat_o(dsp_to_buf));
 | 
			
		||||
@@ -78,6 +89,26 @@ module vita_rx_chain
 | 
			
		||||
      .data_i(rx_data_int2), .src_rdy_i(rx_src_rdy_int2), .dst_rdy_o(rx_dst_rdy_int2),
 | 
			
		||||
      .data_o(rx_data_o), .src_rdy_o(rx_src_rdy_o), .dst_rdy_i(rx_dst_rdy_i) );
 | 
			
		||||
 | 
			
		||||
    //only clear once a full packet has passed through the output interface
 | 
			
		||||
    reg xfer_pkt, clear_oneshot;
 | 
			
		||||
    assign clear = (clear_oneshot)? ~xfer_pkt : 0;
 | 
			
		||||
    always @(posedge clk) begin
 | 
			
		||||
 | 
			
		||||
        if (reset || clear) begin
 | 
			
		||||
            clear_oneshot <= 0;
 | 
			
		||||
        end
 | 
			
		||||
        else if (clear_int) begin
 | 
			
		||||
            clear_oneshot <= 1;
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        if (reset || clear) begin
 | 
			
		||||
            xfer_pkt <= 0;
 | 
			
		||||
        end
 | 
			
		||||
        else if (rx_src_rdy_o && rx_dst_rdy_i) begin
 | 
			
		||||
            xfer_pkt <= ~rx_data_o[33];
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
   assign debug = vrc_debug; //  | vrf_debug;
 | 
			
		||||
   
 | 
			
		||||
endmodule // vita_rx_chain
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										95
									
								
								fpga/vrt/vita_rx_engine_glue.v
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								fpga/vrt/vita_rx_engine_glue.v
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,95 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2012 Ettus Research LLC
 | 
			
		||||
//
 | 
			
		||||
// This program is free software: you can redistribute it and/or modify
 | 
			
		||||
// it under the terms of the GNU General Public License as published by
 | 
			
		||||
// the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
// (at your option) any later version.
 | 
			
		||||
//
 | 
			
		||||
// This program is distributed in the hope that it will be useful,
 | 
			
		||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
// GNU General Public License for more details.
 | 
			
		||||
//
 | 
			
		||||
// You should have received a copy of the GNU General Public License
 | 
			
		||||
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
//The following module is used to re-write receive packets to the host.
 | 
			
		||||
//This module provides a packet-based ram interface for manipulating packets.
 | 
			
		||||
//By default, this module uses the built-in 16 to 8 bit converter engine.
 | 
			
		||||
 | 
			
		||||
module vita_rx_engine_glue
 | 
			
		||||
#(
 | 
			
		||||
    //the dsp unit number: 0, 1, 2...
 | 
			
		||||
    parameter DSPNO = 0,
 | 
			
		||||
 | 
			
		||||
    //buffer size for ram interface engine
 | 
			
		||||
    parameter BUF_SIZE = 10,
 | 
			
		||||
 | 
			
		||||
    //base address for built-in settings registers used in this module
 | 
			
		||||
    parameter MAIN_SETTINGS_BASE = 0
 | 
			
		||||
)
 | 
			
		||||
(
 | 
			
		||||
    //control signals
 | 
			
		||||
    input clock, input reset, input clear,
 | 
			
		||||
 | 
			
		||||
    //main settings bus for built-in modules
 | 
			
		||||
    input set_stb_main, input [7:0] set_addr_main, input [31:0] set_data_main,
 | 
			
		||||
 | 
			
		||||
    //user settings bus, controlled through user setting regs API
 | 
			
		||||
    input set_stb_user, input [7:0] set_addr_user, input [31:0] set_data_user,
 | 
			
		||||
 | 
			
		||||
    //ram interface for engine
 | 
			
		||||
    output access_we,
 | 
			
		||||
    output access_stb,
 | 
			
		||||
    input access_ok,
 | 
			
		||||
    output access_done,
 | 
			
		||||
    output access_skip_read,
 | 
			
		||||
    output [BUF_SIZE-1:0] access_adr,
 | 
			
		||||
    input [BUF_SIZE-1:0] access_len,
 | 
			
		||||
    output [35:0] access_dat_o,
 | 
			
		||||
    input [35:0] access_dat_i,
 | 
			
		||||
 | 
			
		||||
    //debug output (optional)
 | 
			
		||||
    output [31:0] debug
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
    generate
 | 
			
		||||
        if (DSPNO==0) begin
 | 
			
		||||
            `ifndef RX_ENG0_MODULE
 | 
			
		||||
            dspengine_16to8 #(.BASE(MAIN_SETTINGS_BASE), .BUF_SIZE(BUF_SIZE)) dspengine_16to8
 | 
			
		||||
             (.clk(clock),.reset(reset),.clear(clear),
 | 
			
		||||
              .set_stb(set_stb_main), .set_addr(set_addr_main), .set_data(set_data_main),
 | 
			
		||||
              .access_we(access_we), .access_stb(access_stb), .access_ok(access_ok), .access_done(access_done), 
 | 
			
		||||
              .access_skip_read(access_skip_read), .access_adr(access_adr), .access_len(access_len), 
 | 
			
		||||
              .access_dat_i(access_dat_i), .access_dat_o(access_dat_o));
 | 
			
		||||
            `else
 | 
			
		||||
            `RX_ENG0_MODULE #(.BUF_SIZE(BUF_SIZE)) rx_eng0_custom
 | 
			
		||||
             (.clock(clock),.reset(reset),.clear(clear),
 | 
			
		||||
              .set_stb(set_stb_user), .set_addr(set_addr_user), .set_data(set_data_user),
 | 
			
		||||
              .access_we(access_we), .access_stb(access_stb), .access_ok(access_ok), .access_done(access_done), 
 | 
			
		||||
              .access_skip_read(access_skip_read), .access_adr(access_adr), .access_len(access_len), 
 | 
			
		||||
              .access_dat_i(access_dat_i), .access_dat_o(access_dat_o));
 | 
			
		||||
            `endif
 | 
			
		||||
        end
 | 
			
		||||
        else begin
 | 
			
		||||
            `ifndef RX_ENG1_MODULE
 | 
			
		||||
            dspengine_16to8 #(.BASE(MAIN_SETTINGS_BASE), .BUF_SIZE(BUF_SIZE)) dspengine_16to8
 | 
			
		||||
             (.clk(clock),.reset(reset),.clear(clear),
 | 
			
		||||
              .set_stb(set_stb_main), .set_addr(set_addr_main), .set_data(set_data_main),
 | 
			
		||||
              .access_we(access_we), .access_stb(access_stb), .access_ok(access_ok), .access_done(access_done), 
 | 
			
		||||
              .access_skip_read(access_skip_read), .access_adr(access_adr), .access_len(access_len), 
 | 
			
		||||
              .access_dat_i(access_dat_i), .access_dat_o(access_dat_o));
 | 
			
		||||
            `else
 | 
			
		||||
            `RX_ENG1_MODULE #(.BUF_SIZE(BUF_SIZE)) rx_eng1_custom
 | 
			
		||||
             (.clock(clock),.reset(reset),.clear(clear),
 | 
			
		||||
              .set_stb(set_stb_user), .set_addr(set_addr_user), .set_data(set_data_user),
 | 
			
		||||
              .access_we(access_we), .access_stb(access_stb), .access_ok(access_ok), .access_done(access_done), 
 | 
			
		||||
              .access_skip_read(access_skip_read), .access_adr(access_adr), .access_len(access_len), 
 | 
			
		||||
              .access_dat_i(access_dat_i), .access_dat_o(access_dat_o));
 | 
			
		||||
            `endif
 | 
			
		||||
        end
 | 
			
		||||
    endgenerate
 | 
			
		||||
 | 
			
		||||
endmodule //vita_rx_engine_glue
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2011 Ettus Research LLC
 | 
			
		||||
// Copyright 2011-2012 Ettus Research LLC
 | 
			
		||||
//
 | 
			
		||||
// This program is free software: you can redistribute it and/or modify
 | 
			
		||||
// it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -85,26 +85,26 @@ module vita_rx_framer
 | 
			
		||||
     (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr),
 | 
			
		||||
      .in(set_data),.out(samples_per_packet),.changed());
 | 
			
		||||
 | 
			
		||||
   setting_reg #(.my_addr(BASE+8),.width(4), .at_reset(1)) sr_numchan
 | 
			
		||||
   assign numchan = 0;/*
 | 
			
		||||
   setting_reg #(.my_addr(BASE+8),.width(4), .at_reset(0)) sr_numchan
 | 
			
		||||
     (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr),
 | 
			
		||||
      .in(set_data),.out(numchan),.changed());
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
   // Output FIFO for packetized data
 | 
			
		||||
   localparam VITA_IDLE 	 = 0;
 | 
			
		||||
   localparam VITA_HEADER 	 = 1;
 | 
			
		||||
   localparam VITA_STREAMID 	 = 2;
 | 
			
		||||
   localparam VITA_SECS 	 = 3;
 | 
			
		||||
   localparam VITA_TICS 	 = 4;
 | 
			
		||||
   localparam VITA_TICS2 	 = 5;
 | 
			
		||||
   localparam VITA_PAYLOAD 	 = 6;
 | 
			
		||||
   localparam VITA_TRAILER 	 = 7;
 | 
			
		||||
   localparam VITA_ERR_HEADER 	 = 9;  // All ERR at 4'b1000 or'ed with base
 | 
			
		||||
   localparam VITA_ERR_STREAMID  = 10;
 | 
			
		||||
   localparam VITA_ERR_SECS 	 = 11;
 | 
			
		||||
   localparam VITA_ERR_TICS 	 = 12;
 | 
			
		||||
   localparam VITA_ERR_TICS2 	 = 13;
 | 
			
		||||
   localparam VITA_ERR_PAYLOAD 	 = 14;
 | 
			
		||||
   localparam VITA_ERR_TRAILER 	 = 15; // Extension context packets have no trailer
 | 
			
		||||
   localparam VITA_TICS 	 = 3;
 | 
			
		||||
   localparam VITA_TICS2 	 = 4;
 | 
			
		||||
   localparam VITA_PAYLOAD 	 = 5;
 | 
			
		||||
   localparam VITA_TRAILER 	 = 6;
 | 
			
		||||
   localparam VITA_ERR_HEADER 	 = 7;  // All ERR at 4'b1000 or'ed with base
 | 
			
		||||
   localparam VITA_ERR_STREAMID  = 8;
 | 
			
		||||
   localparam VITA_ERR_TICS 	 = 9;
 | 
			
		||||
   localparam VITA_ERR_TICS2 	 = 10;
 | 
			
		||||
   localparam VITA_ERR_PAYLOAD 	 = 11;
 | 
			
		||||
   localparam VITA_ERR_TRAILER 	 = 12; // Extension context packets have no trailer
 | 
			
		||||
      
 | 
			
		||||
   always @(posedge clk)
 | 
			
		||||
     if(reset | clear | clear_pkt_count)
 | 
			
		||||
@@ -122,17 +122,15 @@ module vita_rx_framer
 | 
			
		||||
       VITA_HEADER : pkt_fifo_line <= {2'b01,3'b000,vita_header[28],2'b01,vita_header[25:24],
 | 
			
		||||
				       vita_header[23:20],pkt_count[3:0],vita_pkt_len[15:0]};
 | 
			
		||||
       VITA_STREAMID : pkt_fifo_line <= {2'b00,vita_streamid};
 | 
			
		||||
       VITA_SECS : pkt_fifo_line <= {2'b00,vita_time_fifo_o[63:32]};
 | 
			
		||||
       VITA_TICS : pkt_fifo_line <= {2'b00,32'd0};
 | 
			
		||||
       VITA_TICS : pkt_fifo_line <= {2'b00,vita_time_fifo_o[63:32]};
 | 
			
		||||
       VITA_TICS2 : pkt_fifo_line <= {2'b00,vita_time_fifo_o[31:0]};
 | 
			
		||||
       VITA_PAYLOAD : pkt_fifo_line <= {2'b00,data_fifo_o};
 | 
			
		||||
       VITA_TRAILER : pkt_fifo_line <= {2'b10,vita_trailer[31:21],1'b1,vita_trailer[19:9],trl_eob,8'd0};
 | 
			
		||||
 | 
			
		||||
       // Error packets are Extension Context packets, which have no trailer
 | 
			
		||||
       VITA_ERR_HEADER : pkt_fifo_line <= {2'b01,4'b0101,4'b0000,vita_header[23:20],pkt_count,16'd6};
 | 
			
		||||
       VITA_ERR_HEADER : pkt_fifo_line <= {2'b01,4'b0101,4'b0000,vita_header[23:20],pkt_count,16'd5};
 | 
			
		||||
       VITA_ERR_STREAMID : pkt_fifo_line <= {2'b00,vita_streamid};
 | 
			
		||||
       VITA_ERR_SECS : pkt_fifo_line <= {2'b00,vita_time_fifo_o[63:32]};
 | 
			
		||||
       VITA_ERR_TICS : pkt_fifo_line <= {2'b00,32'd0};
 | 
			
		||||
       VITA_ERR_TICS : pkt_fifo_line <= {2'b00,vita_time_fifo_o[63:32]};
 | 
			
		||||
       VITA_ERR_TICS2 : pkt_fifo_line <= {2'b00,vita_time_fifo_o[31:0]};
 | 
			
		||||
       VITA_ERR_PAYLOAD : pkt_fifo_line <= {2'b10,27'd0,flags_fifo_o};
 | 
			
		||||
       //VITA_ERR_TRAILER : pkt_fifo_line <= {2'b11,vita_trailer};
 | 
			
		||||
@@ -164,11 +162,11 @@ module vita_rx_framer
 | 
			
		||||
	     if(has_streamid)
 | 
			
		||||
	       vita_state <= VITA_STREAMID;
 | 
			
		||||
	     else
 | 
			
		||||
	       vita_state <= VITA_SECS;
 | 
			
		||||
	       vita_state <= VITA_TICS;
 | 
			
		||||
	   VITA_PAYLOAD :
 | 
			
		||||
	     if(sample_fifo_src_rdy_i)
 | 
			
		||||
	       begin
 | 
			
		||||
		  if(sample_phase == (numchan-4'd1))
 | 
			
		||||
		  if(sample_phase == numchan)
 | 
			
		||||
		    begin
 | 
			
		||||
		       sample_phase <= 0;
 | 
			
		||||
		       sample_ctr   <= sample_ctr + 1;
 | 
			
		||||
@@ -194,12 +192,12 @@ module vita_rx_framer
 | 
			
		||||
     case(vita_state)
 | 
			
		||||
       VITA_IDLE :
 | 
			
		||||
	 req_write_pkt_fifo <= 0;
 | 
			
		||||
       VITA_HEADER, VITA_STREAMID, VITA_SECS, VITA_TICS, VITA_TICS2, VITA_TRAILER :
 | 
			
		||||
       VITA_HEADER, VITA_STREAMID, VITA_TICS, VITA_TICS2, VITA_TRAILER :
 | 
			
		||||
	 req_write_pkt_fifo <= 1;
 | 
			
		||||
       VITA_PAYLOAD :
 | 
			
		||||
	 // Write if sample ready and no error flags
 | 
			
		||||
     	 req_write_pkt_fifo <= (sample_fifo_src_rdy_i & ~|flags_fifo_o[4:1]);
 | 
			
		||||
       VITA_ERR_HEADER, VITA_ERR_STREAMID, VITA_ERR_SECS, VITA_ERR_TICS, VITA_ERR_TICS2, VITA_ERR_PAYLOAD :
 | 
			
		||||
       VITA_ERR_HEADER, VITA_ERR_STREAMID, VITA_ERR_TICS, VITA_ERR_TICS2, VITA_ERR_PAYLOAD :
 | 
			
		||||
	 req_write_pkt_fifo <= 1;
 | 
			
		||||
       default :
 | 
			
		||||
	 req_write_pkt_fifo <= 0;
 | 
			
		||||
@@ -217,7 +215,7 @@ module vita_rx_framer
 | 
			
		||||
   assign data_o[35:34] = 2'b00;  // Always write full lines
 | 
			
		||||
   assign sample_fifo_dst_rdy_o  = pkt_fifo_rdy & 
 | 
			
		||||
				   ( ((vita_state==VITA_PAYLOAD) & 
 | 
			
		||||
				      (sample_phase == (numchan-4'd1)) & 
 | 
			
		||||
				      (sample_phase == numchan) & 
 | 
			
		||||
				      ~|flags_fifo_o[4:1]) |
 | 
			
		||||
				     (vita_state==VITA_ERR_PAYLOAD));
 | 
			
		||||
   
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2011 Ettus Research LLC
 | 
			
		||||
// Copyright 2011-2012 Ettus Research LLC
 | 
			
		||||
//
 | 
			
		||||
// This program is free software: you can redistribute it and/or modify
 | 
			
		||||
// it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -17,21 +17,22 @@
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
module vita_tx_chain
 | 
			
		||||
  #(parameter BASE_CTRL=0,
 | 
			
		||||
    parameter BASE_DSP=0,
 | 
			
		||||
  #(parameter BASE=0,
 | 
			
		||||
    parameter FIFOSIZE=10,
 | 
			
		||||
    parameter POST_ENGINE_FIFOSIZE=10,
 | 
			
		||||
    parameter REPORT_ERROR=0,
 | 
			
		||||
    parameter DO_FLOW_CONTROL=0,
 | 
			
		||||
    parameter PROT_ENG_FLAGS=0,
 | 
			
		||||
    parameter USE_TRANS_HEADER=0,
 | 
			
		||||
    parameter DSP_NUMBER=0)
 | 
			
		||||
   (input clk, input reset,
 | 
			
		||||
    input dac_clk,
 | 
			
		||||
    input set_stb, input [7:0] set_addr, input [31:0] set_data,
 | 
			
		||||
    input set_stb_user, input [7:0] set_addr_user, input [31:0] set_data_user,
 | 
			
		||||
    input [63:0] vita_time,
 | 
			
		||||
    input [35:0] tx_data_i, input tx_src_rdy_i, output tx_dst_rdy_o,
 | 
			
		||||
    output [35:0] err_data_o, output err_src_rdy_o, input err_dst_rdy_i,
 | 
			
		||||
    output [23:0] tx_i, output [23:0] tx_q,
 | 
			
		||||
    output underrun, output run,
 | 
			
		||||
    output [31:0] sample, input strobe,
 | 
			
		||||
    output underrun, output run, output clear_o,
 | 
			
		||||
    output [31:0] debug);
 | 
			
		||||
 | 
			
		||||
   localparam MAXCHAN = 1;
 | 
			
		||||
@@ -39,8 +40,6 @@ module vita_tx_chain
 | 
			
		||||
 | 
			
		||||
   wire [FIFOWIDTH-1:0] tx1_data;
 | 
			
		||||
   wire 		tx1_src_rdy, tx1_dst_rdy;
 | 
			
		||||
   wire 		clear_vita;
 | 
			
		||||
   wire [31:0] 		sample_tx;
 | 
			
		||||
   wire [31:0] 		streamid, message;
 | 
			
		||||
   wire 		trigger, sent;
 | 
			
		||||
   wire [31:0] 		debug_vtc, debug_vtd, debug_tx_dsp;
 | 
			
		||||
@@ -49,62 +48,104 @@ module vita_tx_chain
 | 
			
		||||
   wire [31:0] 		error_code;
 | 
			
		||||
   wire 		clear_seqnum;
 | 
			
		||||
   wire [31:0] 		current_seqnum;
 | 
			
		||||
   wire 		strobe_tx;
 | 
			
		||||
   
 | 
			
		||||
 | 
			
		||||
   wire clear, flush;
 | 
			
		||||
   assign clear_o = clear;
 | 
			
		||||
   assign underrun = error;
 | 
			
		||||
   assign message = error_code;
 | 
			
		||||
   
 | 
			
		||||
   setting_reg #(.my_addr(BASE_CTRL+1)) sr
 | 
			
		||||
     (.clk(dac_clk),.rst(reset),.strobe(set_stb),.addr(set_addr),
 | 
			
		||||
      .in(set_data),.out(),.changed(clear_vita));
 | 
			
		||||
 | 
			
		||||
   setting_reg #(.my_addr(BASE_CTRL+2), .at_reset(0)) sr_streamid
 | 
			
		||||
     (.clk(dac_clk),.rst(reset),.strobe(set_stb),.addr(set_addr),
 | 
			
		||||
   setting_reg #(.my_addr(BASE+0), .width(1)) sr
 | 
			
		||||
     (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr),
 | 
			
		||||
      .in(set_data),.out(flush),.changed(clear));
 | 
			
		||||
 | 
			
		||||
   setting_reg #(.my_addr(BASE+2), .at_reset(0)) sr_streamid
 | 
			
		||||
     (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr),
 | 
			
		||||
      .in(set_data),.out(streamid),.changed(clear_seqnum));
 | 
			
		||||
 | 
			
		||||
   vita_tx_deframer #(.BASE(BASE_CTRL), 
 | 
			
		||||
    //flush control - full rate vacuum of input until flush cleared
 | 
			
		||||
    wire tx_dst_rdy_int, tx_src_rdy_int;
 | 
			
		||||
    wire [35:0] tx_data_int;
 | 
			
		||||
    valve36 flusher_valve
 | 
			
		||||
    (.clk(clk), .reset(reset), .clear(clear & flush), .shutoff(flush),
 | 
			
		||||
     .data_i(tx_data_i), .src_rdy_i(tx_src_rdy_i), .dst_rdy_o(tx_dst_rdy_o),
 | 
			
		||||
     .data_o(tx_data_int), .src_rdy_o(tx_src_rdy_int), .dst_rdy_i(tx_dst_rdy_int));
 | 
			
		||||
 | 
			
		||||
   wire [35:0] tx_data_int1;
 | 
			
		||||
   wire tx_src_rdy_int1, tx_dst_rdy_int1;
 | 
			
		||||
 | 
			
		||||
    generate
 | 
			
		||||
    if (FIFOSIZE==0) begin
 | 
			
		||||
        assign tx_data_int1 = tx_data_int;
 | 
			
		||||
        assign tx_src_rdy_int1 = tx_src_rdy_int;
 | 
			
		||||
        assign tx_dst_rdy_int = tx_dst_rdy_int1;
 | 
			
		||||
    end
 | 
			
		||||
    else begin
 | 
			
		||||
       wire [FIFOSIZE-1:0] access_adr, access_len;
 | 
			
		||||
       wire 	       access_we, access_stb, access_ok, access_done, access_skip_read;
 | 
			
		||||
       wire [35:0] 	       dsp_to_buf, buf_to_dsp;
 | 
			
		||||
       wire [35:0] tx_data_int0;
 | 
			
		||||
       wire tx_src_rdy_int0, tx_dst_rdy_int0;
 | 
			
		||||
 | 
			
		||||
       double_buffer #(.BUF_SIZE(FIFOSIZE)) db
 | 
			
		||||
         (.clk(clk),.reset(reset),.clear(clear),
 | 
			
		||||
          .access_we(access_we), .access_stb(access_stb), .access_ok(access_ok), .access_done(access_done),
 | 
			
		||||
          .access_skip_read(access_skip_read), .access_adr(access_adr), .access_len(access_len),
 | 
			
		||||
          .access_dat_i(dsp_to_buf), .access_dat_o(buf_to_dsp),
 | 
			
		||||
 | 
			
		||||
          .data_i(tx_data_int), .src_rdy_i(tx_src_rdy_int), .dst_rdy_o(tx_dst_rdy_int),
 | 
			
		||||
          .data_o(tx_data_int0), .src_rdy_o(tx_src_rdy_int0), .dst_rdy_i(tx_dst_rdy_int0));
 | 
			
		||||
 | 
			
		||||
       vita_tx_engine_glue #(.DSPNO(DSP_NUMBER), .MAIN_SETTINGS_BASE(BASE+1), .BUF_SIZE(FIFOSIZE), .HEADER_OFFSET(USE_TRANS_HEADER)) dspengine_tx
 | 
			
		||||
         (.clock(clk),.reset(reset),.clear(clear),
 | 
			
		||||
          .set_stb_main(set_stb), .set_addr_main(set_addr), .set_data_main(set_data),
 | 
			
		||||
          .set_stb_user(set_stb_user), .set_addr_user(set_addr_user), .set_data_user(set_data_user),
 | 
			
		||||
          .access_we(access_we), .access_stb(access_stb), .access_ok(access_ok), .access_done(access_done),
 | 
			
		||||
          .access_skip_read(access_skip_read), .access_adr(access_adr), .access_len(access_len),
 | 
			
		||||
          .access_dat_i(buf_to_dsp), .access_dat_o(dsp_to_buf));
 | 
			
		||||
 | 
			
		||||
       fifo_cascade #(.WIDTH(36), .SIZE(POST_ENGINE_FIFOSIZE)) post_engine_buffering(
 | 
			
		||||
        .clk(clk), .reset(reset), .clear(clear),
 | 
			
		||||
        .datain(tx_data_int0), .src_rdy_i(tx_src_rdy_int0), .dst_rdy_o(tx_dst_rdy_int0),
 | 
			
		||||
        .dataout(tx_data_int1), .src_rdy_o(tx_src_rdy_int1), .dst_rdy_i(tx_dst_rdy_int1));
 | 
			
		||||
 | 
			
		||||
    end
 | 
			
		||||
    endgenerate
 | 
			
		||||
 | 
			
		||||
   vita_tx_deframer #(.BASE(BASE), 
 | 
			
		||||
		      .MAXCHAN(MAXCHAN), 
 | 
			
		||||
		      .USE_TRANS_HEADER(USE_TRANS_HEADER)) 
 | 
			
		||||
   vita_tx_deframer
 | 
			
		||||
     (.clk(dac_clk), .reset(reset), .clear(clear_vita), .clear_seqnum(clear_seqnum),
 | 
			
		||||
     (.clk(clk), .reset(reset), .clear(clear), .clear_seqnum(clear_seqnum),
 | 
			
		||||
      .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data),
 | 
			
		||||
      .data_i(tx_data_i), .src_rdy_i(tx_src_rdy_i), .dst_rdy_o(tx_dst_rdy_o),
 | 
			
		||||
      .data_i(tx_data_int1), .src_rdy_i(tx_src_rdy_int1), .dst_rdy_o(tx_dst_rdy_int1),
 | 
			
		||||
      .sample_fifo_o(tx1_data), .sample_fifo_src_rdy_o(tx1_src_rdy), .sample_fifo_dst_rdy_i(tx1_dst_rdy),
 | 
			
		||||
      .current_seqnum(current_seqnum),
 | 
			
		||||
      .debug(debug_vtd) );
 | 
			
		||||
 | 
			
		||||
   vita_tx_control #(.BASE(BASE_CTRL), .WIDTH(32*MAXCHAN)) vita_tx_control
 | 
			
		||||
     (.clk(clk), .reset(reset), .clear(clear_vita),
 | 
			
		||||
      .dac_clk(dac_clk),
 | 
			
		||||
   vita_tx_control #(.BASE(BASE), .WIDTH(32*MAXCHAN)) vita_tx_control
 | 
			
		||||
     (.clk(clk), .reset(reset), .clear(clear),
 | 
			
		||||
      .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data),
 | 
			
		||||
      .vita_time(vita_time), .error(error), .ack(ack), .error_code(error_code),
 | 
			
		||||
      .sample_fifo_i(tx1_data), .sample_fifo_src_rdy_i(tx1_src_rdy), .sample_fifo_dst_rdy_o(tx1_dst_rdy),
 | 
			
		||||
      .sample(sample_tx), .run(run), .strobe(strobe_tx), .packet_consumed(packet_consumed),
 | 
			
		||||
      .sample(sample), .run(run), .strobe(strobe), .packet_consumed(packet_consumed),
 | 
			
		||||
      .debug(debug_vtc) );
 | 
			
		||||
   
 | 
			
		||||
   dsp_core_tx #(.BASE(BASE_DSP)) dsp_core_tx
 | 
			
		||||
     (.clk(dac_clk),.rst(reset),
 | 
			
		||||
      .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data),
 | 
			
		||||
      .sample(sample_tx), .run(run), .strobe(strobe_tx),
 | 
			
		||||
      .tx_i(tx_i),.tx_q(tx_q),
 | 
			
		||||
      .debug(debug_tx_dsp) );
 | 
			
		||||
 | 
			
		||||
   wire [35:0] 		flow_data, err_data_int;
 | 
			
		||||
   wire 		flow_src_rdy, flow_dst_rdy, err_src_rdy_int, err_dst_rdy_int;
 | 
			
		||||
   
 | 
			
		||||
   gen_context_pkt #(.PROT_ENG_FLAGS(PROT_ENG_FLAGS),.DSP_NUMBER(DSP_NUMBER)) gen_flow_pkt
 | 
			
		||||
     (.clk(clk), .reset(reset), .clear(clear_vita),
 | 
			
		||||
     (.clk(clk), .reset(reset), .clear(clear),
 | 
			
		||||
      .trigger(trigger & (DO_FLOW_CONTROL==1)), .sent(), 
 | 
			
		||||
      .streamid(streamid), .vita_time(vita_time), .message(32'd0),
 | 
			
		||||
      .seqnum(current_seqnum),
 | 
			
		||||
      .data_o(flow_data), .src_rdy_o(flow_src_rdy), .dst_rdy_i(flow_dst_rdy));
 | 
			
		||||
   trigger_context_pkt #(.BASE(BASE_CTRL)) trigger_context_pkt
 | 
			
		||||
     (.clk(clk), .reset(reset), .clear(clear_vita),
 | 
			
		||||
   trigger_context_pkt #(.BASE(BASE)) trigger_context_pkt
 | 
			
		||||
     (.clk(clk), .reset(reset), .clear(clear),
 | 
			
		||||
      .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data),
 | 
			
		||||
      .packet_consumed(packet_consumed), .trigger(trigger));
 | 
			
		||||
   
 | 
			
		||||
   gen_context_pkt #(.PROT_ENG_FLAGS(PROT_ENG_FLAGS),.DSP_NUMBER(DSP_NUMBER)) gen_tx_err_pkt
 | 
			
		||||
     (.clk(clk), .reset(reset), .clear(clear_vita),
 | 
			
		||||
     (.clk(clk), .reset(reset), .clear(clear),
 | 
			
		||||
      .trigger((error|ack) & (REPORT_ERROR==1)), .sent(), 
 | 
			
		||||
      .streamid(streamid), .vita_time(vita_time), .message(message),
 | 
			
		||||
      .seqnum(current_seqnum),
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,6 @@ module vita_tx_control
 | 
			
		||||
  #(parameter BASE=0,
 | 
			
		||||
    parameter WIDTH=32)
 | 
			
		||||
   (input clk, input reset, input clear,
 | 
			
		||||
    input dac_clk,
 | 
			
		||||
    input set_stb, input [7:0] set_addr, input [31:0] set_data,
 | 
			
		||||
    
 | 
			
		||||
    input [63:0] vita_time,
 | 
			
		||||
@@ -51,21 +50,19 @@ module vita_tx_control
 | 
			
		||||
   
 | 
			
		||||
   wire        now, early, late, too_early;
 | 
			
		||||
 | 
			
		||||
   // FIXME ignore too_early for now for timing reasons
 | 
			
		||||
   assign too_early = 0;
 | 
			
		||||
   time_compare 
 | 
			
		||||
     time_compare (.time_now(vita_time), .trigger_time(send_time), 
 | 
			
		||||
		   .now(now), .early(early), .late(late), .too_early());
 | 
			
		||||
		   .now(now), .early(early), .late(late), .too_early(too_early));
 | 
			
		||||
 | 
			
		||||
   reg 	       late_qual, late_del;
 | 
			
		||||
 | 
			
		||||
   always @(posedge dac_clk)
 | 
			
		||||
   always @(posedge clk)
 | 
			
		||||
     if(reset | clear)
 | 
			
		||||
       late_del <= 0;
 | 
			
		||||
     else
 | 
			
		||||
       late_del <= late;
 | 
			
		||||
   
 | 
			
		||||
   always @(posedge dac_clk)
 | 
			
		||||
   always @(posedge clk)
 | 
			
		||||
     if(reset | clear)
 | 
			
		||||
       late_qual <= 0;
 | 
			
		||||
     else
 | 
			
		||||
@@ -89,7 +86,7 @@ module vita_tx_control
 | 
			
		||||
 | 
			
		||||
   wire [31:0] error_policy;
 | 
			
		||||
   setting_reg #(.my_addr(BASE+3)) sr_error_policy
 | 
			
		||||
     (.clk(dac_clk),.rst(reset),.strobe(set_stb),.addr(set_addr),
 | 
			
		||||
     (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr),
 | 
			
		||||
      .in(set_data),.out(error_policy),.changed());
 | 
			
		||||
 | 
			
		||||
   wire        policy_wait = error_policy[0];
 | 
			
		||||
@@ -97,7 +94,7 @@ module vita_tx_control
 | 
			
		||||
   wire        policy_next_burst = error_policy[2];
 | 
			
		||||
   reg 	       send_error, send_ack;
 | 
			
		||||
   
 | 
			
		||||
   always @(posedge dac_clk)
 | 
			
		||||
   always @(posedge clk)
 | 
			
		||||
     if(reset | clear)
 | 
			
		||||
       begin
 | 
			
		||||
	  ibs_state <= IBS_IDLE;
 | 
			
		||||
@@ -188,21 +185,25 @@ module vita_tx_control
 | 
			
		||||
   
 | 
			
		||||
   assign sample_fifo_dst_rdy_o = (ibs_state == IBS_ERROR) | (strobe & (ibs_state == IBS_RUN));  // FIXME also cleanout
 | 
			
		||||
 | 
			
		||||
   assign sample = (ibs_state == IBS_RUN) ? sample_fifo_i[5+64+16+WIDTH-1:5+64+16] : {WIDTH{1'b0}};
 | 
			
		||||
   //assign run = (ibs_state == IBS_RUN) | (ibs_state == IBS_CONT_BURST);
 | 
			
		||||
   //register the output sample
 | 
			
		||||
   reg [31:0] sample_held;
 | 
			
		||||
   assign sample = sample_held;
 | 
			
		||||
   always @(posedge clk)
 | 
			
		||||
     if(reset | clear)
 | 
			
		||||
        sample_held <= 0;
 | 
			
		||||
     else if (~run)
 | 
			
		||||
       sample_held <= 0;
 | 
			
		||||
     else if (strobe)
 | 
			
		||||
       sample_held <= sample_fifo_i[5+64+16+WIDTH-1:5+64+16];
 | 
			
		||||
 | 
			
		||||
   assign error = send_error;
 | 
			
		||||
   assign ack = send_ack;
 | 
			
		||||
 | 
			
		||||
`ifndef LMS602D_FRONTEND
 | 
			
		||||
   localparam MAX_IDLE = 1000000; 
 | 
			
		||||
   // approx 10 ms timeout with a 100 MHz clock, but burning samples will slow that down
 | 
			
		||||
`else
 | 
			
		||||
   localparam MAX_IDLE = 130000; 
 | 
			
		||||
   // approx 10 ms timeout with a 13 MHz clock, but burning samples will slow that down
 | 
			
		||||
`endif // !`ifndef LMS602D_FRONTEND
 | 
			
		||||
   reg [19:0] countdown;
 | 
			
		||||
   
 | 
			
		||||
   always @(posedge dac_clk)
 | 
			
		||||
   always @(posedge clk)
 | 
			
		||||
     if(reset | clear)
 | 
			
		||||
       begin
 | 
			
		||||
	  run <= 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2011 Ettus Research LLC
 | 
			
		||||
// Copyright 2011-2012 Ettus Research LLC
 | 
			
		||||
//
 | 
			
		||||
// This program is free software: you can redistribute it and/or modify
 | 
			
		||||
// it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -43,10 +43,11 @@ module vita_tx_deframer
 | 
			
		||||
 | 
			
		||||
   localparam FIFOWIDTH = 5+64+16+(32*MAXCHAN);
 | 
			
		||||
   
 | 
			
		||||
   wire [1:0] numchan;
 | 
			
		||||
   wire [1:0] numchan = 0;/*
 | 
			
		||||
   setting_reg #(.my_addr(BASE), .at_reset(0), .width(2)) sr_numchan
 | 
			
		||||
     (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr),
 | 
			
		||||
      .in(set_data),.out(numchan),.changed());
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
   reg [3:0] vita_state;
 | 
			
		||||
   wire      has_streamid, has_classid, has_secs, has_tics, has_trailer;
 | 
			
		||||
@@ -85,7 +86,6 @@ module vita_tx_deframer
 | 
			
		||||
   localparam VITA_TICS 	 = 6;
 | 
			
		||||
   localparam VITA_TICS2 	 = 7;
 | 
			
		||||
   localparam VITA_PAYLOAD 	 = 8;
 | 
			
		||||
   localparam VITA_STORE         = 9;
 | 
			
		||||
   localparam VITA_TRAILER 	 = 10;
 | 
			
		||||
   localparam VITA_DUMP          = 11;
 | 
			
		||||
   
 | 
			
		||||
@@ -118,21 +118,7 @@ module vita_tx_deframer
 | 
			
		||||
	    <= 0;
 | 
			
		||||
	  seqnum_err <= 0;
 | 
			
		||||
       end
 | 
			
		||||
     else 
 | 
			
		||||
       if((vita_state == VITA_STORE) & fifo_space)
 | 
			
		||||
	 if(vita_eof)  
 | 
			
		||||
	   if(eof)
 | 
			
		||||
	     vita_state <= (USE_TRANS_HEADER==1) ? VITA_TRANS_HEADER : VITA_HEADER;
 | 
			
		||||
	   else if(has_trailer_reg)
 | 
			
		||||
	     vita_state <= VITA_TRAILER;
 | 
			
		||||
	   else
 | 
			
		||||
	     vita_state <= VITA_DUMP;
 | 
			
		||||
   	 else
 | 
			
		||||
	   begin
 | 
			
		||||
	      vita_state <= VITA_PAYLOAD;
 | 
			
		||||
	      pkt_len <= pkt_len - 1;
 | 
			
		||||
	   end
 | 
			
		||||
       else if(src_rdy_i)
 | 
			
		||||
     else if(src_rdy_i & dst_rdy_o) begin //valid read
 | 
			
		||||
	 case(vita_state)
 | 
			
		||||
	   VITA_TRANS_HEADER :
 | 
			
		||||
	     begin
 | 
			
		||||
@@ -184,14 +170,33 @@ module vita_tx_deframer
 | 
			
		||||
	     vita_state <= VITA_TICS2;
 | 
			
		||||
	   VITA_TICS2 :
 | 
			
		||||
	     vita_state <= VITA_PAYLOAD;
 | 
			
		||||
	   VITA_PAYLOAD :
 | 
			
		||||
	     if(line_done)
 | 
			
		||||
	       begin
 | 
			
		||||
		  vector_phase <= 0;
 | 
			
		||||
		  vita_state <= VITA_STORE;
 | 
			
		||||
	       end
 | 
			
		||||
	     else
 | 
			
		||||
	       vector_phase <= vector_phase + 1;
 | 
			
		||||
 | 
			
		||||
        VITA_PAYLOAD : begin
 | 
			
		||||
 | 
			
		||||
            //step through each element until line done, then reset
 | 
			
		||||
            vector_phase <= (line_done)? 0: vector_phase + 1;
 | 
			
		||||
 | 
			
		||||
            //decrement the packet count after each line
 | 
			
		||||
            pkt_len <= (line_done)? pkt_len - 1 : pkt_len;
 | 
			
		||||
 | 
			
		||||
            //end of frame reached, determine next state
 | 
			
		||||
            //otherwise, keep processing through the payload
 | 
			
		||||
            if (line_done && vita_eof) begin
 | 
			
		||||
 | 
			
		||||
                if (eof) begin
 | 
			
		||||
                    vita_state <= (USE_TRANS_HEADER==1) ? VITA_TRANS_HEADER : VITA_HEADER;
 | 
			
		||||
                end
 | 
			
		||||
                else if (has_trailer_reg) begin
 | 
			
		||||
                    vita_state <= VITA_TRAILER;
 | 
			
		||||
                end
 | 
			
		||||
                else begin
 | 
			
		||||
                    vita_state <= VITA_DUMP;
 | 
			
		||||
                end
 | 
			
		||||
 | 
			
		||||
            end //line_done && vita_eof
 | 
			
		||||
 | 
			
		||||
        end //end VITA_PAYLOAD
 | 
			
		||||
 | 
			
		||||
	   VITA_TRAILER :
 | 
			
		||||
	     if(eof)
 | 
			
		||||
	       vita_state <= (USE_TRANS_HEADER==1) ? VITA_TRANS_HEADER : VITA_HEADER;
 | 
			
		||||
@@ -200,46 +205,53 @@ module vita_tx_deframer
 | 
			
		||||
	   VITA_DUMP :
 | 
			
		||||
	     if(eof)
 | 
			
		||||
	       vita_state <= (USE_TRANS_HEADER==1) ? VITA_TRANS_HEADER : VITA_HEADER;
 | 
			
		||||
	   VITA_STORE :
 | 
			
		||||
	     ;
 | 
			
		||||
	   default :
 | 
			
		||||
	     vita_state <= (USE_TRANS_HEADER==1) ? VITA_TRANS_HEADER : VITA_HEADER;
 | 
			
		||||
	 endcase // case (vita_state)
 | 
			
		||||
 | 
			
		||||
   assign line_done = (vector_phase == numchan);
 | 
			
		||||
     end //valid read
 | 
			
		||||
 | 
			
		||||
   assign line_done = (MAXCHAN == 1)? 1 : (vector_phase == numchan);
 | 
			
		||||
   
 | 
			
		||||
   wire [FIFOWIDTH-1:0] fifo_i;
 | 
			
		||||
   reg [63:0] 		      send_time;
 | 
			
		||||
   reg [31:0] 		      sample_a, sample_b, sample_c, sample_d;
 | 
			
		||||
   
 | 
			
		||||
   always @(posedge clk)
 | 
			
		||||
     case(vita_state)
 | 
			
		||||
       VITA_SECS :
 | 
			
		||||
       VITA_TICS :
 | 
			
		||||
	 send_time[63:32] <= data_i[31:0];
 | 
			
		||||
       VITA_TICS2 :
 | 
			
		||||
	 send_time[31:0] <= data_i[31:0];
 | 
			
		||||
     endcase // case (vita_state)
 | 
			
		||||
   
 | 
			
		||||
 | 
			
		||||
   //sample registers for de-framing a vector input
 | 
			
		||||
   reg [31:0] sample_reg [1:0];
 | 
			
		||||
   always @(posedge clk)
 | 
			
		||||
     if(vita_state == VITA_PAYLOAD)
 | 
			
		||||
       case(vector_phase)
 | 
			
		||||
	 0: sample_a <= data_i[31:0];
 | 
			
		||||
	 1: sample_b <= data_i[31:0];
 | 
			
		||||
	 2: sample_c <= data_i[31:0];
 | 
			
		||||
	 3: sample_d <= data_i[31:0];
 | 
			
		||||
       endcase // case (vector_phase)
 | 
			
		||||
   
 | 
			
		||||
   wire 		      store = (vita_state == VITA_STORE);
 | 
			
		||||
     if(src_rdy_i && dst_rdy_o)
 | 
			
		||||
        sample_reg[vector_phase] <= data_i[31:0];
 | 
			
		||||
 | 
			
		||||
   wire store = (vita_state == VITA_PAYLOAD)? (src_rdy_i && line_done) : 0;
 | 
			
		||||
   assign dst_rdy_o = (vita_state == VITA_PAYLOAD)? fifo_space : 1;
 | 
			
		||||
 | 
			
		||||
   fifo_short #(.WIDTH(FIFOWIDTH)) short_tx_q
 | 
			
		||||
     (.clk(clk), .reset(reset), .clear(clear),
 | 
			
		||||
      .datain(fifo_i), .src_rdy_i(store), .dst_rdy_o(fifo_space),
 | 
			
		||||
      .dataout(sample_fifo_o), .src_rdy_o(sample_fifo_src_rdy_o), .dst_rdy_i(sample_fifo_dst_rdy_i) );
 | 
			
		||||
 | 
			
		||||
   // sob, eob, has_secs (send_at) ignored on all lines except first
 | 
			
		||||
   assign fifo_i = {sample_d,sample_c,sample_b,sample_a,seqnum_err,has_secs_reg,is_sob_reg,is_eob_reg,eop,
 | 
			
		||||
		    12'd0,seqnum_reg[3:0],send_time};
 | 
			
		||||
    //assign registered/live data to the samples vector
 | 
			
		||||
    //the numchan'th sample vector is muxed to live data
 | 
			
		||||
    wire [(32*MAXCHAN)-1:0] samples;
 | 
			
		||||
    generate
 | 
			
		||||
    genvar i;
 | 
			
		||||
    for (i=0; i < MAXCHAN; i = i +1) begin : assign_samples
 | 
			
		||||
        wire live_data = (i == (MAXCHAN-1))? 1 : numchan == i;
 | 
			
		||||
        assign samples[32*i + 31:32*i] = (live_data)? data_i[31:0] : sample_reg[i];
 | 
			
		||||
    end
 | 
			
		||||
    endgenerate
 | 
			
		||||
 | 
			
		||||
   assign dst_rdy_o = ~(vita_state == VITA_PAYLOAD) & ~((vita_state==VITA_STORE)& ~fifo_space) ;
 | 
			
		||||
   // sob, eob, has_tics (send_at) ignored on all lines except first
 | 
			
		||||
   assign fifo_i = {samples,seqnum_err,has_tics_reg,is_sob_reg,is_eob_reg,eop,
 | 
			
		||||
		    12'd0,seqnum_reg[3:0],send_time};
 | 
			
		||||
 | 
			
		||||
   assign debug = { { 8'b0 },
 | 
			
		||||
		    { 8'b0 },
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										99
									
								
								fpga/vrt/vita_tx_engine_glue.v
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								fpga/vrt/vita_tx_engine_glue.v
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,99 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2012 Ettus Research LLC
 | 
			
		||||
//
 | 
			
		||||
// This program is free software: you can redistribute it and/or modify
 | 
			
		||||
// it under the terms of the GNU General Public License as published by
 | 
			
		||||
// the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
// (at your option) any later version.
 | 
			
		||||
//
 | 
			
		||||
// This program is distributed in the hope that it will be useful,
 | 
			
		||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
// GNU General Public License for more details.
 | 
			
		||||
//
 | 
			
		||||
// You should have received a copy of the GNU General Public License
 | 
			
		||||
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
//The following module is used to re-write transmit packets from the host.
 | 
			
		||||
//This module provides a packet-based ram interface for manipulating packets.
 | 
			
		||||
//By default, this module uses the built-in 8 to 16 bit converter engine.
 | 
			
		||||
 | 
			
		||||
module vita_tx_engine_glue
 | 
			
		||||
#(
 | 
			
		||||
    //the dsp unit number: 0, 1, 2...
 | 
			
		||||
    parameter DSPNO = 0,
 | 
			
		||||
 | 
			
		||||
    //buffer size for ram interface engine
 | 
			
		||||
    parameter BUF_SIZE = 10,
 | 
			
		||||
 | 
			
		||||
    //base address for built-in settings registers used in this module
 | 
			
		||||
    parameter MAIN_SETTINGS_BASE = 0,
 | 
			
		||||
 | 
			
		||||
    //the number of 32bit lines between start of buffer and vita header
 | 
			
		||||
    //the metadata before the header should be preserved by the engine
 | 
			
		||||
    parameter HEADER_OFFSET = 0
 | 
			
		||||
)
 | 
			
		||||
(
 | 
			
		||||
    //control signals
 | 
			
		||||
    input clock, input reset, input clear,
 | 
			
		||||
 | 
			
		||||
    //main settings bus for built-in modules
 | 
			
		||||
    input set_stb_main, input [7:0] set_addr_main, input [31:0] set_data_main,
 | 
			
		||||
 | 
			
		||||
    //user settings bus, controlled through user setting regs API
 | 
			
		||||
    input set_stb_user, input [7:0] set_addr_user, input [31:0] set_data_user,
 | 
			
		||||
 | 
			
		||||
    //ram interface for engine
 | 
			
		||||
    output access_we,
 | 
			
		||||
    output access_stb,
 | 
			
		||||
    input access_ok,
 | 
			
		||||
    output access_done,
 | 
			
		||||
    output access_skip_read,
 | 
			
		||||
    output [BUF_SIZE-1:0] access_adr,
 | 
			
		||||
    input [BUF_SIZE-1:0] access_len,
 | 
			
		||||
    output [35:0] access_dat_o,
 | 
			
		||||
    input [35:0] access_dat_i,
 | 
			
		||||
 | 
			
		||||
    //debug output (optional)
 | 
			
		||||
    output [31:0] debug
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
    generate
 | 
			
		||||
        if (DSPNO==0) begin
 | 
			
		||||
            `ifndef TX_ENG0_MODULE
 | 
			
		||||
            dspengine_8to16 #(.BASE(MAIN_SETTINGS_BASE), .BUF_SIZE(BUF_SIZE), .HEADER_OFFSET(HEADER_OFFSET)) dspengine_8to16
 | 
			
		||||
             (.clk(clock),.reset(reset),.clear(clear),
 | 
			
		||||
              .set_stb(set_stb_main), .set_addr(set_addr_main), .set_data(set_data_main),
 | 
			
		||||
              .access_we(access_we), .access_stb(access_stb), .access_ok(access_ok), .access_done(access_done), 
 | 
			
		||||
              .access_skip_read(access_skip_read), .access_adr(access_adr), .access_len(access_len), 
 | 
			
		||||
              .access_dat_i(access_dat_i), .access_dat_o(access_dat_o));
 | 
			
		||||
            `else
 | 
			
		||||
            `TX_ENG0_MODULE #(.BUF_SIZE(BUF_SIZE), .HEADER_OFFSET(HEADER_OFFSET)) tx_eng0_custom
 | 
			
		||||
             (.clock(clock),.reset(reset),.clear(clear),
 | 
			
		||||
              .set_stb(set_stb_user), .set_addr(set_addr_user), .set_data(set_data_user),
 | 
			
		||||
              .access_we(access_we), .access_stb(access_stb), .access_ok(access_ok), .access_done(access_done), 
 | 
			
		||||
              .access_skip_read(access_skip_read), .access_adr(access_adr), .access_len(access_len), 
 | 
			
		||||
              .access_dat_i(access_dat_i), .access_dat_o(access_dat_o));
 | 
			
		||||
            `endif
 | 
			
		||||
        end
 | 
			
		||||
        else begin
 | 
			
		||||
            `ifndef TX_ENG1_MODULE
 | 
			
		||||
            dspengine_8to16 #(.BASE(MAIN_SETTINGS_BASE), .BUF_SIZE(BUF_SIZE), .HEADER_OFFSET(HEADER_OFFSET)) dspengine_8to16
 | 
			
		||||
             (.clk(clock),.reset(reset),.clear(clear),
 | 
			
		||||
              .set_stb(set_stb_main), .set_addr(set_addr_main), .set_data(set_data_main),
 | 
			
		||||
              .access_we(access_we), .access_stb(access_stb), .access_ok(access_ok), .access_done(access_done), 
 | 
			
		||||
              .access_skip_read(access_skip_read), .access_adr(access_adr), .access_len(access_len), 
 | 
			
		||||
              .access_dat_i(access_dat_i), .access_dat_o(access_dat_o));
 | 
			
		||||
            `else
 | 
			
		||||
            `TX_ENG1_MODULE #(.BUF_SIZE(BUF_SIZE), .HEADER_OFFSET(HEADER_OFFSET)) tx_eng1_custom
 | 
			
		||||
             (.clock(clock),.reset(reset),.clear(clear),
 | 
			
		||||
              .set_stb(set_stb_user), .set_addr(set_addr_user), .set_data(set_data_user),
 | 
			
		||||
              .access_we(access_we), .access_stb(access_stb), .access_ok(access_ok), .access_done(access_done), 
 | 
			
		||||
              .access_skip_read(access_skip_read), .access_adr(access_adr), .access_len(access_len), 
 | 
			
		||||
              .access_dat_i(access_dat_i), .access_dat_o(access_dat_o));
 | 
			
		||||
            `endif
 | 
			
		||||
        end
 | 
			
		||||
    endgenerate
 | 
			
		||||
 | 
			
		||||
endmodule //vita_tx_engine_glue
 | 
			
		||||
		Reference in New Issue
	
	Block a user