mirror of
https://github.com/fairwaves/UHD-Fairwaves.git
synced 2025-11-02 13:03:13 +00:00
212 lines
6.0 KiB
Verilog
212 lines
6.0 KiB
Verilog
|
|
// Copyright 2011-2013 Ettus Research LLC
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// 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_16to8
|
|
#(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_16to8
|
|
(.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr),
|
|
.in(set_data),.out(convert),.changed());
|
|
|
|
reg [2:0] dsp_state;
|
|
localparam DSP_IDLE = 0;
|
|
localparam DSP_PARSE_HEADER = 1;
|
|
localparam DSP_CONVERT = 2;
|
|
localparam DSP_CONVERT_DRAIN_PIPE = 3;
|
|
localparam DSP_READ_TRAILER = 4;
|
|
localparam DSP_WRITE_TRAILER = 5;
|
|
localparam DSP_WRITE_HEADER = 6;
|
|
localparam DSP_DONE = 7;
|
|
|
|
// 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;
|
|
|
|
wire [35:0] prod_i, prod_q;
|
|
wire [15:0] scaled_i, scaled_q;
|
|
wire [7:0] i8, q8;
|
|
reg [7:0] i8_reg, q8_reg;
|
|
wire stb_read, stb_clip, val_read, val_clip;
|
|
wire stb_out, stb_reg;
|
|
reg even;
|
|
|
|
reg [BUF_SIZE-1:0] read_adr, write_adr;
|
|
reg has_trailer_reg;
|
|
|
|
wire last = (read_adr + 1) == (access_len - has_trailer_reg);
|
|
wire last_o, even_o;
|
|
|
|
wire stb_write = stb_out & (even_o | last_o);
|
|
wire send_to_pipe = ~stb_write & (dsp_state == DSP_CONVERT);
|
|
reg [31:0] new_header, new_trailer, trailer_mask;
|
|
reg [15:0] length;
|
|
reg wait_for_trailer;
|
|
|
|
always @(posedge clk)
|
|
if(reset | clear)
|
|
dsp_state <= DSP_IDLE;
|
|
else
|
|
case(dsp_state)
|
|
DSP_IDLE :
|
|
begin
|
|
read_adr <= 0;
|
|
write_adr <= 0;
|
|
even <= 0;
|
|
if(access_ok)
|
|
dsp_state <= DSP_PARSE_HEADER;
|
|
end
|
|
|
|
DSP_PARSE_HEADER :
|
|
begin
|
|
has_trailer_reg <= has_trailer;
|
|
new_header[31:16] <= access_dat_i[31:16];
|
|
new_header[15:0] <= access_len;
|
|
length <= access_len;
|
|
if(is_if_data & convert)
|
|
begin
|
|
read_adr <= hdr_length;
|
|
write_adr <= hdr_length;
|
|
dsp_state <= DSP_CONVERT;
|
|
end
|
|
else
|
|
dsp_state <= DSP_WRITE_HEADER;
|
|
end
|
|
|
|
DSP_CONVERT:
|
|
begin
|
|
new_header[26] <= 1'b1; // all converted packets have a trailer
|
|
if(stb_write)
|
|
write_adr <= write_adr + 1;
|
|
else if(stb_read) // should always be 1 if we are here
|
|
begin
|
|
read_adr <= read_adr + 1;
|
|
even <= ~even;
|
|
if(last)
|
|
begin
|
|
dsp_state <= DSP_CONVERT_DRAIN_PIPE;
|
|
if(~even)
|
|
trailer_mask <= 32'h00400400;
|
|
else
|
|
trailer_mask <= 32'h00400000;
|
|
end
|
|
end
|
|
end
|
|
|
|
DSP_CONVERT_DRAIN_PIPE :
|
|
if(stb_write)
|
|
begin
|
|
write_adr <= write_adr + 1;
|
|
if(last_o)
|
|
if(has_trailer_reg)
|
|
begin
|
|
dsp_state <= DSP_READ_TRAILER;
|
|
wait_for_trailer <= 0;
|
|
end
|
|
else
|
|
begin
|
|
dsp_state <= DSP_WRITE_TRAILER;
|
|
new_trailer <= trailer_mask;
|
|
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] | trailer_mask;
|
|
end
|
|
|
|
DSP_WRITE_TRAILER :
|
|
begin
|
|
dsp_state <= DSP_WRITE_HEADER;
|
|
write_adr <= 0;
|
|
new_header[15:0] <= write_adr + 1;
|
|
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) |
|
|
stb_write;
|
|
|
|
assign access_dat_o = (dsp_state == DSP_WRITE_HEADER) ? { 4'h1, new_header } :
|
|
(dsp_state == DSP_WRITE_TRAILER) ? { 4'h2, new_trailer } :
|
|
(last_o&~even_o) ? {4'h0, i8, q8, 16'd0 } :
|
|
{4'h0, i8_reg, q8_reg, i8, q8 };
|
|
|
|
assign access_adr = (stb_write|(dsp_state == DSP_WRITE_HEADER)|(dsp_state == DSP_WRITE_TRAILER)) ? write_adr : read_adr;
|
|
|
|
// DSP Pipeline
|
|
|
|
wire [15:0] i16 = access_dat_i[31:16];
|
|
wire [15:0] q16 = access_dat_i[15:0];
|
|
|
|
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_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};
|
|
|
|
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
|