mirror of
https://github.com/fairwaves/UHD-Fairwaves.git
synced 2025-11-03 13:33:15 +00:00
umtrx: updated many cores and top level, dsp still needs proper strobes
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright 2010 Ettus Research LLC
|
||||
# Copyright 2010-2012 Ettus Research LLC
|
||||
#
|
||||
|
||||
##################################################
|
||||
@@ -55,4 +55,8 @@ settings_bus_16LE.v \
|
||||
atr_controller16.v \
|
||||
fifo_to_wb.v \
|
||||
gpio_atr.v \
|
||||
user_settings.v \
|
||||
settings_fifo_ctrl.v \
|
||||
simple_spi_core.v \
|
||||
simple_i2c_core.v \
|
||||
))
|
||||
|
||||
@@ -27,7 +27,7 @@ module double_buffer_tb();
|
||||
reg src_rdy_i = 0;
|
||||
wire dst_rdy_o;
|
||||
|
||||
wire dst_rdy_i = 1;
|
||||
wire dst_rdy_i = 0;
|
||||
wire [35:0] data_o;
|
||||
reg [35:0] data_i;
|
||||
|
||||
@@ -46,9 +46,9 @@ module double_buffer_tb();
|
||||
.data_i(data_i), .src_rdy_i(src_rdy_i), .dst_rdy_o(dst_rdy_o),
|
||||
.data_o(data_o), .src_rdy_o(src_rdy_o), .dst_rdy_i(dst_rdy_i));
|
||||
|
||||
dspengine_16to8 dspengine_16to8
|
||||
dspengine_8to16 #(.HEADER_OFFSET(1)) dspengine_8to16
|
||||
(.clk(clk),.reset(rst),.clear(0),
|
||||
.set_stb(set_stb), .set_addr(0), .set_data({13'h0,1'b1,18'h00400}),
|
||||
.set_stb(set_stb), .set_addr(0), .set_data(1),
|
||||
.access_we(access_we), .access_stb(access_stb), .access_ok(access_ok), .access_done(access_done),
|
||||
.access_skip_read(access_skip_read), .access_adr(access_adr), .access_len(access_len),
|
||||
.access_dat_i(buf_to_dsp), .access_dat_o(dsp_to_buf));
|
||||
@@ -69,11 +69,13 @@ module double_buffer_tb();
|
||||
@(posedge clk);
|
||||
@(posedge clk);
|
||||
@(posedge clk);
|
||||
|
||||
/*
|
||||
// Passthrough
|
||||
$display("Passthrough");
|
||||
src_rdy_i <= 1;
|
||||
data_i <= { 2'b00,1'b0,1'b1,32'hFFFFFFFF};
|
||||
data_i <= { 2'b00,1'b0,1'b1,32'h01234567};
|
||||
@(posedge clk);
|
||||
data_i <= { 2'b00,1'b0,1'b0,32'hFFFFFFFF};
|
||||
@(posedge clk);
|
||||
data_i <= { 2'b00,1'b0,1'b0,32'h04050607};
|
||||
@(posedge clk);
|
||||
@@ -86,16 +88,18 @@ module double_buffer_tb();
|
||||
|
||||
repeat (5)
|
||||
@(posedge clk);
|
||||
|
||||
*/
|
||||
$display("Enabled");
|
||||
set_stb <= 1;
|
||||
@(posedge clk);
|
||||
set_stb <= 0;
|
||||
|
||||
/*
|
||||
@(posedge clk);
|
||||
$display("Non-IF Data Passthrough");
|
||||
src_rdy_i <= 1;
|
||||
data_i <= { 2'b00,1'b0,1'b1,32'hC0000000};
|
||||
data_i <= { 2'b00,1'b0,1'b1,32'h89acdef0};
|
||||
@(posedge clk);
|
||||
data_i <= { 2'b00,1'b0,1'b0,32'hC0000000};
|
||||
@(posedge clk);
|
||||
data_i <= { 2'b00,1'b0,1'b0,32'h14151617};
|
||||
@(posedge clk);
|
||||
@@ -111,7 +115,9 @@ module double_buffer_tb();
|
||||
|
||||
$display("No StreamID, No Trailer, Even");
|
||||
src_rdy_i <= 1;
|
||||
data_i <= { 2'b00,1'b0,1'b1,32'h0000FFFF};
|
||||
data_i <= { 2'b00,1'b0,1'b1,32'hAAAAAAAA};
|
||||
@(posedge clk);
|
||||
data_i <= { 2'b00,1'b0,1'b0,32'h0000FFFF};
|
||||
@(posedge clk);
|
||||
data_i <= { 2'b00,1'b0,1'b0,32'h01000200};
|
||||
@(posedge clk);
|
||||
@@ -139,7 +145,9 @@ module double_buffer_tb();
|
||||
|
||||
$display("No StreamID, No Trailer, Odd");
|
||||
src_rdy_i <= 1;
|
||||
data_i <= { 2'b00,1'b0,1'b1,32'h0000FFFF};
|
||||
data_i <= { 2'b00,1'b0,1'b1,32'hBBBBBBBB};
|
||||
@(posedge clk);
|
||||
data_i <= { 2'b00,1'b0,1'b0,32'h0000FFFF};
|
||||
@(posedge clk);
|
||||
data_i <= { 2'b00,1'b0,1'b0,32'h11001200};
|
||||
@(posedge clk);
|
||||
@@ -159,30 +167,59 @@ module double_buffer_tb();
|
||||
|
||||
while(~dst_rdy_o)
|
||||
@(posedge clk);
|
||||
|
||||
*/
|
||||
/*
|
||||
$display("No StreamID, Trailer, Even");
|
||||
src_rdy_i <= 1;
|
||||
data_i <= { 2'b00,1'b0,1'b1,32'h0400FFFF};
|
||||
data_i <= { 2'b00,1'b0,1'b1,32'hCCCCCCCC};
|
||||
@(posedge clk);
|
||||
data_i <= { 2'b00,1'b0,1'b0,32'h21002200};
|
||||
data_i <= { 2'b00,1'b0,1'b0,32'h0400FFFF};
|
||||
@(posedge clk);
|
||||
data_i <= { 2'b00,1'b0,1'b0,32'h23002400};
|
||||
data_i <= { 2'b00,1'b0,1'b0,32'h21222324};
|
||||
@(posedge clk);
|
||||
data_i <= { 2'b00,1'b0,1'b0,32'h25262728};
|
||||
src_rdy_i <= 0;
|
||||
@(posedge clk);
|
||||
src_rdy_i <= 1;
|
||||
@(posedge clk);
|
||||
data_i <= { 2'b00,1'b0,1'b0,32'h25002600};
|
||||
data_i <= { 2'b00,1'b0,1'b0,32'h292a2b2c};
|
||||
@(posedge clk);
|
||||
data_i <= { 2'b00,1'b0,1'b0,32'h27002800};
|
||||
data_i <= { 2'b00,1'b0,1'b0,32'h2d2e2f30};
|
||||
@(posedge clk);
|
||||
data_i <= { 2'b00,1'b1,1'b0,32'h29002a00};
|
||||
data_i <= { 2'b00,1'b1,1'b0,32'hDEADBEEF};
|
||||
@(posedge clk);
|
||||
src_rdy_i <= 0;
|
||||
@(posedge clk);
|
||||
|
||||
*/
|
||||
while(~dst_rdy_o)
|
||||
@(posedge clk);
|
||||
/*
|
||||
$display("No StreamID, Trailer, Odd");
|
||||
src_rdy_i <= 1;
|
||||
data_i <= { 2'b00,1'b0,1'b1,32'hDDDDDDDD};
|
||||
@(posedge clk);
|
||||
data_i <= { 2'b00,1'b0,1'b0,32'h0400FFFF};
|
||||
@(posedge clk);
|
||||
data_i <= { 2'b00,1'b0,1'b0,32'h21222324};
|
||||
@(posedge clk);
|
||||
data_i <= { 2'b00,1'b0,1'b0,32'h25262728};
|
||||
src_rdy_i <= 0;
|
||||
@(posedge clk);
|
||||
src_rdy_i <= 1;
|
||||
@(posedge clk);
|
||||
data_i <= { 2'b00,1'b0,1'b0,32'h292a2b2c};
|
||||
@(posedge clk);
|
||||
data_i <= { 2'b00,1'b0,1'b0,32'h2d2e2f30};
|
||||
@(posedge clk);
|
||||
data_i <= { 2'b00,1'b1,1'b0,32'hDEBDBF0D};
|
||||
@(posedge clk);
|
||||
src_rdy_i <= 0;
|
||||
@(posedge clk);
|
||||
*/
|
||||
while(~dst_rdy_o)
|
||||
@(posedge clk);
|
||||
|
||||
/*
|
||||
$display("No StreamID, Trailer, Odd");
|
||||
src_rdy_i <= 1;
|
||||
data_i <= { 2'b00,1'b0,1'b1,32'h0400FFFF};
|
||||
@@ -226,23 +263,45 @@ module double_buffer_tb();
|
||||
|
||||
while(~dst_rdy_o)
|
||||
@(posedge clk);
|
||||
|
||||
*/
|
||||
$display("StreamID, Trailer, Odd");
|
||||
src_rdy_i <= 1;
|
||||
data_i <= { 2'b00,1'b0,1'b1,32'h1400FFFF};
|
||||
data_i <= { 2'b00,1'b0,1'b1,32'hABCDEF98};
|
||||
@(posedge clk);
|
||||
data_i <= { 2'b00,1'b0,1'b0,32'ha100a200};
|
||||
data_i <= { 2'b00,1'b0,1'b0,32'h1c034567};
|
||||
@(posedge clk);
|
||||
data_i <= { 2'b00,1'b0,1'b0,32'ha0a1a2a3};
|
||||
@(posedge clk);
|
||||
data_i <= { 2'b00,1'b0,1'b0,32'ha4a5a6a7};
|
||||
// src_rdy_i <= 0;
|
||||
// @(posedge clk);
|
||||
// src_rdy_i <= 1;
|
||||
@(posedge clk);
|
||||
data_i <= { 2'b00,1'b0,1'b0,32'ha8a9aaab};
|
||||
@(posedge clk);
|
||||
data_i <= { 2'b00,1'b0,1'b0,32'hacadaeaf};
|
||||
@(posedge clk);
|
||||
data_i <= { 2'b00,1'b1,1'b0,32'hdeadbeef};
|
||||
@(posedge clk);
|
||||
data_i <= { 2'b00,1'b0,1'b0,32'ha300a400};
|
||||
src_rdy_i <= 0;
|
||||
@(posedge clk);
|
||||
src_rdy_i <= 1;
|
||||
data_i <= { 2'b00,1'b0,1'b1,32'hABCDEF98};
|
||||
@(posedge clk);
|
||||
data_i <= { 2'b00,1'b0,1'b0,32'ha500a600};
|
||||
data_i <= { 2'b00,1'b0,1'b0,32'h1c034567};
|
||||
@(posedge clk);
|
||||
data_i <= { 2'b00,1'b0,1'b0,32'ha700a800};
|
||||
data_i <= { 2'b00,1'b0,1'b0,32'ha0a1a2a3};
|
||||
@(posedge clk);
|
||||
data_i <= { 2'b00,1'b1,1'b0,32'hbbb0bbb0};
|
||||
data_i <= { 2'b00,1'b0,1'b0,32'ha4a5a6a7};
|
||||
// src_rdy_i <= 0;
|
||||
// @(posedge clk);
|
||||
// src_rdy_i <= 1;
|
||||
@(posedge clk);
|
||||
data_i <= { 2'b00,1'b0,1'b0,32'ha8a9aaab};
|
||||
@(posedge clk);
|
||||
data_i <= { 2'b00,1'b0,1'b0,32'hacadaeaf};
|
||||
@(posedge clk);
|
||||
data_i <= { 2'b00,1'b1,1'b0,32'hdeadbeef};
|
||||
@(posedge clk);
|
||||
src_rdy_i <= 0;
|
||||
@(posedge clk);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright 2011 Ettus Research LLC
|
||||
// Copyright 2011-2012 Ettus Research LLC
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
@@ -22,16 +22,17 @@
|
||||
// the system or dsp clock on the output side
|
||||
|
||||
module settings_bus_crossclock
|
||||
#(parameter FLOW_CTRL=0)
|
||||
(input clk_i, input rst_i, input set_stb_i, input [7:0] set_addr_i, input [31:0] set_data_i,
|
||||
input clk_o, input rst_o, output set_stb_o, output [7:0] set_addr_o, output [31:0] set_data_o);
|
||||
input clk_o, input rst_o, output set_stb_o, output [7:0] set_addr_o, output [31:0] set_data_o, input blocked);
|
||||
|
||||
wire full, empty;
|
||||
|
||||
fifo_xlnx_16x40_2clk settings_fifo
|
||||
(.rst(rst_i),
|
||||
.wr_clk(clk_i), .din({set_addr_i,set_data_i}), .wr_en(set_stb_i & ~full), .full(full),
|
||||
.rd_clk(clk_o), .dout({set_addr_o,set_data_o}), .rd_en(~empty), .empty(empty));
|
||||
.rd_clk(clk_o), .dout({set_addr_o,set_data_o}), .rd_en(set_stb_o), .empty(empty));
|
||||
|
||||
assign set_stb_o = ~empty;
|
||||
assign set_stb_o = ~empty & (~blocked | ~FLOW_CTRL);
|
||||
|
||||
endmodule // settings_bus_crossclock
|
||||
|
||||
395
fpga/control_lib/settings_fifo_ctrl.v
Normal file
395
fpga/control_lib/settings_fifo_ctrl.v
Normal file
@@ -0,0 +1,395 @@
|
||||
//
|
||||
// Copyright 2012 Ettus Research LLC
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
// A settings and readback bus controlled via fifo36 interface
|
||||
|
||||
module settings_fifo_ctrl
|
||||
#(
|
||||
parameter XPORT_HDR = 1, //extra transport hdr line
|
||||
parameter PROT_DEST = 0, //protocol framer destination
|
||||
parameter PROT_HDR = 1, //needs a protocol header?
|
||||
parameter ACK_SID = 0 //stream ID for packet ACK
|
||||
)
|
||||
(
|
||||
//clock and synchronous reset for all interfaces
|
||||
input clock, input reset, input clear,
|
||||
|
||||
//current system time
|
||||
input [63:0] vita_time,
|
||||
|
||||
//ready signal for multiple peripherals
|
||||
input perfs_ready,
|
||||
|
||||
//input fifo36 interface control
|
||||
input [35:0] in_data, input in_valid, output in_ready,
|
||||
|
||||
//output fifo36 interface status
|
||||
output [35:0] out_data, output out_valid, input out_ready,
|
||||
|
||||
//32-bit settings bus outputs
|
||||
output strobe, output [7:0] addr, output [31:0] data,
|
||||
|
||||
//16X 32-bit inputs for readback
|
||||
input [31:0] word00,
|
||||
input [31:0] word01,
|
||||
input [31:0] word02,
|
||||
input [31:0] word03,
|
||||
input [31:0] word04,
|
||||
input [31:0] word05,
|
||||
input [31:0] word06,
|
||||
input [31:0] word07,
|
||||
input [31:0] word08,
|
||||
input [31:0] word09,
|
||||
input [31:0] word10,
|
||||
input [31:0] word11,
|
||||
input [31:0] word12,
|
||||
input [31:0] word13,
|
||||
input [31:0] word14,
|
||||
input [31:0] word15,
|
||||
|
||||
//debug output
|
||||
output [31:0] debug
|
||||
);
|
||||
|
||||
wire reading = in_valid && in_ready;
|
||||
wire writing = out_valid && out_ready;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
//-- The command fifo:
|
||||
//-- Stores an individual register access command per line.
|
||||
//------------------------------------------------------------------
|
||||
wire [63:0] in_command_ticks, out_command_ticks;
|
||||
wire [31:0] in_command_hdr, out_command_hdr;
|
||||
wire [31:0] in_command_data, out_command_data;
|
||||
wire in_command_has_time, out_command_has_time;
|
||||
wire command_fifo_full, command_fifo_empty;
|
||||
wire command_fifo_read, command_fifo_write;
|
||||
|
||||
shortfifo #(.WIDTH(129)) command_fifo (
|
||||
.clk(clock), .rst(reset), .clear(clear),
|
||||
.datain({in_command_ticks, in_command_hdr, in_command_data, in_command_has_time}),
|
||||
.dataout({out_command_ticks, out_command_hdr, out_command_data, out_command_has_time}),
|
||||
.write(command_fifo_write), .full(command_fifo_full), //input interface
|
||||
.empty(command_fifo_empty), .read(command_fifo_read) //output interface
|
||||
);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
//-- The result fifo:
|
||||
//-- Stores an individual result of a command per line.
|
||||
//------------------------------------------------------------------
|
||||
wire [31:0] in_result_hdr, out_result_hdr;
|
||||
wire [31:0] in_result_data, out_result_data;
|
||||
wire result_fifo_full, result_fifo_empty;
|
||||
wire result_fifo_read, result_fifo_write;
|
||||
|
||||
shortfifo #(.WIDTH(64)) result_fifo (
|
||||
.clk(clock), .rst(reset), .clear(clear),
|
||||
.datain({in_result_hdr, in_result_data}),
|
||||
.dataout({out_result_hdr, out_result_data}),
|
||||
.write(result_fifo_write), .full(result_fifo_full), //input interface
|
||||
.empty(result_fifo_empty), .read(result_fifo_read) //output interface
|
||||
);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
//-- Input state machine:
|
||||
//-- Read input packet and fill a command fifo entry.
|
||||
//------------------------------------------------------------------
|
||||
localparam READ_LINE0 = 0;
|
||||
localparam VITA_HDR = 1;
|
||||
localparam VITA_SID = 2;
|
||||
localparam VITA_CID0 = 3;
|
||||
localparam VITA_CID1 = 4;
|
||||
localparam VITA_TSI = 5;
|
||||
localparam VITA_TSF0 = 6;
|
||||
localparam VITA_TSF1 = 7;
|
||||
localparam READ_HDR = 8;
|
||||
localparam READ_DATA = 9;
|
||||
localparam WAIT_EOF = 10;
|
||||
localparam STORE_CMD = 11;
|
||||
|
||||
localparam START_STATE = (XPORT_HDR)? READ_LINE0 : VITA_HDR;
|
||||
|
||||
reg [4:0] in_state;
|
||||
|
||||
//holdover from current read inputs
|
||||
reg [31:0] in_data_reg, in_hdr_reg;
|
||||
reg [63:0] in_ticks_reg;
|
||||
wire has_sid = in_data[28];
|
||||
wire has_cid = in_data[27];
|
||||
wire has_tsi = in_data[23:22] != 0;
|
||||
wire has_tsf = in_data[21:20] != 0;
|
||||
reg has_sid_reg, has_cid_reg, has_tsi_reg, has_tsf_reg;
|
||||
|
||||
assign in_ready = (in_state < STORE_CMD);
|
||||
assign command_fifo_write = (in_state == STORE_CMD);
|
||||
assign in_command_ticks = in_ticks_reg;
|
||||
assign in_command_data = in_data_reg;
|
||||
assign in_command_hdr = in_hdr_reg;
|
||||
assign in_command_has_time = has_tsf_reg;
|
||||
|
||||
always @(posedge clock) begin
|
||||
if (reset) begin
|
||||
in_state <= START_STATE;
|
||||
end
|
||||
else begin
|
||||
case (in_state)
|
||||
|
||||
READ_LINE0: begin
|
||||
if (reading) in_state <= VITA_HDR;
|
||||
end
|
||||
|
||||
VITA_HDR: begin
|
||||
if (reading) begin
|
||||
if (has_sid) in_state <= VITA_SID;
|
||||
else if (has_cid) in_state <= VITA_CID0;
|
||||
else if (has_tsi) in_state <= VITA_TSI;
|
||||
else if (has_tsf) in_state <= VITA_TSF0;
|
||||
else in_state <= READ_HDR;
|
||||
end
|
||||
has_sid_reg <= has_sid;
|
||||
has_cid_reg <= has_cid;
|
||||
has_tsi_reg <= has_tsi;
|
||||
has_tsf_reg <= has_tsf;
|
||||
end
|
||||
|
||||
VITA_SID: begin
|
||||
if (reading) begin
|
||||
if (has_cid_reg) in_state <= VITA_CID0;
|
||||
else if (has_tsi_reg) in_state <= VITA_TSI;
|
||||
else if (has_tsf_reg) in_state <= VITA_TSF0;
|
||||
else in_state <= READ_HDR;
|
||||
end
|
||||
end
|
||||
|
||||
VITA_CID0: begin
|
||||
if (reading) in_state <= VITA_CID1;
|
||||
end
|
||||
|
||||
VITA_CID1: begin
|
||||
if (reading) begin
|
||||
if (has_tsi_reg) in_state <= VITA_TSI;
|
||||
else if (has_tsf_reg) in_state <= VITA_TSF0;
|
||||
else in_state <= READ_HDR;
|
||||
end
|
||||
end
|
||||
|
||||
VITA_TSI: begin
|
||||
if (reading) begin
|
||||
if (has_tsf_reg) in_state <= VITA_TSF0;
|
||||
else in_state <= READ_HDR;
|
||||
end
|
||||
end
|
||||
|
||||
VITA_TSF0: begin
|
||||
if (reading) in_state <= VITA_TSF1;
|
||||
in_ticks_reg[63:32] <= in_data;
|
||||
end
|
||||
|
||||
VITA_TSF1: begin
|
||||
if (reading) in_state <= READ_HDR;
|
||||
in_ticks_reg[31:0] <= in_data;
|
||||
end
|
||||
|
||||
READ_HDR: begin
|
||||
if (reading) in_state <= READ_DATA;
|
||||
in_hdr_reg <= in_data[31:0];
|
||||
end
|
||||
|
||||
READ_DATA: begin
|
||||
if (reading) in_state <= (in_data[33])? STORE_CMD : WAIT_EOF;
|
||||
in_data_reg <= in_data[31:0];
|
||||
end
|
||||
|
||||
WAIT_EOF: begin
|
||||
if (reading && in_data[33]) in_state <= STORE_CMD;
|
||||
end
|
||||
|
||||
STORE_CMD: begin
|
||||
if (~command_fifo_full) in_state <= START_STATE;
|
||||
end
|
||||
|
||||
endcase //in_state
|
||||
end
|
||||
end
|
||||
|
||||
//------------------------------------------------------------------
|
||||
//-- Command state machine:
|
||||
//-- Read a command fifo entry, act on it, produce result.
|
||||
//------------------------------------------------------------------
|
||||
localparam LOAD_CMD = 0;
|
||||
localparam EVENT_CMD = 1;
|
||||
|
||||
reg cmd_state;
|
||||
reg [31:0] rb_data;
|
||||
|
||||
reg [63:0] command_ticks_reg;
|
||||
reg [31:0] command_hdr_reg;
|
||||
reg [31:0] command_data_reg;
|
||||
|
||||
reg [63:0] vita_time_reg;
|
||||
always @(posedge clock)
|
||||
vita_time_reg <= vita_time;
|
||||
|
||||
wire late;
|
||||
`ifndef FIFO_CTRL_NO_TIME
|
||||
time_compare time_compare(
|
||||
.time_now(vita_time_reg), .trigger_time(command_ticks_reg), .late(late));
|
||||
`else
|
||||
assign late = 1;
|
||||
`endif
|
||||
|
||||
//action occurs in the event state and when there is fifo space (should always be true)
|
||||
//the third condition is that all peripherals in the perfs signal are ready/active high
|
||||
//the fourth condition is that is an event time has been set, action is delayed until that time
|
||||
wire time_ready = (out_command_has_time)? late : 1;
|
||||
wire action = (cmd_state == EVENT_CMD) && ~result_fifo_full && perfs_ready && time_ready;
|
||||
|
||||
assign command_fifo_read = action;
|
||||
assign result_fifo_write = action;
|
||||
assign in_result_hdr = command_hdr_reg;
|
||||
assign in_result_data = rb_data;
|
||||
|
||||
always @(posedge clock) begin
|
||||
if (reset) begin
|
||||
cmd_state <= LOAD_CMD;
|
||||
end
|
||||
else begin
|
||||
case (cmd_state)
|
||||
|
||||
LOAD_CMD: begin
|
||||
if (~command_fifo_empty) cmd_state <= EVENT_CMD;
|
||||
command_ticks_reg <= out_command_ticks;
|
||||
command_hdr_reg <= out_command_hdr;
|
||||
command_data_reg <= out_command_data;
|
||||
end
|
||||
|
||||
EVENT_CMD: begin // poking and peeking happens here!
|
||||
if (action || clear) cmd_state <= LOAD_CMD;
|
||||
end
|
||||
|
||||
endcase //cmd_state
|
||||
end
|
||||
end
|
||||
|
||||
//------------------------------------------------------------------
|
||||
//-- assign to settings bus interface
|
||||
//------------------------------------------------------------------
|
||||
reg strobe_reg;
|
||||
assign strobe = strobe_reg;
|
||||
assign data = command_data_reg;
|
||||
assign addr = command_hdr_reg[7:0];
|
||||
wire poke = command_hdr_reg[8];
|
||||
|
||||
always @(posedge clock) begin
|
||||
if (reset || clear) strobe_reg <= 0;
|
||||
else strobe_reg <= action && poke;
|
||||
end
|
||||
|
||||
//------------------------------------------------------------------
|
||||
//-- readback mux
|
||||
//------------------------------------------------------------------
|
||||
always @(posedge clock) begin
|
||||
case (out_command_hdr[3:0])
|
||||
0 : rb_data <= word00;
|
||||
1 : rb_data <= word01;
|
||||
2 : rb_data <= word02;
|
||||
3 : rb_data <= word03;
|
||||
4 : rb_data <= word04;
|
||||
5 : rb_data <= word05;
|
||||
6 : rb_data <= word06;
|
||||
7 : rb_data <= word07;
|
||||
8 : rb_data <= word08;
|
||||
9 : rb_data <= word09;
|
||||
10: rb_data <= word10;
|
||||
11: rb_data <= word11;
|
||||
12: rb_data <= word12;
|
||||
13: rb_data <= word13;
|
||||
14: rb_data <= word14;
|
||||
15: rb_data <= word15;
|
||||
endcase // case(addr_reg[3:0])
|
||||
end
|
||||
|
||||
//------------------------------------------------------------------
|
||||
//-- Output state machine:
|
||||
//-- Read a command fifo entry, act on it, produce ack packet.
|
||||
//------------------------------------------------------------------
|
||||
localparam WRITE_PROT_HDR = 0;
|
||||
localparam WRITE_VRT_HDR = 1;
|
||||
localparam WRITE_VRT_SID = 2;
|
||||
localparam WRITE_RB_HDR = 3;
|
||||
localparam WRITE_RB_DATA = 4;
|
||||
|
||||
//the state for the start of packet condition
|
||||
localparam WRITE_PKT_HDR = (PROT_HDR)? WRITE_PROT_HDR : WRITE_VRT_HDR;
|
||||
|
||||
reg [2:0] out_state;
|
||||
|
||||
assign out_valid = ~result_fifo_empty;
|
||||
assign result_fifo_read = out_data[33] && writing;
|
||||
|
||||
always @(posedge clock) begin
|
||||
if (reset) begin
|
||||
out_state <= WRITE_PKT_HDR;
|
||||
end
|
||||
else if (writing && out_data[33]) begin
|
||||
out_state <= WRITE_PKT_HDR;
|
||||
end
|
||||
else if (writing) begin
|
||||
out_state <= out_state + 1;
|
||||
end
|
||||
end
|
||||
|
||||
//------------------------------------------------------------------
|
||||
//-- assign to output fifo interface
|
||||
//------------------------------------------------------------------
|
||||
wire [31:0] prot_hdr;
|
||||
assign prot_hdr[15:0] = 16; //bytes in proceeding vita packet
|
||||
assign prot_hdr[16] = 1; //yes frame
|
||||
assign prot_hdr[18:17] = PROT_DEST;
|
||||
assign prot_hdr[31:19] = 0; //nothing
|
||||
|
||||
reg [31:0] out_data_int;
|
||||
always @* begin
|
||||
case (out_state)
|
||||
WRITE_PROT_HDR: out_data_int <= prot_hdr;
|
||||
WRITE_VRT_HDR: out_data_int <= {12'b010100000000, out_result_hdr[19:16], 2'b0, prot_hdr[15:2]};
|
||||
WRITE_VRT_SID: out_data_int <= ACK_SID;
|
||||
WRITE_RB_HDR: out_data_int <= out_result_hdr;
|
||||
WRITE_RB_DATA: out_data_int <= out_result_data;
|
||||
default: out_data_int <= 0;
|
||||
endcase //state
|
||||
end
|
||||
|
||||
assign out_data[35:34] = 2'b0;
|
||||
assign out_data[33] = (out_state == WRITE_RB_DATA);
|
||||
assign out_data[32] = (out_state == WRITE_PKT_HDR);
|
||||
assign out_data[31:0] = out_data_int;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
//-- debug outputs
|
||||
//------------------------------------------------------------------
|
||||
assign debug = {
|
||||
in_state, out_state, //8
|
||||
in_valid, in_ready, in_data[33:32], //4
|
||||
out_valid, out_ready, out_data[33:32], //4
|
||||
command_fifo_empty, command_fifo_full, //2
|
||||
command_fifo_read, command_fifo_write, //2
|
||||
addr, //8
|
||||
strobe_reg, strobe, poke, out_command_has_time //4
|
||||
};
|
||||
|
||||
endmodule //settings_fifo_ctrl
|
||||
116
fpga/control_lib/simple_i2c_core.v
Normal file
116
fpga/control_lib/simple_i2c_core.v
Normal file
@@ -0,0 +1,116 @@
|
||||
//
|
||||
// Copyright 2012 Ettus Research LLC
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
// Simple I2C core
|
||||
|
||||
// Settings reg map:
|
||||
//
|
||||
// BASE+0 control register
|
||||
// byte0 - control bits, data byte, or command bits, prescaler
|
||||
// byte1 - what to do? (documented in cpp file)
|
||||
// write prescaler lo
|
||||
// write prescaler hi
|
||||
// write control
|
||||
// write data
|
||||
// write command
|
||||
// read data
|
||||
// read status
|
||||
//
|
||||
|
||||
// Readback:
|
||||
//
|
||||
// byte0 has readback value based on the last read command
|
||||
//
|
||||
|
||||
module simple_i2c_core
|
||||
#(
|
||||
//settings register base address
|
||||
parameter BASE = 0,
|
||||
|
||||
//i2c line level at reset
|
||||
parameter ARST_LVL = 1
|
||||
)
|
||||
(
|
||||
//clock and synchronous reset
|
||||
input clock, input reset,
|
||||
|
||||
//32-bit settings bus inputs
|
||||
input set_stb, input [7:0] set_addr, input [31:0] set_data,
|
||||
|
||||
//32-bit data readback
|
||||
output reg [31:0] readback,
|
||||
|
||||
//read is high when i2c core can begin another transaction
|
||||
output reg ready,
|
||||
|
||||
// I2C signals
|
||||
// i2c clock line
|
||||
input scl_pad_i, // SCL-line input
|
||||
output scl_pad_o, // SCL-line output (always 1'b0)
|
||||
output scl_padoen_o, // SCL-line output enable (active low)
|
||||
|
||||
// i2c data line
|
||||
input sda_pad_i, // SDA-line input
|
||||
output sda_pad_o, // SDA-line output (always 1'b0)
|
||||
output sda_padoen_o, // SDA-line output enable (active low)
|
||||
|
||||
//optional debug output
|
||||
output [31:0] debug
|
||||
);
|
||||
|
||||
//declare command settings register
|
||||
wire [7:0] sr_what, sr_data;
|
||||
wire sr_changed;
|
||||
setting_reg #(.my_addr(BASE+0),.width(16)) i2c_cmd_sr(
|
||||
.clk(clock),.rst(reset),.strobe(set_stb),.addr(set_addr),.in(set_data),
|
||||
.out({sr_what, sr_data}),.changed(sr_changed));
|
||||
|
||||
//declare wb interface signals
|
||||
wire [2:0] wb_addr;
|
||||
wire [7:0] wb_data_mosi;
|
||||
wire [7:0] wb_data_miso;
|
||||
wire wb_we, wb_stb, wb_cyc;
|
||||
wire wb_ack;
|
||||
|
||||
//create wishbone-based i2c core
|
||||
i2c_master_top #(.ARST_LVL(ARST_LVL)) i2c
|
||||
(.wb_clk_i(clock),.wb_rst_i(reset),.arst_i(1'b0),
|
||||
.wb_adr_i(wb_addr),.wb_dat_i(wb_data_mosi),.wb_dat_o(wb_data_miso),
|
||||
.wb_we_i(wb_we),.wb_stb_i(wb_stb),.wb_cyc_i(wb_cyc),
|
||||
.wb_ack_o(wb_ack),.wb_inta_o(),
|
||||
.scl_pad_i(scl_pad_i),.scl_pad_o(scl_pad_o),.scl_padoen_o(scl_padoen_o),
|
||||
.sda_pad_i(sda_pad_i),.sda_pad_o(sda_pad_o),.sda_padoen_o(sda_padoen_o) );
|
||||
|
||||
//not ready between setting register and wishbone ack
|
||||
always @(posedge clock) begin
|
||||
if (reset || wb_ack) ready <= 1;
|
||||
else if (sr_changed) ready <= 0;
|
||||
end
|
||||
|
||||
//register wishbone data on every ack
|
||||
always @(posedge clock) begin
|
||||
if (wb_ack) readback <= {24'b0, wb_data_miso};
|
||||
end
|
||||
|
||||
//assign wishbone signals
|
||||
assign wb_addr = sr_what[2:0];
|
||||
assign wb_stb = sr_changed;
|
||||
assign wb_we = wb_stb && sr_what[3];
|
||||
assign wb_cyc = wb_stb;
|
||||
assign wb_data_mosi = sr_data;
|
||||
|
||||
endmodule //simple_i2c_core
|
||||
214
fpga/control_lib/simple_spi_core.v
Normal file
214
fpga/control_lib/simple_spi_core.v
Normal file
@@ -0,0 +1,214 @@
|
||||
//
|
||||
// Copyright 2012 Ettus Research LLC
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
// Simple SPI core, the simplest, yet complete spi core I can think of
|
||||
|
||||
// Settings register controlled.
|
||||
// 2 settings regs, control and data
|
||||
// 1 32-bit readback and status signal
|
||||
|
||||
// Settings reg map:
|
||||
//
|
||||
// BASE+0 divider setting
|
||||
// bits [15:0] spi clock divider
|
||||
//
|
||||
// BASE+1 configuration input
|
||||
// bits [23:0] slave select, bit0 = slave0 enabled
|
||||
// bits [29:24] num bits (1 through 32)
|
||||
// bit [30] data input edge = in data bit latched on rising edge of clock
|
||||
// bit [31] data output edge = out data bit latched on rising edge of clock
|
||||
//
|
||||
// BASE+2 input data
|
||||
// Writing this register begins a spi transaction.
|
||||
// Bits are latched out from bit 0.
|
||||
// Therefore, load this register in reverse.
|
||||
//
|
||||
// Readback
|
||||
// Bits are latched into bit 0.
|
||||
// Therefore, data will be in-order.
|
||||
|
||||
module simple_spi_core
|
||||
#(
|
||||
//settings register base address
|
||||
parameter BASE = 0,
|
||||
|
||||
//width of serial enables (up to 24 is possible)
|
||||
parameter WIDTH = 8,
|
||||
|
||||
//idle state of the spi clock
|
||||
parameter CLK_IDLE = 0,
|
||||
|
||||
//idle state of the serial enables
|
||||
parameter SEN_IDLE = 24'hffffff
|
||||
)
|
||||
(
|
||||
//clock and synchronous reset
|
||||
input clock, input reset,
|
||||
|
||||
//32-bit settings bus inputs
|
||||
input set_stb, input [7:0] set_addr, input [31:0] set_data,
|
||||
|
||||
//32-bit data readback
|
||||
output [31:0] readback,
|
||||
|
||||
//read is high when spi core can begin another transaction
|
||||
output ready,
|
||||
|
||||
//spi interface, slave selects, clock, data in, data out
|
||||
output [WIDTH-1:0] sen,
|
||||
output sclk,
|
||||
output mosi,
|
||||
input miso,
|
||||
|
||||
//optional debug output
|
||||
output [31:0] debug
|
||||
);
|
||||
|
||||
wire [15:0] sclk_divider;
|
||||
setting_reg #(.my_addr(BASE+0),.width(16)) divider_sr(
|
||||
.clk(clock),.rst(reset),.strobe(set_stb),.addr(set_addr),.in(set_data),
|
||||
.out(sclk_divider),.changed());
|
||||
|
||||
wire [23:0] slave_select;
|
||||
wire [5:0] num_bits;
|
||||
wire datain_edge, dataout_edge;
|
||||
setting_reg #(.my_addr(BASE+1),.width(32)) config_sr(
|
||||
.clk(clock),.rst(reset),.strobe(set_stb),.addr(set_addr),.in(set_data),
|
||||
.out({dataout_edge, datain_edge, num_bits, slave_select}),.changed());
|
||||
|
||||
wire [31:0] mosi_data;
|
||||
wire trigger_spi;
|
||||
setting_reg #(.my_addr(BASE+2),.width(32)) data_sr(
|
||||
.clk(clock),.rst(reset),.strobe(set_stb),.addr(set_addr),.in(set_data),
|
||||
.out(mosi_data),.changed(trigger_spi));
|
||||
|
||||
localparam WAIT_TRIG = 0;
|
||||
localparam PRE_IDLE = 1;
|
||||
localparam CLK_REG = 2;
|
||||
localparam CLK_INV = 3;
|
||||
localparam POST_IDLE = 4;
|
||||
localparam IDLE_SEN = 5;
|
||||
|
||||
reg [2:0] state;
|
||||
|
||||
reg ready_reg;
|
||||
assign ready = ready_reg && ~trigger_spi;
|
||||
|
||||
//serial clock either idles or is in one of two clock states
|
||||
reg sclk_reg;
|
||||
assign sclk = sclk_reg;
|
||||
|
||||
//serial enables either idle or enabled based on state
|
||||
wire sen_is_idle = (state == WAIT_TRIG) || (state == IDLE_SEN);
|
||||
wire [23:0] sen24 = (sen_is_idle)? SEN_IDLE : (SEN_IDLE ^ slave_select);
|
||||
reg [WIDTH-1:0] sen_reg;
|
||||
always @(posedge clock) sen_reg <= sen24[WIDTH-1:0];
|
||||
assign sen = sen_reg;
|
||||
|
||||
//data output shift register
|
||||
reg [31:0] dataout_reg;
|
||||
wire [31:0] dataout_next = {dataout_reg[30:0], 1'b0};
|
||||
assign mosi = dataout_reg[31];
|
||||
|
||||
//data input shift register
|
||||
reg [31:0] datain_reg;
|
||||
wire [31:0] datain_next = {datain_reg[30:0], miso};
|
||||
assign readback = datain_reg;
|
||||
|
||||
//counter for spi clock
|
||||
reg [15:0] sclk_counter;
|
||||
wire sclk_counter_done = (sclk_counter == sclk_divider);
|
||||
wire [15:0] sclk_counter_next = (sclk_counter_done)? 0 : sclk_counter + 1;
|
||||
|
||||
//counter for latching bits miso/mosi
|
||||
reg [6:0] bit_counter;
|
||||
wire [6:0] bit_counter_next = bit_counter + 1;
|
||||
wire bit_counter_done = (bit_counter_next == num_bits);
|
||||
|
||||
always @(posedge clock) begin
|
||||
if (reset) begin
|
||||
state <= WAIT_TRIG;
|
||||
sclk_reg <= CLK_IDLE;
|
||||
ready_reg <= 0;
|
||||
end
|
||||
else begin
|
||||
case (state)
|
||||
|
||||
WAIT_TRIG: begin
|
||||
if (trigger_spi) state <= PRE_IDLE;
|
||||
ready_reg <= ~trigger_spi;
|
||||
dataout_reg <= mosi_data;
|
||||
sclk_counter <= 0;
|
||||
bit_counter <= 0;
|
||||
sclk_reg <= CLK_IDLE;
|
||||
end
|
||||
|
||||
PRE_IDLE: begin
|
||||
if (sclk_counter_done) state <= CLK_REG;
|
||||
sclk_counter <= sclk_counter_next;
|
||||
sclk_reg <= CLK_IDLE;
|
||||
end
|
||||
|
||||
CLK_REG: begin
|
||||
if (sclk_counter_done) begin
|
||||
state <= CLK_INV;
|
||||
if (datain_edge != CLK_IDLE) datain_reg <= datain_next;
|
||||
if (dataout_edge != CLK_IDLE && bit_counter != 0) dataout_reg <= dataout_next;
|
||||
sclk_reg <= ~CLK_IDLE; //transition to rising when CLK_IDLE == 0
|
||||
end
|
||||
sclk_counter <= sclk_counter_next;
|
||||
end
|
||||
|
||||
CLK_INV: begin
|
||||
if (sclk_counter_done) begin
|
||||
state <= (bit_counter_done)? POST_IDLE : CLK_REG;
|
||||
bit_counter <= bit_counter_next;
|
||||
if (datain_edge == CLK_IDLE) datain_reg <= datain_next;
|
||||
if (dataout_edge == CLK_IDLE && ~bit_counter_done) dataout_reg <= dataout_next;
|
||||
sclk_reg <= CLK_IDLE; //transition to falling when CLK_IDLE == 0
|
||||
end
|
||||
sclk_counter <= sclk_counter_next;
|
||||
end
|
||||
|
||||
POST_IDLE: begin
|
||||
if (sclk_counter_done) state <= IDLE_SEN;
|
||||
sclk_counter <= sclk_counter_next;
|
||||
sclk_reg <= CLK_IDLE;
|
||||
end
|
||||
|
||||
IDLE_SEN: begin
|
||||
if (sclk_counter_done) state <= WAIT_TRIG;
|
||||
sclk_counter <= sclk_counter_next;
|
||||
sclk_reg <= CLK_IDLE;
|
||||
end
|
||||
|
||||
default: state <= WAIT_TRIG;
|
||||
|
||||
endcase //state
|
||||
end
|
||||
end
|
||||
|
||||
assign debug = {
|
||||
trigger_spi, state, //4
|
||||
sclk, mosi, miso, ready, //4
|
||||
sen[7:0], //8
|
||||
1'b0, bit_counter[6:0], //8
|
||||
sclk_counter_done, bit_counter_done, //2
|
||||
sclk_counter[5:0] //6
|
||||
};
|
||||
|
||||
endmodule //simple_spi_core
|
||||
63
fpga/control_lib/user_settings.v
Normal file
63
fpga/control_lib/user_settings.v
Normal file
@@ -0,0 +1,63 @@
|
||||
//
|
||||
// Copyright 2012 Ettus Research LLC
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
// User settings bus
|
||||
//
|
||||
// Provides 8-bit address, 32-bit data write only bus for user settings, consumes to addresses in
|
||||
// normal settings bus.
|
||||
//
|
||||
// Write user address to BASE
|
||||
// Write user data to BASE+1
|
||||
//
|
||||
// The user_set_stb will strobe after data write, must write new address even if same as previous one.
|
||||
|
||||
module user_settings
|
||||
#(parameter BASE=0)
|
||||
(input clk,
|
||||
input rst,
|
||||
|
||||
input set_stb,
|
||||
input [7:0] set_addr,
|
||||
input [31:0] set_data,
|
||||
|
||||
output set_stb_user,
|
||||
output [7:0] set_addr_user,
|
||||
output [31:0] set_data_user
|
||||
);
|
||||
|
||||
wire addr_changed, data_changed;
|
||||
reg stb_int;
|
||||
|
||||
setting_reg #(.my_addr(BASE+0),.width(8)) sr_0
|
||||
(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
|
||||
.in(set_data),.out(set_addr_user),.changed(addr_changed) );
|
||||
|
||||
setting_reg #(.my_addr(BASE+1)) sr_1
|
||||
(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
|
||||
.in(set_data),.out(set_data_user),.changed(data_changed) );
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst|set_stb_user)
|
||||
stb_int <= 0;
|
||||
else
|
||||
if (addr_changed)
|
||||
stb_int <= 1;
|
||||
|
||||
assign set_stb_user = stb_int & data_changed;
|
||||
|
||||
endmodule // user_settings
|
||||
|
||||
Reference in New Issue
Block a user