Squashed B200 FPGA Source. Code from Josh Blum, Ian Buckley, and Matt Ettus.

Original-commit: 0df4b801a34697f2058b4a7b95e08d2a0576c9db
This commit is contained in:
Ben Hilburn
2013-10-10 10:17:27 -07:00
commit c91b74de33
488 changed files with 281740 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
*tb
+29
View File
@@ -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 \
))
View File
+37
View File
@@ -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
+1
View File
@@ -0,0 +1 @@
iverilog -y . -y ../dsp/ -y ../control/ -Wall chdr_12sc_to_16sc_tb.v -o chdr_12sc_to_16sc_tb
+1
View File
@@ -0,0 +1 @@
iverilog -y . -y ../dsp/ -y ../control/ -Wall chdr_16sc_to_12sc_tb.v -o chdr_16sc_to_12sc_tb
+2
View File
@@ -0,0 +1,2 @@
iverilog -y . -y ../dsp/ -y ../control/ -Wall chdr_16sc_to_8sc_tb.v -o chdr_16sc_to_8sc_tb
+2
View File
@@ -0,0 +1,2 @@
iverilog -y . -y ../dsp/ -y ../control/ -Wall chdr_8sc_to_16sc_tb.v -o chdr_8sc_to_16sc_tb
+176
View File
@@ -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
+188
View File
@@ -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
+221
View File
@@ -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
+165
View File
@@ -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
+138
View File
@@ -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
+145
View File
@@ -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
+186
View File
@@ -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
+146
View File
@@ -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
+105
View File
@@ -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
+142
View File
@@ -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
+152
View File
@@ -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
+5
View File
@@ -0,0 +1,5 @@
7F805A6B11006792
88990011CCDD00AA
+115
View File
@@ -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
+148
View File
@@ -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
+107
View File
@@ -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
+51
View File
@@ -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
+79
View File
@@ -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
+69
View File
@@ -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
+12
View File
@@ -0,0 +1,12 @@
7FF8000001115AB6
B6EEFEE599A577E9
F0005AB800CCE7FF
F0005AB800CCE7FF
B6EEFEE599A577E9
7FF8000001115AB6
B6EEFEE599A577E9
7FF8000001115AB6
B6EEFEE599A577E9
9999ACCAEEEEFFFF
7878000065568799
6543111122223333
+8
View File
@@ -0,0 +1,8 @@
8000FFFF7FFF1111
00005A6BEEEE9999
7AAAEEEE7FFF0000
5AB890874676BBBB
EEEE888800007FFF
DACCCADBEEFFEED0
FEEDBEEF0000BAAB
CAB8000BACEDEED0
+12
View File
@@ -0,0 +1,12 @@
8000FFFF7FFF1111
00005A6BEEEE9999
7AAAEEEE7FFF0000
7AAAEEEE7FFF0000
7AAAEEEE7FFF0000
7AAAEEEE7FFF0000
7AAAEEEE7FFF0000
7AAAEEEE7FFF0000
7AAAEEEE7FFF0000
7AAAEEEE7FFF0000
7AAAEEEE7FFF0000
7AAAEEEE7FFF0000
+87
View File
@@ -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;
}
+92
View File
@@ -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
+61
View File
@@ -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
+242
View File
@@ -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
+219
View File
@@ -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
+135
View File
@@ -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
+171
View File
@@ -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
+140
View File
@@ -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
+92
View File
@@ -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
+361
View File
@@ -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
+50
View File
@@ -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
+52
View File
@@ -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