diff options
| -rw-r--r-- | usrp2/control_lib/double_buffer_tb.v | 48 | ||||
| -rw-r--r-- | usrp2/sdr_lib/dspengine_8to16.v | 194 | 
2 files changed, 230 insertions, 12 deletions
| diff --git a/usrp2/control_lib/double_buffer_tb.v b/usrp2/control_lib/double_buffer_tb.v index a9aae6956..3e0b04b8a 100644 --- a/usrp2/control_lib/double_buffer_tb.v +++ b/usrp2/control_lib/double_buffer_tb.v @@ -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 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,7 +69,7 @@ module double_buffer_tb();  	@(posedge clk);  	@(posedge clk);  	@(posedge clk); - +/*  	// Passthrough  	$display("Passthrough");  	src_rdy_i <= 1; @@ -86,12 +86,12 @@ 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; @@ -159,23 +159,23 @@ 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};  	@(posedge clk); -	data_i <= { 2'b00,1'b0,1'b0,32'h21002200}; +	data_i <= { 2'b00,1'b0,1'b0,32'h21222324};  	@(posedge clk); -	data_i <= { 2'b00,1'b0,1'b0,32'h23002400}; +	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); @@ -187,6 +187,30 @@ module double_buffer_tb();  	src_rdy_i <= 1;    	data_i <= { 2'b00,1'b0,1'b1,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}; +	@(posedge clk);  	data_i <= { 2'b00,1'b0,1'b0,32'h31003200};  	@(posedge clk);  	data_i <= { 2'b00,1'b0,1'b0,32'h33003400}; @@ -246,7 +270,7 @@ module double_buffer_tb();  	@(posedge clk);  	src_rdy_i <= 0;  	@(posedge clk); - +*/       end     initial #28000 $finish; diff --git a/usrp2/sdr_lib/dspengine_8to16.v b/usrp2/sdr_lib/dspengine_8to16.v new file mode 100644 index 000000000..39cf440f6 --- /dev/null +++ b/usrp2/sdr_lib/dspengine_8to16.v @@ -0,0 +1,194 @@ + +// 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 dspengine_8to16 +  #(parameter BASE = 0, +    parameter BUF_SIZE = 9) +   (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_PARSE_HEADER = 1; +   localparam DSP_READ = 2; +   localparam DSP_WRITE_0 = 3; +   localparam DSP_WRITE_1 = 4; +   localparam DSP_READ_TRAILER = 5; +   localparam DSP_WRITE_TRAILER = 6; +   localparam DSP_WRITE_HEADER = 7; +   localparam DSP_DONE = 8; + +   // 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; +    +   wire 	      last = (read_adr + 1) == (access_len - has_trailer_reg); + +   reg [31:0] 	      new_header, new_trailer, trailer_mask; +   reg [15:0] 	      length; +   reg 		      wait_for_trailer; +   reg [15:0] 	      data_in_len, data_out_len; + +   reg [7:0] 	      i8_0, q8_0; +   wire [7:0] 	      i8_1 = access_dat_i[15:8]; +   wire [7:0] 	      q8_1 = access_dat_i[7:0]; +   reg 		      skip; +    + +   always @(posedge clk) +     { i8_0, q8_0 } <= access_dat_i[31:16]; +    +   always @(posedge clk) +     if(reset | clear) +       dsp_state <= DSP_IDLE; +     else +       case(dsp_state) +	 DSP_IDLE : +	   begin +	      read_adr <= 0; +	      write_adr <= 0; +	      if(access_ok) +		dsp_state <= DSP_PARSE_HEADER; +	   end +	  +	 DSP_PARSE_HEADER : +	   begin +	      // FIXME is data always valid here? + +	      has_trailer_reg <= has_trailer; +	      new_header[31:16] <= access_dat_i[31:16]; +	      new_header[15:0] <= access_len; +	      length <= access_len; +	      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_len-1; // point to trailer +		   dsp_state <= DSP_READ_TRAILER; +		   wait_for_trailer <= 0; +		   data_in_len <= access_len - hdr_length - 1; +		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 <= access_dat_i[20] & access_dat_i[8]; +	      data_out_len <= {data_in_len,1'b0} - (access_dat_i[20] & access_dat_i[8]); +	      write_adr <= hdr_length_reg + {data_in_len,1'b0} - (access_dat_i[20] & access_dat_i[8]); +	   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; // length = addr of trailer + 1 +	   end + +	 DSP_READ : +	   begin +	      dsp_state <= DSP_WRITE_1; +	      read_adr <= read_adr - 1; +	   end + +	 DSP_WRITE_1 : +	   begin +	      write_adr <= write_adr - 1; +	      odd <= 0; +	      if(write_adr == hdr_length_reg) +		dsp_state <= DSP_WRITE_HEADER; +	      else if(odd) +		dsp_state <= DSP_READ; +	      else +		dsp_state <= DSP_WRITE_0; +	   end + +	 DSP_WRITE_0 : +	   begin +	      write_adr <= write_adr - 1; +	      if(write_adr == hdr_length_reg) +		dsp_state <= DSP_WRITE_HEADER; +	      else +		dsp_state <= DSP_READ; +	   end + +	 DSP_WRITE_HEADER : +	   dsp_state <= DSP_DONE; + +	 DSP_DONE : +	   begin +	      read_adr <= 0; +	      write_adr <= 0; +	      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'h1, 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 | 
