Tx side integration firmware

bug_fixes_integration_tx
David Michaeli 2023-05-30 14:33:08 +03:00
rodzic 132d19259c
commit 0595990c8d
10 zmienionych plików z 945 dodań i 822 usunięć

Wyświetl plik

@ -34,8 +34,7 @@ module complex_fifo #(
function [ADDR_WIDTH-1:0] gray_conv;
input [ADDR_WIDTH-1:0] in;
begin
gray_conv = {in[ADDR_WIDTH-1],
in[ADDR_WIDTH-2:0] ^ in[ADDR_WIDTH-1:1]};
gray_conv = {in[ADDR_WIDTH-1], in[ADDR_WIDTH-2:0] ^ in[ADDR_WIDTH-1:1]};
end
endfunction
@ -55,13 +54,15 @@ module complex_fifo #(
rd_addr_gray_wr_r <= rd_addr_gray_wr;
end
always @(posedge wr_clk_i)
if (wr_rst_b_i == 1'b0)
always @(posedge wr_clk_i) begin
if (wr_rst_b_i == 1'b0) begin
full_o <= 0;
else if (wr_en_i)
end else if (wr_en_i) begin
full_o <= gray_conv(wr_addr + 2) == rd_addr_gray_wr_r;
else
end else begin
full_o <= full_o & (gray_conv(wr_addr + 1'b1) == rd_addr_gray_wr_r);
end
end
always @(posedge rd_clk_i) begin
if (rd_rst_b_i == 1'b0) begin
@ -80,15 +81,15 @@ module complex_fifo #(
wr_addr_gray_rd_r <= wr_addr_gray_rd;
end
always @(posedge rd_clk_i)
if (rd_rst_b_i == 1'b0)
always @(posedge rd_clk_i) begin
if (rd_rst_b_i == 1'b0) begin
empty_o <= 1'b1;
else if (rd_en_i)
end else if (rd_en_i) begin
empty_o <= gray_conv(rd_addr + 1) == wr_addr_gray_rd_r;
else
end else begin
empty_o <= empty_o & (gray_conv(rd_addr) == wr_addr_gray_rd_r);
//reg [DATA_WIDTH-1:0] mem[(1<<ADDR_WIDTH)-1:0];
end
end
always @(posedge rd_clk_i) begin
if (rd_en_i) begin

Wyświetl plik

@ -1,122 +0,0 @@
/*
* Copyright (c) 2012, Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
* All rights reserved.
*
* Based on vga_fifo_dc.v in Richard Herveille's VGA/LCD core
* Copyright (C) 2001 Richard Herveille <richard@asics.ws>
*
* Redistribution and use in source and non-source forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in non-source form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS WORK IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* WORK, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
module dual_clock_fifo #(
parameter ADDR_WIDTH = 8,
parameter DATA_WIDTH = 16
)
(
input wire wr_rst_i,
input wire wr_clk_i,
input wire wr_en_i,
input wire [DATA_WIDTH-1:0] wr_data_i,
input wire rd_rst_i,
input wire rd_clk_i,
input wire rd_en_i,
output reg [DATA_WIDTH-1:0] rd_data_o,
output reg full_o,
output reg empty_o
);
reg [ADDR_WIDTH-1:0] wr_addr;
reg [ADDR_WIDTH-1:0] wr_addr_gray;
reg [ADDR_WIDTH-1:0] wr_addr_gray_rd;
reg [ADDR_WIDTH-1:0] wr_addr_gray_rd_r;
reg [ADDR_WIDTH-1:0] rd_addr;
reg [ADDR_WIDTH-1:0] rd_addr_gray;
reg [ADDR_WIDTH-1:0] rd_addr_gray_wr;
reg [ADDR_WIDTH-1:0] rd_addr_gray_wr_r;
function [ADDR_WIDTH-1:0] gray_conv;
input [ADDR_WIDTH-1:0] in;
begin
gray_conv = {in[ADDR_WIDTH-1],
in[ADDR_WIDTH-2:0] ^ in[ADDR_WIDTH-1:1]};
end
endfunction
always @(posedge wr_clk_i) begin
if (wr_rst_i) begin
wr_addr <= 0;
wr_addr_gray <= 0;
end else if (wr_en_i) begin
wr_addr <= wr_addr + 1'b1;
wr_addr_gray <= gray_conv(wr_addr + 1'b1);
end
end
// synchronize read address to write clock domain
always @(posedge wr_clk_i) begin
rd_addr_gray_wr <= rd_addr_gray;
rd_addr_gray_wr_r <= rd_addr_gray_wr;
end
always @(posedge wr_clk_i)
if (wr_rst_i)
full_o <= 0;
else if (wr_en_i)
full_o <= gray_conv(wr_addr + 2) == rd_addr_gray_wr_r;
else
full_o <= full_o & (gray_conv(wr_addr + 1'b1) == rd_addr_gray_wr_r);
always @(posedge rd_clk_i) begin
if (rd_rst_i) begin
rd_addr <= 0;
rd_addr_gray <= 0;
end else if (rd_en_i) begin
rd_addr <= rd_addr + 1'b1;
rd_addr_gray <= gray_conv(rd_addr + 1'b1);
end
end
// synchronize write address to read clock domain
always @(posedge rd_clk_i) begin
wr_addr_gray_rd <= wr_addr_gray;
wr_addr_gray_rd_r <= wr_addr_gray_rd;
end
always @(posedge rd_clk_i)
if (rd_rst_i)
empty_o <= 1'b1;
else if (rd_en_i)
empty_o <= gray_conv(rd_addr + 1) == wr_addr_gray_rd_r;
else
empty_o <= empty_o & (gray_conv(rd_addr) == wr_addr_gray_rd_r);
reg [DATA_WIDTH-1:0] mem[(1<<ADDR_WIDTH)-1:0];
always @(posedge rd_clk_i)
if (rd_en_i)
rd_data_o <= mem[rd_addr];
always @(posedge wr_clk_i)
if (wr_en_i)
mem[wr_addr] <= wr_data_i;
endmodule

Wyświetl plik

@ -1,5 +1,4 @@
module lvds_rx
(
module lvds_rx (
input i_rst_b,
input i_ddr_clk,
input [1:0] i_ddr_data,
@ -9,26 +8,20 @@ module lvds_rx
output o_fifo_push,
output reg [31:0] o_fifo_data,
input i_sync_input,
output [1:0] o_debug_state );
output [ 1:0] o_debug_state
);
// Internal FSM States
localparam
state_idle = 3'b00,
state_i_phase = 3'b01,
state_q_phase = 3'b11;
localparam state_idle = 2'b00, state_i_phase = 2'b01, state_q_phase = 2'b11;
// Modem sync symbols
localparam
modem_i_sync = 3'b10,
modem_q_sync = 3'b01;
localparam modem_i_sync = 2'b10, modem_q_sync = 2'b01;
// Internal Registers
reg [1:0] r_state_if;
reg [2:0] r_phase_count;
reg r_cnt;
reg r_sync_input;
assign o_debug_state = r_state_if;
// Initial conditions
initial begin
@ -38,15 +31,14 @@ module lvds_rx
// Global Assignments
assign o_fifo_write_clk = i_ddr_clk;
assign o_debug_state = r_state_if;
// Main Process
always @(posedge i_ddr_clk or negedge i_rst_b)
begin
always @(posedge i_ddr_clk or negedge i_rst_b) begin
if (i_rst_b == 1'b0) begin
r_state_if <= state_idle;
o_fifo_push <= 1'b0;
r_phase_count <= 3'b111;
r_cnt <= 0;
r_sync_input <= 1'b0;
end else begin
case (r_state_if)

Wyświetl plik

@ -1,41 +1,50 @@
module lvds_tx
(
module lvds_tx (
input i_rst_b,
input i_ddr_clk,
output [1:0] o_ddr_data,
input i_fifo_empty,
output o_fifo_read_clk,
output o_fifo_pull,
output reg o_fifo_pull,
input [31:0] i_fifo_data,
input i_tx_state,
input i_sync_input,
output [1:0] o_debug_state );
output [ 1:0] o_debug_state
);
// Internal Registers
reg [ 4:0] r_phase_count;
reg [31:0] r_fifo_data;
// Initial conditions
initial begin
r_phase_count = 5'b11111;
r_phase_count = 5'd31;
end
assign o_fifo_read_clk = i_ddr_clk;
// Main Process / shift register
always @(posedge i_ddr_clk)
begin
always @(posedge i_ddr_clk) begin
if (i_rst_b == 1'b0) begin
o_fifo_pull <= ~i_fifo_empty;
r_phase_count <= 5'b11111;
o_fifo_pull <= 1'b0;
r_phase_count <= 5'd31;
r_fifo_data <= 32'b00000000000000000000000000000000;
end else begin
if (r_phase_count == 5'b00001) begin
if (r_phase_count == 5'd3) begin
o_fifo_pull <= ~i_fifo_empty;
end else if (r_phase_count == 5'd1) begin
if (i_tx_state) begin
r_fifo_data <= i_fifo_data;
end else begin
r_fifo_data <= 32'b00000000000000000000000000000000;
end
o_fifo_pull <= 1'b0;
end else begin
o_fifo_pull <= 1'b0;
end
o_ddr_data <= i_fifo_data[r_phase_count:r_phase_count-1];
o_ddr_data <= r_fifo_data[r_phase_count:r_phase_count-1];
r_phase_count <= r_phase_count - 2;
end
end

Wyświetl plik

@ -12,10 +12,13 @@ module smi_ctrl
input i_load_cmd,
// FIFO INTERFACE
output o_fifo_pull,
input [31:0] i_fifo_pulled_data,
input i_fifo_full,
input i_fifo_empty,
output o_rx_fifo_pull,
input [31:0] i_rx_fifo_pulled_data,
input i_rx_fifo_empty,
output o_tx_fifo_push,
output reg [31:0] o_tx_fifo_pushed_data,
input i_tx_fifo_full,
output o_tx_fifo_clock,
// SMI INTERFACE
input i_smi_soe_se,
@ -27,28 +30,34 @@ module smi_ctrl
input i_smi_test,
output o_channel,
// TX CONDITIONAL
output reg o_cond_tx,
// Errors
output reg o_address_error);
// ---------------------------------
// MODULE SPECIFIC IOC LIST
// ------------------------
// ---------------------------------
localparam
ioc_module_version = 5'b00000, // read only
ioc_fifo_status = 5'b00001, // read-only
ioc_channel_select = 5'b00010;
// ---------------------------------
// MODULE SPECIFIC PARAMS
// ----------------------
// ---------------------------------
localparam
module_version = 8'b00000001;
// ---------------------------------------
// MODULE CONTROL
// ---------------------------------------
assign o_channel = r_channel;
always @(posedge i_sys_clk or negedge i_rst_b)
begin
if (i_rst_b == 1'b0) begin
o_address_error <= 1'b0;
w_channel <= 1'b0;
end else begin
if (i_cs == 1'b1) begin
//=============================================
@ -61,9 +70,11 @@ module smi_ctrl
//----------------------------------------------
ioc_fifo_status: begin
o_data_out[0] <= i_fifo_empty;
o_data_out[1] <= r_channel;
o_data_out[7:2] <= 6'b000000;
o_data_out[0] <= i_rx_fifo_empty;
o_data_out[1] <= i_tx_fifo_full;
o_data_out[2] <= r_channel;
o_data_out[3] <= i_smi_test;
o_data_out[7:4] <= 4'b0000;
end
endcase
end
@ -82,29 +93,32 @@ module smi_ctrl
end
end
// Tell the RPI that data is pending in either of the two fifos
assign o_smi_read_req = (!i_fifo_empty) || i_smi_test;
reg [4:0] int_cnt;
// ---------------------------------------
// RX SIDE
// ---------------------------------------
reg [4:0] int_cnt_rx;
reg [7:0] r_smi_test_count;
reg r_fifo_pull;
reg r_fifo_pull_1;
wire w_fifo_pull_trigger;
reg r_channel;
assign o_channel = r_channel;
reg [7:0] r_smi_test_count;
reg [31:0] r_fifo_pulled_data;
wire soe_and_reset;
assign soe_and_reset = i_rst_b & i_smi_soe_se;
assign o_smi_read_req = (!i_rx_fifo_empty) || i_smi_test;
assign o_rx_fifo_pull = !r_fifo_pull_1 && r_fifo_pull && !i_rx_fifo_empty;
always @(negedge soe_and_reset)
begin
if (i_rst_b == 1'b0) begin
int_cnt <= 5'd31;
int_cnt_rx <= 5'd0;
r_smi_test_count <= 8'h56;
r_fifo_pulled_data <= 32'h00000000;
end else begin
// trigger the fifo pulling on the second byte
w_fifo_pull_trigger <= (int_cnt == 5'd23) && !i_smi_test;
w_fifo_pull_trigger <= (int_cnt_rx == 5'd8) && !i_smi_test;
if ( i_smi_test ) begin
if (r_smi_test_count == 0) begin
@ -114,12 +128,12 @@ module smi_ctrl
r_smi_test_count <= {((r_smi_test_count[2] ^ r_smi_test_count[3]) & 1'b1), r_smi_test_count[7:1]};
end
end else begin
int_cnt <= int_cnt - 8;
o_smi_data_out <= r_fifo_pulled_data[int_cnt:int_cnt-7];
int_cnt_rx <= int_cnt_rx + 8;
o_smi_data_out <= r_fifo_pulled_data[int_cnt_rx+7:int_cnt_rx];
// update the internal register as soon as we reach the fourth byte
if (int_cnt == 5'd7) begin
r_fifo_pulled_data <= i_fifo_pulled_data;
if (int_cnt_rx == 5'd24) begin
r_fifo_pulled_data <= i_rx_fifo_pulled_data;
end
end
@ -137,6 +151,113 @@ module smi_ctrl
end
end
assign o_fifo_pull = !r_fifo_pull_1 && r_fifo_pull && !i_fifo_empty;
// -----------------------------------------
// TX SIDE
// -----------------------------------------
localparam
tx_state_first = 2'b00,
tx_state_second = 2'b01,
tx_state_third = 2'b10,
tx_state_fourth = 2'b11;
reg [4:0] int_cnt_tx;
reg [31:0] r_fifo_pushed_data;
reg [1:0] tx_reg_state;
reg modem_tx_ctrl;
reg cond_tx_ctrl;
reg r_fifo_push;
reg r_fifo_push_1;
wire w_fifo_push_trigger;
assign o_smi_write_req = !i_tx_fifo_full;
assign o_tx_fifo_push = !r_fifo_push_1 && r_fifo_push && !i_tx_fifo_full;
assign swe_and_reset = i_rst_b & i_smi_swe_srw;
assign o_tx_fifo_clock = i_sys_clk;
always @(negedge swe_and_reset)
begin
if (i_rst_b == 1'b0) begin
tx_reg_state <= tx_state_first;
w_fifo_push_trigger <= 1'b0;
r_fifo_pushed_data <= 32'h00000000;
modem_tx_ctrl <= 1'b0;
cond_tx_ctrl <= 1'b0;
//cnt <= 0;
end else begin
case (tx_reg_state)
//----------------------------------------------
tx_state_first:
begin
if (i_smi_data_in[7] == 1'b1) begin
r_fifo_pushed_data[31:30] <= 2'b10;
modem_tx_ctrl <= i_smi_data_in[6];
cond_tx_ctrl <= i_smi_data_in[5];
r_fifo_pushed_data[29:25] <= i_smi_data_in[4:0];
tx_reg_state <= tx_state_second;
w_fifo_push_trigger <= 1'b0;
end else begin
// if from some reason we are in the first byte stage and we got
// a byte without '1' on its MSB, that means that we are not synced
// so push a "sync" word into the modem.
cond_tx_ctrl <= 1'b0;
modem_tx_ctrl <= 1'b0;
o_tx_fifo_pushed_data <= 32'h00000000;
w_fifo_push_trigger <= 1'b1;
end
end
//----------------------------------------------
tx_state_second:
begin
if (i_smi_data_in[7] == 1'b0) begin
r_fifo_pushed_data[24:18] <= i_smi_data_in[6:0];
tx_reg_state <= tx_state_third;
end else begin
tx_reg_state <= tx_state_first;
end
w_fifo_push_trigger <= 1'b0;
end
//----------------------------------------------
tx_state_third:
begin
if (i_smi_data_in[7] == 1'b0) begin
r_fifo_pushed_data[17] <= i_smi_data_in[6];
r_fifo_pushed_data[16] <= modem_tx_ctrl;
r_fifo_pushed_data[15:14] <= 2'b01;
r_fifo_pushed_data[13:8] <= i_smi_data_in[5:0];
tx_reg_state <= tx_state_fourth;
end else begin
tx_reg_state <= tx_state_first;
end
w_fifo_push_trigger <= 1'b0;
end
//----------------------------------------------
tx_state_fourth:
begin
if (i_smi_data_in[7] == 1'b0) begin
o_tx_fifo_pushed_data <= {r_fifo_pushed_data[31:8], i_smi_data_in[6:0], 1'b0};
//o_tx_fifo_pushed_data <= {2'b10, cnt, 1'b1, 2'b01, 13'h3F, 1'b0};
//o_tx_fifo_pushed_data <= {cnt, cnt, 6'b111111};
//cnt <= cnt + 1024;
w_fifo_push_trigger <= 1'b1;
o_cond_tx <= cond_tx_ctrl;
end else begin
o_tx_fifo_pushed_data <= 32'h00000000;
w_fifo_push_trigger <= 1'b0;
end
tx_reg_state <= tx_state_first;
end
endcase
end
end
always @(posedge i_sys_clk)
begin
if (i_rst_b == 1'b0) begin
r_fifo_push <= 1'b0;
r_fifo_push_1 <= 1'b0;
end else begin
r_fifo_push <= w_fifo_push_trigger;
r_fifo_push_1 <= r_fifo_push;
end
end
endmodule // smi_ctrl

Wyświetl plik

@ -1,7 +1,6 @@
`include "spi_slave.v"
module spi_if
(
module spi_if (
input i_rst_b, // FPGA Reset
input i_sys_clk, // FPGA Clock
@ -16,7 +15,8 @@ module spi_if
input i_spi_sck,
output o_spi_miso,
input i_spi_mosi,
input i_spi_cs_b );
input i_spi_cs_b
);
localparam
state_idle = 3'b000,
@ -25,6 +25,7 @@ module spi_if
state_load = 3'b011,
state_post_op= 3'b100;
// internal registers / wires
reg [2:0] state_if;
wire w_rx_data_valid;
wire [7:0] w_rx_data;
@ -39,8 +40,7 @@ module spi_if
state_if = state_idle;
end
spi_slave spi
(
spi_slave spi (
.i_sys_clk (i_sys_clk),
.o_rx_data_valid(w_rx_data_valid),
.o_rx_byte (w_rx_data),
@ -53,16 +53,14 @@ module spi_if
.i_spi_cs_b(i_spi_cs_b)
);
always @(posedge i_sys_clk)
begin
always @(posedge i_sys_clk) begin
if (i_rst_b == 1'b0) begin
state_if <= state_idle;
// whenever a new byte arrives
end else if (w_rx_data_valid == 1'b1) begin
// whenever a new byte arrives
case (state_if)
//----------------------------------
state_idle:
begin
state_idle: begin
o_ioc = w_rx_data[4:0];
case (w_rx_data[6:5])
2'b00: o_cs <= 4'b0001;
@ -82,15 +80,13 @@ module spi_if
r_tx_data_valid <= 1'b0;
end
//----------------------------------
state_load:
begin
state_load: begin
o_data_in <= w_rx_data;
o_load_cmd <= 1'b1;
state_if <= state_idle;
end
//----------------------------------
state_post_op:
begin
state_post_op: begin
o_fetch_cmd <= 1'b0;
o_load_cmd <= 1'b0;
state_if <= state_idle;

Wyświetl plik

@ -1,6 +1,4 @@
module spi_slave
#(parameter SPI_MODE = 0)
(
module spi_slave (
// Control/Data Signals,
input i_sys_clk, // FPGA Clock
output reg o_rx_data_valid, // Data Valid pulse (1 clock cycle)
@ -12,7 +10,8 @@ module spi_slave
input i_spi_sck,
output reg o_spi_miso,
input i_spi_mosi,
input i_spi_cs_b );
input i_spi_cs_b
);
reg [2:0] r_rx_bit_count;
reg [2:0] r_tx_bit_count;
@ -25,8 +24,7 @@ module spi_slave
// Purpose: Recover SPI Byte in SPI Clock Domain
// Samples line on correct edge of SPI Clock
always @(posedge i_spi_sck/* or posedge i_spi_cs_b*/)
begin
always @(posedge i_spi_sck /* or posedge i_spi_cs_b*/) begin
if (i_spi_cs_b) begin
r_rx_bit_count <= 0;
r_rx_done <= 1'b0;
@ -43,28 +41,11 @@ module spi_slave
end
end
/*always @(posedge i_sys_clk)
begin
if (i_spi_cs_b) begin
r_rx_bit_count <= 0;
r_rx_done <= 1'b0;
end else if (SCK_risingedge) begin
r_rx_bit_count <= r_rx_bit_count + 1;
r_temp_rx_byte <= {r_temp_rx_byte[6:0], i_spi_mosi};
if (r_rx_bit_count == 3'b111) begin
r_rx_done <= 1'b1;
r_rx_byte <= {r_temp_rx_byte[6:0], i_spi_mosi};
end else if (r_rx_bit_count == 3'b010) begin
r_rx_done <= 1'b0;
end
end
end*/
// Purpose: Cross from SPI Clock Domain to main FPGA clock domain
// Assert o_rx_data_valid for 1 clock cycle when o_rx_byte has valid data.
always @(posedge i_sys_clk)
begin
always @(posedge i_sys_clk) begin
// Here is where clock domains are crossed.
// This will require timing constraint created, can set up long path.
r2_rx_done <= r_rx_done;
@ -84,8 +65,7 @@ module spi_slave
// Purpose: Transmits 1 SPI Byte whenever SPI clock is toggling
// Will transmit read data back to SW over MISO line.
// Want to put data on the line immediately when CS goes low.
always @(posedge i_sys_clk)
begin
always @(posedge i_sys_clk) begin
if (i_spi_cs_b || i_tx_data_valid) begin
r_tx_byte <= i_tx_byte;
r_tx_bit_count <= 3'b110;

Wyświetl plik

@ -3,9 +3,11 @@
`include "io_ctrl.v"
`include "smi_ctrl.v"
`include "lvds_rx.v"
`include "lvds_tx.v"
`include "complex_fifo.v"
module top( input i_glob_clock,
module top (
input i_glob_clock,
input i_rst_b, // i_smi_a1
// RF FRONT-END PATH
@ -106,8 +108,7 @@ module top( input i_glob_clock,
//=========================================================================
// INSTANCES
//=========================================================================
spi_if spi_if_ins
(
spi_if spi_if_ins (
.i_rst_b(i_rst_b),
.i_sys_clk(w_clock_sys),
.o_ioc(w_ioc),
@ -128,8 +129,7 @@ module top( input i_glob_clock,
assign o_miso = (i_ss) ? 1'bZ : int_miso;
// SYSTEM CTRL
sys_ctrl sys_ctrl_ins
(
sys_ctrl sys_ctrl_ins (
.i_rst_b(i_rst_b),
.i_sys_clk(w_clock_sys),
.i_ioc(w_ioc),
@ -142,7 +142,7 @@ module top( input i_glob_clock,
.i_error_list(8'b00000000),
.o_debug_fifo_push(w_debug_fifo_push),
.o_debug_fifo_pull(w_debug_fifo_pull),
.o_debug_smi_test (w_debug_smi_test)
.o_debug_smi_test(w_debug_smi_test),
);
wire w_debug_fifo_push;
@ -150,8 +150,7 @@ module top( input i_glob_clock,
wire w_debug_smi_test;
// IO CTRL
io_ctrl io_ctrl_ins
(
io_ctrl io_ctrl_ins (
.i_rst_b(i_rst_b),
.i_sys_clk(w_clock_sys),
.i_ioc(w_ioc),
@ -181,15 +180,14 @@ module top( input i_glob_clock,
);
//=========================================================================
// CLOCK AND DATA-FLOW
// CONBINATORIAL ASSIGNMENTS
//=========================================================================
assign w_clock_sys = r_counter;
//=========================================================================
// CLOCK AND DATA-FLOW
//=========================================================================
always @(posedge i_glob_clock)
begin
always @(posedge i_glob_clock) begin
if (i_rst_b == 1'b0) begin
r_counter <= 1'b0;
end else begin
@ -209,40 +207,86 @@ module top( input i_glob_clock,
// I/O (SB_IO, SB_GB) DIFFERENTIAL LINES
//=========================================================================
//---------------------------------------------
// LVDS CLOCK
//---------------------------------------------
// Differential clock signal (DDR)
wire lvds_clock; // The direct clock input
wire lvds_clock_buf; // The clock input after global buffer (improved fanout)
SB_IO #(.PIN_TYPE(6'b000001), // Input only, direct mode
.IO_STANDARD("SB_LVDS_INPUT")) // LVDS input
iq_rx_clk ( .PACKAGE_PIN(i_iq_rx_clk_p), // Physical connection to 'i_iq_rx_clk_p'
.D_IN_0 ( lvds_clock )); // Wire out to 'lvds_clock'
SB_IO #(
.PIN_TYPE (6'b000001), // Input only, direct mode
.IO_STANDARD("SB_LVDS_INPUT")
) // LVDS input
iq_rx_clk (
.PACKAGE_PIN(i_iq_rx_clk_p), // Physical connection to 'i_iq_rx_clk_p'
.D_IN_0(lvds_clock)
); // Wire out to 'lvds_clock'
assign lvds_clock_buf = lvds_clock;
//---------------------------------------------
// LVDS RX - I/Q Data
//---------------------------------------------
// Differential 2.4GHz I/Q DDR signal
SB_IO #(.PIN_TYPE(6'b000000), // Input only, DDR mode (sample on both pos edge and
SB_IO #(
.PIN_TYPE (6'b000000), // Input only, DDR mode (sample on both pos edge and
// negedge of the input clock)
.IO_STANDARD("SB_LVDS_INPUT"), // LVDS standard
.NEG_TRIGGER(1'b0)) // The signal is not negated
iq_rx_24 ( .PACKAGE_PIN(i_iq_rx_24_n), // Attention: this is the 'n' input, thus the actual values
.NEG_TRIGGER(1'b0)
) // The signal is not negated
iq_rx_24 (
.PACKAGE_PIN(i_iq_rx_24_n), // Attention: this is the 'n' input, thus the actual values
// will need to be negated (PCB layout constraint)
.INPUT_CLK(lvds_clock_buf), // The I/O sampling clock with DDR
.D_IN_0 ( w_lvds_rx_24_d1 ), // the 0 deg data output
.D_IN_1 ( w_lvds_rx_24_d0 )); // the 180 deg data output
.D_IN_0(w_lvds_rx_24_d0), // the 0 deg data output
.D_IN_1(w_lvds_rx_24_d1)
); // the 180 deg data output
// Differential 0.9GHz I/Q DDR signal
SB_IO #(.PIN_TYPE(6'b000000), // Input only, DDR mode (sample on both pos edge and
SB_IO #(
.PIN_TYPE (6'b000000), // Input only, DDR mode (sample on both pos edge and
// negedge of the input clock)
.IO_STANDARD("SB_LVDS_INPUT"), // LVDS standard
.NEG_TRIGGER(1'b0)) // The signal is negated in hardware
iq_rx_09 ( .PACKAGE_PIN(i_iq_rx_09_p),
.NEG_TRIGGER(1'b0)
) // The signal is negated in hardware
iq_rx_09 (
.PACKAGE_PIN(i_iq_rx_09_p),
.INPUT_CLK(lvds_clock_buf), // The I/O sampling clock with DDR
.D_IN_0 ( w_lvds_rx_09_d1 ), // the 0 deg data output
.D_IN_1 ( w_lvds_rx_09_d0 ) ); // the 180 deg data output
.D_IN_0(w_lvds_rx_09_d0), // the 0 deg data output
.D_IN_1(w_lvds_rx_09_d1)
); // the 180 deg data output
//----------------------------------------------
// LVDS TX - I/Q Data
//----------------------------------------------
// Non-inverting, P-side of pair
SB_IO #(
.PIN_TYPE (6'b010000), // {PIN_OUTPUT_DDR, PIN_INPUT_REGISTER }
.IO_STANDARD("SB_LVCMOS"),
) iq_tx_p (
.PACKAGE_PIN(o_iq_tx_p),
.OUTPUT_CLK(lvds_clock_buf),
.D_OUT_0(~w_lvds_tx_d1),
.D_OUT_1(~w_lvds_tx_d0)
);
// Inverting, N-side of pair
SB_IO #(
.PIN_TYPE (6'b010000), // {PIN_OUTPUT_DDR, PIN_INPUT_REGISTER }
.IO_STANDARD("SB_LVCMOS"),
) iq_tx_n (
.PACKAGE_PIN(o_iq_tx_n),
.OUTPUT_CLK(lvds_clock_buf),
.D_OUT_0(w_lvds_tx_d1),
.D_OUT_1(w_lvds_tx_d0)
);
assign o_iq_tx_clk_p = lvds_clock_buf;
assign o_iq_tx_clk_n = ~lvds_clock_buf;
//=========================================================================
// LVDS RX SIGNAL FROM MODEM
@ -252,6 +296,10 @@ module top( input i_glob_clock,
wire w_lvds_rx_24_d0; // 0 degree
wire w_lvds_rx_24_d1; // 180 degree
wire w_lvds_tx_d0; // 0 degree
wire w_lvds_tx_d1; // 180 degree
// RX FIFO Internals
wire w_rx_09_fifo_write_clk;
wire w_rx_09_fifo_push;
wire [31:0] w_rx_09_fifo_data;
@ -260,12 +308,11 @@ module top( input i_glob_clock,
wire w_rx_24_fifo_push;
wire [31:0] w_rx_24_fifo_data;
lvds_rx lvds_rx_09_inst
(
lvds_rx lvds_rx_09_inst (
.i_rst_b (i_rst_b),
.i_ddr_clk(lvds_clock_buf),
.i_ddr_data ({w_lvds_rx_09_d1, w_lvds_rx_09_d0}),
.i_ddr_data({w_lvds_rx_09_d0, w_lvds_rx_09_d1}),
.i_fifo_full(w_rx_fifo_full),
.o_fifo_write_clk(w_rx_09_fifo_write_clk),
@ -276,12 +323,11 @@ module top( input i_glob_clock,
.o_debug_state()
);
lvds_rx lvds_rx_24_inst
(
lvds_rx lvds_rx_24_inst (
.i_rst_b (i_rst_b),
.i_ddr_clk(lvds_clock_buf),
.i_ddr_data ({!w_lvds_rx_24_d1, !w_lvds_rx_24_d0}),
.i_ddr_data({w_lvds_rx_24_d0, w_lvds_rx_24_d1}),
.i_fifo_full(w_rx_fifo_full),
.o_fifo_write_clk(w_rx_24_fifo_write_clk),
@ -316,9 +362,25 @@ module top( input i_glob_clock,
.debug_pull(w_debug_fifo_pull),
.debug_push(w_debug_fifo_push)
);
complex_fifo tx_fifo (
// smi clock is writing
.wr_rst_b_i(i_rst_b),
.wr_clk_i(w_tx_fifo_clock),
.wr_en_i(w_tx_fifo_push),
.wr_data_i(w_tx_fifo_data),
smi_ctrl smi_ctrl_ins
(
// lvds clock is pulling (reading)
.rd_rst_b_i(i_rst_b),
.rd_clk_i(w_tx_fifo_read_clk),
.rd_en_i(w_tx_fifo_pull),
.rd_data_o(w_tx_fifo_pulled_data),
.full_o(w_tx_fifo_full),
.empty_o(w_tx_fifo_empty),
.debug_pull(1'b0),
.debug_push(1'b0)
);
smi_ctrl smi_ctrl_ins (
.i_rst_b(i_rst_b),
.i_sys_clk(w_clock_sys),
.i_fast_clk(i_glob_clock),
@ -329,10 +391,15 @@ module top( input i_glob_clock,
.i_fetch_cmd(w_fetch),
.i_load_cmd(w_load),
.o_fifo_pull (w_rx_fifo_pull),
.i_fifo_pulled_data (w_rx_fifo_pulled_data),
.i_fifo_full (w_rx_fifo_full),
.i_fifo_empty (w_rx_fifo_empty),
// FIFO RX
.o_rx_fifo_pull(w_rx_fifo_pull),
.i_rx_fifo_pulled_data(w_rx_fifo_pulled_data),
.i_rx_fifo_empty(w_rx_fifo_empty),
// FIFO TX
.o_tx_fifo_push(w_tx_fifo_push),
.o_tx_fifo_pushed_data(w_tx_fifo_data),
.i_tx_fifo_full(w_tx_fifo_full),
.o_tx_fifo_clock(w_tx_fifo_clock),
.i_smi_soe_se(i_smi_soe_se),
.i_smi_swe_srw(i_smi_swe_srw),
@ -350,18 +417,97 @@ module top( input i_glob_clock,
wire w_smi_read_req;
wire w_smi_write_req;
assign io_smi_data = (i_smi_a2)?w_smi_data_output:8'bZ;
assign w_smi_data_input = io_smi_data;
assign o_smi_write_req = w_smi_write_req;
assign o_smi_read_req = w_smi_read_req;
// the "Writing" flag indicates that the data[7:0] direction (inout)
// from the FPGA's SMI module should be "output". This happens when the
// SMI is in the READ mode - data flows from the FPGA to the RPI (RX mode)
// The address has the MSB '1' when in RX mode. otherwise (when IDLE or TX)
// the data is high-z, which is the more "recessive" mode
SB_IO #(
.PIN_TYPE(6'b1010_01),
.PULLUP (1'b0)
) smi_io0 (
.PACKAGE_PIN(io_smi_data[0]),
.OUTPUT_ENABLE(i_smi_a2),
.D_OUT_0(w_smi_data_output[0]),
.D_IN_0(w_smi_data_input[0])
);
SB_IO #(
.PIN_TYPE(6'b1010_01),
.PULLUP (1'b0)
) smi_io1 (
.PACKAGE_PIN(io_smi_data[1]),
.OUTPUT_ENABLE(i_smi_a2),
.D_OUT_0(w_smi_data_output[1]),
.D_IN_0(w_smi_data_input[1])
);
SB_IO #(
.PIN_TYPE(6'b1010_01),
.PULLUP (1'b0)
) smi_io2 (
.PACKAGE_PIN(io_smi_data[2]),
.OUTPUT_ENABLE(i_smi_a2),
.D_OUT_0(w_smi_data_output[2]),
.D_IN_0(w_smi_data_input[2])
);
SB_IO #(
.PIN_TYPE(6'b1010_01),
.PULLUP (1'b0)
) smi_io3 (
.PACKAGE_PIN(io_smi_data[3]),
.OUTPUT_ENABLE(i_smi_a2),
.D_OUT_0(w_smi_data_output[3]),
.D_IN_0(w_smi_data_input[3])
);
SB_IO #(
.PIN_TYPE(6'b1010_01),
.PULLUP (1'b0)
) smi_io4 (
.PACKAGE_PIN(io_smi_data[4]),
.OUTPUT_ENABLE(i_smi_a2),
.D_OUT_0(w_smi_data_output[4]),
.D_IN_0(w_smi_data_input[4])
);
SB_IO #(
.PIN_TYPE(6'b1010_01),
.PULLUP (1'b0)
) smi_io5 (
.PACKAGE_PIN(io_smi_data[5]),
.OUTPUT_ENABLE(i_smi_a2),
.D_OUT_0(w_smi_data_output[5]),
.D_IN_0(w_smi_data_input[5])
);
SB_IO #(
.PIN_TYPE(6'b1010_01),
.PULLUP (1'b0)
) smi_io6 (
.PACKAGE_PIN(io_smi_data[6]),
.OUTPUT_ENABLE(i_smi_a2),
.D_OUT_0(w_smi_data_output[6]),
.D_IN_0(w_smi_data_input[6])
);
SB_IO #(
.PIN_TYPE(6'b1010_01),
.PULLUP (1'b0)
) smi_io7 (
.PACKAGE_PIN(io_smi_data[7]),
.OUTPUT_ENABLE(i_smi_a2),
.D_OUT_0(w_smi_data_output[7]),
.D_IN_0(w_smi_data_input[7])
);
//assign io_smi_data = (i_smi_a2)?w_smi_data_output:8'bZ;
//assign w_smi_data_input = io_smi_data;
// We need the 'o_smi_write_req' to be 1 only when the direction is TX
// (i_smi_a2 == 0) and the write fifo is not full
assign o_smi_read_req = (i_smi_a2) ? w_smi_read_req : w_smi_write_req;
assign o_smi_write_req = 1'bZ;
assign io_pmod[0] = w_rx_fifo_push;
assign io_pmod[1] = w_rx_fifo_pull;
assign io_pmod[2] = w_smi_read_req;
assign io_pmod[3] = w_rx_fifo_full;
assign io_pmod[4] = w_rx_fifo_empty;
assign io_pmod[5] = i_smi_a2;
assign io_pmod[6] = channel;
//assign io_pmod[0] = w_rx_fifo_push;
//assign io_pmod[1] = w_rx_fifo_pull;
//assign io_pmod[2] = w_smi_read_req;
//assign io_pmod[3] = w_rx_fifo_full;
//assign io_pmod[4] = w_rx_fifo_empty;
//assign io_pmod[5] = i_smi_a2;
//assign io_pmod[6] = channel;
//assign io_pmod[7] = ...;
endmodule // top