diff options
| author | Josh Blum <josh@joshknows.com> | 2012-02-17 16:55:59 -0800 | 
|---|---|---|
| committer | Josh Blum <josh@joshknows.com> | 2012-02-17 16:55:59 -0800 | 
| commit | ace4489066d1621a09e70650a00d736f0b03ed8c (patch) | |
| tree | f02b34b70da9e9beb0f34dc5e64d48daa5aa4bf6 | |
| parent | 8f8ac3397aaa85b64aaa8722efdc1c0c40e93052 (diff) | |
| parent | 2e37dd87234e5beddd6f76fcda714916f761f812 (diff) | |
| download | uhd-ace4489066d1621a09e70650a00d736f0b03ed8c.tar.gz uhd-ace4489066d1621a09e70650a00d736f0b03ed8c.tar.bz2 uhd-ace4489066d1621a09e70650a00d736f0b03ed8c.zip | |
Merge branch 'fpga_next' into next
54 files changed, 2565 insertions, 1070 deletions
| diff --git a/fpga/README.txt b/fpga/README.txt new file mode 100644 index 000000000..29e891f6d --- /dev/null +++ b/fpga/README.txt @@ -0,0 +1,78 @@ +######################################################################## +## Welcome to the USRP FPGA source code tree +######################################################################## + +usrp1/ + +    Description: generation 1 products + +    Devices: USRP classic only + +    Tools: Quartus from Altera + +    Project file: usrp1/toplevel/usrp_std/ + +usrp2/ + +    Description: generation 2 products + +    Devices: USRP2, N2XX, B100, E1XX + +    Tools: ISE from Xilinx, GNU make + +    Build Instructions: +        1) ensure that xtclsh is in the $PATH +        2) cd usrp2/top/<project-directory> +        3) make -f Makefile.<device> bin +        4) bin file in build-<device>/*.bin + +######################################################################## +## Customizing the DSP +######################################################################## + +As part of the USRP FPGA build-framework, +there are several convenient places for users to insert +custom DSP modules into the transmit and receive chains. + +* before the DDC module +* after the DDC module +* replace the DDC module +* before the DUC module +* after the DUC module +* replace of the DUC module +* as an RX packet engine +* as an TX packet engine + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Customizing the top level makefile +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Each USRP device has a makefile associated with it. +This makefile contains all of the necessary build rules. +When making a customized FPGA design, +start by copying the current makefile for your device. +Makefiles can be found in the usrp2/top/<dir>/Makefile.* + +Edit your new makefile: +* set BUILD_DIR to a unique directory name +* set CUSTOM_SRCS for your verilog sources +* set CUSTOM_DEFS (see section below) + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Inserting custom modules +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +CUSTOM_DEFS is a string of space-separate key-value pairs. +Set the CUSTOM_DEFS variable so the FPGA fabric glue +will substitute your custom modules into the DSP chain. + +Example: +CUSTOM_DEFS = "TX_ENG0_MODULE=my_tx_engine RX_ENG0_MODULE=my_rx_engine" +Where my_tx_engine and my_rx_engine are the names of custom verilog modules. + +The following module definition keys are possible (X is a DSP number): + +* TX_ENG<X>_MODULE: set the module for the transmit chain engine. +* RX_ENG<X>_MODULE: set the module for the receive chain engine. +* RX_DSP<X>_MODULE: set the module for the transmit dsp chain. +* TX_DSP<X>_MODULE: set the module for the receive dsp chain. + +Examples of custom modules can be found in usrp2/custom/*.v diff --git a/fpga/usrp2/control_lib/Makefile.srcs b/fpga/usrp2/control_lib/Makefile.srcs index 567feacde..6ee7ea262 100644 --- a/fpga/usrp2/control_lib/Makefile.srcs +++ b/fpga/usrp2/control_lib/Makefile.srcs @@ -1,5 +1,5 @@  # -# Copyright 2010 Ettus Research LLC +# Copyright 2010-2012 Ettus Research LLC  #  ################################################## @@ -54,4 +54,5 @@ settings_bus_16LE.v \  atr_controller16.v \  fifo_to_wb.v \  gpio_atr.v \ +user_settings.v \  )) diff --git a/fpga/usrp2/control_lib/double_buffer_tb.v b/fpga/usrp2/control_lib/double_buffer_tb.v index a9aae6956..804e8804d 100644 --- a/fpga/usrp2/control_lib/double_buffer_tb.v +++ b/fpga/usrp2/control_lib/double_buffer_tb.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'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'ha100a200}; +	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'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'ha500a600}; +	data_i <= { 2'b00,1'b0,1'b0,32'ha8a9aaab};  	@(posedge clk); -	data_i <= { 2'b00,1'b0,1'b0,32'ha700a800}; +	data_i <= { 2'b00,1'b0,1'b0,32'hacadaeaf};  	@(posedge clk); -	data_i <= { 2'b00,1'b1,1'b0,32'hbbb0bbb0}; +	data_i <= { 2'b00,1'b1,1'b0,32'hdeadbeef};  	@(posedge clk);  	src_rdy_i <= 0;  	@(posedge clk); diff --git a/fpga/usrp2/control_lib/user_settings.v b/fpga/usrp2/control_lib/user_settings.v new file mode 100644 index 000000000..d87f1de21 --- /dev/null +++ b/fpga/usrp2/control_lib/user_settings.v @@ -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 + diff --git a/fpga/usrp2/custom/custom_dsp_rx.v b/fpga/usrp2/custom/custom_dsp_rx.v new file mode 100644 index 000000000..355adf008 --- /dev/null +++ b/fpga/usrp2/custom/custom_dsp_rx.v @@ -0,0 +1,71 @@ +// +// 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/>. +// + +//COPY ME, CUSTOMIZE ME... + +//The following module effects the IO of the DDC chain. +//By default, this entire module is a simple pass-through. + +//To implement DSP logic before the DDC: +//Implement custom DSP between frontend and ddc input. + +//To implement DSP logic after the DDC: +//Implement custom DSP between ddc output and baseband. + +//To bypass the DDC with custom logic: +//Implement custom DSP between frontend and baseband. + +module custom_dsp_rx +#( +    //frontend bus width +    parameter WIDTH = 24 +) +( +    //control signals +    input clock, //dsp clock +    input reset, //active high synchronous reset +    input clear, //active high on packet control init +    input enable, //active high when streaming enabled + +    //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 +); + +    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; + +endmodule //custom_dsp_rx diff --git a/fpga/usrp2/custom/custom_dsp_tx.v b/fpga/usrp2/custom/custom_dsp_tx.v new file mode 100644 index 000000000..0848a187f --- /dev/null +++ b/fpga/usrp2/custom/custom_dsp_tx.v @@ -0,0 +1,71 @@ +// +// 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/>. +// + +//COPY ME, CUSTOMIZE ME... + +//The following module effects the IO of the DUC chain. +//By default, this entire module is a simple pass-through. + +//To implement DSP logic before the DUC: +//Implement custom DSP between baseband and duc input. + +//To implement DSP logic after the DUC: +//Implement custom DSP between duc output and frontend. + +//To bypass the DUC with custom logic: +//Implement custom DSP between baseband and frontend. + +module custom_dsp_tx +#( +    //frontend bus width +    parameter WIDTH = 24 +) +( +    //control signals +    input clock, //dsp clock +    input reset, //active high synchronous reset +    input clear, //active high on packet control init +    input enable, //active high when streaming enabled + +    //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 +); + +    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; + +endmodule //custom_dsp_tx diff --git a/fpga/usrp2/custom/custom_engine_rx.v b/fpga/usrp2/custom/custom_engine_rx.v new file mode 100644 index 000000000..dfeaad2cd --- /dev/null +++ b/fpga/usrp2/custom/custom_engine_rx.v @@ -0,0 +1,53 @@ +// +// 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/>. +// + +//COPY ME, CUSTOMIZE ME... + +//The following module is used to re-write receive packets to the host. +//This module provides a packet-based ram interface for manipulating packets. +//The user writes a custom engine (state machine) to read the input packet, +//and to produce a new output packet. + +//By default, this entire module is a simple pass-through. + +module custom_engine_rx +#( +    //buffer size for ram interface engine +    parameter BUF_SIZE = 10 +) +( +    //control signals +    input clock, input reset, input clear, + +    //user settings bus, controlled through user setting regs API +    input set_stb, input [7:0] set_addr, input [31:0] set_data, + +    //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 +); + +    assign access_done = access_ok; + +endmodule //custom_engine_rx diff --git a/fpga/usrp2/custom/custom_engine_tx.v b/fpga/usrp2/custom/custom_engine_tx.v new file mode 100644 index 000000000..9be728484 --- /dev/null +++ b/fpga/usrp2/custom/custom_engine_tx.v @@ -0,0 +1,57 @@ +// +// 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/>. +// + +//COPY ME, CUSTOMIZE ME... + +//The following module is used to re-write transmit packets from the host. +//This module provides a packet-based ram interface for manipulating packets. +//The user writes a custom engine (state machine) to read the input packet, +//and to produce a new output packet. + +//By default, this entire module is a simple pass-through. + +module custom_engine_tx +#( +    //buffer size for ram interface engine +    parameter BUF_SIZE = 10, + +    //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, + +    //user settings bus, controlled through user setting regs API +    input set_stb, input [7:0] set_addr, input [31:0] set_data, + +    //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 +); + +    assign access_done = access_ok; + +endmodule //custom_engine_tx diff --git a/fpga/usrp2/custom/power_trig.v b/fpga/usrp2/custom/power_trig.v new file mode 100644 index 000000000..b38059030 --- /dev/null +++ b/fpga/usrp2/custom/power_trig.v @@ -0,0 +1,130 @@ +// +// 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/>. +// + +// This a power trigger module implemented on top of the custom dsp template. +// Power triggering is implemented after the existing DDC chain. +// Triggering is controlled via user settings registers. + +// Register 0: +//  threshold for power trigger +//  32 bit unsigned fixed-point number of some arbitrary scaling + +module power_trig +#( +    //frontend bus width +    parameter WIDTH = 24, +    parameter BASE = 0 +) +( +    //control signals +    input clock, //dsp clock +    input reset, //active high synchronous reset +    input clear, //active high on packet control init +    input enable, //active high when streaming enabled + +    //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 +); + +    //leave frontend tied to existing ddc chain +    assign ddc_in_i = frontend_i; +    assign ddc_in_q = frontend_q; + +    //ddc enable remains tied to global enable +    assign ddc_out_enable = enable; + +    //below we implement a power trigger between baseband samples and ddc output... + +   reg [8:0] 	  wr_addr; +   wire [8:0] 	  rd_addr; +   reg 		  triggered, triggerable; +   wire 	  trigger; +    +   wire [31:0] 	  delayed_sample; +   wire [31:0] 	  thresh; +    +   setting_reg #(.my_addr(BASE+0)) sr_0 +     (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), +      .in(set_data),.out(thresh),.changed()); + +   assign rd_addr = wr_addr + 1; // FIXME adjustable delay + +   ram_2port  #(.DWIDTH(32),.AWIDTH(9)) delay_line +     (.clka(clk),.ena(1),.wea(ddc_out_strobe),.addra(wr_addr),.dia(ddc_out_sample),.doa(), +      .clkb(clk),.enb(ddc_out_strobe),.web(1'b0),.addrb(rd_addr),.dib(32'hFFFF),.dob(delayed_sample)); + +   always @(posedge clock) +     if(reset | ~enable) +       wr_addr <= 0; +     else +       if(ddc_out_strobe) +	 wr_addr <= wr_addr + 1; + +   always @(posedge clock) +     if(reset | ~enable) +       triggerable <= 0; +     else if(wr_addr == 9'h1FF)  // Wait till we're nearly full +       triggerable <= 1; +    + +   reg 			      stb_d1, stb_d2; +   always @(posedge clock) stb_d1 <= ddc_out_strobe; +   always @(posedge clock) stb_d2 <= stb_d1; +    +   assign bb_sample = delayed_sample; +   assign bb_strobe = stb_d1 & triggered; + +   // Compute Mag +   wire [17:0] 		      mult_in = stb_d1 ? { ddc_out_sample[15],ddc_out_sample[15:0], 1'b0 } :  +			      { ddc_out_sample[31], ddc_out_sample[31:16], 1'b0 }; +   wire [35:0] 		      prod; +   reg [31:0] 		      sum; +    +   MULT18X18S mult (.P(prod), .A(mult_in), .B(mult_in), .C(clock), .CE(ddc_out_strobe | stb_d1), .R(reset) ); + +   always @(posedge clock) +     if(stb_d1) +       sum <= prod[35:4]; +     else if(stb_d2) +       sum <= sum + prod[35:4]; + +   always @(posedge clock) +     if(reset | ~enable | ~triggerable) +       triggered <= 0; +     else if(trigger) +       triggered <= 1; + +   assign trigger = (sum > thresh); +    +endmodule // power_trig diff --git a/fpga/usrp2/custom/power_trig_tb.v b/fpga/usrp2/custom/power_trig_tb.v new file mode 100644 index 000000000..b8f3385ce --- /dev/null +++ b/fpga/usrp2/custom/power_trig_tb.v @@ -0,0 +1,71 @@ +// +// 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/>. +// + + +module power_trig_tb(); +   initial $dumpfile("power_trig_tb.vcd"); +   initial $dumpvars(0,power_trig_tb); + +   reg clk = 0; +   always #10 clk <= ~clk; +   reg rst = 1; +   initial #100 rst <= 0; + +   initial +     begin +	set_stb <= 0; +	#1000; +	set_stb <= 1; +     end +    +   reg [31:0] sample_in; +   reg 	      strobe_in; +   wire [31:0] sample_out; +   wire        strobe_out; +   reg 	       set_stb, run; +    +   power_trig #(.BASE(0)) power_trig +     (.clk(clk), .reset(rst), .enable(1), +      .set_stb(set_stb), .set_addr(0), .set_data(32'h000B_B000), +      .run(run), + +      .ddc_out_sample(sample_in), .ddc_out_strobe(strobe_in), +      .bb_sample(sample_out), .bb_strobe(strobe_out)); + +   initial sample_in <= 32'h0100_0300; +    +   always @(posedge clk) +     if(~strobe_in) +       sample_in <= sample_in + 32'h0001_0001; + +   initial +     #100000 $finish; + +   initial  +     begin +	run <= 0; +	#2000 run <= 1; +	#30000 run <= 0; +     end + +   always @(posedge clk) +     if(rst | ~run) +       strobe_in <= 0; +     else +       strobe_in <= ~strobe_in; +    +endmodule // power_trig_tb diff --git a/fpga/usrp2/gpif/Makefile.srcs b/fpga/usrp2/gpif/Makefile.srcs index bf2b7f74d..06cde8afa 100644 --- a/fpga/usrp2/gpif/Makefile.srcs +++ b/fpga/usrp2/gpif/Makefile.srcs @@ -11,4 +11,5 @@ gpif_wr.v \  gpif_rd.v \  packet_reframer.v \  packet_splitter.v \ +slave_fifo.v \  )) diff --git a/fpga/usrp2/gpif/packet_reframer.v b/fpga/usrp2/gpif/packet_reframer.v index 923d499ae..8bb8a3678 100644 --- a/fpga/usrp2/gpif/packet_reframer.v +++ b/fpga/usrp2/gpif/packet_reframer.v @@ -1,5 +1,5 @@  // -// Copyright 2011 Ettus Research LLC +// Copyright 2011-2012 Ettus Research LLC  //  // This program is free software: you can redistribute it and/or modify  // it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@  // -// Join vita packets longer than one GPIF frame, drop padding on short frames +// Join vita packets longer than one GPIF frame  module packet_reframer    (input clk, input reset, input clear, @@ -25,18 +25,20 @@ module packet_reframer     output dst_rdy_o,     output [18:0] data_o,     output src_rdy_o, -   input dst_rdy_i); +   input dst_rdy_i, +   output reg state, +   output eof_out, +   output reg [15:0] length); -   reg [1:0] state; -   reg [15:0] length; +   //reg 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; +       state <= RF_IDLE;       else         if(src_rdy_i & dst_rdy_i)  	 case(state) @@ -47,26 +49,16 @@ module packet_reframer  	     end  	   RF_PKT :  	     begin -		if(length == 2) -		  if(data_i[17]) -		    state <= RF_IDLE; -		  else -		    state <= RF_DUMP; -		else -		  length <= length - 1; +		if(eof_out) state <= RF_IDLE; +		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); +   assign src_rdy_o = src_rdy_i;     wire occ_out = 0; -   wire eof_out = (state == RF_PKT) & (length == 2); +   assign 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}; diff --git a/fpga/usrp2/gpif/slave_fifo.v b/fpga/usrp2/gpif/slave_fifo.v new file mode 100644 index 000000000..10740942b --- /dev/null +++ b/fpga/usrp2/gpif/slave_fifo.v @@ -0,0 +1,467 @@ +// +// 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/>. +// + +////////////////////////////////////////////////////////////////////////////////// + +//this is a FIFO master interface for the FX2 in "slave fifo" mode. + +module slave_fifo +  #(parameter TXFIFOSIZE = 12, parameter RXFIFOSIZE = 12) +   (// GPIF signals +    input gpif_clk, input gpif_rst, +    inout [15:0] gpif_d, +    input [3:0] gpif_ctl, +    output sloe, output slrd, output slwr, output pktend, output [1:0] fifoadr, +     +    // 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, +     +    input dsp_rx_run, +     +    // 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 [15:0] test_len, input [7:0] test_rate, input [3:0] test_ctrl, +    output [31:0] debug0, output [31:0] debug1 +    ); + +   // inputs to FPGA (all active low) +   wire       FX2_DE = ~gpif_ctl[0]; //EP2 FX2 FIFO empty (FLAGA) +   wire       FX2_CE = ~gpif_ctl[1]; //EP4 FX2 FIFO empty (FLAGB) +   wire       FX2_DF = ~gpif_ctl[2]; //EP6 FX2 FIFO full  (FLAGC) +   wire       FX2_CF = ~gpif_ctl[3]; //EP8 FX2 FIFO full  (FLAGD) + +   wire [17:0] 	  gpif_d_out_ctrl, gpif_d_out_data, gpif_d_out; + +   // //////////////////////////////////////////////////////////////////// +   // GPIF bus master state machine + +   //transfer size for GPIF data. this can be anything really, it's specified only for +   //fairness in bus sharing. 256 lines is 512 bytes over the wire, half the size of +   //the double buffers in B100/B150. this should probably be a toplevel parameter or even +   //a settings register value. +   localparam data_transfer_size = 256; +   localparam ctrl_transfer_size = 16; //probably unnecessary since ctrl xfers won't back up + +   // state machine i/o to four fifos +   //tx +   wire ctrl_tx_dst_rdy; //sm input, ctrl tx path has space +   wire ctrl_tx_src_rdy; //sm output, ctrl tx path enable +   reg data_tx_dst_rdy; //sm input, data tx path has space +   wire data_tx_src_rdy; //sm output, data tx path enable + +   //rx +   wire ctrl_rx_dst_rdy; //sm output, ctrl rx path enable +   wire ctrl_rx_src_rdy; //sm input, ctrl rx path has space +   wire data_rx_dst_rdy; //sm output, data rx path enable +   wire data_rx_src_rdy; //sm input, data rx path has space + +   reg [9:0] transfer_count; //number of lines (a line is 16 bits) in active transfer + +   wire       sop, eop; //SOP/EOP markers for TX data packets +    +   reg pktend_latch; + +   reg [3:0] state; //state machine current state +   localparam STATE_IDLE    = 0; +   localparam STATE_DATA_RX = 5; +   localparam STATE_DATA_TX = 3; +   localparam STATE_CTRL_RX = 6; +   localparam STATE_CTRL_TX = 9; +   localparam STATE_DATA_TX_SLOE = 2; +   localparam STATE_CTRL_TX_SLOE = 8; +   localparam STATE_DATA_RX_ADR = 1; +   localparam STATE_CTRL_RX_ADR = 4; +   localparam STATE_PKTEND = 7; + +   //logs the last bus user for xfer fairness +   //we only care about data rx vs. tx since ctrl pkts are so short +   reg last_data_bus_hog; +   localparam BUS_HOG_RX = 0; +   localparam BUS_HOG_TX = 1; + +   // ////////////////////////////////////////////////////////////// +   // FX2 slave FIFO bus master state machine +   // +   always @(posedge gpif_clk) +     if(gpif_rst)  +       state <= STATE_IDLE; +     else +        begin +       case (state) +         STATE_IDLE: +            begin +           transfer_count <= 0; +           //handle transitions to other states +           if(ctrl_tx_dst_rdy & ~FX2_CE) //if there's room in the ctrl fifo and the FX2 has ctrl data +             state <= STATE_CTRL_TX_SLOE; +           else if(ctrl_rx_src_rdy & ~FX2_CF) //if the ctrl fifo has data and the FX2 isn't full +             state <= STATE_CTRL_RX_ADR; +           else if(data_tx_dst_rdy & ~FX2_DE & last_data_bus_hog == BUS_HOG_RX) //if there's room in the data fifo and the FX2 has data +             state <= STATE_DATA_TX_SLOE; +           else if(data_rx_src_rdy & ~FX2_DF & last_data_bus_hog == BUS_HOG_TX) //if the data fifo has data and the FX2 isn't full +             state <= STATE_DATA_RX_ADR; +           else if(data_tx_dst_rdy & ~FX2_DE) +             state <= STATE_DATA_TX_SLOE; +           else if(data_rx_src_rdy & ~FX2_DF) +             state <= STATE_DATA_RX_ADR; +           else if(~data_rx_src_rdy & ~dsp_rx_run & pktend_latch & ~FX2_DF) +             state <= STATE_PKTEND; +              +           if(data_rx_src_rdy) +             pktend_latch <= 1; +            end + +         STATE_DATA_TX_SLOE: //just to assert SLOE one cycle before SLRD +           state <= STATE_DATA_TX; +         STATE_CTRL_TX_SLOE: +           state <= STATE_CTRL_TX; + +         STATE_DATA_RX_ADR: //just to assert FIFOADR one cycle before SLWR +           state <= STATE_DATA_RX; +         STATE_CTRL_RX_ADR: +           state <= STATE_CTRL_RX; + +         STATE_DATA_RX: +            begin +           if((transfer_count == data_transfer_size) | FX2_DF | (~data_rx_src_rdy)) +             state <= STATE_IDLE; + +           transfer_count <= transfer_count + 1; +           last_data_bus_hog <= BUS_HOG_RX; +            end +             +         STATE_PKTEND: +            begin +           state <= STATE_IDLE; +           pktend_latch <= 0; +            end +             +         STATE_DATA_TX: +            begin +           if((transfer_count == data_transfer_size) | FX2_DE )/*| (~data_tx_dst_rdy))*/ +             state <= STATE_IDLE; +           transfer_count <= transfer_count + 1; +           last_data_bus_hog <= BUS_HOG_TX; +            end +         STATE_CTRL_RX: +            begin +           if(FX2_CF | (~ctrl_rx_src_rdy)) +             state <= STATE_IDLE; +           transfer_count <= transfer_count + 1; +            end +         STATE_CTRL_TX: +            begin +           if(FX2_CE | (~ctrl_tx_dst_rdy)) +             state <= STATE_IDLE; +           transfer_count <= transfer_count + 1; +            end +       endcase +        end + +   // /////////////////////////////////////////////////////////////////// +   // fifo signal assignments and enables + +   //enable fifos +   assign data_rx_dst_rdy = (state == STATE_DATA_RX); +   assign data_tx_src_rdy = (state == STATE_DATA_TX); +   assign ctrl_rx_dst_rdy = (state == STATE_CTRL_RX); +   assign ctrl_tx_src_rdy = (state == STATE_CTRL_TX); + +   //tx framing (this is super suspect) +   //eop should be used only to set the EOP bit going into FIFOs +   wire eop_data, eop_ctrl; +   assign sop = (transfer_count == 0); +   assign eop_data = (transfer_count == (data_transfer_size-1)); +   assign eop_ctrl = (transfer_count == (ctrl_transfer_size-1)); +   assign eop = (state == STATE_DATA_TX) ? eop_data : eop_ctrl; + +   // //////////////////////////////////////////////////////////////////// +   // set GPIF pins + +   //set fifoadr to the appropriate endpoint +   // {0,0}: EP2, data TX from host +   // {0,1}: EP4, ctrl TX from host +   // {1,0}: EP6, data RX to host +   // {1,1}: EP8, ctrl RX to host +   assign fifoadr = {(state == STATE_DATA_RX) | (state == STATE_CTRL_RX) | (state == STATE_DATA_RX_ADR) | (state == STATE_CTRL_RX_ADR) | (state == STATE_PKTEND), +                     (state == STATE_CTRL_RX) | (state == STATE_CTRL_RX_ADR) | (state == STATE_CTRL_TX) | (state == STATE_CTRL_TX_SLOE)}; +   //set sloe, slwr, slrd (all active low) +   //SLOE gets asserted when we want data from the FX2; i.e., TX mode +   assign sloe = ~{(state == STATE_DATA_TX) | (state == STATE_CTRL_TX) | (state == STATE_DATA_TX_SLOE) | (state == STATE_CTRL_TX_SLOE)}; +   //"read" and "write" here are from the master's point of view; +   //so "read" means "transmit" and "write" means "receive" +   assign slwr = ~{(state == STATE_DATA_RX) | (state == STATE_CTRL_RX)}; +   assign slrd = ~{(state == STATE_DATA_TX) | (state == STATE_CTRL_TX)}; + +   wire pktend_ctrl, pktend_data; +   assign pktend_ctrl = ((~ctrl_rx_src_rdy | gpif_d_out_ctrl[17]) & (state == STATE_CTRL_RX)); +   assign pktend_data = (state == STATE_PKTEND); +   assign pktend = ~(pktend_ctrl | pktend_data); + +   //mux between ctrl/data RX data out based on endpoint selection +   assign gpif_d_out = fifoadr[0] ? gpif_d_out_ctrl : gpif_d_out_data; +   // GPIF output data lines, tristate +   assign gpif_d = sloe ? gpif_d_out : 16'bz; +    +   // //////////////////////////////////////////////////////////////////// +   // 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 [17:0]    data_tx_int; +   wire           tx_src_rdy_int, tx_dst_rdy_int; +    +   wire [15:0] wr_fifo_space; +    +   always @(posedge gpif_clk) +     if(gpif_rst) +       data_tx_dst_rdy <= 0; +     else +       data_tx_dst_rdy <= wr_fifo_space >= 256; + +   fifo_cascade #(.WIDTH(18), .SIZE(12)) wr_fifo +     (.clk(gpif_clk), .reset(gpif_rst), .clear(clear_tx), +      .datain({eop,sop,gpif_d}), .src_rdy_i(data_tx_src_rdy), .dst_rdy_o(/*data_tx_dst_rdy*/), .space(wr_fifo_space), +      .dataout(data_tx_int), .src_rdy_o(tx_src_rdy_int), .dst_rdy_i(tx_dst_rdy_int), .occupied()); +    +   fifo_2clock_cascade #(.WIDTH(18), .SIZE(4)) wr_fifo_2clk +     (.wclk(gpif_clk), .datain(data_tx_int), .src_rdy_i(tx_src_rdy_int), .dst_rdy_o(tx_dst_rdy_int), .space(), +      .rclk(fifo_clk), .dataout(tx19_data[17:0]), .src_rdy_o(tx19_src_rdy), .dst_rdy_i(tx19_dst_rdy), .occupied(), +      .arst(fifo_rst)); +       +   assign tx19_data[18] = 1'b0; + +   // join vita packets which are longer than one frame, drop frame padding +   wire [18:0] 	  refr_data; +   wire 	  refr_src_rdy, refr_dst_rdy; +   wire refr_state; +   wire refr_eof; +   wire [15:0] refr_len; +    +   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), +      .state(refr_state), .eof_out(refr_eof), .length(refr_len)); + +   fifo19_to_fifo36 #(.LE(1)) f19_to_f36 +     (.clk(fifo_clk), .reset(fifo_rst), .clear(clear_tx), +      .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; +   wire 	  rx19_src_rdy, rx19_dst_rdy; +   wire [15:0] rxfifospace; + +   //deep 36 bit wide input fifo buffers from DSP +   fifo_cascade #(.WIDTH(36), .SIZE(8)) 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)); + +   //convert to fifo19 +   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) ); + +   wire [18:0] 	data_rx_int; +   wire 	rx_src_rdy_int, rx_dst_rdy_int; +   //clock domain crossing fifo for RX data +   fifo_2clock_cascade #(.WIDTH(19), .SIZE(4)) rd_fifo_2clk +     (.wclk(fifo_clk), .datain(rx19_data), .src_rdy_i(rx19_src_rdy), .dst_rdy_o(rx19_dst_rdy), .space(), +      .rclk(~gpif_clk), .dataout(data_rx_int), .src_rdy_o(rx_src_rdy_int), .dst_rdy_i(rx_dst_rdy_int), .occupied(), +      .arst(fifo_rst)); + +   //rd_fifo buffers writes to the 2clock fifo above +   fifo_cascade #(.WIDTH(19), .SIZE(RXFIFOSIZE)) rd_fifo +     (.clk(~gpif_clk), .reset(gpif_rst), .clear(clear_rx), +      .datain(data_rx_int), .src_rdy_i(rx_src_rdy_int), .dst_rdy_o(rx_dst_rdy_int), .space(rxfifospace), +      .dataout(gpif_d_out_data), .src_rdy_o(data_rx_src_rdy), .dst_rdy_i(data_rx_dst_rdy), .occupied()); + +   // //////////////////////////////////////////////////////////////////// +   // FIFO to Wishbone interface + +   wire [18:0] 	  resp_data, resp_int; +   wire 	  resp_src_rdy, resp_dst_rdy; +   wire 	  resp_src_rdy_int, resp_dst_rdy_int; +    +   wire [18:0] 	  tx_err19_data; +   wire 	  tx_err19_src_rdy, tx_err19_dst_rdy; + +   wire [18:0] 	  ctrl_data; +   wire 	  ctrl_src_rdy, ctrl_dst_rdy; + +   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_int), .src_rdy_o(resp_src_rdy_int), .dst_rdy_i(resp_dst_rdy_int), +      .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()); +       +   // //////////////////////////////////////////////////////////////////// +   // TX CTRL PATH (ctrl commands into Wishbone) + +   //how does this use fifo_clk instead of wb_clk +   //answer: on b100 fifo clk IS wb clk +   fifo_2clock_cascade #(.WIDTH(19), .SIZE(4)) ctrl_fifo_2clk +     (.wclk(gpif_clk), .datain({1'b0,eop,sop,gpif_d}),  +      .src_rdy_i(ctrl_tx_src_rdy), .dst_rdy_o(ctrl_tx_dst_rdy), .space(), +      .rclk(fifo_clk), .dataout(ctrl_data),  +      .src_rdy_o(ctrl_src_rdy), .dst_rdy_i(ctrl_dst_rdy), .occupied(), +      .arst(fifo_rst)); + +   // //////////////////////////////////////////////////////////////////// +   // RX CTRL PATH (async packets, ctrl response data) +    +   //tx_err_data_i is the 36wide tx async err data clocked on fifo_clk +   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) ); + +   //mux FIFO-to-WB along with async tx err pkts into one ctrl resp fifo +   //how is this clocked on wb_clk? +   fifo19_mux #(.prio(0)) mux_err_stream +     (.clk(wb_clk), .reset(wb_rst), .clear(clear_rx), +      .data0_i(resp_int), .src0_rdy_i(resp_src_rdy_int), .dst0_rdy_o(resp_dst_rdy_int), +      .data1_i(tx_err19_data), .src1_rdy_i(tx_err19_src_rdy), .dst1_rdy_o(tx_err19_dst_rdy), +      .data_o(resp_data), .src_rdy_o(resp_src_rdy), .dst_rdy_i(resp_dst_rdy)); + +   //clock domain crossing cascade fifo for mux_err_stream to get from wb_clk to gpif_clk +   //the output of this fifo is CTRL DATA PENDING FOR GPIF +   fifo_2clock_cascade #(.WIDTH(18), .SIZE(4)) resp_fifo_2clk +     (.wclk(wb_clk), .datain(resp_data[17:0]), .src_rdy_i(resp_src_rdy), .dst_rdy_o(resp_dst_rdy), .space(), +      .rclk(~gpif_clk), .dataout(gpif_d_out_ctrl),  +      .src_rdy_o(ctrl_rx_src_rdy), .dst_rdy_i(ctrl_rx_dst_rdy), .occupied(), +      .arst(wb_rst)); + +         +   // //////////////////////////////////////////////////////////////////// +   // Debug support, timed and loopback +   // RX side muxes test data into the same stream + +   /////////////////////////////////////////////////////////////////////// +   // debug lines +   wire [31:0] 	  debug_rd, debug_wr, debug_split0, debug_split1; +    +   wire [35:0] 	timedrx_data, loopbackrx_data, testrx_data; +   wire [35:0] 	timedtx_data, loopbacktx_data, testtx_data; +   wire 	timedrx_src_rdy, timedrx_dst_rdy, loopbackrx_src_rdy, loopbackrx_dst_rdy, +		testrx_src_rdy, testrx_dst_rdy; +   wire 	timedtx_src_rdy, timedtx_dst_rdy, loopbacktx_src_rdy, loopbacktx_dst_rdy, +		testtx_src_rdy, testtx_dst_rdy; +   wire 	timedrx_src_rdy_int, timedrx_dst_rdy_int, timedtx_src_rdy_int, timedtx_dst_rdy_int; + +   wire [31:0] 	total, crc_err, seq_err, len_err; +   wire 	sel_testtx = test_ctrl[0]; +   wire 	sel_loopbacktx = test_ctrl[1]; +   wire 	pkt_src_enable = test_ctrl[2]; +   wire 	pkt_sink_enable = test_ctrl[3]; +/*    +   fifo36_mux rx_test_mux_lvl_1 +     (.clk(fifo_clk), .reset(fifo_rst), .clear(clear_rx), +      .data0_i(timedrx_data), .src0_rdy_i(timedrx_src_rdy), .dst0_rdy_o(timedrx_dst_rdy), +      .data1_i(loopbackrx_data), .src1_rdy_i(loopbackrx_src_rdy), .dst1_rdy_o(loopbackrx_dst_rdy), +      .data_o(testrx_data), .src_rdy_o(testrx_src_rdy), .dst_rdy_i(testrx_dst_rdy)); +    +   fifo36_mux rx_test_mux_lvl_2 +     (.clk(fifo_clk), .reset(fifo_rst), .clear(clear_rx), +      .data0_i(testrx_data), .src0_rdy_i(testrx_src_rdy), .dst0_rdy_o(testrx_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(testtx_data), .src1_rdy_o(testtx_src_rdy), .dst1_rdy_i(testtx_dst_rdy) ); +    +   crossbar36 tx_crossbar_lvl_2 +     (.clk(fifo_clk), .reset(fifo_rst), .clear(clear_tx), +      .cross(sel_loopbacktx), +      .data0_i(testtx_data), .src0_rdy_i(testtx_src_rdy), .dst0_rdy_o(testtx_dst_rdy), +      .data1_i(testtx_data), .src1_rdy_i(1'b0), .dst1_rdy_o(),  // No 2nd input +      .data0_o(timedtx_data), .src0_rdy_o(timedtx_src_rdy), .dst0_rdy_i(timedtx_dst_rdy), +      .data1_o(loopbacktx_data), .src1_rdy_o(loopbacktx_src_rdy), .dst1_rdy_i(loopbacktx_dst_rdy) ); +    +   // Fixed rate TX traffic consumer +   fifo_pacer tx_pacer +     (.clk(fifo_clk), .reset(fifo_rst), .rate(test_rate), .enable(pkt_sink_enable), +      .src1_rdy_i(timedtx_src_rdy), .dst1_rdy_o(timedtx_dst_rdy), +      .src2_rdy_o(timedtx_src_rdy_int), .dst2_rdy_i(timedtx_dst_rdy_int), +      .underrun(tx_underrun), .overrun()); + +   packet_verifier32 pktver32 +     (.clk(fifo_clk), .reset(fifo_rst), .clear(clear_tx), +      .data_i(timedtx_data), .src_rdy_i(timedtx_src_rdy_int), .dst_rdy_o(timedtx_dst_rdy_int), +      .total(total), .crc_err(crc_err), .seq_err(seq_err), .len_err(len_err)); + +   // Fixed rate RX traffic generator +   vita_pkt_gen pktgen +     (.clk(fifo_clk), .reset(fifo_rst), .clear(clear_rx), +      .len(test_len), +      .data_o(timedrx_data), .src_rdy_o(timedrx_src_rdy_int), .dst_rdy_i(timedrx_dst_rdy_int)); + +   fifo_pacer rx_pacer +     (.clk(fifo_clk), .reset(fifo_rst), .rate(test_rate), .enable(pkt_src_enable), +      .src1_rdy_i(timedrx_src_rdy_int), .dst1_rdy_o(timedrx_dst_rdy_int), +      .src2_rdy_o(timedrx_src_rdy), .dst2_rdy_i(timedrx_dst_rdy), +      .underrun(), .overrun(rx_overrun)); +*/ +   // //////////////////////////////////////////// +   //    DEBUG +    +   assign debug0 = { pktend_latch, data_rx_src_rdy, gpif_ctl[3:0], sloe, slrd, slwr, pktend, fifoadr[1:0], state[3:0], gpif_d[15:0]}; +   //assign debug0 = { data_tx_src_rdy, data_tx_dst_rdy, tx_src_rdy_int, tx_dst_rdy_int,  +   //                  tx19_src_rdy, tx19_dst_rdy, refr_src_rdy, refr_dst_rdy,  +   //                  tx36_src_rdy, tx36_dst_rdy, +   //                  gpif_ctl[3:0], fifoadr[1:0],  +   //                  wr_fifo_space[15:0]}; +   assign debug1 = { 16'b0, transfer_count[7:0], ctrl_rx_src_rdy, ctrl_tx_dst_rdy, data_rx_src_rdy, +                     data_tx_dst_rdy, ctrl_tx_src_rdy, ctrl_rx_dst_rdy, data_tx_src_rdy, data_rx_dst_rdy}; +endmodule // slave_fifo diff --git a/fpga/usrp2/sdr_lib/Makefile.srcs b/fpga/usrp2/sdr_lib/Makefile.srcs index 629b92cc8..e6c4c5343 100644 --- a/fpga/usrp2/sdr_lib/Makefile.srcs +++ b/fpga/usrp2/sdr_lib/Makefile.srcs @@ -1,5 +1,5 @@  # -# Copyright 2010 Ettus Research LLC +# Copyright 2010-2012 Ettus Research LLC  #  ################################################## @@ -23,9 +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 \ +dspengine_8to16.v \  hb_dec.v \  hb_interp.v \  pipectrl.v \ @@ -39,4 +40,6 @@ sign_extend.v \  small_hb_dec.v \  small_hb_int.v \  tx_frontend.v \ +dsp_tx_glue.v \ +dsp_rx_glue.v \  )) diff --git a/fpga/usrp2/sdr_lib/cordic_z24.v b/fpga/usrp2/sdr_lib/cordic_z24.v index 97b7beaf7..51b074a33 100644 --- a/fpga/usrp2/sdr_lib/cordic_z24.v +++ b/fpga/usrp2/sdr_lib/cordic_z24.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 diff --git a/fpga/usrp2/sdr_lib/ddc_chain.v b/fpga/usrp2/sdr_lib/ddc_chain.v new file mode 100644 index 000000000..c32c9f491 --- /dev/null +++ b/fpga/usrp2/sdr_lib/ddc_chain.v @@ -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 diff --git a/fpga/usrp2/sdr_lib/dsp_core_rx.v b/fpga/usrp2/sdr_lib/dsp_core_rx.v deleted file mode 100644 index d1c7e238a..000000000 --- a/fpga/usrp2/sdr_lib/dsp_core_rx.v +++ /dev/null @@ -1,144 +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 dsp_core_rx -  #(parameter BASE = 160) -  (input clk, input rst, -   input set_stb, input [7:0] set_addr, input [31:0] set_data, - -   input [23:0] adc_i, input adc_ovf_i, -   input [23:0] adc_q, input adc_ovf_q, -    -   output [31:0] sample, -   input run, -   output strobe, -   output [31:0] debug -   ); - -   wire [31:0] phase_inc; -   reg [31:0]  phase; - -   wire [24:0] i_cordic, q_cordic; -   wire [23:0] i_cordic_clip, q_cordic_clip; -   wire [23:0] i_cic, q_cic; -   wire [23:0] i_hb1, q_hb1; -   wire [23:0] i_hb2, q_hb2; -    -   wire        strobe_cic, strobe_hb1, strobe_hb2; -   wire        enable_hb1, enable_hb2; -   wire [7:0]  cic_decim_rate; - -   reg [23:0]  adc_i_mux, adc_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)) sr_1 -     (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), -      .in(set_data),.out({scale_i,scale_q}),.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 -	  adc_i_mux <= adc_q; -	  adc_q_mux <= realmode ? 24'd0 : adc_i; -       end -     else -       begin -	  adc_i_mux <= adc_i; -	  adc_q_mux <= realmode ? 24'd0 : adc_q; -       end - -   // NCO -   always @(posedge clk) -     if(rst) -       phase <= 0; -     else if(~run) -       phase <= 0; -     else -       phase <= phase + phase_inc; - -   // CORDIC  24-bit I/O -   cordic_z24 #(.bitwidth(25)) -     cordic(.clock(clk), .reset(rst), .enable(run), -	    .xi({adc_i_mux[23],adc_i_mux}),. yi({adc_q_mux[23],adc_q_mux}), .zi(phase[31:8]), -	    .xo(i_cordic),.yo(q_cordic),.zo() ); - -   clip_reg #(.bits_in(25), .bits_out(24)) clip_i -     (.clk(clk), .in(i_cordic), .strobe_in(1'b1), .out(i_cordic_clip)); -   clip_reg #(.bits_in(25), .bits_out(24)) clip_q -     (.clk(clk), .in(q_cordic), .strobe_in(1'b1), .out(q_cordic_clip)); - -   // CIC decimator  24 bit I/O -   cic_strober cic_strober(.clock(clk),.reset(rst),.enable(run),.rate(cic_decim_rate), -			   .strobe_fast(1),.strobe_slow(strobe_cic) ); - -   cic_decim #(.bw(24)) -     decim_i (.clock(clk),.reset(rst),.enable(run), -	      .rate(cic_decim_rate),.strobe_in(1'b1),.strobe_out(strobe_cic), -	      .signal_in(i_cordic_clip),.signal_out(i_cic)); -    -   cic_decim #(.bw(24)) -     decim_q (.clock(clk),.reset(rst),.enable(run), -	      .rate(cic_decim_rate),.strobe_in(1'b1),.strobe_out(strobe_cic), -	      .signal_in(q_cordic_clip),.signal_out(q_cic)); - -   // First (small) halfband  24 bit I/O -   small_hb_dec #(.WIDTH(24)) small_hb_i -     (.clk(clk),.rst(rst),.bypass(~enable_hb1),.run(run), -      .stb_in(strobe_cic),.data_in(i_cic),.stb_out(strobe_hb1),.data_out(i_hb1)); -    -   small_hb_dec #(.WIDTH(24)) small_hb_q -     (.clk(clk),.rst(rst),.bypass(~enable_hb1),.run(run), -      .stb_in(strobe_cic),.data_in(q_cic),.stb_out(),.data_out(q_hb1)); - -   // Second (large) halfband  24 bit I/O -   wire [8:0]  cpi_hb = enable_hb1 ? {cic_decim_rate,1'b0} : {1'b0,cic_decim_rate}; -   hb_dec #(.WIDTH(24)) hb_i -     (.clk(clk),.rst(rst),.bypass(~enable_hb2),.run(run),.cpi(cpi_hb), -      .stb_in(strobe_hb1),.data_in(i_hb1),.stb_out(strobe_hb2),.data_out(i_hb2)); - -   hb_dec #(.WIDTH(24)) hb_q -     (.clk(clk),.rst(rst),.bypass(~enable_hb2),.run(run),.cpi(cpi_hb), -      .stb_in(strobe_hb1),.data_in(q_hb1),.stb_out(),.data_out(q_hb2)); - -   // Round final answer to 16 bits -   round_sd #(.WIDTH_IN(24),.WIDTH_OUT(16)) round_i -     (.clk(clk),.reset(rst), .in(i_hb2),.strobe_in(strobe_hb2), .out(sample[31:16]), .strobe_out(strobe)); - -   round_sd #(.WIDTH_IN(24),.WIDTH_OUT(16)) round_q -     (.clk(clk),.reset(rst), .in(q_hb2),.strobe_in(strobe_hb2), .out(sample[15:0]), .strobe_out()); -    -   assign      debug = {enable_hb1, enable_hb2, run, strobe, strobe_cic, strobe_hb1, strobe_hb2}; -    -endmodule // dsp_core_rx diff --git a/fpga/usrp2/sdr_lib/dsp_core_rx_old.v b/fpga/usrp2/sdr_lib/dsp_core_rx_old.v deleted file mode 100644 index 90d5d839f..000000000 --- a/fpga/usrp2/sdr_lib/dsp_core_rx_old.v +++ /dev/null @@ -1,200 +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/>. -// - - -`define DSP_CORE_RX_BASE 160 -module dsp_core_rx_old -  (input clk, input rst, -   input set_stb, input [7:0] set_addr, input [31:0] set_data, - -   input [13:0] adc_a, input adc_ovf_a, -   input [13:0] adc_b, input adc_ovf_b, -    -   input [15:0] io_rx, - -   output [31:0] sample, -   input run, -   output strobe, -   output [31:0] debug -   ); - -   wire [15:0] scale_i, scale_q; -   wire [13:0] adc_a_ofs, adc_b_ofs; -   reg [13:0] adc_i, adc_q; -   wire [31:0] phase_inc; -   reg [31:0]  phase; - -   wire [35:0] prod_i, prod_q; -   wire [23:0] i_cordic, q_cordic; -   wire [23:0] i_cic, q_cic; -   wire [17:0] i_cic_scaled, q_cic_scaled; -   wire [17:0] i_hb1, q_hb1; -   wire [17:0] i_hb2, q_hb2; -   wire [15:0] i_out, q_out; - -   wire        strobe_cic, strobe_hb1, strobe_hb2; -   wire        enable_hb1, enable_hb2; -   wire [7:0]  cic_decim_rate; - -   wire [31:10] UNUSED_1; -   wire [31:4] 	UNUSED_2; -   wire [31:2] 	UNUSED_3; -    -   setting_reg #(.my_addr(`DSP_CORE_RX_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(`DSP_CORE_RX_BASE+1)) sr_1 -     (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), -      .in(set_data),.out({scale_i,scale_q}),.changed()); -    -   setting_reg #(.my_addr(`DSP_CORE_RX_BASE+2)) sr_2 -     (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), -      .in(set_data),.out({UNUSED_1, enable_hb1, enable_hb2, cic_decim_rate}),.changed()); - -   rx_dcoffset #(.WIDTH(14),.ADDR(`DSP_CORE_RX_BASE+6)) rx_dcoffset_a -     (.clk(clk),.rst(rst),.set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), -      .adc_in(adc_a),.adc_out(adc_a_ofs)); -    -   rx_dcoffset #(.WIDTH(14),.ADDR(`DSP_CORE_RX_BASE+7)) rx_dcoffset_b -     (.clk(clk),.rst(rst),.set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), -      .adc_in(adc_b),.adc_out(adc_b_ofs)); - -   wire [3:0]  muxctrl; -   setting_reg #(.my_addr(`DSP_CORE_RX_BASE+8)) sr_8 -     (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), -      .in(set_data),.out({UNUSED_2,muxctrl}),.changed()); - -   wire [1:0] gpio_ena; -   setting_reg #(.my_addr(`DSP_CORE_RX_BASE+9)) sr_9 -     (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), -      .in(set_data),.out({UNUSED_3,gpio_ena}),.changed()); - -   // The TVRX connects to what is called adc_b, thus A and B are -   // swapped throughout the design. -   // -   // In the interest of expediency and keeping the s/w sane, we just remap them here. -   // The I & Q fields are mapped the same: -   // 0 -> "the real A" (as determined by the TVRX) -   // 1 -> "the real B" -   // 2 -> const zero -    -   always @(posedge clk) -     case(muxctrl[1:0])		// The I mapping -       0: adc_i <= adc_b_ofs;	// "the real A" -       1: adc_i <= adc_a_ofs; -       2: adc_i <= 0; -       default: adc_i <= 0; -     endcase // case(muxctrl[1:0]) -           -   always @(posedge clk) -     case(muxctrl[3:2])		// The Q mapping -       0: adc_q <= adc_b_ofs;	// "the real A" -       1: adc_q <= adc_a_ofs; -       2: adc_q <= 0; -       default: adc_q <= 0; -     endcase // case(muxctrl[3:2]) -        -   always @(posedge clk) -     if(rst) -       phase <= 0; -     else if(~run) -       phase <= 0; -     else -       phase <= phase + phase_inc; - -   MULT18X18S mult_i -     (.P(prod_i),    // 36-bit multiplier output -      .A({{4{adc_i[13]}},adc_i} ),    // 18-bit multiplier input -      .B({{2{scale_i[15]}},scale_i}),    // 18-bit multiplier input -      .C(clk),    // Clock input -      .CE(1),  // Clock enable input -      .R(rst)     // Synchronous reset input -      ); - -   MULT18X18S mult_q -     (.P(prod_q),    // 36-bit multiplier output -      .A({{4{adc_q[13]}},adc_q} ),    // 18-bit multiplier input -      .B({{2{scale_q[15]}},scale_q}),    // 18-bit multiplier input -      .C(clk),    // Clock input -      .CE(1),  // Clock enable input -      .R(rst)     // Synchronous reset input -      );  - -    -   cordic_z24 #(.bitwidth(24)) -     cordic(.clock(clk), .reset(rst), .enable(run), -	    .xi(prod_i[23:0]),. yi(prod_q[23:0]), .zi(phase[31:8]), -	    .xo(i_cordic),.yo(q_cordic),.zo() ); - -   cic_strober cic_strober(.clock(clk),.reset(rst),.enable(run),.rate(cic_decim_rate), -			   .strobe_fast(1),.strobe_slow(strobe_cic) ); - -   cic_decim #(.bw(24)) -     decim_i (.clock(clk),.reset(rst),.enable(run), -	      .rate(cic_decim_rate),.strobe_in(1'b1),.strobe_out(strobe_cic), -	      .signal_in(i_cordic),.signal_out(i_cic)); -    -   cic_decim #(.bw(24)) -     decim_q (.clock(clk),.reset(rst),.enable(run), -	      .rate(cic_decim_rate),.strobe_in(1'b1),.strobe_out(strobe_cic), -	      .signal_in(q_cordic),.signal_out(q_cic)); - -   round_reg #(.bits_in(24),.bits_out(18)) round_icic (.clk(clk),.in(i_cic),.out(i_cic_scaled)); -   round_reg #(.bits_in(24),.bits_out(18)) round_qcic (.clk(clk),.in(q_cic),.out(q_cic_scaled)); -   reg 	       strobe_cic_d1; -   always @(posedge clk) strobe_cic_d1 <= strobe_cic; -    -   small_hb_dec #(.WIDTH(18)) small_hb_i -     (.clk(clk),.rst(rst),.bypass(~enable_hb1),.run(run), -      .stb_in(strobe_cic_d1),.data_in(i_cic_scaled),.stb_out(strobe_hb1),.data_out(i_hb1)); -    -   small_hb_dec #(.WIDTH(18)) small_hb_q -     (.clk(clk),.rst(rst),.bypass(~enable_hb1),.run(run), -      .stb_in(strobe_cic_d1),.data_in(q_cic_scaled),.stb_out(),.data_out(q_hb1)); - -   wire [8:0]  cpi_hb = enable_hb1 ? {cic_decim_rate,1'b0} : {1'b0,cic_decim_rate}; -   hb_dec #(.IWIDTH(18), .OWIDTH(18), .CWIDTH(18), .ACCWIDTH(24)) hb_i -     (.clk(clk),.rst(rst),.bypass(~enable_hb2),.run(run),.cpi(cpi_hb), -      .stb_in(strobe_hb1),.data_in(i_hb1),.stb_out(strobe_hb2),.data_out(i_hb2)); - -   hb_dec #(.IWIDTH(18), .OWIDTH(18), .CWIDTH(18), .ACCWIDTH(24)) hb_q -     (.clk(clk),.rst(rst),.bypass(~enable_hb2),.run(run),.cpi(cpi_hb), -      .stb_in(strobe_hb1),.data_in(q_hb1),.stb_out(),.data_out(q_hb2)); - -   round #(.bits_in(18),.bits_out(16)) round_iout (.in(i_hb2),.out(i_out)); -   round #(.bits_in(18),.bits_out(16)) round_qout (.in(q_hb2),.out(q_out)); - -   // Streaming GPIO -   // -   // io_rx[15] => I channel LSB if gpio_ena[0] high -   // io_rx[14] => Q channel LSB if gpio_ena[1] high - -   reg [31:0] sample_reg; -   always @(posedge clk) -     begin -	sample_reg[31:17] <= i_out[15:1]; -	sample_reg[15:1]  <= q_out[15:1]; -	sample_reg[16]    <= gpio_ena[0] ? io_rx[15] : i_out[0];  -	sample_reg[0]     <= gpio_ena[1] ? io_rx[14] : q_out[0]; -     end -    -   assign      sample = sample_reg; -   assign      strobe = strobe_hb2; -   assign      debug = {enable_hb1, enable_hb2, run, strobe, strobe_cic, strobe_cic_d1, strobe_hb1, strobe_hb2}; -    -endmodule // dsp_core_rx diff --git a/fpga/usrp2/sdr_lib/dsp_core_rx_tb.v b/fpga/usrp2/sdr_lib/dsp_core_rx_tb.v index 271db8cef..a221bed44 100644 --- a/fpga/usrp2/sdr_lib/dsp_core_rx_tb.v +++ b/fpga/usrp2/sdr_lib/dsp_core_rx_tb.v @@ -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 diff --git a/fpga/usrp2/sdr_lib/dsp_core_rx_udp.v b/fpga/usrp2/sdr_lib/dsp_core_rx_udp.v deleted file mode 100644 index 08dab37e6..000000000 --- a/fpga/usrp2/sdr_lib/dsp_core_rx_udp.v +++ /dev/null @@ -1,200 +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 dsp_core_rx -  #(parameter BASE = 160) -  (input clk, input rst, -   input set_stb, input [7:0] set_addr, input [31:0] set_data, - -   input [13:0] adc_a, input adc_ovf_a, -   input [13:0] adc_b, input adc_ovf_b, -    -   input [15:0] io_rx, - -   output [31:0] sample, -   input run, -   output strobe, -   output [31:0] debug -   ); - -   wire [15:0] scale_i, scale_q; -   wire [13:0] adc_a_ofs, adc_b_ofs; -   reg [13:0] adc_i, adc_q; -   wire [31:0] phase_inc; -   reg [31:0]  phase; - -   wire [35:0] prod_i, prod_q; -   wire [23:0] i_cordic, q_cordic; -   wire [23:0] i_cic, q_cic; -   wire [17:0] i_cic_scaled, q_cic_scaled; -   wire [17:0] i_hb1, q_hb1; -   wire [17:0] i_hb2, q_hb2; -   wire [15:0] i_out, q_out; - -   wire        strobe_cic, strobe_hb1, strobe_hb2; -   wire        enable_hb1, enable_hb2; -   wire [7:0]  cic_decim_rate; - -   wire [31:10] UNUSED_1; -   wire [31:4] 	UNUSED_2; -   wire [31:2] 	UNUSED_3; -    -   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)) sr_1 -     (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), -      .in(set_data),.out({scale_i,scale_q}),.changed()); -    -   setting_reg #(.my_addr(BASE+2)) sr_2 -     (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), -      .in(set_data),.out({UNUSED_1, enable_hb1, enable_hb2, cic_decim_rate}),.changed()); - -   rx_dcoffset #(.WIDTH(14),.ADDR(BASE+3)) rx_dcoffset_a -     (.clk(clk),.rst(rst),.set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), -      .adc_in(adc_a),.adc_out(adc_a_ofs)); -    -   rx_dcoffset #(.WIDTH(14),.ADDR(BASE+4)) rx_dcoffset_b -     (.clk(clk),.rst(rst),.set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), -      .adc_in(adc_b),.adc_out(adc_b_ofs)); - -   wire [3:0]  muxctrl; -   setting_reg #(.my_addr(BASE+5)) sr_8 -     (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), -      .in(set_data),.out({UNUSED_2,muxctrl}),.changed()); - -   wire [1:0] gpio_ena; -   setting_reg #(.my_addr(BASE+6)) sr_9 -     (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), -      .in(set_data),.out({UNUSED_3,gpio_ena}),.changed()); - -   // The TVRX connects to what is called adc_b, thus A and B are -   // swapped throughout the design. -   // -   // In the interest of expediency and keeping the s/w sane, we just remap them here. -   // The I & Q fields are mapped the same: -   // 0 -> "the real A" (as determined by the TVRX) -   // 1 -> "the real B" -   // 2 -> const zero -    -   always @(posedge clk) -     case(muxctrl[1:0])		// The I mapping -       0: adc_i <= adc_b_ofs;	// "the real A" -       1: adc_i <= adc_a_ofs; -       2: adc_i <= 0; -       default: adc_i <= 0; -     endcase // case(muxctrl[1:0]) -           -   always @(posedge clk) -     case(muxctrl[3:2])		// The Q mapping -       0: adc_q <= adc_b_ofs;	// "the real A" -       1: adc_q <= adc_a_ofs; -       2: adc_q <= 0; -       default: adc_q <= 0; -     endcase // case(muxctrl[3:2]) -        -   always @(posedge clk) -     if(rst) -       phase <= 0; -     else if(~run) -       phase <= 0; -     else -       phase <= phase + phase_inc; - -   MULT18X18S mult_i -     (.P(prod_i),    // 36-bit multiplier output -      .A({{4{adc_i[13]}},adc_i} ),    // 18-bit multiplier input -      .B({{2{scale_i[15]}},scale_i}),    // 18-bit multiplier input -      .C(clk),    // Clock input -      .CE(1),  // Clock enable input -      .R(rst)     // Synchronous reset input -      ); - -   MULT18X18S mult_q -     (.P(prod_q),    // 36-bit multiplier output -      .A({{4{adc_q[13]}},adc_q} ),    // 18-bit multiplier input -      .B({{2{scale_q[15]}},scale_q}),    // 18-bit multiplier input -      .C(clk),    // Clock input -      .CE(1),  // Clock enable input -      .R(rst)     // Synchronous reset input -      );  - -    -   cordic_z24 #(.bitwidth(24)) -     cordic(.clock(clk), .reset(rst), .enable(run), -	    .xi(prod_i[23:0]),. yi(prod_q[23:0]), .zi(phase[31:8]), -	    .xo(i_cordic),.yo(q_cordic),.zo() ); - -   cic_strober cic_strober(.clock(clk),.reset(rst),.enable(run),.rate(cic_decim_rate), -			   .strobe_fast(1),.strobe_slow(strobe_cic) ); - -   cic_decim #(.bw(24)) -     decim_i (.clock(clk),.reset(rst),.enable(run), -	      .rate(cic_decim_rate),.strobe_in(1'b1),.strobe_out(strobe_cic), -	      .signal_in(i_cordic),.signal_out(i_cic)); -    -   cic_decim #(.bw(24)) -     decim_q (.clock(clk),.reset(rst),.enable(run), -	      .rate(cic_decim_rate),.strobe_in(1'b1),.strobe_out(strobe_cic), -	      .signal_in(q_cordic),.signal_out(q_cic)); - -   round_reg #(.bits_in(24),.bits_out(18)) round_icic (.clk(clk),.in(i_cic),.out(i_cic_scaled)); -   round_reg #(.bits_in(24),.bits_out(18)) round_qcic (.clk(clk),.in(q_cic),.out(q_cic_scaled)); -   reg 	       strobe_cic_d1; -   always @(posedge clk) strobe_cic_d1 <= strobe_cic; -    -   small_hb_dec #(.WIDTH(18)) small_hb_i -     (.clk(clk),.rst(rst),.bypass(~enable_hb1),.run(run), -      .stb_in(strobe_cic_d1),.data_in(i_cic_scaled),.stb_out(strobe_hb1),.data_out(i_hb1)); -    -   small_hb_dec #(.WIDTH(18)) small_hb_q -     (.clk(clk),.rst(rst),.bypass(~enable_hb1),.run(run), -      .stb_in(strobe_cic_d1),.data_in(q_cic_scaled),.stb_out(),.data_out(q_hb1)); - -   wire [8:0]  cpi_hb = enable_hb1 ? {cic_decim_rate,1'b0} : {1'b0,cic_decim_rate}; -   hb_dec #(.IWIDTH(18), .OWIDTH(18), .CWIDTH(18), .ACCWIDTH(24)) hb_i -     (.clk(clk),.rst(rst),.bypass(~enable_hb2),.run(run),.cpi(cpi_hb), -      .stb_in(strobe_hb1),.data_in(i_hb1),.stb_out(strobe_hb2),.data_out(i_hb2)); - -   hb_dec #(.IWIDTH(18), .OWIDTH(18), .CWIDTH(18), .ACCWIDTH(24)) hb_q -     (.clk(clk),.rst(rst),.bypass(~enable_hb2),.run(run),.cpi(cpi_hb), -      .stb_in(strobe_hb1),.data_in(q_hb1),.stb_out(),.data_out(q_hb2)); - -   round #(.bits_in(18),.bits_out(16)) round_iout (.in(i_hb2),.out(i_out)); -   round #(.bits_in(18),.bits_out(16)) round_qout (.in(q_hb2),.out(q_out)); - -   // Streaming GPIO -   // -   // io_rx[15] => I channel LSB if gpio_ena[0] high -   // io_rx[14] => Q channel LSB if gpio_ena[1] high - -   reg [31:0] sample_reg; -   always @(posedge clk) -     begin -	sample_reg[31:17] <= i_out[15:1]; -	sample_reg[15:1]  <= q_out[15:1]; -	sample_reg[16]    <= gpio_ena[0] ? io_rx[15] : i_out[0];  -	sample_reg[0]     <= gpio_ena[1] ? io_rx[14] : q_out[0]; -     end -    -   assign      sample = sample_reg; -   assign      strobe = strobe_hb2; -   assign      debug = {enable_hb1, enable_hb2, run, strobe, strobe_cic, strobe_cic_d1, strobe_hb1, strobe_hb2}; -    -endmodule // dsp_core_rx diff --git a/fpga/usrp2/sdr_lib/dsp_rx_glue.v b/fpga/usrp2/sdr_lib/dsp_rx_glue.v new file mode 100644 index 000000000..038a67a29 --- /dev/null +++ b/fpga/usrp2/sdr_lib/dsp_rx_glue.v @@ -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 diff --git a/fpga/usrp2/sdr_lib/dsp_tx_glue.v b/fpga/usrp2/sdr_lib/dsp_tx_glue.v new file mode 100644 index 000000000..46f6789ee --- /dev/null +++ b/fpga/usrp2/sdr_lib/dsp_tx_glue.v @@ -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 diff --git a/fpga/usrp2/sdr_lib/dspengine_16to8.v b/fpga/usrp2/sdr_lib/dspengine_16to8.v index 53c5d29da..448c57d35 100644 --- a/fpga/usrp2/sdr_lib/dspengine_16to8.v +++ b/fpga/usrp2/sdr_lib/dspengine_16to8.v @@ -1,5 +1,5 @@ -// Copyright 2011 Ettus Research LLC +// Copyright 2011-2012 Ettus Research LLC  //  // This program is free software: you can redistribute it and/or modify  // it under the terms of the GNU General Public License as published by @@ -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; @@ -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 diff --git a/fpga/usrp2/sdr_lib/dspengine_8to16.v b/fpga/usrp2/sdr_lib/dspengine_8to16.v new file mode 100644 index 000000000..85187d78d --- /dev/null +++ b/fpga/usrp2/sdr_lib/dspengine_8to16.v @@ -0,0 +1,203 @@ + +// 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/>. +// + +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[31:24]; +   wire [7:0] 	      q8_1 = access_dat_i[23:16]; +   reg 		      skip; +    + +   always @(posedge clk) +     { i8_0, q8_0 } <= access_dat_i[15:0]; +    +   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 diff --git a/fpga/usrp2/sdr_lib/dsp_core_tx.v b/fpga/usrp2/sdr_lib/duc_chain.v index 4e0163e0a..bd3402a1f 100644 --- a/fpga/usrp2/sdr_lib/dsp_core_tx.v +++ b/fpga/usrp2/sdr_lib/duc_chain.v @@ -1,5 +1,5 @@  // -// Copyright 2011 Ettus Research LLC +// Copyright 2011-2012 Ettus Research LLC  //  // This program is free software: you can redistribute it and/or modify  // it under the terms of the GNU General Public License as published by @@ -15,26 +15,35 @@  // along with this program.  If not, see <http://www.gnu.org/licenses/>.  // +//! The USRP digital up-conversion chain -module dsp_core_tx -  #(parameter BASE=0) -  (input clk, input rst, +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, -   output [23:0] tx_i, output [23:0] tx_q, +   // To TX frontend +   output [WIDTH-1:0] tx_fe_i, +   output [WIDTH-1:0] tx_fe_q, -   // To tx_control +   // From TX control     input [31:0] sample,     input run,     output strobe,     output [31:0] debug     ); -   wire [15:0] i, q, scale_i, scale_q; +   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]  dacmux_a, dacmux_b; +   wire [3:0]  tx_femux_a, tx_femux_b;     wire        enable_hb1, enable_hb2;     wire        rate_change; @@ -42,9 +51,9 @@ module dsp_core_tx       (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),        .in(set_data),.out(phase_inc),.changed()); -   setting_reg #(.my_addr(BASE+1)) sr_1 +   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_i,scale_q}),.changed()); +      .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), @@ -57,13 +66,13 @@ module dsp_core_tx     reg 	       strobe_hb2 = 1;     cic_strober #(.WIDTH(8)) -     cic_strober(.clock(clk),.reset(rst),.enable(run & ~rate_change),.rate(interp_rate), +     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(run & ~rate_change),.rate(enable_hb2 ? 2 : 1), +     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(run & ~rate_change),.rate(enable_hb1 ? 2 : 1), +     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; @@ -74,7 +83,7 @@ module dsp_core_tx     always @(posedge clk)       if(rst)         phase <= 0; -     else if(~run) +     else if(~duc_enb)         phase <= 0;       else         phase <= phase + phase_inc; @@ -82,8 +91,8 @@ module dsp_core_tx     wire        signed [17:0] da, db;     wire        signed [35:0] prod_i, prod_q; -   wire [17:0] bb_i = {sample[31:16],2'b0}; -   wire [17:0] bb_q = {sample[15:0],2'b0}; +   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; @@ -92,10 +101,10 @@ module dsp_core_tx     // 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(24)) hb_interp_i -     (.clk(clk),.rst(rst),.bypass(~enable_hb1),.cpo(cpo),.stb_in(strobe_hb1),.data_in(bb_i),.stb_out(strobe_hb2),.data_out(hb1_i)); -   hb_interp #(.IWIDTH(18),.OWIDTH(18),.ACCWIDTH(24)) hb_interp_q -     (.clk(clk),.rst(rst),.bypass(~enable_hb1),.cpo(cpo),.stb_in(strobe_hb1),.data_in(bb_q),.stb_out(strobe_hb2),.data_out(hb1_q)); +   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), @@ -105,24 +114,22 @@ module dsp_core_tx        .output_rate(interp_rate),.stb_out(strobe_cic),.data_out(hb2_q));     cic_interp  #(.bw(18),.N(4),.log2_of_max_rate(7)) -     cic_interp_i(.clock(clk),.reset(rst),.enable(run & ~rate_change),.rate(interp_rate), +     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(run & ~rate_change),.rate(interp_rate), +     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)); -   assign      strobe = strobe_hb1; - -   localparam  cwidth = 24;  // was 18 +   localparam  cwidth = WIDTH;  // was 18     localparam  zwidth = 24;  // was 16     wire [cwidth-1:0] da_c, db_c;     cordic_z24 #(.bitwidth(cwidth)) -     cordic(.clock(clk), .reset(rst), .enable(run), +     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() ); @@ -130,7 +137,7 @@ module dsp_core_tx     MULT18X18S MULT18X18S_inst        (.P(prod_i),    // 36-bit multiplier output        .A(da_c[cwidth-1:cwidth-18]),    // 18-bit multiplier input -      .B({{2{scale_i[15]}},scale_i}),    // 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 @@ -139,15 +146,20 @@ module dsp_core_tx     MULT18X18S MULT18X18S_inst_2        (.P(prod_q),    // 36-bit multiplier output        .A(db_c[cwidth-1:cwidth-18]),    // 18-bit multiplier input -      .B({{2{scale_q[15]}},scale_q}),    // 18-bit multiplier input +      .B(scale_factor),    // 18-bit multiplier input        .C(clk),    // Clock input        .CE(1),  // Clock enable input        .R(rst)     // Synchronous reset input        ); -   assign tx_i = prod_i[28:5]; -   assign tx_q = prod_q[28:5]; -    +   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 diff --git a/fpga/usrp2/sdr_lib/dummy_rx.v b/fpga/usrp2/sdr_lib/dummy_rx.v index b22d5f896..42bbe36b2 100644 --- a/fpga/usrp2/sdr_lib/dummy_rx.v +++ b/fpga/usrp2/sdr_lib/dummy_rx.v @@ -76,4 +76,4 @@ module dummy_rx         q_out <= q_out + 1; -endmodule // dsp_core_rx +endmodule // ddc_chain diff --git a/fpga/usrp2/timing/time_64bit.v b/fpga/usrp2/timing/time_64bit.v index 03df07108..6f335890e 100644 --- a/fpga/usrp2/timing/time_64bit.v +++ b/fpga/usrp2/timing/time_64bit.v @@ -1,5 +1,5 @@  // -// Copyright 2011 Ettus Research LLC +// Copyright 2011-2012 Ettus Research LLC  //  // This program is free software: you can redistribute it and/or modify  // it under the terms of the GNU General Public License as published by @@ -18,7 +18,7 @@  module time_64bit -  #(parameter TICKS_PER_SEC = 32'd100000000, +  #(      parameter BASE = 0)     (input clk, input rst,      input set_stb, input [7:0] set_addr, input [31:0] set_data,   @@ -31,23 +31,20 @@ module time_64bit      output [31:0] debug      ); -   localparam 	   NEXT_SECS = 0;    -   localparam 	   NEXT_TICKS = 1; +   localparam 	   NEXT_TICKS_HI = 0; +   localparam 	   NEXT_TICKS_LO = 1;     localparam      PPS_POLSRC = 2;     localparam      PPS_IMM = 3; -   localparam      TPS = 4;     localparam      MIMO_SYNC = 5; -   reg [31:0] 	   seconds, ticks; -   wire 	   end_of_second; +   reg [63:0] 	   ticks;     always @(posedge clk) -     vita_time <= {seconds,ticks}; +     vita_time <= ticks;     wire [63:0] 	   vita_time_rcvd; -   wire [31:0] 	   next_ticks_preset, next_seconds_preset; -   wire [31:0] 	   ticks_per_sec_reg; +   wire [63:0] 	   next_ticks_preset;     wire 	   set_on_pps_trig;     reg 		   set_on_next_pps;     wire 	   pps_polarity, pps_source, set_imm; @@ -57,18 +54,18 @@ module time_64bit     reg [15:0] 	   sync_counter;     wire 	   sync_rcvd; -   wire [31:0] 	   mimo_secs, mimo_ticks; +   wire [63:0] 	   mimo_ticks;     wire 	   mimo_sync_now;     wire 	   mimo_sync;     wire [7:0] 	   sync_delay; -   setting_reg #(.my_addr(BASE+NEXT_TICKS)) sr_next_ticks +   setting_reg #(.my_addr(BASE+NEXT_TICKS_LO)) sr_next_ticks_lo       (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), -      .in(set_data),.out(next_ticks_preset),.changed()); +      .in(set_data),.out(next_ticks_preset[31:0]),.changed()); -   setting_reg #(.my_addr(BASE+NEXT_SECS)) sr_next_secs +   setting_reg #(.my_addr(BASE+NEXT_TICKS_HI)) sr_next_ticks_hi       (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), -      .in(set_data),.out(next_seconds_preset),.changed(set_on_pps_trig)); +      .in(set_data),.out(next_ticks_preset[63:32]),.changed(set_on_pps_trig));     setting_reg #(.my_addr(BASE+PPS_POLSRC), .width(2)) sr_pps_polsrc       (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), @@ -78,10 +75,6 @@ module time_64bit       (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),        .in(set_data),.out(set_imm),.changed()); -   setting_reg #(.my_addr(BASE+TPS), .at_reset(TICKS_PER_SEC)) sr_tps -     (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), -      .in(set_data),.out(ticks_per_sec_reg),.changed()); -     setting_reg #(.my_addr(BASE+MIMO_SYNC), .at_reset(0), .width(9)) sr_mimosync       (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),        .in(set_data),.out({mimo_sync,sync_delay}),.changed()); @@ -110,29 +103,21 @@ module time_64bit       else if(set_imm | pps_edge)         set_on_next_pps <= 0; -   wire [31:0] 	   ticks_plus_one = ticks + 1; +   wire [63:0] 	   ticks_plus_one = ticks + 1;     always @(posedge clk)       if(rst)         begin -	  seconds <= 32'd0; -	  ticks <= 32'd0; +	  ticks <= 64'd0;         end       else if((set_imm | pps_edge) & set_on_next_pps)         begin -	  seconds <= next_seconds_preset;  	  ticks <= next_ticks_preset;         end       else if(mimo_sync_now)         begin -	  seconds <= mimo_secs;  	  ticks <= mimo_ticks;         end -     else if(ticks_plus_one == ticks_per_sec_reg) -       begin -	  seconds <= seconds + 1; -	  ticks <= 0; -       end       else         ticks <= ticks_plus_one; @@ -162,9 +147,8 @@ module time_64bit        .sync_rcvd(sync_rcvd),        .exp_time_in(exp_time_in) ); -   assign mimo_secs = vita_time_rcvd[63:32]; -   assign mimo_ticks = vita_time_rcvd[31:0] + {16'd0,sync_delay}; -   assign mimo_sync_now = mimo_sync & sync_rcvd & (mimo_ticks <= TICKS_PER_SEC); +   assign mimo_ticks = vita_time_rcvd[63:0] + {48'd0,sync_delay}; +   assign mimo_sync_now = mimo_sync & sync_rcvd;     assign debug = { { 24'b0} ,  		    { 2'b0, exp_time_in, exp_time_out, mimo_sync, mimo_sync_now, sync_rcvd, send_sync} }; diff --git a/fpga/usrp2/timing/time_compare.v b/fpga/usrp2/timing/time_compare.v index 54ea000d6..21607f51c 100644 --- a/fpga/usrp2/timing/time_compare.v +++ b/fpga/usrp2/timing/time_compare.v @@ -1,5 +1,5 @@  // -// Copyright 2011 Ettus Research LLC +// Copyright 2011-2012 Ettus Research LLC  //  // This program is free software: you can redistribute it and/or modify  // it under the terms of the GNU General Public License as published by @@ -16,49 +16,19 @@  // -// Top 32 bits are integer seconds, bottom 32 are clock ticks within a second +// 64 bits worth of ticks  module time_compare    (input [63:0] time_now,     input [63:0] trigger_time,     output now,     output early, -   output late,  +   output late,     output too_early); -    -   wire    sec_match   = (time_now[63:32] == trigger_time[63:32]); -   wire    sec_late    = (time_now[63:32] > trigger_time[63:32]); -   wire    tick_match  = (time_now[31:0] == trigger_time[31:0]); -   wire    tick_late   = (time_now[31:0] > trigger_time[31:0]); -/*    -   assign now 	       = sec_match & tick_match; -   assign late 	       = sec_late | (sec_match & tick_late); -   assign early        = ~now & ~late; -*/ +    assign now = time_now == trigger_time; +    assign late = time_now > trigger_time; +    assign early = ~now & ~late; +    assign too_early = 0; //not implemented -   /* -   assign now = (time_now == trigger_time); -   assign late = (time_now > trigger_time); -   assign early = (time_now < trigger_time); -   */ - -   // Compare fewer bits instead of 64 to speed up logic -   // Unused bits are not significant -   //     Top bit of seconds would put us in year 2038, long after -   //        the warranty has run out :) -   //     Top 5 bits of ticks are always zero for clocks less than 134MHz -   //     "late" can drop bottom few bits of ticks, and just delay signaling -   //        of late.   -   //     "now" cannot drop those bits, it needs to be exact. -    -   wire [57:0] short_now = {time_now[62:32],time_now[26:0]}; -   wire [57:0] short_trig = {trigger_time[62:32],trigger_time[26:0]}; - -   assign now = (short_now == short_trig); -   assign late = (short_now[57:5] > short_trig[57:5]); -   assign early = (short_now < short_trig); -    -   assign too_early    = (trigger_time[63:32] > (time_now[63:32] + 4));  // Don't wait too long -     endmodule // time_compare diff --git a/fpga/usrp2/top/B100/B100.ucf b/fpga/usrp2/top/B100/B100.ucf index 69fd49971..1c04c5d8d 100644 --- a/fpga/usrp2/top/B100/B100.ucf +++ b/fpga/usrp2/top/B100/B100.ucf @@ -25,6 +25,9 @@ NET "reset_n"  LOC = "D5"  ;  NET "PPS_IN"  LOC = "M14"  ;  NET "reset_codec"  LOC = "B14"  ; +## recycles fpga_cfg_cclk for reset from fw +NET "ext_reset"  LOC = "R14"  ; +  ## GPIF  NET "GPIF_D<15>"  LOC = "P7"  ;  NET "GPIF_D<14>"  LOC = "N8"  ; @@ -43,17 +46,18 @@ NET "GPIF_D<2>"  LOC = "N9"  ;  NET "GPIF_D<1>"  LOC = "P9"  ;  NET "GPIF_D<0>"  LOC = "P8"  ; -NET "GPIF_CTL<3>"  LOC = "N5"  ; +##NET "GPIF_CTL<3>"  LOC = "N5"  ; +NET "GPIF_CTL<3>"  LOC = "P12"  ;  NET "GPIF_CTL<2>"  LOC = "M11"  ;  NET "GPIF_CTL<1>"  LOC = "M9"  ;  NET "GPIF_CTL<0>"  LOC = "M7"  ; -NET "GPIF_RDY<3>"  LOC = "N11"  ; -NET "GPIF_RDY<2>"  LOC = "T10"  ; -NET "GPIF_RDY<1>"  LOC = "T4"  ; -NET "GPIF_RDY<0>"  LOC = "R5"  ; +##NET "GPIF_RDY<3>"  LOC = "N11"  ; +##NET "GPIF_RDY<2>"  LOC = "T10"  ; +NET "GPIF_SLWR"  LOC = "T4"  ; +NET "GPIF_SLRD"  LOC = "R5"  ; -NET "GPIF_CS"  LOC = "P12"  ; +##NET "GPIF_CS"  LOC = "P12"  ;  NET "GPIF_SLOE"  LOC = "R11"  ;  NET "GPIF_PKTEND"  LOC = "P10"  ;  NET "GPIF_ADR<0>"  LOC = "T11"  ; diff --git a/fpga/usrp2/top/B100/B100.v b/fpga/usrp2/top/B100/B100.v index f2d75c54e..dcda974b4 100644 --- a/fpga/usrp2/top/B100/B100.v +++ b/fpga/usrp2/top/B100/B100.v @@ -23,8 +23,8 @@ module B100     output [2:0] debug_led, output [31:0] debug, output [1:0] debug_clk,     // GPIF -   inout [15:0] GPIF_D, input [3:0] GPIF_CTL, output [3:0] GPIF_RDY, -   input [1:0] GPIF_ADR, output GPIF_CS, output GPIF_SLOE, output GPIF_PKTEND, +   inout [15:0] GPIF_D, input [3:0] GPIF_CTL, output GPIF_SLOE,  +   output [1:0] GPIF_ADR, output GPIF_SLWR, output GPIF_SLRD, output GPIF_PKTEND,     input IFCLK,     inout SDA_FPGA, inout SCL_FPGA, // I2C @@ -41,7 +41,8 @@ module B100     input [11:0] adc, input RXSYNC,     input PPS_IN, -   input reset_n, output reset_codec +   input reset_n, output reset_codec, +   input ext_reset     );     assign reset_codec = 1;  // Believed to be active low @@ -55,7 +56,7 @@ module B100     BUFG clk_fpga_BUFG (.I(clk_fpga_in), .O(clk_fpga)); -   reset_sync reset_sync(.clk(clk_fpga), .reset_in(~reset_n), .reset_out(reset)); +   reset_sync reset_sync(.clk(clk_fpga), .reset_in((~reset_n) | (~ext_reset)), .reset_out(reset));     // /////////////////////////////////////////////////////////////////////////     // SPI @@ -156,9 +157,10 @@ module B100     u1plus_core u1p_c(.clk_fpga(clk_fpga), .rst_fpga(reset),  		     .debug_led(debug_led), .debug(debug), .debug_clk(debug_clk),  		     .debug_txd(), .debug_rxd(1'b1), -		     .gpif_d(GPIF_D), .gpif_ctl(GPIF_CTL), .gpif_rdy(GPIF_RDY), -		     .gpif_misc({GPIF_CS,GPIF_SLOE,GPIF_PKTEND}), -		     .gpif_clk(IFCLK), +		      +		     .gpif_d(GPIF_D), .gpif_ctl(GPIF_CTL), .gpif_pktend(GPIF_PKTEND), +		     .gpif_sloe(GPIF_SLOE), .gpif_slwr(GPIF_SLWR), .gpif_slrd(GPIF_SLRD), +		     .gpif_fifoadr(GPIF_ADR), .gpif_clk(IFCLK),  		     .db_sda(SDA_FPGA), .db_scl(SCL_FPGA),  		     .sclk(sclk), .sen({SEN_CODEC,SEN_TX_DB,SEN_RX_DB}), .mosi(mosi), .miso(miso), diff --git a/fpga/usrp2/top/B100/Makefile.B100 b/fpga/usrp2/top/B100/Makefile.B100 index 90dd25942..3cdbb62c0 100644 --- a/fpga/usrp2/top/B100/Makefile.B100 +++ b/fpga/usrp2/top/B100/Makefile.B100 @@ -1,5 +1,5 @@  # -# Copyright 2008 Ettus Research LLC +# Copyright 2008-2012 Ettus Research LLC  #  ################################################## @@ -7,7 +7,14 @@  ##################################################  TOP_MODULE := B100  BUILD_DIR := build-B100/ -export PROJ_FILE := $(BUILD_DIR)$(TOP_MODULE).ise + +# set me in a custom makefile +CUSTOM_SRCS = +CUSTOM_DEFS = + +################################################## +# Include other makefiles +##################################################  include ../Makefile.common  include ../../fifo/Makefile.srcs @@ -50,7 +57,7 @@ SOURCES = $(abspath $(TOP_SRCS)) $(FIFO_SRCS) \  $(CONTROL_LIB_SRCS) $(SDR_LIB_SRCS) $(SERDES_SRCS) \  $(SIMPLE_GEMAC_SRCS) $(TIMING_SRCS) $(OPENCORES_SRCS) \  $(VRT_SRCS) $(UDP_SRCS) $(COREGEN_SRCS) $(EXTRAM_SRCS) \ -$(GPIF_SRCS) +$(GPIF_SRCS) $(CUSTOM_SRCS)  ##################################################  # Process Properties @@ -63,7 +70,8 @@ SYNTHESIZE_PROPERTIES = \  "Register Balancing" Yes \  "Use Clock Enable" Auto \  "Use Synchronous Reset" Auto \ -"Use Synchronous Set" Auto +"Use Synchronous Set" Auto \ +"Verilog Macros" "$(CUSTOM_MOD_DEFS)"  TRANSLATE_PROPERTIES = \  "Macro Search Path" "$(shell pwd)/../../coregen/" diff --git a/fpga/usrp2/top/B100/core_compile b/fpga/usrp2/top/B100/core_compile index b2ccc8b49..b62cbaee0 100755 --- a/fpga/usrp2/top/B100/core_compile +++ b/fpga/usrp2/top/B100/core_compile @@ -1 +1 @@ -iverilog -Wall -y. -y ../../control_lib/ -y ../../fifo/ -y ../../gpif/ -y ../../models/ -y ../../sdr_lib/ -y ../../coregen/ -y ../../vrt/ -y ../../opencores/i2c/rtl/verilog/ -y ../../opencores/spi/rtl/verilog/ -y ../../timing/ -y ../../opencores/8b10b/ -I ../../opencores/spi/rtl/verilog/ -I ../../opencores/i2c/rtl/verilog/ -y ../../simple_gemac u1plus_core.v  2>&1   | grep -v timescale | grep -v coregen | grep -v models +iverilog -Wall -y. -y ../../control_lib/ -y ../../custom/ -y ../../fifo/ -y ../../gpif/ -y ../../models/ -y ../../sdr_lib/ -y ../../coregen/ -y ../../vrt/ -y ../../opencores/i2c/rtl/verilog/ -y ../../opencores/spi/rtl/verilog/ -y ../../timing/ -y ../../opencores/8b10b/ -I ../../opencores/spi/rtl/verilog/ -I ../../opencores/i2c/rtl/verilog/ -y ../../simple_gemac u1plus_core.v  2>&1   | grep -v timescale | grep -v coregen | grep -v models diff --git a/fpga/usrp2/top/B100/timing.ucf b/fpga/usrp2/top/B100/timing.ucf index b2a455f6d..96c47cf2c 100644 --- a/fpga/usrp2/top/B100/timing.ucf +++ b/fpga/usrp2/top/B100/timing.ucf @@ -3,3 +3,12 @@ TIMESPEC "TS_CLK_FPGA_P" = PERIOD "CLK_FPGA_P" 15625 ps HIGH 50 %;  NET "IFCLK" TNM_NET = "IFCLK";  TIMESPEC "TS_IFCLK" = PERIOD "IFCLK" 20833 ps HIGH 50 %; + +#constrain FX2 IO +NET "GPIF_D<*>" MAXDELAY = 5.5 ns; +NET "GPIF_CTL<*>" MAXDELAY = 5.5 ns; +NET "GPIF_ADR<*>" MAXDELAY = 5.5ns; +NET "GPIF_SLWR" MAXDELAY = 5.5 ns; +NET "GPIF_SLRD" MAXDELAY = 5.5 ns; +NET "GPIF_SLOE" MAXDELAY = 5.5 ns; +NET "GPIF_PKTEND" MAXDELAY = 5.5 ns; diff --git a/fpga/usrp2/top/B100/u1plus_core.v b/fpga/usrp2/top/B100/u1plus_core.v index c883c5ca8..e335fb8bb 100644 --- a/fpga/usrp2/top/B100/u1plus_core.v +++ b/fpga/usrp2/top/B100/u1plus_core.v @@ -1,5 +1,5 @@  // -// Copyright 2011 Ettus Research LLC +// Copyright 2011-2012 Ettus Research LLC  //  // This program is free software: you can redistribute it and/or modify  // it under the terms of the GNU General Public License as published by @@ -23,8 +23,9 @@ module u1plus_core     output debug_txd, input debug_rxd,     // GPIF -   inout [15:0] gpif_d, input [3:0] gpif_ctl, output [3:0] gpif_rdy, -   output [2:0] gpif_misc, input gpif_clk, +   inout [15:0] gpif_d, input [3:0] gpif_ctl, output gpif_sloe, +   output gpif_slwr, output gpif_slrd, output gpif_pktend, output [1:0] gpif_fifoadr, +   input gpif_clk,     inout db_sda, inout db_scl,     output sclk, output [15:0] sen, output mosi, input miso, @@ -37,7 +38,7 @@ module u1plus_core     );     localparam TXFIFOSIZE = 11; -   localparam RXFIFOSIZE = 11; +   localparam RXFIFOSIZE = 12;     // 64 total regs in address space     localparam SR_RX_CTRL0 = 0;       // 9 regs (+0 to +8) @@ -52,9 +53,9 @@ module u1plus_core     localparam SR_TX_FRONT = 54;      // 5 regs (+0 to +4)     localparam SR_REG_TEST32 = 60;    // 1 reg -   localparam SR_CLEAR_RX_FIFO = 61; // 1 reg -   localparam SR_CLEAR_TX_FIFO = 62; // 1 reg +   localparam SR_CLEAR_FIFO = 61;    // 1 reg     localparam SR_GLOBAL_RESET = 63;  // 1 reg +   localparam SR_USER_REGS = 64;     // 2 regs     localparam SR_GPIO = 128;         // 5 regs @@ -64,11 +65,11 @@ module u1plus_core     wire 	pps_int;     wire [63:0] 	vita_time, vita_time_pps;     reg [15:0] 	reg_cgen_ctrl, reg_test; -    -   wire [7:0] 	set_addr; -   wire [31:0] 	set_data; -   wire 	set_stb; -    + +   wire [7:0]  set_addr, set_addr_user; +   wire [31:0] set_data, set_data_user; +   wire        set_stb, set_stb_user; +     wire [31:0]  debug0;     wire [31:0]  debug1; @@ -105,68 +106,70 @@ module u1plus_core     wire 	 tx_src_rdy, tx_dst_rdy, rx_src_rdy, rx_dst_rdy,   		 tx_err_src_rdy, tx_err_dst_rdy; -   wire 	 clear_tx, clear_rx; -    -   setting_reg #(.my_addr(SR_CLEAR_RX_FIFO), .width(1)) sr_clear_rx -     (.clk(wb_clk),.rst(wb_rst),.strobe(set_stb),.addr(set_addr), -      .in(set_data),.out(),.changed(clear_rx)); +   wire 	 clear_fifo; -   setting_reg #(.my_addr(SR_CLEAR_TX_FIFO), .width(1)) sr_clear_tx +   setting_reg #(.my_addr(SR_CLEAR_FIFO), .width(1)) sr_clear_fifo       (.clk(wb_clk),.rst(wb_rst),.strobe(set_stb),.addr(set_addr), -      .in(set_data),.out(),.changed(clear_tx)); +      .in(set_data),.out(),.changed(clear_fifo)); -   gpif #(.TXFIFOSIZE(TXFIFOSIZE), .RXFIFOSIZE(RXFIFOSIZE)) -   gpif (.gpif_clk(gpif_clk), .gpif_rst(gpif_rst), .gpif_d(gpif_d), -	 .gpif_ctl(gpif_ctl), .gpif_rdy(gpif_rdy), .gpif_misc(gpif_misc), +   wire 	 run_rx0, run_rx1; + +   slave_fifo #(.TXFIFOSIZE(TXFIFOSIZE), .RXFIFOSIZE(RXFIFOSIZE)) +   slave_fifo (.gpif_clk(gpif_clk), .gpif_rst(gpif_rst), .gpif_d(gpif_d), +	 .gpif_ctl(gpif_ctl), .sloe(gpif_sloe), .slwr(gpif_slwr), .slrd(gpif_slrd), +     .pktend(gpif_pktend), .fifoadr(gpif_fifoadr),  	 .wb_clk(wb_clk), .wb_rst(wb_rst),  	 .wb_adr_o(m0_adr), .wb_dat_mosi(m0_dat_mosi), .wb_dat_miso(m0_dat_miso),  	 .wb_sel_o(m0_sel), .wb_cyc_o(m0_cyc), .wb_stb_o(m0_stb), .wb_we_o(m0_we),  	 .wb_ack_i(m0_ack), .triggers(8'd0), -	 .fifo_clk(wb_clk), .fifo_rst(wb_rst), .clear_tx(clear_tx), .clear_rx(clear_rx), +	 .dsp_rx_run(run_rx0 | run_rx1), +	  +	 .fifo_clk(wb_clk), .fifo_rst(wb_rst), .clear_tx(clear_fifo), .clear_rx(clear_fifo),  	 .tx_data_o(tx_data), .tx_src_rdy_o(tx_src_rdy), .tx_dst_rdy_i(tx_dst_rdy),  	 .rx_data_i(rx_data), .rx_src_rdy_i(rx_src_rdy), .rx_dst_rdy_o(rx_dst_rdy),  	 .tx_err_data_i(tx_err_data), .tx_err_src_rdy_i(tx_err_src_rdy), .tx_err_dst_rdy_o(tx_err_dst_rdy),  	 .tx_underrun(tx_underrun_gpif), .rx_overrun(rx_overrun_gpif), -	 .frames_per_packet(frames_per_packet), +	 .test_len(0), .test_rate(0), .test_ctrl(0),  	 .debug0(debug0), .debug1(debug1));     // /////////////////////////////////////////////////////////////////////////     // RX ADC Frontend, does IQ Balance, DC Offset, muxing -   wire [23:0] 	 adc_i, adc_q;  // 24 bits is total overkill here, but it matches u2/u2p -   wire 	 run_rx0, run_rx1; -    +   wire [23:0] 	 rx_fe_i, rx_fe_q;  // 24 bits is total overkill here, but it matches u2/u2p +     rx_frontend #(.BASE(SR_RX_FRONT)) rx_frontend       (.clk(wb_clk),.rst(wb_rst),        .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data),        .adc_a({rx_i,4'b00}),.adc_ovf_a(0),        .adc_b({rx_q,4'b00}),.adc_ovf_b(0), -      .i_out(adc_i), .q_out(adc_q), .run(run_rx0 | run_rx1), .debug()); +      .i_out(rx_fe_i), .q_out(rx_fe_q), .run(run_rx0 | run_rx1), .debug());     // /////////////////////////////////////////////////////////////////////////     // DSP RX 0     wire [31:0] 	 sample_rx0; -   wire 	 strobe_rx0; +   wire 	 strobe_rx0, clear_rx0;     wire [35:0] 	 vita_rx_data0;     wire 	 vita_rx_src_rdy0, vita_rx_dst_rdy0; -   dsp_core_rx #(.BASE(SR_RX_DSP0)) dsp_core_rx0 -     (.clk(wb_clk),.rst(wb_rst), +   ddc_chain #(.BASE(SR_RX_DSP0), .DSPNO(0)) ddc_chain0 +     (.clk(wb_clk), .rst(wb_rst), .clr(clear_rx0),        .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), -      .adc_i(adc_i),.adc_ovf_i(0),.adc_q(adc_q),.adc_ovf_q(0), +      .set_stb_user(set_stb_user), .set_addr_user(set_addr_user), .set_data_user(set_data_user), +      .rx_fe_i(rx_fe_i),.rx_fe_q(rx_fe_q),        .sample(sample_rx0), .run(run_rx0), .strobe(strobe_rx0),        .debug() ); -   vita_rx_chain #(.BASE(SR_RX_CTRL0), .UNIT(0), .FIFOSIZE(10), .PROT_ENG_FLAGS(0)) vita_rx_chain0 -     (.clk(wb_clk),.reset(wb_rst),.clear(clear_rx), +   vita_rx_chain #(.BASE(SR_RX_CTRL0), .UNIT(0), .FIFOSIZE(10), .PROT_ENG_FLAGS(0), .DSP_NUMBER(0)) vita_rx_chain0 +     (.clk(wb_clk),.reset(wb_rst),        .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), +      .set_stb_user(set_stb_user), .set_addr_user(set_addr_user), .set_data_user(set_data_user),        .vita_time(vita_time), .overrun(rx_overrun_dsp0), -      .sample(sample_rx0), .run(run_rx0), .strobe(strobe_rx0), +      .sample(sample_rx0), .run(run_rx0), .strobe(strobe_rx0), .clear_o(clear_rx0),        .rx_data_o(vita_rx_data0), .rx_dst_rdy_i(vita_rx_dst_rdy0), .rx_src_rdy_o(vita_rx_src_rdy0),        .debug() ); @@ -174,22 +177,24 @@ module u1plus_core     // DSP RX 1     wire [31:0] 	 sample_rx1; -   wire 	 strobe_rx1; +   wire 	 strobe_rx1, clear_rx1;     wire [35:0] 	 vita_rx_data1;     wire 	 vita_rx_src_rdy1, vita_rx_dst_rdy1; -   dsp_core_rx #(.BASE(SR_RX_DSP1)) dsp_core_rx1 -     (.clk(wb_clk),.rst(wb_rst), +   ddc_chain #(.BASE(SR_RX_DSP1), .DSPNO(1)) ddc_chain1 +     (.clk(wb_clk),.rst(wb_rst), .clr(clear_rx1),        .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), -      .adc_i(adc_i),.adc_ovf_i(0),.adc_q(adc_q),.adc_ovf_q(0), +      .set_stb_user(set_stb_user), .set_addr_user(set_addr_user), .set_data_user(set_data_user), +      .rx_fe_i(rx_fe_i),.rx_fe_q(rx_fe_q),        .sample(sample_rx1), .run(run_rx1), .strobe(strobe_rx1),        .debug() ); -   vita_rx_chain #(.BASE(SR_RX_CTRL1), .UNIT(1), .FIFOSIZE(10), .PROT_ENG_FLAGS(0)) vita_rx_chain1 -     (.clk(wb_clk),.reset(wb_rst),.clear(clear_rx), +   vita_rx_chain #(.BASE(SR_RX_CTRL1), .UNIT(1), .FIFOSIZE(10), .PROT_ENG_FLAGS(0), .DSP_NUMBER(1)) vita_rx_chain1 +     (.clk(wb_clk),.reset(wb_rst),        .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), +      .set_stb_user(set_stb_user), .set_addr_user(set_addr_user), .set_data_user(set_data_user),        .vita_time(vita_time), .overrun(rx_overrun_dsp1), -      .sample(sample_rx1), .run(run_rx1), .strobe(strobe_rx1), +      .sample(sample_rx1), .run(run_rx1), .strobe(strobe_rx1), .clear_o(clear_rx1),        .rx_data_o(vita_rx_data1), .rx_dst_rdy_i(vita_rx_dst_rdy1), .rx_src_rdy_o(vita_rx_src_rdy1),        .debug() ); @@ -197,7 +202,7 @@ module u1plus_core     // RX Stream muxing     fifo36_mux #(.prio(0)) mux_data_streams -     (.clk(wb_clk), .reset(wb_rst), .clear(0), +     (.clk(wb_clk), .reset(wb_rst), .clear(clear_fifo),        .data0_i(vita_rx_data0), .src0_rdy_i(vita_rx_src_rdy0), .dst0_rdy_o(vita_rx_dst_rdy0),        .data1_i(vita_rx_data1), .src1_rdy_i(vita_rx_src_rdy1), .dst1_rdy_o(vita_rx_dst_rdy1),        .data_o(rx_data), .src_rdy_o(rx_src_rdy), .dst_rdy_i(rx_dst_rdy)); @@ -205,27 +210,38 @@ module u1plus_core     // ///////////////////////////////////////////////////////////////////////////////////     // DSP TX -   wire [23:0] 	 tx_i_int, tx_q_int;     wire 	 run_tx; -    -   vita_tx_chain #(.BASE_CTRL(SR_TX_CTRL), .BASE_DSP(SR_TX_DSP),  +   wire [23:0] 	 tx_fe_i, tx_fe_q; +   wire [31:0]   sample_tx; +   wire strobe_tx, clear_tx; + +   vita_tx_chain #(.BASE(SR_TX_CTRL), .FIFOSIZE(10), .POST_ENGINE_FIFOSIZE(11),  		   .REPORT_ERROR(1), .DO_FLOW_CONTROL(0),  		   .PROT_ENG_FLAGS(0), .USE_TRANS_HEADER(0),  		   .DSP_NUMBER(0))      vita_tx_chain       (.clk(wb_clk), .reset(wb_rst),        .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), +      .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(tx_data), .tx_src_rdy_i(tx_src_rdy), .tx_dst_rdy_o(tx_dst_rdy),        .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_int),.tx_q(tx_q_int), -      .underrun(tx_underrun_dsp), .run(run_tx), +      .sample(sample_tx), .strobe(strobe_tx), +      .underrun(tx_underrun_dsp), .run(run_tx), .clear_o(clear_tx),        .debug(debug_vt)); +   duc_chain #(.BASE(SR_TX_DSP), .DSPNO(0)) duc_chain +     (.clk(wb_clk), .rst(wb_rst), .clr(clear_tx), +      .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), +      .set_stb_user(set_stb_user), .set_addr_user(set_addr_user), .set_data_user(set_data_user), +      .tx_fe_i(tx_fe_i),.tx_fe_q(tx_fe_q), +      .sample(sample_tx), .run(run_tx), .strobe(strobe_tx), +      .debug() ); +     tx_frontend #(.BASE(SR_TX_FRONT), .WIDTH_OUT(14)) tx_frontend       (.clk(wb_clk), .rst(wb_rst),        .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), -      .tx_i(tx_i_int), .tx_q(tx_q_int), .run(1'b1), +      .tx_i(tx_fe_i), .tx_q(tx_fe_q), .run(1'b1),        .dac_a(tx_i), .dac_b(tx_q));     // ///////////////////////////////////////////////////////////////////////////////////// @@ -387,11 +403,17 @@ module u1plus_core        .wb_stb_i(s8_stb),.wb_we_i(s8_we),.wb_ack_o(s8_ack),        .strobe(set_stb),.addr(set_addr),.data(set_data) ); +   user_settings #(.BASE(SR_USER_REGS)) user_settings +     (.clk(wb_clk),.rst(wb_rst),.set_stb(set_stb), +      .set_addr(set_addr),.set_data(set_data), +      .set_addr_user(set_addr_user),.set_data_user(set_data_user), +      .set_stb_user(set_stb_user) ); +     // /////////////////////////////////////////////////////////////////////////     // Readback mux 32 -- Slave #7     //compatibility number -> increment when the fpga has been sufficiently altered -   localparam compat_num = {16'd8, 16'd1}; //major, minor +   localparam compat_num = {16'd9, 16'd0}; //major, minor     wire [31:0] reg_test32; @@ -416,7 +438,7 @@ module u1plus_core     // /////////////////////////////////////////////////////////////////////////     // VITA Timing -   time_64bit #(.TICKS_PER_SEC(32'd64000000),.BASE(SR_TIME64)) time_64bit +   time_64bit #(.BASE(SR_TIME64)) time_64bit       (.clk(wb_clk), .rst(wb_rst), .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data),        .pps(pps_in), .vita_time(vita_time), .vita_time_pps(vita_time_pps), .pps_int(pps_int),        .exp_time_in(0)); diff --git a/fpga/usrp2/top/E1x0/Makefile.E100 b/fpga/usrp2/top/E1x0/Makefile.E100 index 9b9a48911..ad5a0c1bd 100644 --- a/fpga/usrp2/top/E1x0/Makefile.E100 +++ b/fpga/usrp2/top/E1x0/Makefile.E100 @@ -1,5 +1,5 @@  # -# Copyright 2008 Ettus Research LLC +# Copyright 2008-2012 Ettus Research LLC  #  ################################################## @@ -8,6 +8,10 @@  TOP_MODULE = u1e  BUILD_DIR = $(abspath build$(ISE)-E100) +# set me in a custom makefile +CUSTOM_SRCS = +CUSTOM_DEFS = +  ##################################################  # Include other makefiles  ################################################## @@ -53,7 +57,7 @@ SOURCES = $(abspath $(TOP_SRCS)) $(FIFO_SRCS) \  $(CONTROL_LIB_SRCS) $(SDR_LIB_SRCS) $(SERDES_SRCS) \  $(SIMPLE_GEMAC_SRCS) $(TIMING_SRCS) $(OPENCORES_SRCS) \  $(VRT_SRCS) $(UDP_SRCS) $(COREGEN_SRCS) $(EXTRAM_SRCS) \ -$(GPMC_SRCS) +$(GPMC_SRCS) $(CUSTOM_SRCS)  ##################################################  # Process Properties @@ -66,7 +70,8 @@ SYNTHESIZE_PROPERTIES = \  "Register Balancing" Yes \  "Use Clock Enable" Auto \  "Use Synchronous Reset" Auto \ -"Use Synchronous Set" Auto +"Use Synchronous Set" Auto \ +"Verilog Macros" "$(CUSTOM_MOD_DEFS)"  TRANSLATE_PROPERTIES = \  "Macro Search Path" "$(shell pwd)/../../coregen/" diff --git a/fpga/usrp2/top/E1x0/Makefile.E110 b/fpga/usrp2/top/E1x0/Makefile.E110 index be2761baf..291ac0a44 100644 --- a/fpga/usrp2/top/E1x0/Makefile.E110 +++ b/fpga/usrp2/top/E1x0/Makefile.E110 @@ -1,5 +1,5 @@  # -# Copyright 2008 Ettus Research LLC +# Copyright 2008-2012 Ettus Research LLC  #  ################################################## @@ -8,6 +8,10 @@  TOP_MODULE = u1e  BUILD_DIR = $(abspath build$(ISE)-E110) +# set me in a custom makefile +CUSTOM_SRCS = +CUSTOM_DEFS = +  ##################################################  # Include other makefiles  ################################################## @@ -53,7 +57,7 @@ SOURCES = $(abspath $(TOP_SRCS)) $(FIFO_SRCS) \  $(CONTROL_LIB_SRCS) $(SDR_LIB_SRCS) $(SERDES_SRCS) \  $(SIMPLE_GEMAC_SRCS) $(TIMING_SRCS) $(OPENCORES_SRCS) \  $(VRT_SRCS) $(UDP_SRCS) $(COREGEN_SRCS) $(EXTRAM_SRCS) \ -$(GPMC_SRCS) +$(GPMC_SRCS) $(CUSTOM_SRCS)  ##################################################  # Process Properties @@ -66,7 +70,8 @@ SYNTHESIZE_PROPERTIES = \  "Register Balancing" Yes \  "Use Clock Enable" Auto \  "Use Synchronous Reset" Auto \ -"Use Synchronous Set" Auto +"Use Synchronous Set" Auto \ +"Verilog Macros" "$(CUSTOM_MOD_DEFS)"  TRANSLATE_PROPERTIES = \  "Macro Search Path" "$(shell pwd)/../../coregen/" diff --git a/fpga/usrp2/top/E1x0/core_compile b/fpga/usrp2/top/E1x0/core_compile index 02d7f006e..14e138fa3 100755 --- a/fpga/usrp2/top/E1x0/core_compile +++ b/fpga/usrp2/top/E1x0/core_compile @@ -1,3 +1,3 @@ -iverilog -Wall -y. -y ../../control_lib/ -y ../../fifo/ -y ../../gpmc/ -y ../../models/ -y ../../sdr_lib/ -y ../../coregen/ -y ../../vrt/ -y ../../opencores/i2c/rtl/verilog/ -y ../../opencores/spi/rtl/verilog/ -y ../../timing/ -y ../../opencores/8b10b/ -I ../../opencores/spi/rtl/verilog/ -I ../../opencores/i2c/rtl/verilog/ -y ../../simple_gemac -y $XILINX/verilog/src/unisims u1e_core.v  2>&1  | grep -v timescale | grep -v coregen | grep -v models +iverilog -Wall -y. -y ../../control_lib/ -y ../../custom/ -y ../../fifo/ -y ../../gpmc/ -y ../../models/ -y ../../sdr_lib/ -y ../../coregen/ -y ../../vrt/ -y ../../opencores/i2c/rtl/verilog/ -y ../../opencores/spi/rtl/verilog/ -y ../../timing/ -y ../../opencores/8b10b/ -I ../../opencores/spi/rtl/verilog/ -I ../../opencores/i2c/rtl/verilog/ -y ../../simple_gemac -y $XILINX/verilog/src/unisims u1e_core.v  2>&1  | grep -v timescale | grep -v coregen | grep -v models diff --git a/fpga/usrp2/top/E1x0/u1e_core.v b/fpga/usrp2/top/E1x0/u1e_core.v index aede63bac..ee27af939 100644 --- a/fpga/usrp2/top/E1x0/u1e_core.v +++ b/fpga/usrp2/top/E1x0/u1e_core.v @@ -1,5 +1,5 @@  // -// Copyright 2011 Ettus Research LLC +// Copyright 2011-2012 Ettus Research LLC  //  // This program is free software: you can redistribute it and/or modify  // it under the terms of the GNU General Public License as published by @@ -56,9 +56,9 @@ module u1e_core     localparam SR_TX_FRONT = 54;      // 5 regs (+0 to +4)     localparam SR_REG_TEST32 = 60;    // 1 reg -   localparam SR_CLEAR_RX_FIFO = 61; // 1 reg -   localparam SR_CLEAR_TX_FIFO = 62; // 1 reg +   localparam SR_CLEAR_FIFO = 61;    // 1 reg     localparam SR_GLOBAL_RESET = 63;  // 1 reg +   localparam SR_USER_REGS = 64;     // 2 regs     localparam SR_GPIO = 128;         // 5 regs @@ -70,10 +70,10 @@ module u1e_core     reg [15:0] 	reg_cgen_ctrl, reg_test, xfer_rate;     wire [7:0] 	test_rate;     wire [3:0] 	test_ctrl; -    -   wire [7:0] 	set_addr; -   wire [31:0] 	set_data; -   wire 	set_stb; + +   wire [7:0]  set_addr, set_addr_user; +   wire [31:0] set_data, set_data_user; +   wire        set_stb, set_stb_user;     wire [31:0] 	debug_vt;     wire 	rx_overrun_dsp0, rx_overrun_dsp1, rx_overrun_gpmc, tx_underrun_dsp, tx_underrun_gpmc; @@ -103,15 +103,13 @@ module u1e_core     wire 	 tx_src_rdy, tx_dst_rdy, rx_src_rdy, rx_dst_rdy,   		 tx_err_src_rdy, tx_err_dst_rdy; -   wire 	 clear_tx, clear_rx; -    -   setting_reg #(.my_addr(SR_CLEAR_RX_FIFO), .width(1)) sr_clear_rx -     (.clk(wb_clk),.rst(wb_rst),.strobe(set_stb),.addr(set_addr), -      .in(set_data),.out(),.changed(clear_rx)); +   wire 	 clear_fifo; -   setting_reg #(.my_addr(SR_CLEAR_TX_FIFO), .width(1)) sr_clear_tx +   setting_reg #(.my_addr(SR_CLEAR_FIFO), .width(1)) sr_clear_fifo       (.clk(wb_clk),.rst(wb_rst),.strobe(set_stb),.addr(set_addr), -      .in(set_data),.out(),.changed(clear_tx)); +      .in(set_data),.out(),.changed(clear_fifo)); + +   wire 	 run_rx0, run_rx1;     gpmc #(.TXFIFOSIZE(TXFIFOSIZE), .RXFIFOSIZE(RXFIFOSIZE))     gpmc (.arst(wb_rst), @@ -126,7 +124,7 @@ module u1e_core  	 .wb_sel_o(m0_sel), .wb_cyc_o(m0_cyc), .wb_stb_o(m0_stb), .wb_we_o(m0_we),  	 .wb_ack_i(m0_ack), -	 .fifo_clk(wb_clk), .fifo_rst(wb_rst), .clear_tx(clear_tx), .clear_rx(clear_rx), +	 .fifo_clk(wb_clk), .fifo_rst(wb_rst), .clear_tx(clear_fifo), .clear_rx(clear_fifo),  	 .tx_data_o(tx_data), .tx_src_rdy_o(tx_src_rdy), .tx_dst_rdy_i(tx_dst_rdy),  	 .rx_data_i(rx_data), .rx_src_rdy_i(rx_src_rdy), .rx_dst_rdy_o(rx_dst_rdy), @@ -142,36 +140,37 @@ module u1e_core     // /////////////////////////////////////////////////////////////////////////     // RX ADC Frontend, does IQ Balance, DC Offset, muxing -   wire [23:0] 	 adc_i, adc_q;  // 24 bits is total overkill here, but it matches u2/u2p -   wire 	 run_rx0, run_rx1; -    +   wire [23:0] 	 rx_fe_i, rx_fe_q;  // 24 bits is total overkill here, but it matches u2/u2p +     rx_frontend #(.BASE(SR_RX_FRONT)) rx_frontend       (.clk(wb_clk),.rst(wb_rst),        .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data),        .adc_a({rx_i,4'b00}),.adc_ovf_a(0),        .adc_b({rx_q,4'b00}),.adc_ovf_b(0), -      .i_out(adc_i), .q_out(adc_q), .run(run_rx0 | run_rx1), .debug()); +      .i_out(rx_fe_i), .q_out(rx_fe_q), .run(run_rx0 | run_rx1), .debug());     // /////////////////////////////////////////////////////////////////////////     // DSP RX 0     wire [31:0] 	 sample_rx0; -   wire 	 strobe_rx0; +   wire 	 strobe_rx0, clear_rx0;     wire [35:0] 	 vita_rx_data0;     wire 	 vita_rx_src_rdy0, vita_rx_dst_rdy0; -   dsp_core_rx #(.BASE(SR_RX_DSP0)) dsp_core_rx0 -     (.clk(wb_clk),.rst(wb_rst), +   ddc_chain #(.BASE(SR_RX_DSP0), .DSPNO(0)) ddc_chain0 +     (.clk(wb_clk), .rst(wb_rst), .clr(clear_rx0),        .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), -      .adc_i(adc_i),.adc_ovf_i(0),.adc_q(adc_q),.adc_ovf_q(0), +      .set_stb_user(set_stb_user), .set_addr_user(set_addr_user), .set_data_user(set_data_user), +      .rx_fe_i(rx_fe_i),.rx_fe_q(rx_fe_q),        .sample(sample_rx0), .run(run_rx0), .strobe(strobe_rx0),        .debug() ); -   vita_rx_chain #(.BASE(SR_RX_CTRL0), .UNIT(0), .FIFOSIZE(10), .PROT_ENG_FLAGS(0)) vita_rx_chain0 -     (.clk(wb_clk),.reset(wb_rst),.clear(clear_rx), +   vita_rx_chain #(.BASE(SR_RX_CTRL0), .UNIT(0), .FIFOSIZE(10), .PROT_ENG_FLAGS(0), .DSP_NUMBER(0)) vita_rx_chain0 +     (.clk(wb_clk),.reset(wb_rst),        .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), +      .set_stb_user(set_stb_user), .set_addr_user(set_addr_user), .set_data_user(set_data_user),        .vita_time(vita_time), .overrun(rx_overrun_dsp0), -      .sample(sample_rx0), .run(run_rx0), .strobe(strobe_rx0), +      .sample(sample_rx0), .run(run_rx0), .strobe(strobe_rx0), .clear_o(clear_rx0),        .rx_data_o(vita_rx_data0), .rx_dst_rdy_i(vita_rx_dst_rdy0), .rx_src_rdy_o(vita_rx_src_rdy0),        .debug() ); @@ -179,22 +178,24 @@ module u1e_core     // DSP RX 1     wire [31:0] 	 sample_rx1; -   wire 	 strobe_rx1; +   wire 	 strobe_rx1, clear_rx1;     wire [35:0] 	 vita_rx_data1;     wire 	 vita_rx_src_rdy1, vita_rx_dst_rdy1; -   dsp_core_rx #(.BASE(SR_RX_DSP1)) dsp_core_rx1 -     (.clk(wb_clk),.rst(wb_rst), +   ddc_chain #(.BASE(SR_RX_DSP1), .DSPNO(1)) ddc_chain1 +     (.clk(wb_clk),.rst(wb_rst), .clr(clear_rx1),        .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), -      .adc_i(adc_i),.adc_ovf_i(0),.adc_q(adc_q),.adc_ovf_q(0), +      .set_stb_user(set_stb_user), .set_addr_user(set_addr_user), .set_data_user(set_data_user), +      .rx_fe_i(rx_fe_i),.rx_fe_q(rx_fe_q),        .sample(sample_rx1), .run(run_rx1), .strobe(strobe_rx1),        .debug() ); -   vita_rx_chain #(.BASE(SR_RX_CTRL1), .UNIT(1), .FIFOSIZE(10), .PROT_ENG_FLAGS(0)) vita_rx_chain1 -     (.clk(wb_clk),.reset(wb_rst),.clear(clear_rx), +   vita_rx_chain #(.BASE(SR_RX_CTRL1), .UNIT(1), .FIFOSIZE(10), .PROT_ENG_FLAGS(0), .DSP_NUMBER(1)) vita_rx_chain1 +     (.clk(wb_clk),.reset(wb_rst),        .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), +      .set_stb_user(set_stb_user), .set_addr_user(set_addr_user), .set_data_user(set_data_user),        .vita_time(vita_time), .overrun(rx_overrun_dsp1), -      .sample(sample_rx1), .run(run_rx1), .strobe(strobe_rx1), +      .sample(sample_rx1), .run(run_rx1), .strobe(strobe_rx1), .clear_o(clear_rx1),        .rx_data_o(vita_rx_data1), .rx_dst_rdy_i(vita_rx_dst_rdy1), .rx_src_rdy_o(vita_rx_src_rdy1),        .debug() ); @@ -202,7 +203,7 @@ module u1e_core     // RX Stream muxing     fifo36_mux #(.prio(0)) mux_data_streams -     (.clk(wb_clk), .reset(wb_rst), .clear(0), +     (.clk(wb_clk), .reset(wb_rst), .clear(clear_fifo),        .data0_i(vita_rx_data0), .src0_rdy_i(vita_rx_src_rdy0), .dst0_rdy_o(vita_rx_dst_rdy0),        .data1_i(vita_rx_data1), .src1_rdy_i(vita_rx_src_rdy1), .dst1_rdy_o(vita_rx_dst_rdy1),        .data_o(rx_data), .src_rdy_o(rx_src_rdy), .dst_rdy_i(rx_dst_rdy)); @@ -210,27 +211,38 @@ module u1e_core     // ///////////////////////////////////////////////////////////////////////////////////     // DSP TX -   wire [23:0] 	 tx_i_int, tx_q_int;     wire 	 run_tx; -    -   vita_tx_chain #(.BASE_CTRL(SR_TX_CTRL), .BASE_DSP(SR_TX_DSP),  +   wire [23:0] 	 tx_fe_i, tx_fe_q; +   wire [31:0]   sample_tx; +   wire strobe_tx, clear_tx; + +   vita_tx_chain #(.BASE(SR_TX_CTRL), .FIFOSIZE(10), .POST_ENGINE_FIFOSIZE(11),  		   .REPORT_ERROR(1), .DO_FLOW_CONTROL(0),  		   .PROT_ENG_FLAGS(0), .USE_TRANS_HEADER(0),  		   .DSP_NUMBER(0))      vita_tx_chain       (.clk(wb_clk), .reset(wb_rst),        .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), +      .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(tx_data), .tx_src_rdy_i(tx_src_rdy), .tx_dst_rdy_o(tx_dst_rdy),        .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_int),.tx_q(tx_q_int), -      .underrun(tx_underrun_dsp), .run(run_tx), +      .sample(sample_tx), .strobe(strobe_tx), +      .underrun(tx_underrun_dsp), .run(run_tx), .clear_o(clear_tx),        .debug(debug_vt)); +   duc_chain #(.BASE(SR_TX_DSP), .DSPNO(0)) duc_chain +     (.clk(wb_clk), .rst(wb_rst), .clr(clear_tx), +      .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), +      .set_stb_user(set_stb_user), .set_addr_user(set_addr_user), .set_data_user(set_data_user), +      .tx_fe_i(tx_fe_i),.tx_fe_q(tx_fe_q), +      .sample(sample_tx), .run(run_tx), .strobe(strobe_tx), +      .debug() ); +     tx_frontend #(.BASE(SR_TX_FRONT), .WIDTH_OUT(14)) tx_frontend       (.clk(wb_clk), .rst(wb_rst),        .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), -      .tx_i(tx_i_int), .tx_q(tx_q_int), .run(1'b1), +      .tx_i(tx_fe_i), .tx_q(tx_fe_q), .run(1'b1),        .dac_a(tx_i), .dac_b(tx_q));     // ///////////////////////////////////////////////////////////////////////////////////// @@ -432,11 +444,17 @@ module u1e_core        .wb_stb_i(s8_stb),.wb_we_i(s8_we),.wb_ack_o(s8_ack),        .strobe(set_stb),.addr(set_addr),.data(set_data) ); +   user_settings #(.BASE(SR_USER_REGS)) user_settings +     (.clk(wb_clk),.rst(wb_rst),.set_stb(set_stb), +      .set_addr(set_addr),.set_data(set_data), +      .set_addr_user(set_addr_user),.set_data_user(set_data_user), +      .set_stb_user(set_stb_user) ); +     // /////////////////////////////////////////////////////////////////////////     // Readback mux 32 -- Slave #7     //compatibility number -> increment when the fpga has been sufficiently altered -   localparam compat_num = {16'd8, 16'd1}; //major, minor +   localparam compat_num = {16'd9, 16'd0}; //major, minor     wire [31:0] reg_test32; @@ -462,7 +480,7 @@ module u1e_core     // /////////////////////////////////////////////////////////////////////////     // VITA Timing -   time_64bit #(.TICKS_PER_SEC(32'd64000000),.BASE(SR_TIME64)) time_64bit +   time_64bit #(.BASE(SR_TIME64)) time_64bit       (.clk(wb_clk), .rst(wb_rst), .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data),        .pps(pps_in), .vita_time(vita_time), .vita_time_pps(vita_time_pps), .pps_int(pps_int),        .exp_time_in(0)); diff --git a/fpga/usrp2/top/N2x0/Makefile.N200R3 b/fpga/usrp2/top/N2x0/Makefile.N200R3 index 9ed5ece00..680cadf44 100644 --- a/fpga/usrp2/top/N2x0/Makefile.N200R3 +++ b/fpga/usrp2/top/N2x0/Makefile.N200R3 @@ -1,5 +1,5 @@  # -# Copyright 2008 Ettus Research LLC +# Copyright 2008-2012 Ettus Research LLC  #  ################################################## @@ -8,6 +8,10 @@  TOP_MODULE = u2plus  BUILD_DIR = $(abspath build$(ISE)-N200R3) +# set me in a custom makefile +CUSTOM_SRCS = +CUSTOM_DEFS = +  ##################################################  # Include other makefiles  ################################################## @@ -52,7 +56,8 @@ u2plus.ucf  SOURCES = $(abspath $(TOP_SRCS)) $(FIFO_SRCS) \  $(CONTROL_LIB_SRCS) $(SDR_LIB_SRCS) $(SERDES_SRCS) \  $(SIMPLE_GEMAC_SRCS) $(TIMING_SRCS) $(OPENCORES_SRCS) \ -$(VRT_SRCS) $(UDP_SRCS) $(COREGEN_SRCS) $(EXTRAM_SRCS) +$(VRT_SRCS) $(UDP_SRCS) $(COREGEN_SRCS) $(EXTRAM_SRCS) \ +$(CUSTOM_SRCS)  ##################################################  # Process Properties @@ -65,7 +70,8 @@ SYNTHESIZE_PROPERTIES = \  "Register Balancing" Yes \  "Use Clock Enable" Auto \  "Use Synchronous Reset" Auto \ -"Use Synchronous Set" Auto +"Use Synchronous Set" Auto \ +"Verilog Macros" "$(CUSTOM_DEFS)"  TRANSLATE_PROPERTIES = \  "Macro Search Path" "$(shell pwd)/../../coregen/" diff --git a/fpga/usrp2/top/N2x0/Makefile.N200R4 b/fpga/usrp2/top/N2x0/Makefile.N200R4 index f8640224f..5c9ffd7a6 100644 --- a/fpga/usrp2/top/N2x0/Makefile.N200R4 +++ b/fpga/usrp2/top/N2x0/Makefile.N200R4 @@ -1,5 +1,5 @@  # -# Copyright 2008 Ettus Research LLC +# Copyright 2008-2012 Ettus Research LLC  #  ################################################## @@ -8,6 +8,10 @@  TOP_MODULE = u2plus  BUILD_DIR = $(abspath build$(ISE)-N200R4) +# set me in a custom makefile +CUSTOM_SRCS = +CUSTOM_DEFS = +  ##################################################  # Include other makefiles  ################################################## @@ -53,7 +57,8 @@ u2plus.ucf  SOURCES = $(abspath $(TOP_SRCS)) $(FIFO_SRCS) \  $(CONTROL_LIB_SRCS) $(SDR_LIB_SRCS) $(SERDES_SRCS) \  $(SIMPLE_GEMAC_SRCS) $(TIMING_SRCS) $(OPENCORES_SRCS) \ -$(VRT_SRCS) $(UDP_SRCS) $(COREGEN_SRCS) $(EXTRAM_SRCS) +$(VRT_SRCS) $(UDP_SRCS) $(COREGEN_SRCS) $(EXTRAM_SRCS) \ +$(CUSTOM_SRCS)  ##################################################  # Process Properties @@ -67,7 +72,7 @@ SYNTHESIZE_PROPERTIES = \  "Use Clock Enable" Auto \  "Use Synchronous Reset" Auto \  "Use Synchronous Set" Auto \ -"Verilog Macros" "LVDS=1" +"Verilog Macros" "LVDS=1 $(CUSTOM_DEFS)"  TRANSLATE_PROPERTIES = \  "Macro Search Path" "$(shell pwd)/../../coregen/" diff --git a/fpga/usrp2/top/N2x0/Makefile.N210R3 b/fpga/usrp2/top/N2x0/Makefile.N210R3 index 2937dc409..0b53ac951 100644 --- a/fpga/usrp2/top/N2x0/Makefile.N210R3 +++ b/fpga/usrp2/top/N2x0/Makefile.N210R3 @@ -1,5 +1,5 @@  # -# Copyright 2008 Ettus Research LLC +# Copyright 2008-2012 Ettus Research LLC  #  ################################################## @@ -8,6 +8,10 @@  TOP_MODULE = u2plus  BUILD_DIR = $(abspath build$(ISE)-N210R3) +# set me in a custom makefile +CUSTOM_SRCS = +CUSTOM_DEFS = +  ##################################################  # Include other makefiles  ################################################## @@ -52,7 +56,8 @@ u2plus.ucf  SOURCES = $(abspath $(TOP_SRCS)) $(FIFO_SRCS) \  $(CONTROL_LIB_SRCS) $(SDR_LIB_SRCS) $(SERDES_SRCS) \  $(SIMPLE_GEMAC_SRCS) $(TIMING_SRCS) $(OPENCORES_SRCS) \ -$(VRT_SRCS) $(UDP_SRCS) $(COREGEN_SRCS) $(EXTRAM_SRCS) +$(VRT_SRCS) $(UDP_SRCS) $(COREGEN_SRCS) $(EXTRAM_SRCS) \ +$(CUSTOM_SRCS)  ##################################################  # Process Properties @@ -65,7 +70,8 @@ SYNTHESIZE_PROPERTIES = \  "Register Balancing" Yes \  "Use Clock Enable" Auto \  "Use Synchronous Reset" Auto \ -"Use Synchronous Set" Auto +"Use Synchronous Set" Auto \ +"Verilog Macros" "$(CUSTOM_DEFS)"  TRANSLATE_PROPERTIES = \  "Macro Search Path" "$(shell pwd)/../../coregen/" diff --git a/fpga/usrp2/top/N2x0/Makefile.N210R4 b/fpga/usrp2/top/N2x0/Makefile.N210R4 index 39a2508f9..a7d2a9b49 100644 --- a/fpga/usrp2/top/N2x0/Makefile.N210R4 +++ b/fpga/usrp2/top/N2x0/Makefile.N210R4 @@ -1,5 +1,5 @@  # -# Copyright 2008 Ettus Research LLC +# Copyright 2008-2012 Ettus Research LLC  #  ################################################## @@ -8,6 +8,10 @@  TOP_MODULE = u2plus  BUILD_DIR = $(abspath build$(ISE)-N210R4) +# set me in a custom makefile +CUSTOM_SRCS = +CUSTOM_DEFS = +  ##################################################  # Include other makefiles  ################################################## @@ -53,7 +57,8 @@ u2plus.ucf  SOURCES = $(abspath $(TOP_SRCS)) $(FIFO_SRCS) \  $(CONTROL_LIB_SRCS) $(SDR_LIB_SRCS) $(SERDES_SRCS) \  $(SIMPLE_GEMAC_SRCS) $(TIMING_SRCS) $(OPENCORES_SRCS) \ -$(VRT_SRCS) $(UDP_SRCS) $(COREGEN_SRCS) $(EXTRAM_SRCS) +$(VRT_SRCS) $(UDP_SRCS) $(COREGEN_SRCS) $(EXTRAM_SRCS) \ +$(CUSTOM_SRCS)  ##################################################  # Process Properties @@ -67,7 +72,7 @@ SYNTHESIZE_PROPERTIES = \  "Use Clock Enable" Auto \  "Use Synchronous Reset" Auto \  "Use Synchronous Set" Auto \ -"Verilog Macros" "LVDS=1" +"Verilog Macros" "LVDS=1 $(CUSTOM_DEFS)"  TRANSLATE_PROPERTIES = \  "Macro Search Path" "$(shell pwd)/../../coregen/" diff --git a/fpga/usrp2/top/N2x0/u2plus_core.v b/fpga/usrp2/top/N2x0/u2plus_core.v index 3ead0db8e..378f212e4 100644 --- a/fpga/usrp2/top/N2x0/u2plus_core.v +++ b/fpga/usrp2/top/N2x0/u2plus_core.v @@ -1,5 +1,5 @@  // -// Copyright 2011 Ettus Research LLC +// Copyright 2011-2012 Ettus Research LLC  //  // This program is free software: you can redistribute it and/or modify  // it under the terms of the GNU General Public License as published by @@ -152,7 +152,7 @@ module u2plus_core     localparam SR_SIMTIMER =   8;   // 2     localparam SR_TIME64   =  10;   // 6     localparam SR_BUF_POOL =  16;   // 4 - +   localparam SR_USER_REGS = 20;   // 2     localparam SR_RX_FRONT =  24;   // 5     localparam SR_RX_CTRL0 =  32;   // 9     localparam SR_RX_DSP0  =  48;   // 7 @@ -170,15 +170,16 @@ module u2plus_core     // 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;     localparam SERDES_TX_FIFOSIZE = 9;     localparam SERDES_RX_FIFOSIZE = 9;  // RX currently doesn't use a fifo? -    -   wire [7:0] 	set_addr, set_addr_dsp; -   wire [31:0] 	set_data, set_data_dsp; -   wire 	set_stb, set_stb_dsp; -    + +   wire [7:0]  set_addr, set_addr_dsp, set_addr_user; +   wire [31:0] set_data, set_data_dsp, set_data_user; +   wire        set_stb, set_stb_dsp, set_stb_user; +     reg 		wb_rst;      wire 	dsp_rst = wb_rst; @@ -435,7 +436,7 @@ module u2plus_core     // Buffer Pool Status -- Slave #5        //compatibility number -> increment when the fpga has been sufficiently altered -   localparam compat_num = {16'd8, 16'd2}; //major, minor +   localparam compat_num = {16'd9, 16'd0}; //major, minor     wb_readback_mux buff_pool_status       (.wb_clk_i(wb_clk), .wb_rst_i(wb_rst), .wb_stb_i(s5_stb), @@ -478,7 +479,13 @@ module u2plus_core     settings_bus_crossclock settings_bus_crossclock       (.clk_i(wb_clk), .rst_i(wb_rst), .set_stb_i(set_stb), .set_addr_i(set_addr), .set_data_i(set_data),        .clk_o(dsp_clk), .rst_o(dsp_rst), .set_stb_o(set_stb_dsp), .set_addr_o(set_addr_dsp), .set_data_o(set_data_dsp)); -    + +   user_settings #(.BASE(SR_USER_REGS)) user_settings +     (.clk(dsp_clk),.rst(dsp_rst),.set_stb(set_stb_dsp), +      .set_addr(set_addr_dsp),.set_data(set_data_dsp), +      .set_addr_user(set_addr_user),.set_data_user(set_data_user), +      .set_stb_user(set_stb_user) ); +     // Output control lines     wire [7:0] 	 clock_outs, serdes_outs, adc_outs;     assign 	 {clock_ready, clk_en[1:0], clk_sel[1:0]} = clock_outs[4:0]; @@ -559,68 +566,62 @@ module u2plus_core     // /////////////////////////////////////////////////////////////////////////     // ADC Frontend -   wire [23:0] 	 adc_i, adc_q; +   wire [23:0] 	 rx_fe_i, rx_fe_q;     rx_frontend #(.BASE(SR_RX_FRONT)) rx_frontend       (.clk(dsp_clk),.rst(dsp_rst),        .set_stb(set_stb_dsp),.set_addr(set_addr_dsp),.set_data(set_data_dsp),        .adc_a({adc_a,2'b00}),.adc_ovf_a(adc_ovf_a),        .adc_b({adc_b,2'b00}),.adc_ovf_b(adc_ovf_b), -      .i_out(adc_i), .q_out(adc_q), .run(run_rx0_d1 | run_rx1_d1), .debug()); +      .i_out(rx_fe_i), .q_out(rx_fe_q), .run(run_rx0_d1 | run_rx1_d1), .debug());     // /////////////////////////////////////////////////////////////////////////     // DSP RX 0     wire [31:0] 	 sample_rx0; -   wire 	 clear_rx0, strobe_rx0; +   wire 	 strobe_rx0, clear_rx0;     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), +   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(adc_i),.adc_ovf_i(adc_ovf_a),.adc_q(adc_q),.adc_ovf_q(adc_ovf_b), +      .set_stb_user(set_stb_user), .set_addr_user(set_addr_user), .set_data_user(set_data_user), +      .rx_fe_i(rx_fe_i),.rx_fe_q(rx_fe_q),        .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), +      .sample(sample_rx0), .run(run_rx0), .strobe(strobe_rx0), .clear_o(clear_rx0),        .rx_data_o(wr1_dat), .rx_src_rdy_o(wr1_ready_i), .rx_dst_rdy_i(wr1_ready_o),        .debug() );     // /////////////////////////////////////////////////////////////////////////     // DSP RX 1     wire [31:0] 	 sample_rx1; -   wire 	 clear_rx1, strobe_rx1; +   wire 	 strobe_rx1, clear_rx1;     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), +   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(adc_i),.adc_ovf_i(adc_ovf_a),.adc_q(adc_q),.adc_ovf_q(adc_ovf_b), +      .set_stb_user(set_stb_user), .set_addr_user(set_addr_user), .set_data_user(set_data_user), +      .rx_fe_i(rx_fe_i),.rx_fe_q(rx_fe_q),        .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), +      .sample(sample_rx1), .run(run_rx1), .strobe(strobe_rx1), .clear_o(clear_rx1),        .rx_data_o(wr3_dat), .rx_src_rdy_o(wr3_ready_i), .rx_dst_rdy_i(wr3_ready_o),        .debug() ); @@ -632,10 +633,6 @@ module u2plus_core     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)); -     assign 	 RAM_A[20:18] = 3'b0;     ext_fifo #(.EXT_WIDTH(36),.INT_WIDTH(36),.RAM_DEPTH(18),.FIFO_DEPTH(18))  @@ -661,28 +658,39 @@ module u2plus_core  	.debug(debug_extfifo),  	.debug2(debug_extfifo2) ); -   wire [23:0] 	 tx_i, tx_q; +   wire [23:0] 	 tx_fe_i, tx_fe_q; +   wire [31:0]   sample_tx; +   wire strobe_tx; -   vita_tx_chain #(.BASE_CTRL(SR_TX_CTRL), .BASE_DSP(SR_TX_DSP),  +   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(tx_data), .tx_src_rdy_i(tx_src_rdy), .tx_dst_rdy_o(tx_dst_rdy),        .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), +      .sample(sample_tx), .strobe(strobe_tx), +      .underrun(underrun), .run(run_tx), .clear_o(clear_tx),        .debug(debug_vt)); +   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_fe_i),.tx_fe_q(tx_fe_q), +      .sample(sample_tx), .run(run_tx), .strobe(strobe_tx), +      .debug() ); +     tx_frontend #(.BASE(SR_TX_FRONT)) tx_frontend       (.clk(dsp_clk), .rst(dsp_rst),        .set_stb(set_stb_dsp),.set_addr(set_addr_dsp),.set_data(set_data_dsp), -      .tx_i(tx_i), .tx_q(tx_q), .run(1'b1), +      .tx_i(tx_fe_i), .tx_q(tx_fe_q), .run(1'b1),        .dac_a(dac_a), .dac_b(dac_b)); -          +     // ///////////////////////////////////////////////////////////////////////////////////     // SERDES @@ -701,7 +709,7 @@ module u2plus_core     wire [31:0] 	 debug_sync; -   time_64bit #(.TICKS_PER_SEC(32'd100000000),.BASE(SR_TIME64)) time_64bit +   time_64bit #(.BASE(SR_TIME64)) time_64bit       (.clk(dsp_clk), .rst(dsp_rst), .set_stb(set_stb_dsp), .set_addr(set_addr_dsp), .set_data(set_data_dsp),        .pps(pps_in), .vita_time(vita_time), .vita_time_pps(vita_time_pps), .pps_int(pps_int),        .exp_time_in(exp_time_in), .exp_time_out(exp_time_out), .good_sync(good_sync), .debug(debug_sync)); diff --git a/fpga/usrp2/top/USRP2/Makefile b/fpga/usrp2/top/USRP2/Makefile index 8ebb43639..1fc375c76 100644 --- a/fpga/usrp2/top/USRP2/Makefile +++ b/fpga/usrp2/top/USRP2/Makefile @@ -1,5 +1,5 @@  # -# Copyright 2008 Ettus Research LLC +# Copyright 2008-2012 Ettus Research LLC  #  ################################################## @@ -8,6 +8,10 @@  TOP_MODULE = u2_rev3  BUILD_DIR = $(abspath build) +# set me in a custom makefile +CUSTOM_SRCS = +CUSTOM_DEFS = +  ##################################################  # Include other makefiles  ################################################## @@ -52,7 +56,8 @@ u2_rev3.ucf  SOURCES = $(abspath $(TOP_SRCS)) $(FIFO_SRCS) \  $(CONTROL_LIB_SRCS) $(SDR_LIB_SRCS) $(SERDES_SRCS) \  $(SIMPLE_GEMAC_SRCS) $(TIMING_SRCS) $(OPENCORES_SRCS) \ -$(VRT_SRCS) $(UDP_SRCS) $(COREGEN_SRCS) $(EXTRAM_SRCS) +$(VRT_SRCS) $(UDP_SRCS) $(COREGEN_SRCS) $(EXTRAM_SRCS) \ +$(CUSTOM_SRCS)  ##################################################  # Process Properties @@ -65,7 +70,8 @@ SYNTHESIZE_PROPERTIES = \  "Register Balancing" Yes \  "Use Clock Enable" Auto \  "Use Synchronous Reset" Auto \ -"Use Synchronous Set" Auto +"Use Synchronous Set" Auto \ +"Verilog Macros" "$(CUSTOM_DEFS)"  TRANSLATE_PROPERTIES = \  "Macro Search Path" "$(shell pwd)/../../coregen/" diff --git a/fpga/usrp2/top/USRP2/u2_core.v b/fpga/usrp2/top/USRP2/u2_core.v index bbd0e9337..9b26b98e1 100644 --- a/fpga/usrp2/top/USRP2/u2_core.v +++ b/fpga/usrp2/top/USRP2/u2_core.v @@ -1,5 +1,5 @@  // -// Copyright 2011 Ettus Research LLC +// Copyright 2011-2012 Ettus Research LLC  //  // This program is free software: you can redistribute it and/or modify  // it under the terms of the GNU General Public License as published by @@ -157,7 +157,7 @@ module u2_core     localparam SR_SIMTIMER =   8;   // 2     localparam SR_TIME64   =  10;   // 6     localparam SR_BUF_POOL =  16;   // 4 - +   localparam SR_USER_REGS = 20;   // 2     localparam SR_RX_FRONT =  24;   // 5     localparam SR_RX_CTRL0 =  32;   // 9     localparam SR_RX_DSP0  =  48;   // 7 @@ -175,15 +175,16 @@ module u2_core     // 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;     localparam SERDES_TX_FIFOSIZE = 9;     localparam SERDES_RX_FIFOSIZE = 9;  // RX currently doesn't use a fifo? -    -   wire [7:0] 	set_addr, set_addr_dsp; -   wire [31:0] 	set_data, set_data_dsp; -   wire 	set_stb, set_stb_dsp; -    + +   wire [7:0]  set_addr, set_addr_dsp, set_addr_user; +   wire [31:0] set_data, set_data_dsp, set_data_user; +   wire        set_stb, set_stb_dsp, set_stb_user; +     wire 	ram_loader_done, ram_loader_rst;     wire 	wb_rst;     wire 	dsp_rst = wb_rst; @@ -441,7 +442,7 @@ module u2_core     // Buffer Pool Status -- Slave #5        //compatibility number -> increment when the fpga has been sufficiently altered -   localparam compat_num = {16'd8, 16'd2}; //major, minor +   localparam compat_num = {16'd9, 16'd0}; //major, minor     wb_readback_mux buff_pool_status       (.wb_clk_i(wb_clk), .wb_rst_i(wb_rst), .wb_stb_i(s5_stb), @@ -484,7 +485,13 @@ module u2_core     settings_bus_crossclock settings_bus_crossclock       (.clk_i(wb_clk), .rst_i(wb_rst), .set_stb_i(set_stb), .set_addr_i(set_addr), .set_data_i(set_data),        .clk_o(dsp_clk), .rst_o(dsp_rst), .set_stb_o(set_stb_dsp), .set_addr_o(set_addr_dsp), .set_data_o(set_data_dsp)); -    + +   user_settings #(.BASE(SR_USER_REGS)) user_settings +     (.clk(dsp_clk),.rst(dsp_rst),.set_stb(set_stb_dsp), +      .set_addr(set_addr_dsp),.set_data(set_data_dsp), +      .set_addr_user(set_addr_user),.set_data_user(set_data_user), +      .set_stb_user(set_stb_user) ); +     // Output control lines     wire [7:0] 	 clock_outs, serdes_outs, adc_outs;     assign 	 {clock_ready, clk_en[1:0], clk_sel[1:0]} = clock_outs[4:0]; @@ -547,68 +554,62 @@ module u2_core     // /////////////////////////////////////////////////////////////////////////     // ADC Frontend -   wire [23:0] 	 adc_i, adc_q; +   wire [23:0] 	 rx_fe_i, rx_fe_q;     rx_frontend #(.BASE(SR_RX_FRONT)) rx_frontend       (.clk(dsp_clk),.rst(dsp_rst),        .set_stb(set_stb_dsp),.set_addr(set_addr_dsp),.set_data(set_data_dsp),        .adc_a({adc_a,2'b00}),.adc_ovf_a(adc_ovf_a),        .adc_b({adc_b,2'b00}),.adc_ovf_b(adc_ovf_b), -      .i_out(adc_i), .q_out(adc_q), .run(run_rx0_d1 | run_rx1_d1), .debug()); +      .i_out(rx_fe_i), .q_out(rx_fe_q), .run(run_rx0_d1 | run_rx1_d1), .debug());     // /////////////////////////////////////////////////////////////////////////     // DSP RX 0     wire [31:0] 	 sample_rx0; -   wire 	 clear_rx0, strobe_rx0; +   wire 	 strobe_rx0, clear_rx0;     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), +   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(adc_i),.adc_ovf_i(adc_ovf_a),.adc_q(adc_q),.adc_ovf_q(adc_ovf_b), +      .set_stb_user(set_stb_user), .set_addr_user(set_addr_user), .set_data_user(set_data_user), +      .rx_fe_i(rx_fe_i),.rx_fe_q(rx_fe_q),        .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), +      .sample(sample_rx0), .run(run_rx0), .strobe(strobe_rx0), .clear_o(clear_rx0),        .rx_data_o(wr1_dat), .rx_src_rdy_o(wr1_ready_i), .rx_dst_rdy_i(wr1_ready_o),        .debug() );     // /////////////////////////////////////////////////////////////////////////     // DSP RX 1     wire [31:0] 	 sample_rx1; -   wire 	 clear_rx1, strobe_rx1; +   wire 	 strobe_rx1, clear_rx1;     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), +   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(adc_i),.adc_ovf_i(adc_ovf_a),.adc_q(adc_q),.adc_ovf_q(adc_ovf_b), +      .set_stb_user(set_stb_user), .set_addr_user(set_addr_user), .set_data_user(set_data_user), +      .rx_fe_i(rx_fe_i),.rx_fe_q(rx_fe_q),        .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), +      .sample(sample_rx1), .run(run_rx1), .strobe(strobe_rx1), .clear_o(clear_rx1),        .rx_data_o(wr3_dat), .rx_src_rdy_o(wr3_ready_i), .rx_dst_rdy_i(wr3_ready_o),        .debug() ); @@ -620,10 +621,6 @@ module u2_core     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)); -     ext_fifo #(.EXT_WIDTH(18),.INT_WIDTH(36),.RAM_DEPTH(19),.FIFO_DEPTH(19))        ext_fifo_i1         (.int_clk(dsp_clk), @@ -647,28 +644,39 @@ module u2_core  	.debug(debug_extfifo),  	.debug2(debug_extfifo2) ); -   wire [23:0] 	 tx_i, tx_q; +   wire [23:0] 	 tx_fe_i, tx_fe_q; +   wire [31:0]   sample_tx; +   wire strobe_tx; -   vita_tx_chain #(.BASE_CTRL(SR_TX_CTRL), .BASE_DSP(SR_TX_DSP),  +   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(tx_data), .tx_src_rdy_i(tx_src_rdy), .tx_dst_rdy_o(tx_dst_rdy),        .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), +      .sample(sample_tx), .strobe(strobe_tx), +      .underrun(underrun), .run(run_tx), .clear_o(clear_tx),        .debug(debug_vt)); +   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_fe_i),.tx_fe_q(tx_fe_q), +      .sample(sample_tx), .run(run_tx), .strobe(strobe_tx), +      .debug() ); +     tx_frontend #(.BASE(SR_TX_FRONT)) tx_frontend       (.clk(dsp_clk), .rst(dsp_rst),        .set_stb(set_stb_dsp),.set_addr(set_addr_dsp),.set_data(set_data_dsp), -      .tx_i(tx_i), .tx_q(tx_q), .run(1'b1), +      .tx_i(tx_fe_i), .tx_q(tx_fe_q), .run(1'b1),        .dac_a(dac_a), .dac_b(dac_b)); -          +     // ///////////////////////////////////////////////////////////////////////////////////     // SERDES @@ -689,7 +697,7 @@ module u2_core     wire [31:0] 	 debug_sync; -   time_64bit #(.TICKS_PER_SEC(32'd100000000),.BASE(SR_TIME64)) time_64bit +   time_64bit #(.BASE(SR_TIME64)) time_64bit       (.clk(dsp_clk), .rst(dsp_rst), .set_stb(set_stb_dsp), .set_addr(set_addr_dsp), .set_data(set_data_dsp),        .pps(pps_in), .vita_time(vita_time), .vita_time_pps(vita_time_pps), .pps_int(pps_int),        .exp_time_in(exp_time_in), .exp_time_out(exp_time_out), .good_sync(good_sync), .debug(debug_sync)); diff --git a/fpga/usrp2/vrt/Makefile.srcs b/fpga/usrp2/vrt/Makefile.srcs index 166ed44ef..84ba5dc29 100644 --- a/fpga/usrp2/vrt/Makefile.srcs +++ b/fpga/usrp2/vrt/Makefile.srcs @@ -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 \  )) diff --git a/fpga/usrp2/vrt/gen_context_pkt.v b/fpga/usrp2/vrt/gen_context_pkt.v index bdfca8237..d6674e887 100644 --- a/fpga/usrp2/vrt/gen_context_pkt.v +++ b/fpga/usrp2/vrt/gen_context_pkt.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 }; diff --git a/fpga/usrp2/vrt/vita_rx_chain.v b/fpga/usrp2/vrt/vita_rx_chain.v index 8b41e5fa8..c57e6cc05 100644 --- a/fpga/usrp2/vrt/vita_rx_chain.v +++ b/fpga/usrp2/vrt/vita_rx_chain.v @@ -1,5 +1,5 @@  // -// Copyright 2011 Ettus Research LLC +// Copyright 2011-2012 Ettus Research LLC  //  // This program is free software: you can redistribute it and/or modify  // it under the terms of the GNU General Public License as published by @@ -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; + +   setting_reg #(.my_addr(BASE+3)) sr +     (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), +      .in(set_data),.out(),.changed(clear)); +     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)); diff --git a/fpga/usrp2/vrt/vita_rx_engine_glue.v b/fpga/usrp2/vrt/vita_rx_engine_glue.v new file mode 100644 index 000000000..56447a7aa --- /dev/null +++ b/fpga/usrp2/vrt/vita_rx_engine_glue.v @@ -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 diff --git a/fpga/usrp2/vrt/vita_rx_framer.v b/fpga/usrp2/vrt/vita_rx_framer.v index bd09315bc..514df1151 100644 --- a/fpga/usrp2/vrt/vita_rx_framer.v +++ b/fpga/usrp2/vrt/vita_rx_framer.v @@ -1,5 +1,5 @@  // -// Copyright 2011 Ettus Research LLC +// Copyright 2011-2012 Ettus Research LLC  //  // This program is free software: you can redistribute it and/or modify  // it under the terms of the GNU General Public License as published by @@ -93,18 +93,16 @@ module vita_rx_framer     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 +120,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,7 +160,7 @@ 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 @@ -194,12 +190,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; diff --git a/fpga/usrp2/vrt/vita_tx_chain.v b/fpga/usrp2/vrt/vita_tx_chain.v index ac9f08fc8..82a43d57a 100644 --- a/fpga/usrp2/vrt/vita_tx_chain.v +++ b/fpga/usrp2/vrt/vita_tx_chain.v @@ -1,5 +1,5 @@  // -// Copyright 2011 Ettus Research LLC +// Copyright 2011-2012 Ettus Research LLC  //  // This program is free software: you can redistribute it and/or modify  // it under the terms of the GNU General Public License as published by @@ -17,8 +17,9 @@  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, @@ -26,11 +27,12 @@ module vita_tx_chain      parameter DSP_NUMBER=0)     (input clk, input reset,      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; @@ -38,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; @@ -48,61 +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 + +   setting_reg #(.my_addr(BASE+0), .width(1)) sr       (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), -      .in(set_data),.out(),.changed(clear_vita)); +      .in(set_data),.out(flush),.changed(clear)); -   setting_reg #(.my_addr(BASE_CTRL+2), .at_reset(0)) sr_streamid +   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(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), +   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(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), diff --git a/fpga/usrp2/vrt/vita_tx_control.v b/fpga/usrp2/vrt/vita_tx_control.v index 5df89bdbe..c3ce2b96a 100644 --- a/fpga/usrp2/vrt/vita_tx_control.v +++ b/fpga/usrp2/vrt/vita_tx_control.v @@ -50,11 +50,9 @@ 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; @@ -187,8 +185,17 @@ 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; diff --git a/fpga/usrp2/vrt/vita_tx_deframer.v b/fpga/usrp2/vrt/vita_tx_deframer.v index 06ca27767..6919da11a 100644 --- a/fpga/usrp2/vrt/vita_tx_deframer.v +++ b/fpga/usrp2/vrt/vita_tx_deframer.v @@ -1,5 +1,5 @@  // -// Copyright 2011 Ettus Research LLC +// Copyright 2011-2012 Ettus Research LLC  //  // This program is free software: you can redistribute it and/or modify  // it under the terms of the GNU General Public License as published by @@ -85,7 +85,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 +117,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 +169,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 +204,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 }, diff --git a/fpga/usrp2/vrt/vita_tx_engine_glue.v b/fpga/usrp2/vrt/vita_tx_engine_glue.v new file mode 100644 index 000000000..db0d55dee --- /dev/null +++ b/fpga/usrp2/vrt/vita_tx_engine_glue.v @@ -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 | 
