Squashed B200 FPGA Source. Code from Josh Blum, Ian Buckley, and Matt Ettus.
Original-commit: 0df4b801a34697f2058b4a7b95e08d2a0576c9db
This commit is contained in:
@@ -0,0 +1 @@
|
||||
*tb
|
||||
@@ -0,0 +1,29 @@
|
||||
#
|
||||
# Copyright 2013 Ettus Research LLC
|
||||
#
|
||||
|
||||
##################################################
|
||||
# VITA Sources
|
||||
##################################################
|
||||
VITA_SRCS = $(abspath $(addprefix $(BASE_DIR)/../lib/vita/, \
|
||||
new_tx_control.v \
|
||||
new_tx_deframer.v \
|
||||
tx_responder.v \
|
||||
trigger_context_pkt.v \
|
||||
context_packet_gen.v \
|
||||
new_rx_control.v \
|
||||
new_rx_framer.v \
|
||||
chdr_16sc_to_xxxx_chain.v \
|
||||
chdr_xxxx_to_16sc_chain.v \
|
||||
chdr_16sc_to_12sc.v \
|
||||
chdr_12sc_to_16sc.v \
|
||||
chdr_16sc_to_8sc.v \
|
||||
chdr_8sc_to_16sc.v \
|
||||
chdr_16sc_to_32f.v \
|
||||
chdr_32f_to_16sc.v \
|
||||
chdr_16sc_to_32f.v \
|
||||
chdr_32f_to_16sc.v \
|
||||
float_to_iq.v \
|
||||
iq_to_float.v \
|
||||
binary_encoder.v \
|
||||
))
|
||||
@@ -0,0 +1,37 @@
|
||||
`define log2(N) (\
|
||||
N < 2 ? 0 : \
|
||||
N < 4 ? 1 : \
|
||||
N < 8 ? 2 : \
|
||||
N < 16 ? 3 : \
|
||||
N < 32 ? 4 : \
|
||||
N < 64 ? 5 : \
|
||||
N < 128 ? 6 : \
|
||||
N < 256 ? 7 : \
|
||||
N < 512 ? 8 : \
|
||||
N < 1024 ? 9 : \
|
||||
10)
|
||||
|
||||
module binary_encoder
|
||||
#(
|
||||
parameter SIZE = 16
|
||||
)
|
||||
(
|
||||
input [SIZE-1:0] in,
|
||||
output [`log2(SIZE)-1:0] out
|
||||
);
|
||||
|
||||
genvar m,n;
|
||||
|
||||
generate
|
||||
// Loop enough times to represent the total number of input bits as an encoded value
|
||||
for (m = 0; m <= `log2(SIZE-1); m = m + 1) begin: expand_or_tree
|
||||
wire [SIZE-1:0] encoding;
|
||||
// Build enable mask by iterating through every input bit.
|
||||
for (n = 0; n < SIZE ; n = n + 1) begin: encode_this_bit
|
||||
assign encoding[n] = n[m];
|
||||
end
|
||||
// OR tree for this output bit with appropraite bits enabled.
|
||||
assign out[m] = |(encoding & in);
|
||||
end
|
||||
endgenerate
|
||||
endmodule // binary_encoder
|
||||
Executable
+1
@@ -0,0 +1 @@
|
||||
iverilog -y . -y ../dsp/ -y ../control/ -Wall chdr_12sc_to_16sc_tb.v -o chdr_12sc_to_16sc_tb
|
||||
Executable
+1
@@ -0,0 +1 @@
|
||||
iverilog -y . -y ../dsp/ -y ../control/ -Wall chdr_16sc_to_12sc_tb.v -o chdr_16sc_to_12sc_tb
|
||||
Executable
+2
@@ -0,0 +1,2 @@
|
||||
iverilog -y . -y ../dsp/ -y ../control/ -Wall chdr_16sc_to_8sc_tb.v -o chdr_16sc_to_8sc_tb
|
||||
|
||||
Executable
+2
@@ -0,0 +1,2 @@
|
||||
iverilog -y . -y ../dsp/ -y ../control/ -Wall chdr_8sc_to_16sc_tb.v -o chdr_8sc_to_16sc_tb
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
//
|
||||
// Copyright 2013 Ettus Research LLC
|
||||
//
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
module chdr_12sc_to_16sc
|
||||
#(parameter BASE = 0)
|
||||
( input set_stb, input [7:0] set_addr, input [31:0] set_data,
|
||||
//input side of device
|
||||
input clk, input reset,
|
||||
input [63:0] i_tdata,
|
||||
input i_tlast,
|
||||
input i_tvalid,
|
||||
output i_tready,
|
||||
//output side of device
|
||||
output reg [63:0] o_tdata,
|
||||
output o_tlast,
|
||||
output o_tvalid,
|
||||
input o_tready,
|
||||
|
||||
output [31:0] debug
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
wire chdr_has_hdr = 1'b1;
|
||||
wire chdr_has_time = i_tdata[61];
|
||||
wire chdr_has_tlr = 1'b0;
|
||||
|
||||
wire [15:0] chdr_header_lines = chdr_has_time? 16 : 8;
|
||||
wire [15:0] just_samples_in = i_tdata[47:32] - chdr_header_lines;
|
||||
|
||||
//calculating output length based on input ( 4/3*input = output)
|
||||
|
||||
wire [30:0] calc_output_len = ({just_samples_in,14'h0} + {just_samples_in,12'h0} + {just_samples_in,10'h0} + {just_samples_in,8'h0} + {just_samples_in,6'h0} + {just_samples_in,4'h0} + {just_samples_in,2'h0}+{just_samples_in} +'b0001000000000000)<<2;
|
||||
|
||||
wire [15:0] samples = calc_output_len[30:16];
|
||||
wire [15:0] chdr_payload_lines = samples + chdr_header_lines;
|
||||
|
||||
|
||||
reg has_exline;
|
||||
reg in_exline;
|
||||
|
||||
|
||||
|
||||
wire set_sid;
|
||||
wire [15:0] my_newhome;
|
||||
|
||||
|
||||
setting_reg #(.my_addr(BASE), .width(17)) new_destination
|
||||
(.clk(clk), .rst(reset), .strobe(set_stb), .addr(set_addr), .in(set_data),
|
||||
.out({set_sid, my_newhome[15:0]}));
|
||||
|
||||
localparam HEADER = 3'd0; // IDLE
|
||||
localparam TIME = 3'd1;
|
||||
localparam ODD_LINE_ZERO = 3'd2;
|
||||
localparam EVEN_LINE_ONE = 3'd3;
|
||||
localparam ODD_LINE_TWO = 3'd4;
|
||||
localparam EVEN_LINE_THREE = 3'd5;
|
||||
|
||||
reg [2:0] state;
|
||||
|
||||
|
||||
|
||||
always @(posedge clk) begin
|
||||
|
||||
if (reset) begin
|
||||
state <= HEADER;
|
||||
end
|
||||
|
||||
else if (o_tvalid && o_tready) case(state)
|
||||
|
||||
|
||||
HEADER: begin
|
||||
has_exline <= ( (samples[4:2] == 5) || (samples[4:2] == 7) || (samples[4:2] == 0));
|
||||
state <= (chdr_has_time)? TIME : ODD_LINE_ZERO;
|
||||
end
|
||||
|
||||
TIME: begin
|
||||
state <= (i_tlast)? HEADER: ODD_LINE_ZERO;
|
||||
end
|
||||
|
||||
ODD_LINE_ZERO: begin
|
||||
if ((i_tlast & !has_exline) || in_exline) begin
|
||||
state <= HEADER;
|
||||
in_exline <= 0;
|
||||
end
|
||||
else if (i_tlast & has_exline) begin
|
||||
in_exline <= 1;
|
||||
state <= EVEN_LINE_ONE;
|
||||
end
|
||||
else
|
||||
state <= EVEN_LINE_ONE;
|
||||
end
|
||||
|
||||
EVEN_LINE_ONE: begin
|
||||
if ((i_tlast & !has_exline) || in_exline) begin
|
||||
state <= HEADER;
|
||||
in_exline <= 0;
|
||||
end
|
||||
else if (i_tlast & has_exline) begin
|
||||
in_exline <= 1;
|
||||
state <= ODD_LINE_TWO;
|
||||
end
|
||||
else
|
||||
state <= ODD_LINE_TWO;
|
||||
end
|
||||
|
||||
ODD_LINE_TWO: begin
|
||||
if ((i_tlast & !has_exline) || in_exline) begin
|
||||
state <= HEADER;
|
||||
in_exline <= 0;
|
||||
end
|
||||
else if (i_tlast & has_exline) begin
|
||||
in_exline <= 1;
|
||||
state <= EVEN_LINE_THREE;
|
||||
end
|
||||
else
|
||||
state <= EVEN_LINE_THREE;
|
||||
end
|
||||
|
||||
EVEN_LINE_THREE: begin
|
||||
if (in_exline) begin
|
||||
state <= HEADER;
|
||||
in_exline <= 0;
|
||||
end
|
||||
else
|
||||
state <= ODD_LINE_ZERO;
|
||||
end
|
||||
|
||||
default: state <= HEADER;
|
||||
|
||||
endcase
|
||||
end
|
||||
|
||||
|
||||
//hold data after each input xfer
|
||||
reg [63:0] hold_tdata;
|
||||
always @(posedge clk) begin
|
||||
if (i_tvalid && i_tready) hold_tdata <= i_tdata;
|
||||
end
|
||||
|
||||
//main mux
|
||||
|
||||
always @(*)
|
||||
case(state)
|
||||
|
||||
HEADER: o_tdata <= {i_tdata[63:48],chdr_payload_lines,
|
||||
set_sid ? {i_tdata[15:0], my_newhome[15:0]}:i_tdata[31:0]};
|
||||
|
||||
TIME: o_tdata <= i_tdata;
|
||||
|
||||
ODD_LINE_ZERO: o_tdata <= {i_tdata[63:52], 4'h0, i_tdata[51:40], 4'h0, i_tdata[39:28],4'h0, i_tdata[27:16], 4'h0};
|
||||
|
||||
EVEN_LINE_ONE: o_tdata <= {hold_tdata[15:4],4'h0,hold_tdata[3:0],i_tdata[63:56],4'h0,i_tdata[55:44], 4'h0,i_tdata[43:32],4'h0};
|
||||
|
||||
ODD_LINE_TWO: o_tdata <= {hold_tdata[31:20], 4'h0, hold_tdata[19:8],4'h0, hold_tdata[7:0],i_tdata[63:60],4'h0,i_tdata[59:48],4'h0};
|
||||
|
||||
EVEN_LINE_THREE: o_tdata <= {hold_tdata[47:36],4'h0,hold_tdata[35:24],4'h0,hold_tdata[23:12],4'h0,hold_tdata[11:0],4'h0};
|
||||
|
||||
|
||||
default: o_tdata <= i_tdata;
|
||||
|
||||
endcase
|
||||
|
||||
assign o_tvalid = (in_exline)? 1'b1: i_tvalid;
|
||||
assign i_tready = (state != EVEN_LINE_THREE) & o_tready & !in_exline;
|
||||
assign o_tlast = (has_exline)? in_exline: ((state != EVEN_LINE_THREE) && i_tlast);
|
||||
|
||||
endmodule
|
||||
@@ -0,0 +1,188 @@
|
||||
`timescale 1ns/1ps
|
||||
|
||||
module chdr_12sc_to_16sc_tb();
|
||||
|
||||
reg clk = 0;
|
||||
reg reset = 1;
|
||||
//generate clock
|
||||
always #10 clk = ~clk;
|
||||
|
||||
initial $dumpfile("chdr_12sc_to_16sc_tb.vcd");
|
||||
initial $dumpvars(0,chdr_12sc_to_16sc_tb);
|
||||
|
||||
//tells when to finish
|
||||
initial
|
||||
begin
|
||||
#50 reset = 0;
|
||||
#50000;
|
||||
$finish;
|
||||
end
|
||||
|
||||
//setting registers and wire
|
||||
reg [63:0] i_tdata;
|
||||
reg i_tlast = 0;
|
||||
reg i_tvalid = 0;
|
||||
wire i_tready ;
|
||||
reg [7:0] set_addr;
|
||||
reg [31:0] set_data;
|
||||
reg set_stb;
|
||||
|
||||
|
||||
wire [63:0] o_tdata;
|
||||
wire o_tlast;
|
||||
|
||||
wire o_tvalid;
|
||||
reg o_tready;
|
||||
|
||||
chdr_12sc_to_16sc #(.BASE(89))dut
|
||||
(.clk(clk), .reset(reset),
|
||||
.set_data(set_data), .set_stb(set_stb), .set_addr(set_addr),
|
||||
.i_tdata(i_tdata), .i_tlast(i_tlast), .i_tvalid(i_tvalid), .i_tready(i_tready),
|
||||
.o_tdata(o_tdata), .o_tlast(o_tlast), .o_tvalid(o_tvalid), .o_tready(o_tready), .debug());
|
||||
|
||||
//if you want to feed a bigger input change array sizes here
|
||||
|
||||
reg [63:0] data[0:11];
|
||||
initial $readmemh("from12_to_x.hex", data);
|
||||
|
||||
//test packet loop
|
||||
task test_packet;
|
||||
input [15:0] len;
|
||||
input [31:0] sid;
|
||||
reg [1:0] index;
|
||||
|
||||
begin
|
||||
index <= 0;
|
||||
@(posedge clk) ;
|
||||
//send header
|
||||
i_tdata = {1'b0, 1'b0, 1'b1, 1'b0, 12'h0, (len + 16'd16),sid};
|
||||
i_tvalid <= 1;
|
||||
i_tlast <= 0;
|
||||
@(posedge clk);
|
||||
while (i_tready != 1)
|
||||
@(posedge clk);
|
||||
i_tdata <= {64'b0};
|
||||
@(posedge clk);
|
||||
while (i_tready != 1)
|
||||
@(posedge clk);
|
||||
|
||||
//-1 for last bit accounting
|
||||
repeat (len[15:3] + (len[2]|len[1]|len[0]) - 1)
|
||||
begin
|
||||
i_tdata <= {data[index]};
|
||||
index <= index+1;
|
||||
@(posedge clk);
|
||||
while (i_tready != 1)
|
||||
@(posedge clk);
|
||||
end
|
||||
i_tlast <= 1'b1;
|
||||
i_tdata <= {data[index]};
|
||||
@(posedge clk);
|
||||
while (i_tready != 1)
|
||||
@(posedge clk);
|
||||
|
||||
i_tvalid <= 0;
|
||||
end
|
||||
endtask // test_packet
|
||||
|
||||
//test_destination loop
|
||||
|
||||
task test_destination;
|
||||
input enable;
|
||||
input [15:0] dest_home;
|
||||
|
||||
|
||||
begin
|
||||
@(posedge clk);
|
||||
|
||||
set_data <= {enable,dest_home};
|
||||
set_addr <= 89;
|
||||
set_stb <= 1;
|
||||
|
||||
@(posedge clk);
|
||||
set_stb <= 0;
|
||||
end
|
||||
endtask
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//main loop
|
||||
initial
|
||||
begin
|
||||
i_tvalid <= 0;
|
||||
o_tready <= 1;
|
||||
i_tdata <= 0;
|
||||
|
||||
@(negedge reset);
|
||||
@(posedge clk);
|
||||
@(posedge clk);
|
||||
|
||||
|
||||
//testing ending positions
|
||||
|
||||
//from 1 to 7 should be line zero
|
||||
/*
|
||||
test_destination(1,16'hFEED);
|
||||
test_packet(0, 32'hDEAD_BEEF);
|
||||
#100
|
||||
*/
|
||||
|
||||
test_destination(1,16'hFEED);
|
||||
test_packet(3, 32'hDEAD_BEEF);
|
||||
#100
|
||||
|
||||
test_destination(1,16'hFEED);
|
||||
test_packet(6, 32'hDEAD_BEEF);
|
||||
#100
|
||||
|
||||
test_destination(1,16'hFEED);
|
||||
test_packet(9, 32'hDEAD_BEEF);
|
||||
#100
|
||||
|
||||
|
||||
|
||||
|
||||
//from 8 to 13 should be line one
|
||||
|
||||
test_destination(1,16'hFEED);
|
||||
test_packet(12, 32'hDEAD_BEEF);
|
||||
#100
|
||||
|
||||
test_destination(1,16'hFEED);
|
||||
test_packet(15, 32'hDEAD_BEEF);
|
||||
#100
|
||||
|
||||
test_destination(1,16'hFEED);
|
||||
test_packet(18, 32'hDEAD_BEEF);
|
||||
#100
|
||||
|
||||
test_destination(1,16'hFEED);
|
||||
test_packet(21, 32'hDEAD_BEEF);
|
||||
#100
|
||||
|
||||
|
||||
test_destination(1,16'hFEED);
|
||||
test_packet(24, 32'hDEAD_BEEF);
|
||||
|
||||
#100
|
||||
|
||||
test_destination(1,16'hFEED);
|
||||
test_packet(27, 32'hDEAD_BEEF);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
endmodule
|
||||
@@ -0,0 +1,221 @@
|
||||
//
|
||||
// Copyright 2013 Ettus Research LLC
|
||||
//
|
||||
|
||||
|
||||
module chdr_16sc_to_12sc
|
||||
#(parameter BASE=0)
|
||||
( input set_stb, input [7:0] set_addr, input [31:0] set_data,
|
||||
//left side of device
|
||||
input clk, input reset,
|
||||
input [63:0] i_tdata,
|
||||
input i_tlast,
|
||||
input i_tvalid,
|
||||
output i_tready,
|
||||
//right side of device
|
||||
output reg [63:0] o_tdata = 0,
|
||||
output o_tlast,
|
||||
output o_tvalid,
|
||||
input o_tready,
|
||||
|
||||
output [31:0] debug
|
||||
);
|
||||
|
||||
wire chdr_has_hdr = 1'b1;
|
||||
wire chdr_has_time = i_tdata[61];
|
||||
wire chdr_has_tlr = 1'b0;
|
||||
|
||||
wire [11:0] imag0;
|
||||
wire [11:0] real0;
|
||||
wire [11:0] imag1;
|
||||
wire [11:0] real1;
|
||||
wire [11:0] imag2;
|
||||
wire [11:0] real2;
|
||||
|
||||
|
||||
|
||||
wire [16:0] round_i0;
|
||||
wire [16:0] round_r0;
|
||||
wire [16:0] round_i1;
|
||||
wire [16:0] round_r1;
|
||||
wire [16:0] round_i2;
|
||||
wire [16:0] round_r2;
|
||||
|
||||
//pipiline registers
|
||||
|
||||
reg [11:0] imag0_out;
|
||||
reg [11:0] real0_out;
|
||||
reg [11:0] imag1_out;
|
||||
reg [11:0] real1_out;
|
||||
|
||||
reg [15:0] len_data;
|
||||
|
||||
//chdr length calculations
|
||||
wire [15:0] chdr_header_lines = chdr_has_time? 16 : 8;
|
||||
wire [15:0] in_samples = i_tdata[47:32] - chdr_header_lines;
|
||||
wire [15:0] samples = (in_samples*3) >> 2;
|
||||
wire [15:0] chdr_payload_lines = samples + chdr_header_lines;
|
||||
|
||||
|
||||
reg needs_exline = 0;
|
||||
reg in_exline = 0;
|
||||
|
||||
|
||||
wire set_sid;
|
||||
wire [15:0] my_newhome;
|
||||
|
||||
setting_reg #(.my_addr(BASE), .width(17)) new_destination
|
||||
(.clk(clk), .rst(reset), .strobe(set_stb), .addr(set_addr), .in(set_data),
|
||||
.out({set_sid, my_newhome[15:0]}));
|
||||
|
||||
//state machine
|
||||
|
||||
localparam HEADER = 3'd0; // IDLE
|
||||
localparam TIME = 3'd1;
|
||||
localparam LINE_ODD_ZERO = 3'd2;
|
||||
localparam LINE_EVEN_ONE = 3'd3;
|
||||
localparam LINE_ODD_TWO = 3'd4;
|
||||
localparam REG_STATE = 3'd5;
|
||||
|
||||
reg [2:0] state;
|
||||
|
||||
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (reset) begin
|
||||
state <= HEADER;
|
||||
needs_exline <= 0;
|
||||
in_exline <= 0;
|
||||
end
|
||||
|
||||
|
||||
else if ((o_tvalid && o_tready) || (i_tready && i_tvalid)) case(state)
|
||||
|
||||
|
||||
HEADER: begin
|
||||
|
||||
needs_exline <= (in_samples[4:2] == 3 || in_samples[4:2] == 4 || in_samples[4:2] == 6);
|
||||
state <= (i_tdata[61])? TIME: REG_STATE;
|
||||
|
||||
end
|
||||
|
||||
TIME: begin
|
||||
state <= (i_tlast) ? HEADER: REG_STATE;
|
||||
end
|
||||
|
||||
REG_STATE: begin
|
||||
if (i_tlast & !needs_exline || in_exline) begin
|
||||
state <= HEADER;
|
||||
in_exline <= 0;
|
||||
end
|
||||
else if (i_tlast & needs_exline) begin
|
||||
state <= LINE_EVEN_ONE;
|
||||
in_exline <= 1;
|
||||
|
||||
end
|
||||
else
|
||||
state <= LINE_EVEN_ONE;
|
||||
end
|
||||
|
||||
|
||||
LINE_EVEN_ONE: begin
|
||||
if (i_tlast & !needs_exline || in_exline) begin
|
||||
state <= HEADER;
|
||||
in_exline <= 0;
|
||||
end
|
||||
else if (i_tlast & needs_exline) begin
|
||||
state <= LINE_ODD_TWO;
|
||||
in_exline <= 1;
|
||||
|
||||
end
|
||||
else
|
||||
state <= LINE_ODD_TWO;
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
LINE_ODD_TWO: begin
|
||||
if (i_tlast & !needs_exline || in_exline) begin
|
||||
state <= HEADER;
|
||||
in_exline <= 0;
|
||||
end
|
||||
else if (i_tlast & needs_exline) begin
|
||||
state <= LINE_ODD_ZERO;
|
||||
in_exline <= 1;
|
||||
|
||||
end
|
||||
else
|
||||
state <= LINE_ODD_ZERO;
|
||||
end
|
||||
|
||||
LINE_ODD_ZERO: begin
|
||||
if (i_tlast & !needs_exline || in_exline) begin
|
||||
state <= HEADER;
|
||||
in_exline <= 0;
|
||||
end
|
||||
else if (i_tlast & needs_exline) begin
|
||||
state <= REG_STATE;
|
||||
in_exline <= 1;
|
||||
end
|
||||
else
|
||||
state <= REG_STATE;
|
||||
end
|
||||
|
||||
default: state <= HEADER;
|
||||
|
||||
endcase
|
||||
end
|
||||
|
||||
assign round_i0 = ({i_tdata[63],i_tdata[63:48]} + 'h0008);
|
||||
assign round_r0 = ({i_tdata[47],i_tdata[47:32]} + 'h0008);
|
||||
|
||||
assign imag0 = (round_i0[16] == 0 && round_i0[15] == 1)?(12'h7FF):(round_i0[16] == 1 && round_i0[15] == 0)? (12'h800):(round_i0[15:4]);
|
||||
|
||||
assign real0 = (round_r0[16] == 0 && round_r0[15] == 1)?(12'h7FF):(round_r0[16] == 1 && round_r0[15] == 0)? (12'h800):(round_r0[15:4]);
|
||||
|
||||
assign round_i1 = ({i_tdata[31],i_tdata[31:16]} + 'h0008);
|
||||
assign round_r1 = ({i_tdata[15],i_tdata[15:0]} + 'h0008);
|
||||
|
||||
assign imag1 = (round_i1[16] == 0 && round_i1[15] == 1)?(12'h7FF):(round_i1[16] == 1 && round_i1[15] == 0)? (12'h800):(round_i1[15:4]);
|
||||
|
||||
assign real1 = (round_r1[16] == 0 && round_r1[15] == 1)?(12'h7FF):(round_r1[16] == 1 && round_r1[15] == 0)? (12'h800):(round_r1[15:4]);
|
||||
|
||||
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (i_tvalid && o_tready)
|
||||
begin
|
||||
imag0_out <= imag0;
|
||||
real0_out <= real0;
|
||||
imag1_out <= imag1;
|
||||
real1_out <= real1;
|
||||
end
|
||||
|
||||
|
||||
|
||||
always @(*)
|
||||
case(state)
|
||||
|
||||
HEADER: o_tdata <= {i_tdata[63:48], chdr_payload_lines,
|
||||
set_sid ? {i_tdata[15:0], my_newhome[15:0]}:i_tdata[31:0]};
|
||||
TIME: o_tdata <= i_tdata;
|
||||
|
||||
|
||||
REG_STATE: o_tdata <= {imag0,real0,imag1, real1, 16'b0};
|
||||
|
||||
LINE_EVEN_ONE: o_tdata <= {imag0_out, real0_out, imag1_out, real1_out, imag0, real0[11:8]};
|
||||
LINE_ODD_TWO: o_tdata <= {real0_out[7:0], imag1_out, real1_out, imag0, real0,imag1[11:4]};
|
||||
LINE_ODD_ZERO: o_tdata <= {imag1_out[3:0], real1_out, imag0, real0, imag1, real1};
|
||||
|
||||
default : o_tdata <= i_tdata;
|
||||
endcase
|
||||
|
||||
assign o_tvalid =((in_exline) || (state != REG_STATE & i_tvalid) || (i_tlast & i_tvalid & !needs_exline));
|
||||
assign i_tready = (o_tready & !in_exline)||(state == REG_STATE && !i_tlast);
|
||||
assign o_tlast = (needs_exline)? in_exline: i_tlast;
|
||||
|
||||
|
||||
|
||||
endmodule
|
||||
@@ -0,0 +1,165 @@
|
||||
//Purpose: to test 8 to 16 converter
|
||||
`timescale 1ns/1ps
|
||||
|
||||
module chdr_16sc_to_12sc_tb();
|
||||
|
||||
reg clk = 0;
|
||||
reg reset = 1;
|
||||
//generate clock
|
||||
always #10 clk = ~clk;
|
||||
|
||||
initial $dumpfile("chdr_16sc_to_12sc_tb.vcd");
|
||||
initial $dumpvars(0,chdr_16sc_to_12sc_tb);
|
||||
|
||||
//tells when to finish
|
||||
initial
|
||||
begin
|
||||
#50 reset = 0;
|
||||
#50000;
|
||||
$finish;
|
||||
end
|
||||
|
||||
//setting registers and wire
|
||||
reg [63:0] i_tdata;
|
||||
reg i_tlast = 0;
|
||||
reg i_tvalid = 0;
|
||||
wire i_tready ;
|
||||
reg [7:0] set_addr;
|
||||
reg [31:0] set_data;
|
||||
reg set_stb;
|
||||
|
||||
|
||||
wire [63:0] o_tdata;
|
||||
wire o_tlast;
|
||||
|
||||
wire o_tvalid;
|
||||
reg o_tready;
|
||||
|
||||
chdr_16sc_to_12sc #(.BASE(89))dut
|
||||
(.clk(clk), .reset(reset),
|
||||
.set_data(set_data), .set_stb(set_stb), .set_addr(set_addr),
|
||||
.i_tdata(i_tdata), .i_tlast(i_tlast), .i_tvalid(i_tvalid), .i_tready(i_tready),
|
||||
.o_tdata(o_tdata), .o_tlast(o_tlast), .o_tvalid(o_tvalid), .o_tready(o_tready), .debug());
|
||||
|
||||
//if you want to feed a bigger input change array sizes here
|
||||
|
||||
reg [63:0] data[0:7];
|
||||
initial $readmemh("from16_to_x.hex", data);
|
||||
|
||||
//test packet loop
|
||||
task test_packet;
|
||||
input [15:0] len;
|
||||
input [31:0] sid;
|
||||
reg [1:0] index;
|
||||
|
||||
begin
|
||||
index <= 0;
|
||||
@(posedge clk) ;
|
||||
//send header
|
||||
i_tdata = {1'b0, 1'b0, 1'b1, 1'b0, 12'h0, len + 16'd16,sid};
|
||||
i_tvalid <= 1;
|
||||
i_tlast <= 0;
|
||||
@(posedge clk);
|
||||
while (i_tready != 1)
|
||||
@(posedge clk);
|
||||
i_tdata <= {64'b0};
|
||||
@(posedge clk);
|
||||
while (i_tready != 1)
|
||||
@(posedge clk);
|
||||
|
||||
//-1 for last bit accounting
|
||||
repeat (len[15:3] + (len[2]|len[1]|len[0]) - 1)
|
||||
begin
|
||||
i_tdata <= {data[index]};
|
||||
index <= index+1;
|
||||
//while (i_tready != 1)
|
||||
//@(posedge clk);
|
||||
@(posedge clk);
|
||||
while (i_tready != 1)
|
||||
@(posedge clk);
|
||||
|
||||
end
|
||||
i_tlast <= 1'b1;
|
||||
i_tdata <= {data[index]};
|
||||
|
||||
@(posedge clk);
|
||||
while (i_tready != 1)
|
||||
@(posedge clk);
|
||||
|
||||
i_tvalid <= 0;
|
||||
end
|
||||
endtask // test_packet
|
||||
|
||||
//test_destination loop
|
||||
|
||||
task test_destination;
|
||||
input enable;
|
||||
input [15:0] dest_home;
|
||||
|
||||
|
||||
begin
|
||||
@(posedge clk);
|
||||
|
||||
set_data <= {enable,dest_home};
|
||||
set_addr <= 89;
|
||||
set_stb <= 1;
|
||||
|
||||
@(posedge clk);
|
||||
set_stb <= 0;
|
||||
end
|
||||
endtask
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//main loop
|
||||
initial
|
||||
begin
|
||||
i_tvalid <= 0;
|
||||
o_tready <= 1;
|
||||
|
||||
i_tdata <= 0;
|
||||
|
||||
@(negedge reset);
|
||||
@(posedge clk);
|
||||
@(posedge clk);
|
||||
|
||||
//end on line one
|
||||
//1
|
||||
test_destination(1,16'hFEED);
|
||||
test_packet(4, 32'hDEAD_BEEF);
|
||||
//2
|
||||
test_destination(1,16'hFEED);
|
||||
test_packet(8, 32'hDEAD_BEEF);
|
||||
//3
|
||||
test_destination(1,16'hFEED);
|
||||
test_packet(12, 32'hDEAD_BEEF);
|
||||
//4
|
||||
|
||||
test_destination(1,16'hFEED);
|
||||
test_packet(16, 32'hDEAD_BEEF);
|
||||
//5
|
||||
test_destination(1,16'hFEED);
|
||||
test_packet(20, 32'hDEAD_BEEF);
|
||||
//6
|
||||
test_destination(1,16'hFEED);
|
||||
test_packet(24, 32'hDEAD_BEEF);
|
||||
|
||||
//end on line two
|
||||
|
||||
//7
|
||||
|
||||
test_destination(1,16'hFEED);
|
||||
test_packet(28, 32'hDEAD_BEEF);
|
||||
//8
|
||||
|
||||
test_destination(1,16'hFEED);
|
||||
test_packet(32, 32'hDEAD_BEEF);
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
endmodule
|
||||
@@ -0,0 +1,138 @@
|
||||
//
|
||||
// Copyright 2013 Ettus Research LLC
|
||||
//
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
module chdr_16sc_to_32f
|
||||
#(parameter BASE=0)
|
||||
( input clk, input reset, input set_stb, input [7:0] set_addr,
|
||||
input [31:0] set_data,
|
||||
input [63:0] i_tdata,
|
||||
input i_tlast,
|
||||
input i_tvalid,
|
||||
output i_tready,
|
||||
|
||||
|
||||
output reg [63:0] o_tdata,
|
||||
output o_tlast,
|
||||
output o_tvalid,
|
||||
input o_tready,
|
||||
|
||||
output [31:0] debug
|
||||
);
|
||||
|
||||
|
||||
wire [31:0] s0_real;
|
||||
wire [31:0] s0_imag;
|
||||
wire [31:0] s1_real;
|
||||
wire [31:0] s1_imag;
|
||||
|
||||
|
||||
wire chdr_has_hdr = 1'b1;
|
||||
wire chdr_has_time = i_tdata[61];
|
||||
wire chdr_has_tlr = 1'b0;
|
||||
|
||||
|
||||
//chdr length calculations
|
||||
|
||||
wire [15:0] chdr_header_lines = chdr_has_time? 16:8;
|
||||
wire [15:0] samples = ((i_tdata[47:32] - chdr_header_lines) << 1);
|
||||
wire [15:0] i_samples = (i_tdata[47:32] - chdr_header_lines);
|
||||
|
||||
|
||||
wire [15:0] chdr_payload_lines = samples + chdr_header_lines;
|
||||
|
||||
|
||||
|
||||
wire set_sid;
|
||||
wire [15:0] my_newhome;
|
||||
|
||||
setting_reg #(.my_addr(BASE), .width(17)) new_destination
|
||||
(.clk(clk), .rst(reset), .strobe(set_stb), .addr(set_addr), .in(set_data),.out({set_sid, my_newhome[15:0]}));
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//state machines
|
||||
localparam HEADER = 2'd0;//IDLE
|
||||
localparam TIME = 2'd1;
|
||||
localparam ODD = 2'd2;
|
||||
localparam EVEN = 2'd3;
|
||||
reg [1:0] state;
|
||||
reg end_on_odd;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
always @(posedge clk) begin
|
||||
|
||||
|
||||
if (reset) begin
|
||||
state <= HEADER;
|
||||
end_on_odd <= 1'b0;
|
||||
end
|
||||
else if (o_tready && i_tvalid) case(state)
|
||||
|
||||
HEADER: begin
|
||||
state <= (i_tdata[61])? TIME : ODD;
|
||||
end_on_odd <= (i_samples[2:1] == 2 || i_samples[2:1] == 1);
|
||||
end
|
||||
|
||||
TIME: begin
|
||||
state <= (i_tlast)? HEADER: ODD;
|
||||
end
|
||||
|
||||
ODD: begin
|
||||
state <= (i_tlast & end_on_odd)? HEADER:EVEN;
|
||||
end
|
||||
|
||||
EVEN: begin
|
||||
state <= (i_tlast) ? HEADER: ODD;
|
||||
end
|
||||
|
||||
default: state <= HEADER;
|
||||
endcase
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
iq_to_float #(.BITS_IN(16), .BITS_OUT(32))
|
||||
iq_to_float_imag0 (.in(i_tdata[63:48]), .out(s0_imag[31:0]));
|
||||
|
||||
iq_to_float #(.BITS_IN(16), .BITS_OUT(32))
|
||||
iq_to_float_real0 (.in(i_tdata[47:32]), .out(s0_real[31:0]));
|
||||
|
||||
iq_to_float #(.BITS_IN(16), .BITS_OUT(32))
|
||||
iq_to_float_imag1 (.in(i_tdata[31:16]), .out(s1_imag[31:0]));
|
||||
|
||||
iq_to_float #(.BITS_IN(16), .BITS_OUT(32))
|
||||
iq_to_float_real1 (.in(i_tdata[15:0]), .out(s1_real[31:0]));
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
always @(*)
|
||||
case(state)
|
||||
|
||||
HEADER: o_tdata <= {i_tdata[63:48], chdr_payload_lines,
|
||||
set_sid ? {i_tdata[15:0], my_newhome[15:0]}:i_tdata[31:0]};
|
||||
TIME: o_tdata <= i_tdata;
|
||||
ODD: o_tdata <= {s0_imag,s0_real};
|
||||
EVEN: o_tdata <= {s1_imag,s1_real};
|
||||
|
||||
|
||||
default : o_tdata = i_tdata;
|
||||
endcase
|
||||
|
||||
assign o_tvalid = i_tvalid;
|
||||
assign i_tready = o_tready && ((state != ODD) || (i_tlast && end_on_odd));
|
||||
assign o_tlast = i_tlast && ((state == EVEN) || (state == ODD && end_on_odd));
|
||||
|
||||
endmodule
|
||||
@@ -0,0 +1,145 @@
|
||||
//Purpose: to test 8 to 16 converter
|
||||
`timescale 1ns/1ps
|
||||
|
||||
module chdr_16sc_to_32f_tb();
|
||||
|
||||
reg clk = 0;
|
||||
reg reset = 1;
|
||||
//generate clock
|
||||
always #10 clk = ~clk;
|
||||
|
||||
initial $dumpfile("chdr_16sc_to_32f_tb.vcd");
|
||||
initial $dumpvars(0,chdr_16sc_to_32f_tb);
|
||||
|
||||
|
||||
//tells when to finish
|
||||
initial
|
||||
begin
|
||||
#50 reset = 0;
|
||||
#50000;
|
||||
$finish;
|
||||
end
|
||||
|
||||
//setting registers and wire
|
||||
reg [63:0] i_tdata;
|
||||
reg i_tlast = 0;
|
||||
reg i_tvalid = 0;
|
||||
wire i_tready ;
|
||||
reg [7:0] set_addr;
|
||||
reg [31:0] set_data;
|
||||
reg set_stb;
|
||||
|
||||
|
||||
wire [63:0] o_tdata;
|
||||
wire o_tlast;
|
||||
|
||||
wire o_tvalid;
|
||||
reg o_tready;
|
||||
|
||||
chdr_16sc_to_32f #(.BASE(89))dut
|
||||
(.clk(clk), .reset(reset),
|
||||
.set_data(set_data), .set_stb(set_stb), .set_addr(set_addr),
|
||||
.i_tdata(i_tdata), .i_tlast(i_tlast), .i_tvalid(i_tvalid), .i_tready(i_tready),
|
||||
.o_tdata(o_tdata), .o_tlast(o_tlast), .o_tvalid(o_tvalid), .o_tready(o_tready), .debug());
|
||||
|
||||
|
||||
//change [15:0] to whatever amount of samples you want to test. however float to iq was tested thouroughly independently. so it works
|
||||
reg [15:0]data[0:15];
|
||||
initial $readmemh("iq_to_float_input.txt", data);
|
||||
|
||||
//test packet loop
|
||||
task test_packet;
|
||||
input [15:0] len;
|
||||
input [31:0] sid;
|
||||
reg [3:0] index;
|
||||
|
||||
begin
|
||||
|
||||
index <= 0;
|
||||
|
||||
|
||||
@(posedge clk);
|
||||
//send header
|
||||
i_tdata <= {1'b0, 1'b0, 1'b1, 1'b0, 12'h0, (len + 16'd16),sid};
|
||||
i_tvalid <= 1;
|
||||
i_tlast <= 0;
|
||||
|
||||
@(posedge clk);
|
||||
while (i_tready != 1)
|
||||
@(posedge clk);
|
||||
i_tdata <= {64'b0};
|
||||
|
||||
@(posedge clk);
|
||||
while (i_tready != 1)
|
||||
@(posedge clk);
|
||||
//-1 for last bit accounting
|
||||
repeat (len[15:3] + (len[2]|len[1]|len[0])-1)
|
||||
begin
|
||||
i_tdata <= {data[index], data[index+1], data[index+2], data[index+3]};
|
||||
index <= index+4;
|
||||
|
||||
@(posedge clk);
|
||||
while (i_tready != 1)
|
||||
@(posedge clk);
|
||||
end
|
||||
i_tlast <= 1'b1;
|
||||
i_tdata <= {data[index], data[index+1], data[index+2], data[index+3]};
|
||||
|
||||
|
||||
@(posedge clk);
|
||||
while (i_tready != 1)
|
||||
@(posedge clk);
|
||||
i_tvalid <= 0;
|
||||
end
|
||||
endtask // test_packet
|
||||
|
||||
//test_destination loop
|
||||
|
||||
task test_destination;
|
||||
input enable;
|
||||
input [15:0] dest_home;
|
||||
|
||||
|
||||
begin
|
||||
@(posedge clk);
|
||||
|
||||
set_data <= {enable,dest_home};
|
||||
set_addr <= 89;
|
||||
set_stb <= 1;
|
||||
|
||||
@(posedge clk);
|
||||
set_stb <= 0;
|
||||
end
|
||||
endtask
|
||||
|
||||
//main loop
|
||||
initial
|
||||
begin
|
||||
i_tvalid <= 0;
|
||||
o_tready <= 1;
|
||||
|
||||
i_tdata <= 0;
|
||||
|
||||
@(negedge reset);
|
||||
@(posedge clk);
|
||||
@(posedge clk);
|
||||
|
||||
|
||||
test_destination(1,16'hFEED);
|
||||
test_packet(2, 32'hDEAD_BEEF);
|
||||
|
||||
test_destination(1,16'hFEED);
|
||||
test_packet(4, 32'hDEAD_BEEF);
|
||||
|
||||
test_destination(1,16'hFEED);
|
||||
test_packet(6, 32'hDEAD_BEEF);
|
||||
|
||||
test_destination(1,16'hFEED);
|
||||
test_packet(8, 32'hDEAD_BEEF);
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
endmodule
|
||||
@@ -0,0 +1,186 @@
|
||||
module chdr_16sc_to_8sc
|
||||
#(parameter BASE=0)
|
||||
(input clk, input reset,
|
||||
input set_stb, input [7:0] set_addr, input [31:0] set_data,
|
||||
//input side of device
|
||||
input [63:0] i_tdata,
|
||||
input i_tlast,
|
||||
input i_tvalid,
|
||||
output i_tready,
|
||||
//output side of device
|
||||
output reg [63:0] o_tdata,
|
||||
output o_tlast,
|
||||
output o_tvalid,
|
||||
input o_tready,
|
||||
|
||||
output [31:0] debug
|
||||
);
|
||||
|
||||
//pipeline register
|
||||
reg [63:0] hold_tdata;
|
||||
//bit assignments
|
||||
wire chdr_has_hdr = 1'b1;
|
||||
wire chdr_has_time = i_tdata[61];
|
||||
wire chdr_has_tlr = 1'b0;
|
||||
|
||||
wire [7:0] rounded_i1;
|
||||
wire [7:0] rounded_q1;
|
||||
wire [7:0] rounded_i0;
|
||||
wire [7:0] rounded_q0;
|
||||
|
||||
wire [7:0] rounded_i2;
|
||||
wire [7:0] rounded_q2;
|
||||
wire [7:0] rounded_i3;
|
||||
wire [7:0] rounded_q3;
|
||||
|
||||
//chdr length calculations
|
||||
wire [15:0] chdr_header_lines8 = chdr_has_time? 16 : 8;
|
||||
|
||||
wire [15:0] chdr_almost_payload_lines8 = ((i_tdata[47:32] - chdr_header_lines8) >> 1);
|
||||
|
||||
wire [15:0] chdr_payload_lines8 = chdr_almost_payload_lines8 + chdr_header_lines8;
|
||||
wire [15:0] my_newhome;
|
||||
|
||||
wire set_sid;
|
||||
|
||||
setting_reg #(.my_addr(BASE), .width(17)) new_destination
|
||||
(.clk(clk), .rst(reset), .strobe(set_stb), .addr(set_addr), .in(set_data),
|
||||
.out({set_sid, my_newhome[15:0]}));
|
||||
|
||||
localparam HEADER = 2'd0;//IDLE
|
||||
localparam TIME = 2'd1;
|
||||
localparam ODD = 2'd2;
|
||||
localparam EVEN = 2'd3;
|
||||
|
||||
|
||||
reg [1:0] state;
|
||||
|
||||
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (reset) begin
|
||||
state <= HEADER;
|
||||
hold_tdata <= 0;
|
||||
end
|
||||
else case(state)
|
||||
|
||||
HEADER: begin
|
||||
if (i_tvalid && o_tready) begin
|
||||
state <= (i_tdata[61])? TIME : ODD;
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
TIME: begin
|
||||
if (i_tvalid && o_tready) begin
|
||||
state <= (i_tlast)? HEADER: ODD;
|
||||
hold_tdata <= i_tdata;
|
||||
end
|
||||
end
|
||||
|
||||
ODD: begin
|
||||
if (i_tvalid && o_tready) begin
|
||||
state <= (i_tlast)? HEADER: EVEN;
|
||||
hold_tdata <= i_tdata;
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
EVEN: begin
|
||||
if (i_tvalid && o_tready)
|
||||
state <= (i_tlast) ? HEADER: ODD;
|
||||
hold_tdata <= i_tdata;
|
||||
|
||||
end
|
||||
|
||||
default: state <= HEADER;
|
||||
|
||||
endcase
|
||||
end
|
||||
|
||||
//assign 8 bit i and q signals from this line and last
|
||||
|
||||
//new data processing
|
||||
round #(.bits_in(16),
|
||||
.bits_out(8))
|
||||
round_i2
|
||||
(.in(i_tdata[63:48]),
|
||||
.out(rounded_i2[7:0])
|
||||
);
|
||||
|
||||
round #(.bits_in(16),
|
||||
.bits_out(8))
|
||||
round_q2
|
||||
(.in(i_tdata[47:32]),
|
||||
.out(rounded_q2[7:0])
|
||||
);
|
||||
|
||||
round #(.bits_in(16),
|
||||
.bits_out(8))
|
||||
round_i3
|
||||
(.in(i_tdata[31:16]),
|
||||
.out(rounded_i3[7:0])
|
||||
);
|
||||
|
||||
round #(.bits_in(16),
|
||||
.bits_out(8))
|
||||
round_q3
|
||||
(.in(i_tdata[15:0]),
|
||||
.out(rounded_q3[7:0])
|
||||
);
|
||||
|
||||
// old data processing
|
||||
round #(.bits_in(16),
|
||||
.bits_out(8))
|
||||
round_i0(.in(hold_tdata[63:48]), .out(rounded_i0[7:0])
|
||||
);
|
||||
|
||||
round #(.bits_in(16),
|
||||
.bits_out(8))
|
||||
round_q0
|
||||
(.in(hold_tdata[47:32]),
|
||||
.out(rounded_q0[7:0])
|
||||
);
|
||||
|
||||
round #(.bits_in(16),
|
||||
.bits_out(8))
|
||||
round_i1
|
||||
(.in(hold_tdata[31:16]),
|
||||
.out(rounded_i1[7:0])
|
||||
);
|
||||
|
||||
round #(.bits_in(16),
|
||||
.bits_out(8))
|
||||
round_q1
|
||||
(.in(hold_tdata[15:0]),
|
||||
.out(rounded_q1[7:0])
|
||||
);
|
||||
|
||||
// main mux
|
||||
always @(*)
|
||||
case(state)
|
||||
HEADER: o_tdata = {i_tdata[63:48], chdr_payload_lines8,
|
||||
set_sid ? {i_tdata[15:0], my_newhome[15:0]}:i_tdata[31:0]};
|
||||
TIME: o_tdata = i_tdata;
|
||||
ODD: o_tdata = {rounded_i2, rounded_q2, rounded_i3, rounded_q3,rounded_i0, rounded_q0, rounded_i1, rounded_q1};
|
||||
EVEN: o_tdata = {rounded_i0, rounded_q0, rounded_i1, rounded_q1,rounded_i2, rounded_q2, rounded_i3, rounded_q3};
|
||||
default : o_tdata = i_tdata;
|
||||
endcase
|
||||
|
||||
assign o_tvalid = i_tvalid && (state != ODD || i_tlast);
|
||||
assign i_tready = o_tready || (state == ODD && !i_tlast);
|
||||
assign o_tlast = i_tlast;
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
`timescale 1ns/1ps
|
||||
|
||||
module chdr_16sc_to_8sc_tb();
|
||||
|
||||
reg clk = 0;
|
||||
reg reset = 1;
|
||||
//generate clock
|
||||
always #10 clk = ~clk;
|
||||
|
||||
initial $dumpfile("chdr_16sc_to_8sc_tb.vcd");
|
||||
initial $dumpvars(0,chdr_16sc_to_8sc_tb);
|
||||
|
||||
//tells when to finish
|
||||
initial
|
||||
begin
|
||||
#50 reset = 0;
|
||||
#50000;
|
||||
$finish;
|
||||
end
|
||||
|
||||
//setting registers and wire
|
||||
reg [63:0] i_tdata;
|
||||
reg i_tlast = 0;
|
||||
reg i_tvalid = 0;
|
||||
wire i_tready;
|
||||
|
||||
wire [63:0] o_tdata;
|
||||
wire o_tlast;
|
||||
|
||||
wire o_tvalid;
|
||||
reg o_tready;
|
||||
|
||||
reg [7:0] set_addr;
|
||||
reg [31:0] set_data;
|
||||
reg set_stb;
|
||||
|
||||
chdr_16sc_to_8sc #(.BASE(89))dut
|
||||
(.clk(clk), .reset(reset),
|
||||
.set_data(set_data), .set_stb(set_stb), .set_addr(set_addr),
|
||||
.i_tdata(i_tdata), .i_tlast(i_tlast), .i_tvalid(i_tvalid), .i_tready(i_tready),
|
||||
.o_tdata(o_tdata), .o_tlast(o_tlast), .o_tvalid(o_tvalid), .o_tready(o_tready), .debug());
|
||||
|
||||
reg [63:0] data[0:7];
|
||||
initial $readmemh("from16_to_x.hex", data);
|
||||
task test_packet;
|
||||
input [15:0] len;
|
||||
input [31:0] sid;
|
||||
reg [4:0] index;
|
||||
|
||||
begin
|
||||
|
||||
index <= 0;
|
||||
@(posedge clk) ;
|
||||
//send header
|
||||
i_tdata <= {4'h2 /* flags */ , 12'h0 /* seqnum */, (len + 16'd16), sid};
|
||||
i_tvalid <= 1;
|
||||
i_tlast <= 0;
|
||||
@(posedge clk);
|
||||
while (i_tready != 1)
|
||||
@(posedge clk);
|
||||
i_tdata <= {64'b0};
|
||||
@(posedge clk);
|
||||
while (i_tready != 1)
|
||||
@(posedge clk);
|
||||
//-1 for last bit accounting
|
||||
repeat (len[15:3] + (len[2]|len[1]|len[0])-1)
|
||||
begin
|
||||
i_tdata <= {data[index]};
|
||||
index <= index+1;
|
||||
@(posedge clk);
|
||||
while (i_tready != 1)
|
||||
@(posedge clk);
|
||||
end
|
||||
i_tlast <= 1'b1;
|
||||
i_tdata <= {data[index]};
|
||||
@(posedge clk);
|
||||
while (i_tready != 1)
|
||||
@(posedge clk);
|
||||
i_tvalid <= 0;
|
||||
end
|
||||
endtask // test_packet
|
||||
|
||||
task test_destination;
|
||||
input enable;
|
||||
input [15:0] dest_home;
|
||||
|
||||
|
||||
begin
|
||||
@(posedge clk);
|
||||
|
||||
set_data <= {enable,dest_home};
|
||||
set_addr <= 89;
|
||||
set_stb <= 1;
|
||||
|
||||
@(posedge clk);
|
||||
set_stb <= 0;
|
||||
end
|
||||
endtask
|
||||
|
||||
|
||||
initial
|
||||
begin
|
||||
i_tvalid <= 0;
|
||||
o_tready <= 1;
|
||||
|
||||
i_tdata <= 0;
|
||||
|
||||
@(negedge reset);
|
||||
@(posedge clk);
|
||||
@(posedge clk);
|
||||
|
||||
test_destination(1,16'hFEED);
|
||||
test_packet(2, 32'hDEAD_BEEF);
|
||||
|
||||
test_destination(1,16'hFEED);
|
||||
test_packet(4, 32'hDEAD_BEEF);
|
||||
|
||||
test_destination(1,16'hFEED);
|
||||
test_packet(6, 32'hDEAD_BEEF);
|
||||
|
||||
test_destination(1,16'hFEED);
|
||||
test_packet(8, 32'hDEAD_BEEF);
|
||||
|
||||
test_destination(1,16'hFEED);
|
||||
test_packet(10, 32'hDEAD_BEEF);
|
||||
|
||||
test_destination(1,16'hFEED);
|
||||
test_packet(12, 32'hDEAD_BEEF);
|
||||
|
||||
test_destination(1,16'hFEED);
|
||||
test_packet(14, 32'hDEAD_BEEF);
|
||||
|
||||
test_destination(1,16'hFEED);
|
||||
test_packet(16, 32'hDEAD_BEEF);
|
||||
|
||||
test_destination(1,16'hFEED);
|
||||
test_packet(32, 32'hDEAD_BEEF);
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
endmodule
|
||||
@@ -0,0 +1,105 @@
|
||||
//
|
||||
// Copyright 2013 Ettus Research LLC
|
||||
//
|
||||
|
||||
|
||||
//selectable conversion chain
|
||||
|
||||
module chdr_16sc_to_xxxx_chain
|
||||
#(parameter BASE = 0)
|
||||
(input clk, input reset,
|
||||
|
||||
input set_stb, input [7:0] set_addr, input [31:0] set_data,
|
||||
|
||||
input [63:0] i_tdata,
|
||||
input i_tlast,
|
||||
input i_tvalid,
|
||||
output i_tready,
|
||||
|
||||
output [63:0] o_tdata,
|
||||
output o_tlast,
|
||||
output o_tvalid,
|
||||
input o_tready,
|
||||
|
||||
output [31:0] debug
|
||||
);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Demux destination setting register - safe switch for demux
|
||||
//------------------------------------------------------------------
|
||||
wire [1:0] demux_dst;
|
||||
setting_reg #(.my_addr(BASE), .width(2), .at_reset(2'b00)) sr_demux_dst
|
||||
(.clk(clk),.rst(reset),
|
||||
.strobe(set_stb),.addr(set_addr), .in(set_data),
|
||||
.out({demux_dst}),.changed());
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// All FIFO IO lines
|
||||
//------------------------------------------------------------------
|
||||
wire [63:0] i0_tdata; wire i0_tlast, i0_tvalid, i0_tready;
|
||||
wire [63:0] i1_tdata; wire i1_tlast, i1_tvalid, i1_tready;
|
||||
wire [63:0] i2_tdata; wire i2_tlast, i2_tvalid, i2_tready;
|
||||
wire [63:0] i3_tdata; wire i3_tlast, i3_tvalid, i3_tready;
|
||||
|
||||
wire [63:0] o0_tdata; wire o0_tlast, o0_tvalid, o0_tready;
|
||||
wire [63:0] o1_tdata; wire o1_tlast, o1_tvalid, o1_tready;
|
||||
wire [63:0] o2_tdata; wire o2_tlast, o2_tvalid, o2_tready;
|
||||
wire [63:0] o3_tdata; wire o3_tlast, o3_tvalid, o3_tready;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Instantiate converters
|
||||
//------------------------------------------------------------------
|
||||
assign {o0_tdata, o0_tlast, o0_tvalid, i0_tready} = {i0_tdata, i0_tlast, i0_tvalid, o0_tready};
|
||||
//assign {o1_tdata, o1_tlast, o1_tvalid, i1_tready} = {i1_tdata, i1_tlast, i1_tvalid, o1_tready};
|
||||
//assign {o2_tdata, o2_tlast, o2_tvalid, i2_tready} = {i2_tdata, i2_tlast, i2_tvalid, o2_tready};
|
||||
//assign {o3_tdata, o3_tlast, o3_tvalid, i3_tready} = {i3_tdata, i3_tlast, i3_tvalid, o3_tready};
|
||||
|
||||
//leave path 0 for pass through
|
||||
|
||||
chdr_16sc_to_12sc
|
||||
#(.BASE(89)) convert_16sc_to_12sc
|
||||
|
||||
(.clk(clk), .reset(reset),.set_data(0), .set_stb(0), .set_addr(0),
|
||||
.i_tdata(i1_tdata), .i_tlast(i1_tlast), .i_tvalid(i1_tvalid), .i_tready(i1_tready),
|
||||
.o_tdata(o1_tdata), .o_tlast(o1_tlast), .o_tvalid(o1_tvalid), .o_tready(o1_tready)
|
||||
);
|
||||
|
||||
chdr_16sc_to_32f
|
||||
#(.BASE(89)) convert_16sc_to_32f
|
||||
|
||||
(.clk(clk), .reset(reset),.set_data(0), .set_stb(0), .set_addr(0),
|
||||
.i_tdata(i2_tdata), .i_tlast(i2_tlast), .i_tvalid(i2_tvalid), .i_tready(i2_tready),
|
||||
.o_tdata(o2_tdata), .o_tlast(o2_tlast), .o_tvalid(o2_tvalid), .o_tready(o2_tready)
|
||||
);
|
||||
|
||||
chdr_16sc_to_8sc #(.BASE(89)) convert_16sc_to_8sc
|
||||
(.clk(clk), .reset(reset),.set_data(0), .set_stb(0), .set_addr(0),
|
||||
.i_tdata(i3_tdata), .i_tlast(i3_tlast), .i_tvalid(i3_tvalid), .i_tready(i3_tready),
|
||||
.o_tdata(o3_tdata), .o_tlast(o3_tlast), .o_tvalid(o3_tvalid), .o_tready(o3_tready)
|
||||
);
|
||||
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Ingress and Outgress muxing
|
||||
//------------------------------------------------------------------
|
||||
//assign {o_tdata, o_tlast, o_tvalid, i_tready} = {i_tdata, i_tlast, i_tvalid, o_tready};
|
||||
///*
|
||||
axi_demux4 #(.ACTIVE_CHAN(4'b1111), .WIDTH(64), .BUFFER(1)) demux_pack_chain
|
||||
(.clk(clk), .reset(reset), .clear(1'b0),
|
||||
.header(), .dest(demux_dst),
|
||||
.i_tdata(i_tdata), .i_tlast(i_tlast), .i_tvalid(i_tvalid), .i_tready(i_tready),
|
||||
.o0_tdata(i0_tdata), .o0_tlast(i0_tlast), .o0_tvalid(i0_tvalid), .o0_tready(i0_tready),
|
||||
.o1_tdata(i1_tdata), .o1_tlast(i1_tlast), .o1_tvalid(i1_tvalid), .o1_tready(i1_tready),
|
||||
.o2_tdata(i2_tdata), .o2_tlast(i2_tlast), .o2_tvalid(i2_tvalid), .o2_tready(i2_tready),
|
||||
.o3_tdata(i3_tdata), .o3_tlast(i3_tlast), .o3_tvalid(i3_tvalid), .o3_tready(i3_tready));
|
||||
|
||||
axi_mux4 #(.PRIO(1), .WIDTH(64), .BUFFER(1)) mux_pack_chain
|
||||
(.clk(clk), .reset(reset), .clear(1'b0),
|
||||
.i0_tdata(o0_tdata), .i0_tlast(o0_tlast), .i0_tvalid(o0_tvalid), .i0_tready(o0_tready),
|
||||
.i1_tdata(o1_tdata), .i1_tlast(o1_tlast), .i1_tvalid(o1_tvalid), .i1_tready(o1_tready),
|
||||
.i2_tdata(o2_tdata), .i2_tlast(o2_tlast), .i2_tvalid(o2_tvalid), .i2_tready(o2_tready),
|
||||
.i3_tdata(o3_tdata), .i3_tlast(o3_tlast), .i3_tvalid(o3_tvalid), .i3_tready(o3_tready),
|
||||
.o_tdata(o_tdata), .o_tlast(o_tlast), .o_tvalid(o_tvalid), .o_tready(o_tready));
|
||||
//*/
|
||||
|
||||
endmodule //chdr_16sc_to_xxxx_chain
|
||||
@@ -0,0 +1,142 @@
|
||||
//
|
||||
// Copyright 2013 Ettus Research LLC
|
||||
//
|
||||
|
||||
|
||||
|
||||
module chdr_32f_to_16sc
|
||||
#(parameter BASE=0)
|
||||
(input set_stb, input [7:0] set_addr, input [31:0] set_data,
|
||||
|
||||
input clk, input reset,
|
||||
input [63:0] i_tdata,
|
||||
input i_tlast,
|
||||
input i_tvalid,
|
||||
output i_tready,
|
||||
|
||||
output reg [63:0] o_tdata,
|
||||
output o_tlast,
|
||||
output o_tvalid,
|
||||
input o_tready,
|
||||
|
||||
output [31:0] debug
|
||||
);
|
||||
|
||||
|
||||
wire chdr_has_hdr = 1'b1;
|
||||
wire chdr_has_time = i_tdata[61];
|
||||
wire chdr_has_tlr = 1'b0;
|
||||
|
||||
wire [15:0] s0_imag;
|
||||
wire [15:0] s0_real;
|
||||
wire [15:0] s1_imag;
|
||||
wire [15:0] s1_real;
|
||||
|
||||
|
||||
reg [15:0] imag0;
|
||||
reg [15:0] real0;
|
||||
wire [15:0] imag1;
|
||||
wire [15:0] real1;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//chdr length calculations
|
||||
wire [15:0] chdr_header_lines = chdr_has_time? 16 : 8;
|
||||
|
||||
wire [15:0] samples = ((i_tdata[47:32] - chdr_header_lines) >> 1);
|
||||
|
||||
wire [15:0] chdr_payload_lines = samples + chdr_header_lines;
|
||||
|
||||
|
||||
wire set_sid;
|
||||
wire [15:0] my_newhome;
|
||||
|
||||
setting_reg #(.my_addr(BASE), .width(17)) new_destination
|
||||
(.clk(clk), .rst(reset), .strobe(set_stb), .addr(set_addr), .in(set_data),
|
||||
.out({set_sid, my_newhome[15:0]}));
|
||||
|
||||
|
||||
|
||||
localparam HEADER = 2'd0;//IDLE
|
||||
localparam TIME = 2'd1;
|
||||
localparam ODD = 2'd2;
|
||||
localparam EVEN = 2'd3;
|
||||
|
||||
reg [1:0] state;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (reset) begin
|
||||
state <= HEADER;
|
||||
|
||||
end
|
||||
else if (i_tvalid && i_tready) case(state)
|
||||
|
||||
HEADER: begin
|
||||
if (!i_tlast) state <= (i_tdata[61])? TIME : ODD;
|
||||
end
|
||||
|
||||
TIME: begin
|
||||
state <= (i_tlast)? HEADER: ODD;
|
||||
end
|
||||
|
||||
ODD: begin
|
||||
state <= (i_tlast)? HEADER: EVEN;
|
||||
end
|
||||
|
||||
EVEN: begin
|
||||
state <= (i_tlast)? HEADER: ODD;
|
||||
end
|
||||
|
||||
default: state <= HEADER;
|
||||
endcase
|
||||
end // always @ (posedge clk)
|
||||
|
||||
//hold data after each input transfer
|
||||
reg [63:0] hold_tdata;
|
||||
always @(posedge clk) begin
|
||||
if (i_tvalid && i_tready) hold_tdata <= i_tdata;
|
||||
end
|
||||
|
||||
|
||||
|
||||
float_to_iq #(.BITS_IN(32),.BITS_OUT(16))
|
||||
float_to_iq_imag0 (.in(i_tdata[63:32]),.out(s1_imag[15:0]));
|
||||
|
||||
float_to_iq #(.BITS_IN(32),.BITS_OUT(16))
|
||||
float_to_iq_real0 (.in(i_tdata[31:0]),.out(s1_real[15:0]));
|
||||
|
||||
|
||||
float_to_iq #(.BITS_IN(32),.BITS_OUT(16))
|
||||
float_to_iq_imag1 (.in(hold_tdata[63:32]),.out(s0_imag[15:0]));
|
||||
|
||||
|
||||
float_to_iq #(.BITS_IN(32),.BITS_OUT(16))
|
||||
float_to_iq_real1 (.in(hold_tdata[31:0]),.out(s0_real[15:0]));
|
||||
|
||||
|
||||
|
||||
|
||||
always @(*)
|
||||
case(state)
|
||||
|
||||
HEADER: o_tdata <= {i_tdata[63:48], chdr_payload_lines,
|
||||
set_sid ? {i_tdata[15:0], my_newhome[15:0]}:i_tdata[31:0]};
|
||||
TIME: o_tdata <= i_tdata;
|
||||
ODD: o_tdata <= {s1_imag, s1_real, 32'h0};
|
||||
EVEN: o_tdata <= {s0_imag, s0_real, s1_imag, s1_real};
|
||||
|
||||
default : o_tdata = i_tdata;
|
||||
endcase
|
||||
|
||||
assign o_tvalid = i_tvalid && (state != ODD || i_tlast);
|
||||
assign i_tready = o_tready || (state == ODD && !i_tlast);
|
||||
assign o_tlast = i_tlast;
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
`timescale 1ns/1ps
|
||||
|
||||
module chdr_32f_to_16sc_tb();
|
||||
|
||||
reg clk = 0;
|
||||
reg reset = 1;
|
||||
//generate clock
|
||||
always #10 clk = ~clk;
|
||||
|
||||
initial $dumpfile("chdr_32f_to_16sc_tb.vcd");
|
||||
initial $dumpvars(0,chdr_32f_to_16sc_tb);
|
||||
|
||||
|
||||
|
||||
//tells when to finish
|
||||
initial
|
||||
begin
|
||||
#50 reset = 0;
|
||||
#50000;
|
||||
$finish;
|
||||
end
|
||||
|
||||
//setting registers and wire
|
||||
reg [63:0] i_tdata;
|
||||
reg i_tlast = 0;
|
||||
reg i_tvalid = 0;
|
||||
wire i_tready;
|
||||
|
||||
wire [63:0] o_tdata;
|
||||
wire o_tlast;
|
||||
|
||||
wire o_tvalid;
|
||||
reg o_tready;
|
||||
|
||||
reg [7:0] set_addr;
|
||||
reg [31:0] set_data;
|
||||
reg set_stb;
|
||||
|
||||
chdr_32f_to_16sc #(.BASE(89))dut
|
||||
(.clk(clk), .reset(reset),
|
||||
.set_data(set_data), .set_stb(set_stb), .set_addr(set_addr),
|
||||
.i_tdata(i_tdata), .i_tlast(i_tlast), .i_tvalid(i_tvalid), .i_tready(i_tready),
|
||||
.o_tdata(o_tdata), .o_tlast(o_tlast), .o_tvalid(o_tvalid), .o_tready(o_tready), .debug());
|
||||
|
||||
|
||||
reg [31:0]data[0:7];
|
||||
initial $readmemh("iq_to_float_output.txt", data);
|
||||
|
||||
|
||||
task test_packet;
|
||||
input [15:0] len;
|
||||
input [31:0] sid;
|
||||
reg [4:0] index;
|
||||
|
||||
begin
|
||||
|
||||
index <= 0;
|
||||
|
||||
|
||||
@(posedge clk) ;
|
||||
//send header
|
||||
i_tdata <= {1'b0, 1'b0, 1'b1, 1'b0, 12'h0, (len + 16'd16), sid};
|
||||
i_tvalid <= 1;
|
||||
i_tlast <= 0;
|
||||
@(posedge clk);
|
||||
while (i_tready != 1)
|
||||
@(posedge clk);
|
||||
i_tdata <= {64'b0};
|
||||
|
||||
@(posedge clk);
|
||||
while (i_tready != 1)
|
||||
@(posedge clk);
|
||||
//-1 for last bit accounting
|
||||
repeat (len[15:3] + (len[2]|len[1]|len[0]) - 1)
|
||||
begin
|
||||
|
||||
i_tdata <= {data[index],data[index+1]};
|
||||
index <= index+2;
|
||||
|
||||
@(posedge clk);
|
||||
while (i_tready != 1)
|
||||
@(posedge clk);
|
||||
end
|
||||
|
||||
|
||||
|
||||
i_tlast <= 1'b1;
|
||||
i_tdata <= {data[index], data[index+1]};
|
||||
|
||||
|
||||
|
||||
@(posedge clk);
|
||||
while (i_tready != 1)
|
||||
@(posedge clk);
|
||||
i_tvalid <= 0;
|
||||
end
|
||||
endtask // test_packet
|
||||
|
||||
task test_destination;
|
||||
input enable;
|
||||
input [15:0] dest_home;
|
||||
|
||||
|
||||
begin
|
||||
@(posedge clk);
|
||||
|
||||
set_data <= {enable,dest_home};
|
||||
set_addr <= 89;
|
||||
set_stb <= 1;
|
||||
|
||||
@(posedge clk);
|
||||
set_stb <= 0;
|
||||
end
|
||||
endtask
|
||||
|
||||
|
||||
initial
|
||||
begin
|
||||
i_tvalid <= 0;
|
||||
o_tready <= 1;
|
||||
|
||||
i_tdata <= 0;
|
||||
|
||||
@(negedge reset);
|
||||
@(posedge clk);
|
||||
@(posedge clk);
|
||||
|
||||
|
||||
test_destination(1,16'hFEED);
|
||||
test_packet(4, 32'hDEAD_BEEF);
|
||||
|
||||
test_destination(1,16'hFEED);
|
||||
test_packet(8, 32'hDEAD_BEEF);
|
||||
|
||||
test_destination(1,16'hFEED);
|
||||
test_packet(16, 32'hDEAD_BEEF);
|
||||
|
||||
test_destination(1,16'hFEED);
|
||||
test_packet(20, 32'hDEAD_BEEF);
|
||||
|
||||
test_destination(1,16'hFEED);
|
||||
test_packet(24, 32'hDEAD_BEEF);
|
||||
|
||||
test_destination(1,16'hFEED);
|
||||
test_packet(28, 32'hDEAD_BEEF);
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
endmodule
|
||||
@@ -0,0 +1,5 @@
|
||||
7F805A6B11006792
|
||||
88990011CCDD00AA
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
module chdr_8sc_to_16sc
|
||||
#(parameter BASE=0)
|
||||
(input clk, input reset,
|
||||
input set_stb, input [7:0] set_addr, input [31:0] set_data,
|
||||
|
||||
input [63:0] i_tdata,
|
||||
input i_tlast,
|
||||
input i_tvalid,
|
||||
output i_tready,
|
||||
|
||||
output reg [63:0] o_tdata,
|
||||
output o_tlast,
|
||||
output o_tvalid,
|
||||
input o_tready,
|
||||
|
||||
output [31:0] debug
|
||||
);
|
||||
|
||||
//bit assignments
|
||||
wire chdr_has_hdr = 1'b1;
|
||||
wire chdr_has_time = i_tdata[61];
|
||||
wire chdr_has_tlr = 1'b0;
|
||||
wire set_sid;
|
||||
|
||||
//chdr length calculations
|
||||
wire [15:0] chdr_header_lines16 = chdr_has_time? 16 : 8;
|
||||
|
||||
wire [15:0] chdr_almost_payload_lines16 = ((i_tdata[47:32] - chdr_header_lines16) << 1);
|
||||
|
||||
wire [15:0] chdr_payload_lines16 = chdr_almost_payload_lines16 + chdr_header_lines16;
|
||||
|
||||
//new destination reg set
|
||||
wire [15:0] my_newhome;
|
||||
|
||||
|
||||
setting_reg #(.my_addr(BASE), .width(17)) new_destination
|
||||
(.clk(clk), .rst(reset), .strobe(set_stb), .addr(set_addr), .in(set_data),
|
||||
.out({set_sid, my_newhome[15:0]}));
|
||||
|
||||
|
||||
//state declarations
|
||||
|
||||
|
||||
localparam HEADER = 2'd0;//IDLE
|
||||
localparam TIME = 2'd1;
|
||||
localparam ODD = 2'd2;
|
||||
localparam EVEN = 2'd3;
|
||||
|
||||
reg [1:0] state;
|
||||
reg end_on_odd;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (reset) begin
|
||||
state <= HEADER;
|
||||
end_on_odd <= 1'b0;
|
||||
end
|
||||
else case(state)
|
||||
|
||||
HEADER: begin
|
||||
if (i_tvalid && o_tready) begin
|
||||
state <= (i_tdata[61])? TIME : ODD;
|
||||
end_on_odd <= (i_tdata[34:32] > 0) && (i_tdata[34:32] < 5);
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
TIME: begin
|
||||
if (i_tvalid && o_tready) begin
|
||||
|
||||
state <= (i_tlast)? HEADER: ODD;
|
||||
end
|
||||
end
|
||||
|
||||
ODD: begin
|
||||
if (i_tvalid && o_tready) begin
|
||||
state <= (i_tlast & end_on_odd) ? HEADER : EVEN;
|
||||
end
|
||||
end
|
||||
|
||||
EVEN: begin
|
||||
if (i_tvalid && o_tready)
|
||||
state <= (i_tlast) ? HEADER: ODD;
|
||||
end
|
||||
default: state <= HEADER;
|
||||
|
||||
endcase
|
||||
end
|
||||
|
||||
always @(*)
|
||||
case(state)
|
||||
HEADER: o_tdata <= {i_tdata[63:48], chdr_payload_lines16,
|
||||
set_sid ? {i_tdata[15:0], my_newhome[15:0]}:i_tdata[31:0]};
|
||||
TIME: o_tdata <= i_tdata;
|
||||
ODD: o_tdata <= {i_tdata[63:56], 8'h0, i_tdata[55:48] , 8'h0, i_tdata[47:40], 8'h0, i_tdata[39:32] , 8'h0};
|
||||
EVEN: o_tdata <= {i_tdata[31:24], 8'h0, i_tdata[23:16], 8'h0, i_tdata[15:8], 8'h0, i_tdata[7:0], 8'h0};
|
||||
|
||||
|
||||
default : o_tdata = i_tdata;
|
||||
endcase
|
||||
|
||||
assign o_tvalid = i_tvalid;
|
||||
assign i_tready = o_tready && ((state != ODD) || (i_tlast & end_on_odd));
|
||||
assign o_tlast = i_tlast && ((state == EVEN)||((state == ODD) & end_on_odd));
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
//Purpose: to test 8 to 16 converter
|
||||
`timescale 1ns/1ps
|
||||
|
||||
module chdr_8sc_to_16sc_tb();
|
||||
|
||||
reg clk = 0;
|
||||
reg reset = 1;
|
||||
//generate clock
|
||||
always #10 clk = ~clk;
|
||||
|
||||
initial $dumpfile("chdr_8sc_to_16sc_tb.vcd");
|
||||
initial $dumpvars(0,chdr_8sc_to_16sc_tb);
|
||||
|
||||
//tells when to finish
|
||||
initial
|
||||
begin
|
||||
#50 reset = 0;
|
||||
#50000;
|
||||
$finish;
|
||||
end
|
||||
|
||||
//setting registers and wire
|
||||
reg [63:0] i_tdata;
|
||||
reg i_tlast = 0;
|
||||
reg i_tvalid = 0;
|
||||
wire i_tready ;
|
||||
reg [7:0] set_addr;
|
||||
reg [31:0] set_data;
|
||||
reg set_stb;
|
||||
|
||||
|
||||
wire [63:0] o_tdata;
|
||||
wire o_tlast;
|
||||
|
||||
wire o_tvalid;
|
||||
reg o_tready;
|
||||
|
||||
chdr_8sc_to_16sc #(.BASE(89))dut
|
||||
(.clk(clk), .reset(reset),
|
||||
.set_data(set_data), .set_stb(set_stb), .set_addr(set_addr),
|
||||
.i_tdata(i_tdata), .i_tlast(i_tlast), .i_tvalid(i_tvalid), .i_tready(i_tready),
|
||||
.o_tdata(o_tdata), .o_tlast(o_tlast), .o_tvalid(o_tvalid), .o_tready(o_tready), .debug());
|
||||
|
||||
//if you want to feed a bigger input change array sizes here
|
||||
|
||||
reg [63:0] data[0:7];
|
||||
initial $readmemh("from8_to_x.hex", data);
|
||||
|
||||
//test packet loop
|
||||
task test_packet;
|
||||
input [15:0] len;
|
||||
input [31:0] sid;
|
||||
reg [1:0] index;
|
||||
|
||||
begin
|
||||
index <= 0;
|
||||
@(posedge clk) ;
|
||||
//send header
|
||||
i_tdata <= {1'b0, 1'b0, 1'b1, 1'b0, 12'h0, (len + 16'd16),sid};
|
||||
i_tvalid <= 1;
|
||||
i_tlast <= 0;
|
||||
@(posedge clk);
|
||||
while (i_tready != 1)
|
||||
@(posedge clk);
|
||||
i_tdata <= {64'b0};
|
||||
@(posedge clk);
|
||||
while (i_tready != 1)
|
||||
@(posedge clk);
|
||||
//-1 for last bit accounting
|
||||
repeat ( len[15:3] + (len[2]|len[1]|len[0]) - 1 )
|
||||
begin
|
||||
i_tdata <= {data[index]};
|
||||
index <= index+1;
|
||||
@(posedge clk);
|
||||
while (i_tready != 1)
|
||||
@(posedge clk);
|
||||
end
|
||||
i_tlast <= 1'b1;
|
||||
i_tdata <= {data[index]};
|
||||
@(posedge clk);
|
||||
while (i_tready != 1)
|
||||
@(posedge clk);
|
||||
i_tvalid <= 0;
|
||||
end
|
||||
endtask // test_packet
|
||||
|
||||
//test_destination loop
|
||||
|
||||
task test_destination;
|
||||
input enable;
|
||||
input [15:0] dest_home;
|
||||
|
||||
|
||||
begin
|
||||
@(posedge clk);
|
||||
|
||||
set_data <= {enable,dest_home};
|
||||
set_addr <= 89;
|
||||
set_stb <= 1;
|
||||
|
||||
@(posedge clk);
|
||||
set_stb <= 0;
|
||||
end
|
||||
endtask
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//main loop
|
||||
initial
|
||||
begin
|
||||
i_tvalid <= 0;
|
||||
o_tready <= 1;
|
||||
|
||||
i_tdata <= 0;
|
||||
|
||||
@(negedge reset);
|
||||
@(posedge clk);
|
||||
@(posedge clk);
|
||||
|
||||
/* Uncomment to test without changed sid
|
||||
test_destination(0,16'hFEED);
|
||||
test_packet(20, 32'hDEAD_BEEF);
|
||||
*/
|
||||
test_destination(1,16'hFEED);
|
||||
test_packet(2, 32'hDEAD_BEEF);
|
||||
#1000;
|
||||
test_packet(4, 32'hDEAD_BEEF);
|
||||
#1000;
|
||||
test_packet(6, 32'hDEAD_BEEF);
|
||||
#1000;
|
||||
test_packet(8, 32'hDEAD_BEEF);
|
||||
#1000;
|
||||
test_packet(10, 32'hDEAD_BEEF);
|
||||
#1000;
|
||||
test_packet(12, 32'hDEAD_BEEF);
|
||||
#1000;
|
||||
test_packet(14, 32'hDEAD_BEEF);
|
||||
#1000;
|
||||
test_packet(16, 32'hDEAD_BEEF);
|
||||
#1000;
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
endmodule
|
||||
@@ -0,0 +1,107 @@
|
||||
|
||||
//
|
||||
// Copyright 2013 Ettus Research LLC
|
||||
//
|
||||
|
||||
|
||||
//selectable conversion chain
|
||||
|
||||
module chdr_xxxx_to_16sc_chain
|
||||
#(parameter BASE = 0)
|
||||
(input clk, input reset,
|
||||
|
||||
input set_stb, input [7:0] set_addr, input [31:0] set_data,
|
||||
|
||||
input [63:0] i_tdata,
|
||||
input i_tlast,
|
||||
input i_tvalid,
|
||||
output i_tready,
|
||||
|
||||
output [63:0] o_tdata,
|
||||
output o_tlast,
|
||||
output o_tvalid,
|
||||
input o_tready,
|
||||
|
||||
output [31:0] debug
|
||||
);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Demux destination setting register - safe switch for demux
|
||||
//------------------------------------------------------------------
|
||||
wire [1:0] demux_dst;
|
||||
setting_reg #(.my_addr(BASE), .width(2), .at_reset(2'b00)) sr_demux_dst
|
||||
(.clk(clk),.rst(reset),
|
||||
.strobe(set_stb),.addr(set_addr), .in(set_data),
|
||||
.out({demux_dst}),.changed());
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// All FIFO IO lines
|
||||
//------------------------------------------------------------------
|
||||
wire [63:0] i0_tdata; wire i0_tlast, i0_tvalid, i0_tready;
|
||||
wire [63:0] i1_tdata; wire i1_tlast, i1_tvalid, i1_tready;
|
||||
wire [63:0] i2_tdata; wire i2_tlast, i2_tvalid, i2_tready;
|
||||
wire [63:0] i3_tdata; wire i3_tlast, i3_tvalid, i3_tready;
|
||||
|
||||
wire [63:0] o0_tdata; wire o0_tlast, o0_tvalid, o0_tready;
|
||||
wire [63:0] o1_tdata; wire o1_tlast, o1_tvalid, o1_tready;
|
||||
wire [63:0] o2_tdata; wire o2_tlast, o2_tvalid, o2_tready;
|
||||
wire [63:0] o3_tdata; wire o3_tlast, o3_tvalid, o3_tready;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Instantiate converters
|
||||
//------------------------------------------------------------------
|
||||
assign {o0_tdata, o0_tlast, o0_tvalid, i0_tready} = {i0_tdata, i0_tlast, i0_tvalid, o0_tready};
|
||||
//assign {o1_tdata, o1_tlast, o1_tvalid, i1_tready} = {i1_tdata, i1_tlast, i1_tvalid, o1_tready};
|
||||
//assign {o2_tdata, o2_tlast, o2_tvalid, i2_tready} = {i2_tdata, i2_tlast, i2_tvalid, o2_tready};
|
||||
//assign {o3_tdata, o3_tlast, o3_tvalid, i3_tready} = {i3_tdata, i3_tlast, i3_tvalid, o3_tready};
|
||||
|
||||
//leave path 0 for pass through
|
||||
|
||||
chdr_12sc_to_16sc
|
||||
#(.BASE(89)) convert_12sc_to_16sc
|
||||
|
||||
(.clk(clk), .reset(reset),.set_data(0), .set_stb(0), .set_addr(0),
|
||||
.i_tdata(i1_tdata), .i_tlast(i1_tlast), .i_tvalid(i1_tvalid), .i_tready(i1_tready),
|
||||
.o_tdata(o1_tdata), .o_tlast(o1_tlast), .o_tvalid(o1_tvalid), .o_tready(o1_tready)
|
||||
);
|
||||
|
||||
chdr_32f_to_16sc
|
||||
#(.BASE(89)) convert_32f_to_16sc
|
||||
|
||||
(.clk(clk), .reset(reset),.set_data(0), .set_stb(0), .set_addr(0),
|
||||
.i_tdata(i2_tdata), .i_tlast(i2_tlast), .i_tvalid(i2_tvalid), .i_tready(i2_tready),
|
||||
.o_tdata(o2_tdata), .o_tlast(o2_tlast), .o_tvalid(o2_tvalid), .o_tready(o2_tready)
|
||||
);
|
||||
|
||||
|
||||
chdr_8sc_to_16sc #(.BASE(89)) convert_8sc_to_16sc
|
||||
(.clk(clk), .reset(reset),.set_data(0), .set_stb(0), .set_addr(0),
|
||||
.i_tdata(i3_tdata), .i_tlast(i3_tlast), .i_tvalid(i3_tvalid), .i_tready(i3_tready),
|
||||
.o_tdata(o3_tdata), .o_tlast(o3_tlast), .o_tvalid(o3_tvalid), .o_tready(o3_tready)
|
||||
);
|
||||
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Ingress and Outgress muxing
|
||||
//------------------------------------------------------------------
|
||||
//assign {o_tdata, o_tlast, o_tvalid, i_tready} = {i_tdata, i_tlast, i_tvalid, o_tready};
|
||||
///*
|
||||
axi_demux4 #(.ACTIVE_CHAN(4'b1111), .WIDTH(64), .BUFFER(1)) demux_pack_chain
|
||||
(.clk(clk), .reset(reset), .clear(1'b0),
|
||||
.header(), .dest(demux_dst),
|
||||
.i_tdata(i_tdata), .i_tlast(i_tlast), .i_tvalid(i_tvalid), .i_tready(i_tready),
|
||||
.o0_tdata(i0_tdata), .o0_tlast(i0_tlast), .o0_tvalid(i0_tvalid), .o0_tready(i0_tready),
|
||||
.o1_tdata(i1_tdata), .o1_tlast(i1_tlast), .o1_tvalid(i1_tvalid), .o1_tready(i1_tready),
|
||||
.o2_tdata(i2_tdata), .o2_tlast(i2_tlast), .o2_tvalid(i2_tvalid), .o2_tready(i2_tready),
|
||||
.o3_tdata(i3_tdata), .o3_tlast(i3_tlast), .o3_tvalid(i3_tvalid), .o3_tready(i3_tready));
|
||||
|
||||
axi_mux4 #(.PRIO(1), .WIDTH(64), .BUFFER(1)) mux_pack_chain
|
||||
(.clk(clk), .reset(reset), .clear(1'b0),
|
||||
.i0_tdata(o0_tdata), .i0_tlast(o0_tlast), .i0_tvalid(o0_tvalid), .i0_tready(o0_tready),
|
||||
.i1_tdata(o1_tdata), .i1_tlast(o1_tlast), .i1_tvalid(o1_tvalid), .i1_tready(o1_tready),
|
||||
.i2_tdata(o2_tdata), .i2_tlast(o2_tlast), .i2_tvalid(o2_tvalid), .i2_tready(o2_tready),
|
||||
.i3_tdata(o3_tdata), .i3_tlast(o3_tlast), .i3_tvalid(o3_tvalid), .i3_tready(o3_tready),
|
||||
.o_tdata(o_tdata), .o_tlast(o_tlast), .o_tvalid(o_tvalid), .o_tready(o_tready));
|
||||
//*/
|
||||
|
||||
endmodule //chdr_xxxx_to_16sc_chain
|
||||
@@ -0,0 +1,51 @@
|
||||
|
||||
module context_packet_gen
|
||||
(input clk, input reset, input clear,
|
||||
input trigger,
|
||||
input [11:0] seqnum,
|
||||
input [31:0] sid,
|
||||
input [63:0] body,
|
||||
input [63:0] vita_time,
|
||||
|
||||
output done,
|
||||
output reg [63:0] o_tdata, output o_tlast, output o_tvalid, input o_tready);
|
||||
|
||||
reg [1:0] cp_state;
|
||||
localparam CP_IDLE = 2'd0;
|
||||
localparam CP_HEAD = 2'd1;
|
||||
localparam CP_TIME = 2'd2;
|
||||
localparam CP_DATA = 2'd3;
|
||||
|
||||
always @(posedge clk)
|
||||
if(reset|clear)
|
||||
cp_state <= CP_IDLE;
|
||||
else
|
||||
case(cp_state)
|
||||
CP_IDLE :
|
||||
if(trigger)
|
||||
cp_state <= CP_HEAD;
|
||||
CP_HEAD :
|
||||
if(o_tready)
|
||||
cp_state <= CP_TIME;
|
||||
CP_TIME :
|
||||
if(o_tready)
|
||||
cp_state <= CP_DATA;
|
||||
CP_DATA :
|
||||
if(o_tready)
|
||||
cp_state <= CP_IDLE;
|
||||
endcase // case (cp_state)
|
||||
|
||||
assign o_tvalid = (cp_state != CP_IDLE);
|
||||
assign o_tlast = (cp_state == CP_DATA);
|
||||
|
||||
always @*
|
||||
case(cp_state)
|
||||
CP_HEAD : o_tdata <= { 4'hA, seqnum, 16'd24, sid };
|
||||
CP_TIME : o_tdata <= vita_time;
|
||||
CP_DATA : o_tdata <= body;
|
||||
default : o_tdata <= body;
|
||||
endcase // case (cp_state)
|
||||
|
||||
assign done = o_tlast & o_tvalid & o_tready;
|
||||
|
||||
endmodule // context_packet_gen
|
||||
@@ -0,0 +1,79 @@
|
||||
module float_to_iq
|
||||
|
||||
#(parameter BITS_IN = 32,
|
||||
parameter BITS_OUT = 16
|
||||
)
|
||||
|
||||
(
|
||||
|
||||
input [31:0] in,
|
||||
output [15:0] out
|
||||
);
|
||||
|
||||
//flags
|
||||
|
||||
wire neg_inf;
|
||||
wire pos_inf;
|
||||
wire denorm;
|
||||
wire tiny_exp;
|
||||
|
||||
|
||||
|
||||
assign pos_inf = (in[31] == 0 && in[30:23] == 1 && in[22:0] == 0);
|
||||
assign neg_inf = (in[31] == 1 && in[30:23] == 1 && in[22:0] == 0);
|
||||
assign denorm = (in[30:23] == 0);
|
||||
assign tiny_exp = (in[30:23] < 'd111);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
wire [23:0] implied_bit_fraction;
|
||||
wire [24:0] operation_round;
|
||||
wire [15:0] round_fraction;
|
||||
wire [15:0] shifted_fraction;
|
||||
wire [7:0] shift_val;
|
||||
|
||||
wire [22:0] true_frac;
|
||||
|
||||
|
||||
|
||||
|
||||
assign shift_val = (in[30:23] > 127)? (in[30:23] - 127): (127 - in[30:23]);
|
||||
assign implied_bit_fraction = {1'b1,in[22:0]};
|
||||
|
||||
|
||||
|
||||
assign operation_round = (implied_bit_fraction + 'h000080);
|
||||
|
||||
|
||||
//testing for overflow
|
||||
assign round_fraction = (operation_round[24] == 0)?(operation_round[23:8]):(16'h7FFF);
|
||||
//shift the rounded value
|
||||
wire [15:0] shift = round_fraction >> (15 - shift_val);
|
||||
//2's complement the shifted output if the signed bit is 1
|
||||
wire [15:0] final_val = (in[31] == 1)?(~shift + 1'b1):shift;
|
||||
|
||||
|
||||
|
||||
assign out = (pos_inf)?{1'b0,15'h7FFF}:(neg_inf)?{1'b1,15'h8000}:(denorm || tiny_exp)? 16'b0: final_val;
|
||||
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
module float_to_iq_tb();
|
||||
|
||||
reg clk, reset;
|
||||
|
||||
integer x,file;
|
||||
reg [31:0] in;
|
||||
wire [15:0] out;
|
||||
|
||||
initial clk = 0;
|
||||
|
||||
always #10 clk = ~clk;
|
||||
|
||||
initial $dumpfile("float_to_iq_tb.vcd");
|
||||
initial $dumpvars(0,float_to_iq_tb);
|
||||
|
||||
initial
|
||||
begin
|
||||
|
||||
x <= 0;
|
||||
reset <= 1;
|
||||
in <= 0;
|
||||
file = $fopen("float_to_iq_VER.txt");
|
||||
|
||||
repeat(65536) @(posedge clk);
|
||||
reset <=0;
|
||||
repeat(65536) @(posedge clk)
|
||||
begin
|
||||
in <= data[x];
|
||||
x <= x+1;
|
||||
$fdisplayh(file,out);
|
||||
end
|
||||
$fclose(file);
|
||||
repeat(65536) @(posedge clk);
|
||||
$finish;
|
||||
end
|
||||
|
||||
float_to_iq #(.BITS_IN(32),.BITS_OUT(16))
|
||||
dut
|
||||
(
|
||||
.in(in), .out(out), .clk(clk), .reset(reset)
|
||||
);
|
||||
//input
|
||||
reg [31:0] data [0:65535];
|
||||
initial $readmemh("iq_to_float_output.txt",data);
|
||||
//golden output
|
||||
//
|
||||
/*
|
||||
reg [15:0] out_array [0:65535];
|
||||
initial $readmemh("my_data.txt",out_array);
|
||||
reg fail;
|
||||
initial
|
||||
fail <= 0;
|
||||
//compare golden output with your output
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (out != out_array[index]) begin
|
||||
$display("Line %d : Expected %x, got %x",index,out_array[index],out);
|
||||
fail <= 1;
|
||||
end
|
||||
end
|
||||
*/
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
7FF8000001115AB6
|
||||
B6EEFEE599A577E9
|
||||
F0005AB800CCE7FF
|
||||
F0005AB800CCE7FF
|
||||
B6EEFEE599A577E9
|
||||
7FF8000001115AB6
|
||||
B6EEFEE599A577E9
|
||||
7FF8000001115AB6
|
||||
B6EEFEE599A577E9
|
||||
9999ACCAEEEEFFFF
|
||||
7878000065568799
|
||||
6543111122223333
|
||||
@@ -0,0 +1,8 @@
|
||||
8000FFFF7FFF1111
|
||||
00005A6BEEEE9999
|
||||
7AAAEEEE7FFF0000
|
||||
5AB890874676BBBB
|
||||
EEEE888800007FFF
|
||||
DACCCADBEEFFEED0
|
||||
FEEDBEEF0000BAAB
|
||||
CAB8000BACEDEED0
|
||||
@@ -0,0 +1,12 @@
|
||||
8000FFFF7FFF1111
|
||||
00005A6BEEEE9999
|
||||
7AAAEEEE7FFF0000
|
||||
7AAAEEEE7FFF0000
|
||||
7AAAEEEE7FFF0000
|
||||
7AAAEEEE7FFF0000
|
||||
7AAAEEEE7FFF0000
|
||||
7AAAEEEE7FFF0000
|
||||
7AAAEEEE7FFF0000
|
||||
7AAAEEEE7FFF0000
|
||||
7AAAEEEE7FFF0000
|
||||
7AAAEEEE7FFF0000
|
||||
@@ -0,0 +1,87 @@
|
||||
//PURPOSE: C test bench for floating point converter IQ_to_FLOAT
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <bitset>
|
||||
#include <cmath>
|
||||
#include "math.h"
|
||||
#include <iomanip>
|
||||
|
||||
using namespace std;
|
||||
//INITIAL TESTING PURPOSES: Use if you want to print individual bits
|
||||
template <typename T>
|
||||
|
||||
void print_bits(T n) {
|
||||
T mask = 1 << (sizeof(T)*8-1);
|
||||
while (mask) {
|
||||
cout << ((mask & n) ? "1" : "0");
|
||||
mask >>= 1;
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
||||
|
||||
FILE *convFile;
|
||||
FILE *newFile;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
convFile = fopen("iq_to_float_input.txt", "w");
|
||||
newFile = fopen("iq_to_float_output.txt", "w");
|
||||
//iterate through test cases
|
||||
|
||||
for (signed int i = -0x8000; i <= 0x7FFF; i++) {
|
||||
|
||||
float end = float(i*exp2(-15));
|
||||
|
||||
|
||||
unsigned int n = *(reinterpret_cast<unsigned int*>(&end));
|
||||
|
||||
//IN CASE YOU NEED TO LOOK AT SPECIFIC EXPONENT, FRAC, ETC VALUES
|
||||
//ACTIVATE BY UNCOMMENTING
|
||||
/*
|
||||
|
||||
unsigned int signed_bit = n>>31;
|
||||
|
||||
unsigned int exp = ((n>>23) &0xFF);
|
||||
|
||||
unsigned int frac = (n &0x7FFFFF);
|
||||
|
||||
cout << "end: " << end << endl;
|
||||
cout << "n: " << hex << n << endl;
|
||||
|
||||
|
||||
|
||||
cout << "signed bit:" << hex << signed_bit << endl;
|
||||
cout << "exp: " << hex << exp << endl;
|
||||
cout << "fract: " << hex << frac << endl;
|
||||
|
||||
float f = *(float*)&n;
|
||||
cout << "f" << f << endl;
|
||||
*/
|
||||
|
||||
// print_bits<unsigned short>(start);
|
||||
// print_bits<unsigned int>(n);
|
||||
unsigned int something = i;
|
||||
something &= 0xFFFF;
|
||||
|
||||
fprintf(convFile, "%x\n",something);
|
||||
fprintf(newFile, "%x\n",n);
|
||||
}
|
||||
|
||||
fclose(convFile);
|
||||
fclose(newFile);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
module iq_to_float
|
||||
|
||||
#(parameter BITS_IN =16,
|
||||
parameter BITS_OUT = 32
|
||||
)
|
||||
|
||||
(
|
||||
input [15:0] in,
|
||||
output [31:0] out
|
||||
|
||||
);
|
||||
|
||||
//imaginary
|
||||
|
||||
|
||||
//2s complement
|
||||
wire [15:0] unsigned_mag;
|
||||
wire [15:0] complement;
|
||||
|
||||
//leading bit registers
|
||||
wire [15:0] lead;
|
||||
wire [15:0] reversed_mag;
|
||||
|
||||
//16-4 encoder
|
||||
wire [3:0] binary_out;
|
||||
|
||||
wire [22:0] fraction;
|
||||
wire [7:0] exponent;
|
||||
|
||||
wire [15:0] binary_in;
|
||||
|
||||
binary_encoder #(.SIZE(16))
|
||||
encoding
|
||||
(.in(binary_in),.out(binary_out));
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Detect sign, if negative detected perform 2's complement
|
||||
|
||||
assign unsigned_mag = (in[15] == 1)?((~in[15:0])+1'b1):in[15:0];
|
||||
|
||||
//detect leading one
|
||||
|
||||
assign complement = ((~reversed_mag[BITS_IN-1:0])+1'b1);
|
||||
|
||||
assign lead = complement & reversed_mag;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//calculate fraction and exponent using shift value generated
|
||||
|
||||
wire [15:0] pre_frac = unsigned_mag << ((15 - binary_out));
|
||||
assign fraction = {pre_frac[14:0],8'h0};
|
||||
assign exponent = (in == 16'b0)?(8'b0):(binary_out +'d127);
|
||||
|
||||
|
||||
|
||||
|
||||
//construct the output
|
||||
assign out = {in[15], exponent, fraction};
|
||||
|
||||
//reverse the signed input
|
||||
|
||||
genvar r;
|
||||
|
||||
generate
|
||||
for (r = 0; r < 16; r = r+1) begin:bit_reverse
|
||||
assign reversed_mag[r] = unsigned_mag[BITS_IN-r-1];
|
||||
end
|
||||
endgenerate
|
||||
|
||||
//reversed the output of the detect the leading bit procedure
|
||||
|
||||
genvar i;
|
||||
generate
|
||||
for (i= 0; i < 16; i = i+1) begin: i_rev
|
||||
assign binary_in[i] = lead[BITS_IN-i-1];
|
||||
end
|
||||
endgenerate
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,61 @@
|
||||
module iq_to_float_tb();
|
||||
|
||||
|
||||
reg clk, reset;
|
||||
integer x,file;
|
||||
reg [15:0] in;
|
||||
wire [31:0] out;
|
||||
|
||||
initial clk = 0;
|
||||
|
||||
always #10 clk = ~clk;
|
||||
|
||||
initial $dumpfile("iq_to_float_tb.vcd");
|
||||
initial $dumpvars(0,iq_to_float_tb);
|
||||
integer f;
|
||||
initial
|
||||
|
||||
begin
|
||||
x <= 0;
|
||||
reset <= 1;
|
||||
in <= 0;
|
||||
file = $fopen("iq_to_float_VER.txt");
|
||||
|
||||
repeat(65536) @(posedge clk);
|
||||
reset <= 0;
|
||||
repeat(65536) @(posedge clk)
|
||||
begin
|
||||
in <= data[x];
|
||||
x <= x+1;
|
||||
$fdisplayh(file,out);
|
||||
end
|
||||
$fclose(file);
|
||||
|
||||
|
||||
repeat(65536) @(posedge clk);
|
||||
$finish;
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
iq_to_float #(.BITS_IN(16), .BITS_OUT(32))
|
||||
dut
|
||||
(
|
||||
.in(in), .out(out), .clk(clk), .reset(reset)
|
||||
);
|
||||
|
||||
|
||||
|
||||
reg [15:0] data [0:65535];
|
||||
initial $readmemh("iq_to_float_input.txt",data);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
@@ -0,0 +1,242 @@
|
||||
//
|
||||
// Copyright 2013 Ettus Research LLC
|
||||
//
|
||||
|
||||
|
||||
// HALT brings RX to an idle state as quickly as possible if RX is running
|
||||
// without running the risk of leaving a packet fragment in downstream FIFO's.
|
||||
// HALT also flushes all remaining pending commands in the commmand FIFO.
|
||||
// Unlike STOP, HALT doesn't ever create an ERROR packet.
|
||||
|
||||
|
||||
module new_rx_control
|
||||
#(parameter BASE=0)
|
||||
(input clk, input reset, input clear,
|
||||
input set_stb, input [7:0] set_addr, input [31:0] set_data,
|
||||
|
||||
input [63:0] vita_time,
|
||||
|
||||
// DDC connections
|
||||
output run, output eob,
|
||||
input strobe, input full,
|
||||
input [11:0] seqnum,
|
||||
input [31:0] sid,
|
||||
|
||||
output [63:0] err_tdata, output err_tlast, output err_tvalid, input err_tready,
|
||||
output [31:0] debug
|
||||
);
|
||||
|
||||
wire [31:0] command_i;
|
||||
wire [63:0] time_i;
|
||||
wire store_command;
|
||||
|
||||
wire send_imm, chain, reload, stop;
|
||||
wire [27:0] numlines;
|
||||
wire [63:0] rcvtime;
|
||||
|
||||
wire now, early, late;
|
||||
wire command_valid;
|
||||
reg command_ready;
|
||||
|
||||
reg chain_sav, reload_sav;
|
||||
|
||||
|
||||
reg clear_halt;
|
||||
reg halt;
|
||||
wire set_halt;
|
||||
|
||||
reg [63:0] err_tdata_int;
|
||||
wire err_tlast_int;
|
||||
wire err_tvalid_int;
|
||||
wire err_tready_int;
|
||||
|
||||
|
||||
setting_reg #(.my_addr(BASE)) sr_cmd
|
||||
(.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr),
|
||||
.in(set_data),.out(command_i),.changed());
|
||||
|
||||
setting_reg #(.my_addr(BASE+1)) sr_time_h
|
||||
(.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr),
|
||||
.in(set_data),.out(time_i[63:32]),.changed());
|
||||
|
||||
setting_reg #(.my_addr(BASE+2)) sr_time_l
|
||||
(.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr),
|
||||
.in(set_data),.out(time_i[31:0]),.changed(store_command));
|
||||
|
||||
setting_reg #(.my_addr(BASE+3)) sr_rx_halt
|
||||
(.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr),
|
||||
.in(set_data),.out(),.changed(set_halt));
|
||||
|
||||
always @(posedge clk)
|
||||
if (reset | clear | clear_halt)
|
||||
halt <= 1'b0;
|
||||
else
|
||||
halt <= set_halt;
|
||||
|
||||
|
||||
axi_fifo_short #(.WIDTH(96)) commandfifo
|
||||
(.clk(clk),.reset(reset),.clear(clear | clear_halt),
|
||||
.i_tdata({command_i,time_i}), .i_tvalid(store_command), .i_tready(),
|
||||
.o_tdata({send_imm,chain,reload,stop,numlines,rcvtime}),
|
||||
.o_tvalid(command_valid), .o_tready(command_ready),
|
||||
.occupied(), .space() );
|
||||
|
||||
time_compare
|
||||
time_compare (.clk(clk), .reset(reset), .time_now(vita_time), .trigger_time(rcvtime), .now(now), .early(early), .late(late));
|
||||
|
||||
localparam IBS_IDLE = 0;
|
||||
localparam IBS_RUNNING = 1;
|
||||
|
||||
localparam IBS_OVERRUN = 2;
|
||||
localparam IBS_OVR_TIME = 3;
|
||||
localparam IBS_OVR_DATA = 4;
|
||||
|
||||
localparam IBS_BROKENCHAIN = 5;
|
||||
localparam IBS_BRK_TIME = 6;
|
||||
localparam IBS_BRK_DATA = 7;
|
||||
|
||||
localparam IBS_LATECMD = 8;
|
||||
localparam IBS_LATE_TIME = 9;
|
||||
localparam IBS_LATE_DATA = 10;
|
||||
|
||||
localparam IBS_ZEROLEN = 11;
|
||||
localparam IBS_ZERO_TIME = 12;
|
||||
localparam IBS_ZERO_DATA = 13;
|
||||
|
||||
reg [3:0] ibs_state;
|
||||
reg [27:0] lines_left, repeat_lines;
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if(reset | clear)
|
||||
begin
|
||||
ibs_state <= IBS_IDLE;
|
||||
chain_sav <= 1'b0;
|
||||
reload_sav <= 1'b0;
|
||||
clear_halt <= 1'b0;
|
||||
end
|
||||
else
|
||||
case(ibs_state)
|
||||
IBS_IDLE : begin
|
||||
clear_halt <= 1'b0; // Incase we got here through a HALT.
|
||||
if(command_valid)
|
||||
if(stop)
|
||||
ibs_state <= IBS_IDLE;//IBS_ZEROLEN;
|
||||
else if(late & ~send_imm)
|
||||
ibs_state <= IBS_LATECMD;
|
||||
else if(now | send_imm)
|
||||
begin
|
||||
ibs_state <= IBS_RUNNING;
|
||||
lines_left <= numlines;
|
||||
repeat_lines <= numlines;
|
||||
chain_sav <= chain;
|
||||
reload_sav <= reload;
|
||||
end
|
||||
end // case: IBS_IDLE
|
||||
|
||||
IBS_RUNNING : // need to check for full
|
||||
if(strobe)
|
||||
if(full)
|
||||
ibs_state <= IBS_OVERRUN;
|
||||
else
|
||||
if(lines_left == 1)
|
||||
// Provide Halt mechanism used to bring RX into known IDLE state
|
||||
// at re-initialization.
|
||||
if (halt)
|
||||
begin
|
||||
ibs_state <= IBS_IDLE;
|
||||
clear_halt <= 1'b1;
|
||||
end
|
||||
else if(chain_sav)
|
||||
if(command_valid)
|
||||
begin
|
||||
lines_left <= numlines;
|
||||
repeat_lines <= numlines;
|
||||
chain_sav <= chain;
|
||||
reload_sav <= reload;
|
||||
if(stop)
|
||||
ibs_state <= IBS_IDLE;
|
||||
end
|
||||
else if(reload_sav)
|
||||
lines_left <= repeat_lines;
|
||||
else
|
||||
ibs_state <= IBS_BROKENCHAIN;
|
||||
else
|
||||
ibs_state <= IBS_IDLE;
|
||||
else
|
||||
lines_left <= lines_left - 28'd1;
|
||||
|
||||
|
||||
IBS_OVERRUN: if(err_tready_int) ibs_state <= IBS_OVR_TIME;
|
||||
IBS_OVR_TIME: if(err_tready_int) ibs_state <= IBS_OVR_DATA;
|
||||
IBS_OVR_DATA: if(err_tready_int) ibs_state <= IBS_IDLE;
|
||||
|
||||
IBS_BROKENCHAIN: if(err_tready_int) ibs_state <= IBS_BRK_TIME;
|
||||
IBS_BRK_TIME: if(err_tready_int) ibs_state <= IBS_BRK_DATA;
|
||||
IBS_BRK_DATA: if(err_tready_int) ibs_state <= IBS_IDLE;
|
||||
|
||||
IBS_LATECMD: if(err_tready_int) ibs_state <= IBS_LATE_TIME;
|
||||
IBS_LATE_TIME: if(err_tready_int) ibs_state <= IBS_LATE_DATA;
|
||||
IBS_LATE_DATA: if(err_tready_int) ibs_state <= IBS_IDLE;
|
||||
|
||||
IBS_ZEROLEN: if(err_tready_int) ibs_state <= IBS_ZERO_TIME;
|
||||
IBS_ZERO_TIME: if(err_tready_int) ibs_state <= IBS_ZERO_DATA;
|
||||
IBS_ZERO_DATA: if(err_tready_int) ibs_state <= IBS_IDLE;
|
||||
|
||||
default: ibs_state <= IBS_IDLE;
|
||||
|
||||
endcase // case (ibs_state)
|
||||
|
||||
always @*
|
||||
case(ibs_state)
|
||||
IBS_IDLE : command_ready <= stop | late | now | send_imm;
|
||||
IBS_RUNNING : command_ready <= strobe & (lines_left == 1) & chain_sav;
|
||||
default : command_ready <= 1'b0;
|
||||
endcase // case (ibs_state)
|
||||
|
||||
assign run = (ibs_state == IBS_RUNNING);
|
||||
assign eob = strobe & (lines_left == 1) & ( ~chain_sav | (command_valid & stop) | (~command_valid & ~reload_sav) | halt);
|
||||
|
||||
always @*
|
||||
case (ibs_state)
|
||||
IBS_OVERRUN : err_tdata_int <= { 4'hA, seqnum, 16'd24, sid };
|
||||
IBS_OVR_TIME : err_tdata_int <= vita_time;
|
||||
IBS_OVR_DATA : err_tdata_int <= {32'h8, 32'b0};
|
||||
|
||||
IBS_BROKENCHAIN : err_tdata_int <= { 4'hA, seqnum, 16'd24, sid };
|
||||
IBS_BRK_TIME : err_tdata_int <= vita_time;
|
||||
IBS_BRK_DATA : err_tdata_int <= {32'h4, 32'b0};
|
||||
|
||||
IBS_LATECMD : err_tdata_int <= { 4'hA, seqnum, 16'd24, sid };
|
||||
IBS_LATE_TIME : err_tdata_int <= vita_time;
|
||||
IBS_LATE_DATA : err_tdata_int <= {32'h2, 32'b0};
|
||||
|
||||
IBS_ZEROLEN : err_tdata_int <= { 4'hA, seqnum, 16'd24, sid };
|
||||
IBS_ZERO_TIME : err_tdata_int <= vita_time;
|
||||
IBS_ZERO_DATA : err_tdata_int <= {32'hd, 32'b0};
|
||||
|
||||
default : err_tdata_int <= {32'he, 32'b0};
|
||||
endcase // case (ibs_state)
|
||||
|
||||
assign err_tlast_int = (ibs_state == IBS_OVR_DATA)
|
||||
| (ibs_state == IBS_BRK_DATA)
|
||||
| (ibs_state == IBS_LATE_DATA)
|
||||
| (ibs_state == IBS_ZERO_DATA);
|
||||
|
||||
assign err_tvalid_int = ibs_state >= IBS_OVERRUN;
|
||||
|
||||
|
||||
assign debug[3:0] = ibs_state;
|
||||
assign debug[7:4] = {2'b0, command_valid, command_ready};
|
||||
|
||||
axi_fifo_short #(.WIDTH(65)) output_fifo
|
||||
(
|
||||
.clk(clk), .reset(reset), .clear(clear),
|
||||
.i_tdata({err_tlast_int,err_tdata_int}), .i_tvalid(err_tvalid_int), .i_tready(err_tready_int),
|
||||
.o_tdata({err_tlast,err_tdata}), .o_tvalid(err_tvalid), .o_tready(err_tready),
|
||||
.space(), .occupied()
|
||||
);
|
||||
|
||||
|
||||
|
||||
endmodule // new_rx_control
|
||||
@@ -0,0 +1,219 @@
|
||||
|
||||
module new_rx_framer
|
||||
#(parameter BASE=0)
|
||||
(input clk, input reset, input clear,
|
||||
input set_stb, input [7:0] set_addr, input [31:0] set_data,
|
||||
|
||||
input [63:0] vita_time,
|
||||
|
||||
input strobe,
|
||||
input [31:0] sample,
|
||||
input run,
|
||||
input eob,
|
||||
output full,
|
||||
output reg [11:0] seqnum,
|
||||
output [31:0] sid,
|
||||
|
||||
output [63:0] o_tdata, output o_tlast, output o_tvalid, input o_tready,
|
||||
|
||||
output [31:0] debug
|
||||
);
|
||||
|
||||
reg [15:0] len;
|
||||
reg [63:0] hold_time;
|
||||
|
||||
wire [63:0] dfifo_tdata;
|
||||
wire dfifo_tlast, dfifo_tvalid, dfifo_tready;
|
||||
|
||||
wire [80:0] hfifo_tdata;
|
||||
wire hfifo_tvalid, hfifo_tready;
|
||||
|
||||
wire [63:0] o_tdata_int;
|
||||
wire o_tlast_int, o_tvalid_int, o_tready_int;
|
||||
|
||||
wire [15:0] sample_space;
|
||||
|
||||
wire [15:0] maxlen;
|
||||
reg [31:0] holding;
|
||||
|
||||
// FIXME need to handle case where hdr fifo is full (i.e. too many tiny packets)
|
||||
assign full = (sample_space == 16'd0) | (sample_space == 16'd1) | ~hdr_tready;
|
||||
|
||||
setting_reg #(.my_addr(BASE), .width(16)) sr_maxlen
|
||||
(.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr),
|
||||
.in(set_data),.out(maxlen),.changed());
|
||||
|
||||
wire sid_changed;
|
||||
setting_reg #(.my_addr(BASE+1), .width(32)) sr_sid
|
||||
(.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr),
|
||||
.in(set_data),.out(sid),.changed(sid_changed));
|
||||
|
||||
reg [1:0] instate;
|
||||
reg [15:0] numsamps;
|
||||
reg nearly_eop;
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if(reset | clear)
|
||||
begin
|
||||
instate <= 0;
|
||||
numsamps <= 0;
|
||||
nearly_eop <= 0;
|
||||
|
||||
end
|
||||
else if (run)
|
||||
case(instate)
|
||||
0 :
|
||||
if(strobe)
|
||||
if(eop)
|
||||
begin
|
||||
instate <= 0;
|
||||
numsamps <= 0;
|
||||
nearly_eop <= 0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
instate <= 1;
|
||||
numsamps <= numsamps + 1;
|
||||
nearly_eop <= (numsamps >= (maxlen-2));
|
||||
end
|
||||
1 :
|
||||
if(strobe)
|
||||
if(eop)
|
||||
begin
|
||||
instate <= 0;
|
||||
numsamps <= 0;
|
||||
nearly_eop <= 0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
instate <= 2;
|
||||
numsamps <= numsamps + 1;
|
||||
nearly_eop <= (numsamps >= (maxlen-2));
|
||||
end
|
||||
2 :
|
||||
if(strobe)
|
||||
if(eop)
|
||||
begin
|
||||
instate <= 0;
|
||||
numsamps <= 0;
|
||||
nearly_eop <= 0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
instate <= 1;
|
||||
numsamps <= numsamps + 1;
|
||||
nearly_eop <= (numsamps >= (maxlen-2));
|
||||
end
|
||||
endcase // case (instate)
|
||||
|
||||
always @(posedge clk)
|
||||
if(strobe)
|
||||
begin
|
||||
holding <= sample;
|
||||
if(instate == 0)
|
||||
hold_time <= vita_time;
|
||||
end
|
||||
|
||||
always @(posedge clk)
|
||||
if(reset | clear)
|
||||
len <= 5;
|
||||
else
|
||||
if(strobe)
|
||||
if(sample_tlast)
|
||||
len <= 5;
|
||||
else
|
||||
len <= len + 1;
|
||||
|
||||
always @(posedge clk)
|
||||
if(reset | clear | sid_changed)
|
||||
seqnum <= 12'd0;
|
||||
else
|
||||
if(o_tlast_int & o_tvalid_int & o_tready_int)
|
||||
seqnum <= seqnum + 12'd1;
|
||||
|
||||
|
||||
|
||||
wire eop = eob | nearly_eop | full;
|
||||
|
||||
wire [63:0] sample_tdata = instate == 1 ? {holding, sample} : {sample, 32'h0};
|
||||
wire sample_tlast = eop;
|
||||
wire sample_tvalid = run & strobe & ( (instate == 1) | eop );
|
||||
wire sample_tready;
|
||||
|
||||
wire [80:0] hdr_tdata = {eob,len[13:0],2'b0,(instate == 0) ? vita_time : hold_time};
|
||||
wire hdr_tvalid = sample_tlast && sample_tvalid && sample_tready;
|
||||
wire hdr_tready;
|
||||
|
||||
|
||||
axi_fifo #(.WIDTH(65), .SIZE(10)) datafifo
|
||||
(.clk(clk), .reset(reset), .clear(clear),
|
||||
.i_tdata({sample_tlast,sample_tdata}), .i_tvalid(sample_tvalid), .i_tready(sample_tready),
|
||||
.o_tdata({dfifo_tlast,dfifo_tdata}), .o_tvalid(dfifo_tvalid), .o_tready(dfifo_tready),
|
||||
.space(sample_space), .occupied());
|
||||
|
||||
axi_fifo_short #(.WIDTH(81)) hdrfifo
|
||||
(.clk(clk), .reset(reset), .clear(clear),
|
||||
.i_tdata(hdr_tdata), .i_tvalid(hdr_tvalid), .i_tready(hdr_tready),
|
||||
.o_tdata(hfifo_tdata), .o_tvalid(hfifo_tvalid), .o_tready(hfifo_tready),
|
||||
.space(), .occupied());
|
||||
|
||||
// The output state machine is responsible for forming output packets.
|
||||
// Output packets are formed by combining the entries in the header fifo,
|
||||
// and the samples in the data fifo. A single entry in the header fifo
|
||||
// contains both the compressed header and the 64 bit time stamp.
|
||||
|
||||
reg [1:0] outstate;
|
||||
localparam OUT_IDLE = 2'd0;
|
||||
localparam OUT_HEAD = 2'd1;
|
||||
localparam OUT_TIME = 2'd2;
|
||||
localparam OUT_BODY = 2'd3;
|
||||
|
||||
always @(posedge clk)
|
||||
if(reset | clear)
|
||||
outstate <= OUT_IDLE;
|
||||
else
|
||||
case(outstate)
|
||||
OUT_IDLE :
|
||||
if(hfifo_tvalid) //having a header signals a complete packet
|
||||
outstate <= OUT_HEAD;
|
||||
OUT_HEAD :
|
||||
if(o_tvalid_int && o_tready_int)
|
||||
outstate <= OUT_TIME;
|
||||
OUT_TIME :
|
||||
if(o_tvalid_int && o_tready_int)
|
||||
outstate <= OUT_BODY;
|
||||
OUT_BODY :
|
||||
if(o_tvalid_int && o_tready_int && o_tlast_int)
|
||||
outstate <= OUT_IDLE;
|
||||
endcase // case (outstate)
|
||||
|
||||
//output data mux feeds from single line of header fifo or the data fifo
|
||||
assign o_tdata_int = (outstate == OUT_HEAD) ? { 3'b001, hfifo_tdata[80], seqnum, hfifo_tdata[79:64], sid} :
|
||||
(outstate == OUT_TIME) ? hfifo_tdata[63:0] : dfifo_tdata;
|
||||
|
||||
//output the last signal from the data fifo
|
||||
assign o_tlast_int = (outstate == OUT_BODY) ? dfifo_tlast : 1'b0;
|
||||
|
||||
//output valid connected to data valid in non-IDLE states
|
||||
assign o_tvalid_int = (outstate != OUT_IDLE) & dfifo_tvalid;
|
||||
|
||||
//only pop from header fifo on the very last transaction
|
||||
assign hfifo_tready = o_tvalid_int && o_tready_int && o_tlast_int;
|
||||
|
||||
//connect data fifo ready with out ready in the BODY state
|
||||
assign dfifo_tready = (outstate == OUT_BODY) ? o_tready_int : 1'b0;
|
||||
|
||||
axi_fifo_short #(.WIDTH(65)) output_fifo
|
||||
(.clk(clk), .reset(reset), .clear(clear),
|
||||
.i_tdata({o_tlast_int, o_tdata_int}), .i_tvalid(o_tvalid_int), .i_tready(o_tready_int),
|
||||
.o_tdata({o_tlast, o_tdata}), .o_tvalid(o_tvalid), .o_tready(o_tready),
|
||||
.space(), .occupied());
|
||||
|
||||
assign debug[3:0] = {instate, outstate};
|
||||
assign debug[7:4] = {1'b0, sample_tlast, sample_tvalid, sample_tready};
|
||||
assign debug[11:8] = {1'b0, 1'b0, hfifo_tvalid, hfifo_tready};
|
||||
assign debug[15:12] = {1'b0, dfifo_tlast, dfifo_tvalid, dfifo_tready};
|
||||
assign debug[19:16] = {1'b0, o_tlast_int, o_tvalid_int, o_tready_int};
|
||||
|
||||
endmodule // new_rx_framer
|
||||
@@ -0,0 +1,135 @@
|
||||
`timescale 1ns/1ps
|
||||
|
||||
module new_rx_tb();
|
||||
|
||||
reg clk = 0;
|
||||
reg reset = 1;
|
||||
|
||||
always #10 clk = ~clk;
|
||||
|
||||
initial $dumpfile("new_rx_tb.vcd");
|
||||
initial $dumpvars(0,new_rx_tb);
|
||||
|
||||
initial
|
||||
begin
|
||||
#1000 reset = 0;
|
||||
#30000;
|
||||
$finish;
|
||||
end
|
||||
|
||||
reg [7:0] set_addr;
|
||||
reg [31:0] set_data;
|
||||
reg set_stb = 1'b0;
|
||||
|
||||
reg [63:0] vita_time;
|
||||
reg [31:0] sample;
|
||||
reg strobe;
|
||||
|
||||
wire run, full;
|
||||
|
||||
wire [63:0] err_tdata;
|
||||
wire err_tlast, err_tvalid, err_tready;
|
||||
|
||||
wire [63:0] o_tdata;
|
||||
wire o_tlast, o_tvalid;
|
||||
reg o_tready;
|
||||
|
||||
task send_command;
|
||||
input [63:0] send_time;
|
||||
input send_at;
|
||||
input chain;
|
||||
input reload;
|
||||
input stop;
|
||||
input [31:0] len;
|
||||
|
||||
begin
|
||||
set_stb <= 1;
|
||||
set_addr <= 0;
|
||||
set_data <= { send_at, chain, reload, stop, len };
|
||||
@(posedge clk);
|
||||
set_stb <= 1;
|
||||
set_addr <= 1;
|
||||
set_data <= send_time[63:32];
|
||||
@(posedge clk);
|
||||
set_stb <= 1;
|
||||
set_addr <= 2;
|
||||
set_data <= send_time[31:0];
|
||||
@(posedge clk);
|
||||
set_stb <= 0;
|
||||
@(posedge clk);
|
||||
end
|
||||
endtask // send_command
|
||||
|
||||
initial
|
||||
begin
|
||||
o_tready <= 0;
|
||||
while(reset)
|
||||
@(posedge clk);
|
||||
set_stb <= 1; // Set Max Length of Packet
|
||||
set_addr <= 8;
|
||||
set_data <= 18;
|
||||
@(posedge clk);
|
||||
set_stb <= 1; // Set SID
|
||||
set_addr <= 9;
|
||||
set_data <= 32'hF00D_1234;
|
||||
@(posedge clk);
|
||||
|
||||
send_command(64'h100/*time*/, 1/*send at*/, 0/*chain*/, 0/*reload*/,0/*stop*/,150/*len*/);
|
||||
send_command(64'h200/*time*/, 1/*send at*/, 0/*chain*/, 0/*reload*/,0/*stop*/,4/*len*/);
|
||||
//send_command(64'h100/*time*/, 1/*send at*/, 0/*chain*/, 0/*reload*/,0/*stop*/,5/*len*/);
|
||||
|
||||
#8000;
|
||||
o_tready <= 1;
|
||||
end // initial begin
|
||||
|
||||
always @(posedge clk)
|
||||
if(reset)
|
||||
vita_time <= 0;
|
||||
else
|
||||
vita_time <= vita_time + 1;
|
||||
|
||||
new_rx_control #(.BASE(0)) rx_control
|
||||
(.clk(clk), .reset(reset), .clear(1'b0),
|
||||
.set_stb(set_stb), .set_addr(set_addr), .set_data(set_data),
|
||||
.vita_time(vita_time),
|
||||
.run(run), .eob(eob), .strobe(strobe), .full(full),
|
||||
.err_tdata(err_tdata), .err_tlast(err_tlast), .err_tvalid(err_tvalid), .err_tready(err_tready),
|
||||
.debug());
|
||||
|
||||
new_rx_framer #(.BASE(8)) rx_framer
|
||||
(.clk(clk), .reset(reset), .clear(1'b0),
|
||||
.set_stb(set_stb), .set_addr(set_addr), .set_data(set_data),
|
||||
.vita_time(vita_time),
|
||||
.strobe(strobe), .sample(sample), .run(run), .eob(eob), .full(full),
|
||||
.o_tdata(o_tdata), .o_tlast(o_tlast), .o_tvalid(o_tvalid), .o_tready(o_tready)
|
||||
);
|
||||
|
||||
always @*
|
||||
strobe <= run;
|
||||
|
||||
/*
|
||||
always @(posedge clk)
|
||||
if(reset)
|
||||
sample <= 0;
|
||||
else if(run)
|
||||
sample <= sample + 1;
|
||||
*/
|
||||
always @* sample <= vita_time[31:0];
|
||||
|
||||
always @(posedge clk)
|
||||
if(o_tvalid & o_tready)
|
||||
if(o_tlast)
|
||||
$display("%x\tLAST\n",o_tdata);
|
||||
else
|
||||
$display("%x",o_tdata);
|
||||
|
||||
assign err_tready = 1;
|
||||
|
||||
always @(posedge clk)
|
||||
if(err_tvalid & err_tready)
|
||||
if(err_tlast)
|
||||
$display("\t\t\t\tERR LAST \t%x",err_tdata);
|
||||
else
|
||||
$display("\t\t\t\tERR\t\t%x",err_tdata);
|
||||
|
||||
endmodule // new_rx_tb
|
||||
@@ -0,0 +1,171 @@
|
||||
|
||||
|
||||
module new_tx_control
|
||||
#(parameter BASE=0)
|
||||
(input clk, input reset, input clear,
|
||||
input set_stb, input [7:0] set_addr, input [31:0] set_data,
|
||||
|
||||
input [63:0] vita_time,
|
||||
output reg ack_or_error,
|
||||
output packet_consumed,
|
||||
output [11:0] seqnum,
|
||||
output reg [63:0] error_code,
|
||||
output [31:0] sid,
|
||||
|
||||
// From tx_deframer
|
||||
input [175:0] sample_tdata,
|
||||
input sample_tvalid,
|
||||
output sample_tready,
|
||||
|
||||
// To DSP Core
|
||||
output [31:0] sample,
|
||||
output run, input strobe,
|
||||
|
||||
output [31:0] debug
|
||||
);
|
||||
|
||||
wire [31:0] sample1 = sample_tdata[31:0];
|
||||
wire [31:0] sample0 = sample_tdata[63:32];
|
||||
wire [63:0] send_time = sample_tdata[127:64];
|
||||
assign sid = sample_tdata[159:128];
|
||||
assign seqnum = sample_tdata[171:160];
|
||||
wire eop = sample_tdata[172];
|
||||
wire eob = sample_tdata[173];
|
||||
wire send_at = sample_tdata[174];
|
||||
wire odd = sample_tdata[175];
|
||||
|
||||
wire now, early, late, too_early;
|
||||
wire policy_next_burst, policy_next_packet, policy_wait;
|
||||
wire clear_seqnum;
|
||||
|
||||
setting_reg #(.my_addr(BASE), .width(3)) sr_error_policy
|
||||
(.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr),
|
||||
.in(set_data),.out({policy_next_burst,policy_next_packet,policy_wait}),.changed(clear_seqnum));
|
||||
|
||||
time_compare
|
||||
time_compare (.clk(clk), .reset(reset), .time_now(vita_time), .trigger_time(send_time),
|
||||
.now(now), .early(early), .late(late), .too_early(too_early));
|
||||
|
||||
assign run = (state == ST_SAMP0) | (state == ST_SAMP1);
|
||||
|
||||
assign sample = (state == ST_SAMP0) ? sample0 : sample1;
|
||||
|
||||
reg [2:0] state;
|
||||
|
||||
localparam ST_IDLE = 0;
|
||||
localparam ST_SAMP0 = 1;
|
||||
localparam ST_SAMP1 = 2;
|
||||
localparam ST_ERROR = 3;
|
||||
localparam ST_WAIT = 4;
|
||||
|
||||
wire [63:0] CODE_EOB_ACK = {32'd1,20'd0,seqnum};
|
||||
wire [63:0] CODE_UNDERRUN = {32'd2,20'd0,seqnum};
|
||||
wire [63:0] CODE_SEQ_ERROR = {32'd4,20'd0,seqnum};
|
||||
wire [63:0] CODE_TIME_ERROR = {32'd8,20'd0,seqnum};
|
||||
wire [63:0] CODE_UNDERRUN_MIDPKT = {32'd16,20'd0,seqnum};
|
||||
wire [63:0] CODE_SEQ_ERROR_MIDBURST = {32'd32,20'd0,seqnum};
|
||||
|
||||
reg [11:0] expected_seqnum;
|
||||
|
||||
always @(posedge clk)
|
||||
if(reset | clear | clear_seqnum)
|
||||
expected_seqnum <= 12'd0;
|
||||
else
|
||||
if(sample_tvalid & sample_tready & eop)
|
||||
expected_seqnum <= seqnum + 12'd1;
|
||||
|
||||
always @(posedge clk)
|
||||
if(reset | clear)
|
||||
begin
|
||||
state <= ST_IDLE;
|
||||
ack_or_error <= 1'b0;
|
||||
error_code <= 64'd0;
|
||||
end
|
||||
else
|
||||
case(state)
|
||||
ST_IDLE :
|
||||
begin
|
||||
ack_or_error <= 1'b0;
|
||||
if(sample_tvalid)
|
||||
if(~send_at | now)
|
||||
if(expected_seqnum != seqnum)
|
||||
begin
|
||||
state <= ST_ERROR;
|
||||
ack_or_error <= 1'b1;
|
||||
error_code <= CODE_SEQ_ERROR;
|
||||
end
|
||||
else
|
||||
state <= ST_SAMP0;
|
||||
else if(late)
|
||||
begin
|
||||
state <= ST_ERROR;
|
||||
ack_or_error <= 1'b1;
|
||||
error_code <= CODE_TIME_ERROR;
|
||||
end
|
||||
end // case: ST_IDLE
|
||||
ST_SAMP0 :
|
||||
if(strobe)
|
||||
if(~sample_tvalid)
|
||||
begin
|
||||
state <= ST_ERROR;
|
||||
ack_or_error <= 1'b1;
|
||||
error_code <= CODE_UNDERRUN;
|
||||
end
|
||||
else if(eop & odd & eob)
|
||||
begin
|
||||
state <= ST_IDLE;
|
||||
ack_or_error <= 1'b1;
|
||||
error_code <= CODE_EOB_ACK;
|
||||
end
|
||||
else if(eop & odd)
|
||||
state <= ST_SAMP0;
|
||||
else if(expected_seqnum != seqnum)
|
||||
begin
|
||||
state <= ST_ERROR;
|
||||
ack_or_error <= 1'b1;
|
||||
error_code <= CODE_SEQ_ERROR_MIDBURST;
|
||||
end
|
||||
else
|
||||
state <= ST_SAMP1;
|
||||
ST_SAMP1 :
|
||||
if(strobe)
|
||||
if(eop & eob)
|
||||
begin
|
||||
state <= ST_IDLE;
|
||||
ack_or_error <= 1'b1;
|
||||
error_code <= CODE_EOB_ACK;
|
||||
end
|
||||
else
|
||||
state <= ST_SAMP0;
|
||||
ST_ERROR :
|
||||
begin
|
||||
ack_or_error <= 1'b0;
|
||||
if(sample_tvalid & eop)
|
||||
if(policy_next_packet | (policy_next_burst & eob))
|
||||
state <= ST_IDLE;
|
||||
else if(policy_wait)
|
||||
state <= ST_WAIT;
|
||||
end
|
||||
endcase // case (state)
|
||||
|
||||
assign sample_tready = (state == ST_ERROR) | (strobe & ( (state == ST_SAMP1) | ((state == ST_SAMP0) & eop & odd) ) );
|
||||
|
||||
assign packet_consumed = eop & sample_tvalid & sample_tready;
|
||||
|
||||
assign debug = {
|
||||
error_code[15:0], // [28:13]
|
||||
sample_tvalid, //[12]
|
||||
now, // [11]
|
||||
early, // [10]
|
||||
late, // [9]
|
||||
too_early, // [8]
|
||||
strobe, // [7]
|
||||
eop, // [6]
|
||||
eob, // [5]
|
||||
send_at, // [4]
|
||||
odd, // [3]
|
||||
state // [2:0]
|
||||
};
|
||||
|
||||
|
||||
endmodule // new_tx_control
|
||||
@@ -0,0 +1,140 @@
|
||||
`timescale 1ns/1ps
|
||||
|
||||
module new_tx_control_tb();
|
||||
|
||||
reg clk = 0;
|
||||
reg reset = 1;
|
||||
|
||||
always #10 clk = ~clk;
|
||||
|
||||
initial $dumpfile("new_tx_control_tb.vcd");
|
||||
initial $dumpvars(0,new_tx_control_tb);
|
||||
|
||||
initial
|
||||
begin
|
||||
#1000 reset = 0;
|
||||
#30000;
|
||||
$finish;
|
||||
end
|
||||
|
||||
reg [143:0] tdata;
|
||||
reg tlast;
|
||||
wire tlast_int;
|
||||
reg tvalid = 1'b0;
|
||||
wire tready;
|
||||
|
||||
reg [7:0] set_addr;
|
||||
reg [31:0] set_data;
|
||||
reg set_stb = 1'b0;
|
||||
|
||||
reg [31:0] samp0, samp1;
|
||||
|
||||
task send_packet;
|
||||
input [31:0] count;
|
||||
input [31:0] start_data;
|
||||
input [63:0] send_time;
|
||||
input [11:0] pkt_seqnum;
|
||||
input eop;
|
||||
input eob;
|
||||
input send_at;
|
||||
input odd;
|
||||
|
||||
begin
|
||||
// Send a packet
|
||||
samp0 <= start_data;
|
||||
samp1 <= start_data + 1;
|
||||
@(posedge clk);
|
||||
repeat (count-1)
|
||||
begin
|
||||
tdata <= { 1'b0,send_at,1'b0,1'b0,1'b0,pkt_seqnum,send_time,samp0,samp1 };
|
||||
tvalid <= 1;
|
||||
samp0 <= samp0 + 2;
|
||||
samp1 <= samp1 + 2;
|
||||
@(posedge clk);
|
||||
end
|
||||
|
||||
tdata <= { odd,send_at,1'b0,eob,eop,pkt_seqnum,send_time,samp0,samp1 };
|
||||
@(posedge clk);
|
||||
|
||||
tvalid <= 0;
|
||||
@(posedge clk);
|
||||
end
|
||||
endtask // send_packet
|
||||
|
||||
initial
|
||||
begin
|
||||
tvalid <= 1'b0;
|
||||
while(reset)
|
||||
@(posedge clk);
|
||||
set_addr <= 8'd0;
|
||||
set_data <= 32'd2;
|
||||
set_stb <= 1'b1;
|
||||
@(posedge clk);
|
||||
set_stb <= 1'b0;
|
||||
|
||||
// Single Packet burst, timed
|
||||
send_packet(3/*count*/,32'hA000_0000/*data*/,64'h100/*time*/,1/*SEQ*/,1/*EOP*/,1/*eob*/,1/*timed*/,0/*odd*/);
|
||||
|
||||
// 2 packet burst, timed
|
||||
//send_packet(3/*count*/,32'hB000_0000/*data*/,64'h200/*time*/,2/*SEQ*/,1/*EOP*/,0/*eob*/,1/*timed*/,0/*odd*/);
|
||||
//send_packet(3/*count*/,32'hC000_0000/*data*/,64'h0/*time*/,3/*SEQ*/,1/*EOP*/,1/*eob*/,0/*timed*/,0/*odd*/);
|
||||
|
||||
// single odd packet
|
||||
//send_packet(3/*count*/,32'h0A00_0000/*data*/,64'h300/*time*/,4/*SEQ*/,1/*EOP*/,1/*eob*/,1/*timed*/,1/*odd*/);
|
||||
|
||||
// 2 packet burst, timed, odd
|
||||
//send_packet(3/*count*/,32'hD000_0000/*data*/,64'h400/*time*/,5/*SEQ*/,1/*EOP*/,0/*eob*/,1/*timed*/,1/*odd*/);
|
||||
//send_packet(3/*count*/,32'hE000_0000/*data*/,64'd0/*time*/,6/*SEQ*/,1/*EOP*/,1/*eob*/,0/*timed*/,1/*odd*/);
|
||||
|
||||
// 2 packet burst, untimed, no eob set
|
||||
//send_packet(3/*count*/,32'hF000_0000/*data*/,64'd0/*time*/,7/*SEQ*/,1/*EOP*/,0/*eob*/,0/*timed*/,0/*odd*/);
|
||||
//send_packet(3/*count*/,32'h9000_0000/*data*/,64'd0/*time*/,8/*SEQ*/,1/*EOP*/,0/*eob*/,0/*timed*/,0/*odd*/);
|
||||
|
||||
// single packet late
|
||||
send_packet(3/*count*/,32'hD000_0000/*data*/,64'h0/*time*/,4/*SEQ*/,1/*EOP*/,1/*eob*/,1/*timed*/,1/*odd*/);
|
||||
|
||||
end
|
||||
|
||||
reg [63:0] vita_time;
|
||||
wire [31:0] sample;
|
||||
wire [143:0] sample_tdata;
|
||||
wire sample_tready, sample_tvalid;
|
||||
wire [11:0] seqnum;
|
||||
wire [31:0] error_code;
|
||||
|
||||
always @(posedge clk)
|
||||
if(reset)
|
||||
vita_time <= 0;
|
||||
else
|
||||
vita_time <= vita_time + 1;
|
||||
|
||||
axi_fifo #(.WIDTH(144)) axi_fifo_short
|
||||
(.clk(clk), .reset(reset), .clear(1'b0),
|
||||
.i_tdata(tdata), .i_tvalid(tvalid), .i_tready(tready),
|
||||
.o_tdata(sample_tdata), .o_tvalid(sample_tvalid), .o_tready(sample_tready));
|
||||
|
||||
new_tx_control new_tx_control
|
||||
(.clk(clk), .reset(reset), .clear(1'b0),
|
||||
.set_stb(set_stb), .set_addr(set_addr), .set_data(set_data),
|
||||
|
||||
.vita_time(vita_time),
|
||||
.error(error), .ack(ack), .packet_consumed(consumed), .seqnum(seqnum), .error_code(error_code),
|
||||
|
||||
.sample_tdata(sample_tdata), .sample_tvalid(sample_tvalid), .sample_tready(sample_tready),
|
||||
|
||||
.sample(sample), .run(run), .strobe(strobe),
|
||||
.debug()
|
||||
);
|
||||
|
||||
assign strobe = run;
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
if(strobe)
|
||||
$display("%x\t%x", vita_time, sample);
|
||||
if(consumed) $display("CONSUMED %x", seqnum);
|
||||
if(ack) $display("ACK %x", seqnum);
|
||||
if(error) $display("ERROR %x\t%x", seqnum,error_code);
|
||||
end
|
||||
|
||||
endmodule // new_tx_control_tb
|
||||
@@ -0,0 +1,92 @@
|
||||
|
||||
|
||||
module new_tx_deframer
|
||||
(input clk, input reset, input clear,
|
||||
input [63:0] i_tdata, input i_tlast, input i_tvalid, output i_tready,
|
||||
output [175:0] sample_tdata, output sample_tvalid, input sample_tready, output [31:0] debug);
|
||||
|
||||
reg odd, send_at, eob;
|
||||
reg [11:0] seqnum;
|
||||
reg [31:0] sid;
|
||||
reg [63:0] send_time;
|
||||
|
||||
wire [175:0] fifo_tdata = { odd, send_at, eob, i_tlast, seqnum/*12*/, sid, send_time/*64*/, i_tdata/*64*/ };
|
||||
wire fifo_tvalid, fifo_tready;
|
||||
|
||||
reg [1:0] td_state;
|
||||
localparam TD_HEAD = 0;
|
||||
localparam TD_TIME = 1;
|
||||
localparam TD_BODY = 2;
|
||||
localparam TD_DUMP = 3;
|
||||
|
||||
always @(posedge clk)
|
||||
if(reset | clear)
|
||||
begin
|
||||
td_state <= TD_HEAD;
|
||||
odd <= 1'b0;
|
||||
send_at <= 1'b0;
|
||||
eob <= 1'b0;
|
||||
seqnum <= 12'd0;
|
||||
sid <= 32'd0;
|
||||
send_time <= 64'h0;
|
||||
end // if (reset | clear)
|
||||
else
|
||||
case(td_state)
|
||||
TD_HEAD :
|
||||
if(i_tvalid)
|
||||
begin
|
||||
if(~i_tlast)
|
||||
if(i_tdata[63])
|
||||
td_state <= TD_DUMP;
|
||||
else if(i_tdata[61])
|
||||
td_state <= TD_TIME;
|
||||
else
|
||||
td_state <= TD_BODY;
|
||||
odd <= i_tdata[34];
|
||||
send_at <= i_tdata[61];
|
||||
eob <= i_tdata[60];
|
||||
seqnum <= i_tdata[59:48];
|
||||
sid <= i_tdata[31:0];
|
||||
// FIXME record trailer, length, and SID here
|
||||
end
|
||||
TD_TIME :
|
||||
if(i_tvalid)
|
||||
begin
|
||||
send_time <= i_tdata;
|
||||
if(~i_tlast)
|
||||
td_state <= TD_BODY;
|
||||
else
|
||||
td_state <= TD_HEAD;
|
||||
end
|
||||
TD_BODY :
|
||||
if(i_tvalid & fifo_tready)
|
||||
if(i_tlast)
|
||||
td_state <= TD_HEAD;
|
||||
TD_DUMP :
|
||||
if(i_tvalid)
|
||||
if(i_tlast)
|
||||
td_state <= TD_HEAD;
|
||||
endcase // case (td_state)
|
||||
|
||||
assign fifo_tvalid = i_tvalid & (td_state == TD_BODY);
|
||||
assign i_tready = (td_state == TD_BODY) ? fifo_tready : 1'b1;
|
||||
|
||||
axi_fifo_short #(.WIDTH(176)) ofifo
|
||||
(.clk(clk), .reset(reset), .clear(clear),
|
||||
.i_tdata(fifo_tdata), .i_tvalid(fifo_tvalid), .i_tready(fifo_tready),
|
||||
.o_tdata(sample_tdata), .o_tvalid(sample_tvalid), .o_tready(sample_tready),
|
||||
.space(), .occupied());
|
||||
|
||||
|
||||
assign debug = {
|
||||
sample_tvalid, // [8]
|
||||
sample_tready, // [7]
|
||||
i_tvalid, // [6]
|
||||
i_tready, // [5]
|
||||
td_state, // [4:3]
|
||||
odd, // [2]
|
||||
send_at, // [1]
|
||||
eob // [0]
|
||||
};
|
||||
|
||||
endmodule // new_tx_deframer
|
||||
@@ -0,0 +1,361 @@
|
||||
`timescale 1ns/1ps
|
||||
|
||||
module new_tx_tb();
|
||||
`ifdef ISIM
|
||||
`else //iverilog implied.
|
||||
xlnx_glbl glbl (.GSR(),.GTS());
|
||||
`endif
|
||||
|
||||
|
||||
localparam SR_TX_DSP = 8;
|
||||
localparam SR_TX_RESPONDER = 16;
|
||||
localparam SR_TX_CTRL = 24;
|
||||
|
||||
localparam SR_CYCLES = SR_TX_RESPONDER + 0;
|
||||
localparam SR_PACKETS = SR_TX_RESPONDER + 1;
|
||||
|
||||
localparam SR_PHASE_INC = SR_TX_DSP + 0;
|
||||
localparam SR_SCALE_FACTOR = SR_TX_DSP + 1;
|
||||
localparam SR_INTERP = SR_TX_DSP + 2;
|
||||
|
||||
localparam SR_ERROR_POLICY = SR_TX_CTRL + 0;
|
||||
|
||||
|
||||
reg clk = 0;
|
||||
reg reset = 1;
|
||||
|
||||
always #10 clk = ~clk;
|
||||
|
||||
initial $dumpfile("new_tx_tb.vcd");
|
||||
initial $dumpvars(0,new_tx_tb);
|
||||
wire run, strobe;
|
||||
|
||||
initial
|
||||
begin
|
||||
#1000 reset = 0;
|
||||
#30000;
|
||||
$finish;
|
||||
end
|
||||
|
||||
reg [63:0] tdata;
|
||||
reg tlast;
|
||||
reg tvalid = 1'b0;
|
||||
wire tready;
|
||||
|
||||
wire [63:0] i_tdata;
|
||||
wire i_tlast, i_tvalid, i_tready;
|
||||
|
||||
reg [7:0] set_addr;
|
||||
reg [31:0] set_data;
|
||||
reg set_stb = 1'b0;
|
||||
|
||||
reg [63:0] vita_time;
|
||||
wire [31:0] sample;
|
||||
|
||||
wire [175:0] sample_tdata;
|
||||
wire sample_tready, sample_tvalid;
|
||||
|
||||
wire [11:0] seqnum;
|
||||
wire [63:0] error_code;
|
||||
wire [31:0] sid;
|
||||
|
||||
reg [31:0] samp0, samp1;
|
||||
|
||||
reg [11:0] seqno;
|
||||
|
||||
wire ack_or_error, packet_consumed;
|
||||
|
||||
|
||||
//
|
||||
// Task Libaray
|
||||
//
|
||||
task write_setting_bus;
|
||||
input [7:0] address;
|
||||
input [31:0] data;
|
||||
|
||||
begin
|
||||
|
||||
@(negedge clk);
|
||||
set_stb = 1'b0;
|
||||
set_addr = 8'h0;
|
||||
set_data = 32'h0;
|
||||
@(negedge clk);
|
||||
set_stb = 1'b1;
|
||||
set_addr = address;
|
||||
set_data = data;
|
||||
@(negedge clk);
|
||||
set_stb = 1'b0;
|
||||
set_addr = 8'h0;
|
||||
set_data = 32'h0;
|
||||
|
||||
end
|
||||
endtask // write_setting_bus
|
||||
|
||||
|
||||
task send_ramp;
|
||||
input [31:0] burst_count;
|
||||
input [31:0] len;
|
||||
input [31:0] sid;
|
||||
|
||||
reg [31:0] data;
|
||||
|
||||
begin
|
||||
seqno = 0;
|
||||
data = 0;
|
||||
send_packet(len, data, 0, seqno, (burst_count==1), 0, sid);
|
||||
seqno = seqno + 1;
|
||||
data <= data + len;
|
||||
|
||||
if(burst_count > 2)
|
||||
repeat (burst_count - 2)
|
||||
begin
|
||||
send_packet(len, data, 64'h0, seqno, 0, 0, sid);
|
||||
seqno = seqno + 1;
|
||||
data <= data + len;
|
||||
end
|
||||
if(burst_count > 1)
|
||||
send_packet(len, data, 64'h0, seqno, 1, 0, sid);
|
||||
end
|
||||
endtask // send_ramp
|
||||
|
||||
|
||||
task send_dc;
|
||||
input [31:0] burst_count;
|
||||
input [31:0] len;
|
||||
input [31:0] sid;
|
||||
|
||||
reg [31:0] data;
|
||||
|
||||
begin
|
||||
seqno = 0;
|
||||
data = 1 << 14;
|
||||
send_packet(len, data, 0, seqno, (burst_count==1), 0, sid);
|
||||
seqno = seqno + 1;
|
||||
|
||||
|
||||
if(burst_count > 2)
|
||||
repeat (burst_count - 2)
|
||||
begin
|
||||
send_packet(len, data, 64'h0, seqno, 0, 0, sid);
|
||||
seqno = seqno + 1;
|
||||
|
||||
end
|
||||
if(burst_count > 1)
|
||||
send_packet(len, data, 64'h0, seqno, 1, 0, sid);
|
||||
end
|
||||
endtask // send_ramp
|
||||
|
||||
task send_burst;
|
||||
input [31:0] burst_count;
|
||||
input [31:0] len;
|
||||
input [31:0] start_data;
|
||||
input [63:0] send_time;
|
||||
input [11:0] start_seqnum;
|
||||
input send_at;
|
||||
input [31:0] sid;
|
||||
|
||||
begin
|
||||
seqno = start_seqnum;
|
||||
send_packet(len, {seqno,start_data[15:0]}, send_time, seqno, (burst_count==1), send_at, sid);
|
||||
seqno = seqno + 1;
|
||||
|
||||
if(burst_count > 2)
|
||||
repeat (burst_count - 2)
|
||||
begin
|
||||
send_packet(len, {seqno,start_data[15:0]}, 64'h0, seqno, 0, 0, sid);
|
||||
seqno = seqno + 1;
|
||||
end
|
||||
if(burst_count > 1)
|
||||
send_packet(len, {seqno,start_data[15:0]}, 64'h0, seqno, 1, 0, sid);
|
||||
end
|
||||
endtask // send_burst
|
||||
|
||||
task send_burst_with_seqid_error;
|
||||
input [31:0] burst_count;
|
||||
input [31:0] len;
|
||||
input [31:0] start_data;
|
||||
input [63:0] send_time;
|
||||
input [11:0] start_seqnum;
|
||||
input send_at;
|
||||
input [31:0] sid;
|
||||
|
||||
|
||||
begin
|
||||
seqno = start_seqnum;
|
||||
send_packet(len, {seqno,start_data[15:0]}, send_time, seqno, (burst_count==1), send_at, sid);
|
||||
seqno = seqno + 1;
|
||||
|
||||
if(burst_count > 2)
|
||||
repeat (burst_count - 2)
|
||||
begin
|
||||
// Add a SeqID error in the middle of the packet burst
|
||||
if (seqno == (start_seqnum + burst_count/2))
|
||||
seqno = seqno + 1;
|
||||
send_packet(len, {seqno,start_data[15:0]}, 64'h0, seqno, 0, 0, sid);
|
||||
seqno = seqno + 1;
|
||||
end
|
||||
if(burst_count > 1)
|
||||
send_packet(len, {seqno,start_data[15:0]}, 64'h0, seqno, 1, 0, sid);
|
||||
end
|
||||
endtask // send_burst
|
||||
|
||||
task send_packet;
|
||||
input [31:0] len;
|
||||
input [31:0] start_data;
|
||||
input [63:0] send_time;
|
||||
input [11:0] pkt_seqnum;
|
||||
input eob;
|
||||
input send_at;
|
||||
input [31:0] sid;
|
||||
|
||||
begin
|
||||
// Send a packet
|
||||
samp0 <= start_data;
|
||||
samp1 <= start_data + 1;
|
||||
@(posedge clk);
|
||||
|
||||
tlast <= 0;
|
||||
tdata <= { 1'b0, 1'b0 /*trl*/, send_at, eob, pkt_seqnum, len[15:0]+16'd2+send_at+send_at, sid };
|
||||
tvalid <= 1;
|
||||
@(posedge clk)
|
||||
if(send_at)
|
||||
begin
|
||||
tdata <= send_time;
|
||||
@(posedge clk);
|
||||
end
|
||||
|
||||
repeat (len[31:1]+len[0]-1)
|
||||
begin
|
||||
tdata <= {samp0,samp1};
|
||||
samp0 <= samp0 + 2;
|
||||
samp1 <= samp1 + 2;
|
||||
@(posedge clk);
|
||||
end
|
||||
|
||||
tdata <= {samp0,samp1};
|
||||
tlast <= 1'b1;
|
||||
@(posedge clk);
|
||||
tvalid <= 0;
|
||||
@(posedge clk);
|
||||
end
|
||||
endtask // send_packet
|
||||
|
||||
`ifdef SIM_SCRIPT
|
||||
// Load simulation script from local directory
|
||||
`include "simulation_script.v"
|
||||
|
||||
`else
|
||||
initial
|
||||
begin
|
||||
tvalid <= 1'b0;
|
||||
while(reset)
|
||||
@(posedge clk);
|
||||
write_setting_bus(SR_ERROR_POLICY,32'h4);
|
||||
write_setting_bus(SR_PACKETS,32'h8000_0002);
|
||||
|
||||
write_setting_bus(SR_INTERP,32'h1);
|
||||
|
||||
send_burst(2/*count*/,5/*len*/,32'hA000_0000/*start*/,64'h100/*time*/,12'h000/*seqnum*/,1/*sendat*/, 32'hDEADBEEF/*sid*/);
|
||||
//send_burst(3/*count*/,6/*len*/,32'hB000_0000/*start*/,64'h0/*time*/,12'h004/*seqnum*/,0/*sendat*/, 32'hDEADBEEF/*sid*/);
|
||||
|
||||
//Intra burst seq_id error
|
||||
send_burst_with_seqid_error(8/*count*/,10/*len*/,32'hC000_0000/*start*/,64'h200/*time*/,12'h002/*seqnum*/,1/*sendat*/, 32'hDEADBEEF/*sid*/);
|
||||
|
||||
|
||||
// Inter burst sequence error
|
||||
send_burst(2/*count*/,10/*len*/,32'hC000_0000/*start*/,64'h300/*time*/,12'h015/*seqnum*/,1/*sendat*/, 32'hDEADBEEF/*sid*/);
|
||||
|
||||
// Single Packet burst, timed
|
||||
//send_packet(3/*count*/,32'hA000_0000/*data*/,64'h100/*time*/,1/*SEQ*/,1/*EOP*/,1/*eob*/,1/*timed*/,0/*odd*/);
|
||||
|
||||
// 2 packet burst, timed
|
||||
//send_packet(3/*count*/,32'hB000_0000/*data*/,64'h200/*time*/,2/*SEQ*/,1/*EOP*/,0/*eob*/,1/*timed*/,0/*odd*/);
|
||||
//send_packet(3/*count*/,32'hC000_0000/*data*/,64'h0/*time*/,3/*SEQ*/,1/*EOP*/,1/*eob*/,0/*timed*/,0/*odd*/);
|
||||
|
||||
// single odd packet
|
||||
//send_packet(3/*count*/,32'h0A00_0000/*data*/,64'h300/*time*/,4/*SEQ*/,1/*EOP*/,1/*eob*/,1/*timed*/,1/*odd*/);
|
||||
|
||||
// 2 packet burst, timed, odd
|
||||
//send_packet(3/*count*/,32'hD000_0000/*data*/,64'h400/*time*/,5/*SEQ*/,1/*EOP*/,0/*eob*/,1/*timed*/,1/*odd*/);
|
||||
//send_packet(3/*count*/,32'hE000_0000/*data*/,64'd0/*time*/,6/*SEQ*/,1/*EOP*/,1/*eob*/,0/*timed*/,1/*odd*/);
|
||||
|
||||
// 2 packet burst, untimed, no eob set
|
||||
//send_packet(3/*count*/,32'hF000_0000/*data*/,64'd0/*time*/,7/*SEQ*/,1/*EOP*/,0/*eob*/,0/*timed*/,0/*odd*/);
|
||||
//send_packet(3/*count*/,32'h9000_0000/*data*/,64'd0/*time*/,8/*SEQ*/,1/*EOP*/,0/*eob*/,0/*timed*/,0/*odd*/);
|
||||
|
||||
// single packet late
|
||||
//send_packet(3/*count*/,32'hD000_0000/*data*/,64'h0/*time*/,4/*SEQ*/,1/*EOP*/,1/*eob*/,1/*timed*/,1/*odd*/);
|
||||
|
||||
end
|
||||
`endif // !`ifdef SIM_SCRIPT
|
||||
|
||||
always @(posedge clk)
|
||||
if(reset)
|
||||
vita_time <= 0;
|
||||
else
|
||||
vita_time <= vita_time + 1;
|
||||
|
||||
axi_fifo #(.WIDTH(65)) axi_fifo_short
|
||||
(.clk(clk), .reset(reset), .clear(1'b0),
|
||||
.i_tdata({tlast,tdata}), .i_tvalid(tvalid), .i_tready(tready),
|
||||
.o_tdata({i_tlast,i_tdata}), .o_tvalid(i_tvalid), .o_tready(i_tready));
|
||||
|
||||
new_tx_deframer new_tx_deframer
|
||||
(.clk(clk), .reset(reset), .clear(1'b0),
|
||||
.i_tdata(i_tdata), .i_tlast(i_tlast), .i_tvalid(i_tvalid), .i_tready(i_tready),
|
||||
.sample_tdata(sample_tdata), .sample_tvalid(sample_tvalid), .sample_tready(sample_tready));
|
||||
|
||||
new_tx_control #(.BASE(SR_TX_CTRL)) new_tx_control
|
||||
(.clk(clk), .reset(reset), .clear(1'b0),
|
||||
.set_stb(set_stb), .set_addr(set_addr), .set_data(set_data),
|
||||
|
||||
.vita_time(vita_time),
|
||||
.ack_or_error(ack_or_error), .packet_consumed(packet_consumed),
|
||||
.seqnum(seqnum), .error_code(error_code), .sid(sid),
|
||||
|
||||
.sample_tdata(sample_tdata), .sample_tvalid(sample_tvalid), .sample_tready(sample_tready),
|
||||
|
||||
.sample(sample), .run(run), .strobe(strobe),
|
||||
.debug()
|
||||
);
|
||||
|
||||
wire [63:0] o_tdata;
|
||||
wire o_tlast, o_tvalid, o_tready;
|
||||
assign o_tready = 1;
|
||||
|
||||
tx_responder #(.BASE(SR_TX_RESPONDER)) tx_responder
|
||||
(.clk(clk), .reset(reset), .clear(1'b0),
|
||||
.set_stb(set_stb), .set_addr(set_addr), .set_data(set_data),
|
||||
.ack_or_error(ack_or_error), .packet_consumed(packet_consumed),
|
||||
.seqnum(seqnum), .error_code(error_code), .sid(sid),
|
||||
.vita_time(vita_time),
|
||||
.o_tdata(o_tdata), .o_tlast(o_tlast), .o_tvalid(o_tvalid), .o_tready(o_tready));
|
||||
|
||||
always @(posedge clk)
|
||||
if(o_tvalid & o_tready)
|
||||
$display("\t\t\t\t\tRESP %x\t%x",o_tdata,o_tlast);
|
||||
|
||||
always @(posedge clk)
|
||||
if(~reset)
|
||||
begin
|
||||
if(strobe & run)
|
||||
$display("%x\t%x", vita_time, sample);
|
||||
if(strobe & ~run) $display("Spurious Strobe at time %x",vita_time);
|
||||
if(packet_consumed) $display("CONSUMED %x", seqnum);
|
||||
if(ack_or_error)
|
||||
if(error_code[63:32] == 1)
|
||||
$display("ACK -- SEQNUM %x", error_code[31:0]);
|
||||
else
|
||||
$display("ERROR -- SEQNUM %x ERRCODE %x", error_code[31:0],error_code[63:32]);
|
||||
end
|
||||
|
||||
wire [23:0] tx_fe_i, tx_fe_q;
|
||||
|
||||
duc_chain #(.BASE(SR_TX_DSP), .DSPNO(0), .WIDTH(24)) duc_chain
|
||||
(.clk(clk), .rst(reset), .clr(1'b0),
|
||||
.set_stb(set_stb),.set_addr(set_addr),.set_data(set_data),
|
||||
.tx_fe_i(tx_fe_i),.tx_fe_q(tx_fe_q),
|
||||
.sample(sample), .run(run), .strobe(strobe),
|
||||
.debug() );
|
||||
|
||||
endmodule // new_tx_tb
|
||||
@@ -0,0 +1,50 @@
|
||||
//
|
||||
// Copyright 2011 Ettus Research LLC
|
||||
//
|
||||
|
||||
|
||||
|
||||
|
||||
module trigger_context_pkt
|
||||
#(parameter BASE=0)
|
||||
(input clk, input reset, input clear,
|
||||
input set_stb, input [7:0] set_addr, input [31:0] set_data,
|
||||
input packet_consumed, output trigger);
|
||||
|
||||
wire [23:0] cycles;
|
||||
wire [15:0] packets;
|
||||
wire [6:0] dummy1;
|
||||
wire [14:0] dummy2;
|
||||
wire enable_cycle, enable_consumed;
|
||||
reg [30:0] cycle_count, packet_count;
|
||||
|
||||
|
||||
setting_reg #(.my_addr(BASE), .at_reset(0)) sr_cycles
|
||||
(.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr),
|
||||
.in(set_data),.out({enable_cycle,dummy1,cycles}),.changed());
|
||||
|
||||
setting_reg #(.my_addr(BASE+1), .at_reset(0)) sr_packets
|
||||
(.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr),
|
||||
.in(set_data),.out({enable_consumed,dummy2,packets}),.changed());
|
||||
|
||||
always @(posedge clk)
|
||||
if(reset | clear)
|
||||
cycle_count <= 0;
|
||||
else
|
||||
if(trigger)
|
||||
cycle_count <= 0;
|
||||
else if((enable_cycle & packet_consumed) | (cycle_count != 0))
|
||||
cycle_count <= cycle_count + 1;
|
||||
|
||||
always @(posedge clk)
|
||||
if(reset | clear)
|
||||
packet_count <= 0;
|
||||
else
|
||||
if(trigger)
|
||||
packet_count <= 0;
|
||||
else if(packet_consumed & enable_consumed)
|
||||
packet_count <= packet_count + 1;
|
||||
|
||||
assign trigger = (enable_cycle & (cycle_count >= cycles)) | (enable_consumed & (packet_count >= packets));
|
||||
|
||||
endmodule // trigger_context_pkt
|
||||
@@ -0,0 +1,52 @@
|
||||
|
||||
module tx_responder
|
||||
#(parameter BASE = 0)
|
||||
(input clk, input reset, input clear,
|
||||
input set_stb, input [7:0] set_addr, input [31:0] set_data,
|
||||
|
||||
input ack_or_error, input packet_consumed,
|
||||
input [11:0] seqnum,
|
||||
input [63:0] error_code,
|
||||
input [31:0] sid,
|
||||
|
||||
input [63:0] vita_time,
|
||||
output [63:0] o_tdata, output o_tlast, output o_tvalid, input o_tready);
|
||||
|
||||
reg [11:0] seqnum_int;
|
||||
|
||||
always @(posedge clk)
|
||||
if(packet_consumed)
|
||||
seqnum_int <= seqnum;
|
||||
|
||||
wire trigger_fc, trigger_ctxt;
|
||||
wire [95:0] msg_data = { sid[15:0], sid[31:16], (ack_or_error ? error_code : {32'h0,20'h0,seqnum_int}) };
|
||||
wire [95:0] ctxt_data;
|
||||
|
||||
reg [11:0] reply_seqnum;
|
||||
wire done;
|
||||
|
||||
always @(posedge clk)
|
||||
if(reset | clear)
|
||||
reply_seqnum <= 12'd0;
|
||||
else if(done)
|
||||
reply_seqnum <= reply_seqnum + 12'd1;
|
||||
|
||||
trigger_context_pkt #(.BASE(BASE)) trig
|
||||
(.clk(clk), .reset(reset), .clear(clear),
|
||||
.set_stb(set_stb), .set_addr(set_addr), .set_data(set_data),
|
||||
.packet_consumed(packet_consumed), .trigger(trigger_fc));
|
||||
|
||||
axi_fifo_short #(.WIDTH(64+32)) ack_queue
|
||||
(.clk(clk), .reset(reset), .clear(clear),
|
||||
.i_tdata(msg_data), .i_tvalid(ack_or_error | trigger_fc), .i_tready(),
|
||||
.o_tdata(ctxt_data), .o_tvalid(trigger_ctxt), .o_tready(done),
|
||||
.space(), .occupied());
|
||||
|
||||
context_packet_gen ack_err_gen
|
||||
(.clk(clk), .reset(reset), .clear(clear),
|
||||
.trigger(trigger_ctxt), .seqnum(reply_seqnum), .sid(ctxt_data[95:64]),
|
||||
.body(ctxt_data[63:0]), .vita_time(vita_time),
|
||||
.done(done),
|
||||
.o_tdata(o_tdata), .o_tlast(o_tlast), .o_tvalid(o_tvalid), .o_tready(o_tready));
|
||||
|
||||
endmodule // tx_responder
|
||||
Reference in New Issue
Block a user