cariboulabs-cariboulite/firmware/top.v

368 wiersze
11 KiB
Coq
Czysty Zwykły widok Historia

2021-06-13 11:45:08 +00:00
`include "spi_if.v"
`include "sys_ctrl.v"
`include "io_ctrl.v"
`include "smi_ctrl.v"
2021-07-07 12:29:32 +00:00
`include "lvds_rx.v"
2021-07-07 18:53:01 +00:00
`include "complex_fifo.v"
2021-06-13 11:45:08 +00:00
2023-02-14 15:39:24 +00:00
module top( input i_glob_clock,
input i_rst_b, // i_smi_a1
// RF FRONT-END PATH
output o_rx_h_tx_l,
output o_rx_h_tx_l_b,
output o_tr_vc1,
output o_tr_vc1_b,
output o_tr_vc2,
output o_shdn_rx_lna,
output o_shdn_tx_lna,
// MODEM (LVDS & CLOCK)
output o_iq_tx_p,
output o_iq_tx_n,
output o_iq_tx_clk_p,
output o_iq_tx_clk_n,
input i_iq_rx_09_p, // Paired with i_iq_rx_09_n - only the 'B' pins need to be specified
input i_iq_rx_24_n, // Paired with i_iq_rx_24_p - only the 'B' pins need to be specified
input i_iq_rx_clk_p, // Paired with i_iq_rx_clk_n - only the 'B' pins need to be specified
// Note: The icestorm (specifically nextpnr) fails to build if both diff pins are constrained
// in the constrain file and the interface herein. Thus we need to take them out so that
// it will "understand" we actually want an LVDS pair inputs. In addition, the pair is
// defined only by the "B" pins in BANK3 and not the "A" pins (which is counter-logical)
// MIXER
output o_mixer_fm,
output o_mixer_en,
// DIGITAL I/F
input [3:0] i_config,
input i_button,
inout [7:0] io_pmod,
output o_led0,
output o_led1,
// SMI Addressing description
// ==========================
// In CaribouLite, the SMI addresses are connected as follows:
//
// RPI PIN | FPGA TOP-LEVEL SIGNAL
// ------------------------------------------------------------------------
// GPIO2_SA3 | i_smi_a[2] - RX09 / RX24 channel select
// GPIO3_SA2 | i_smi_a[1] - Tx SMI (0) / Rx SMI (1) select
// GPIO4_SA1 | i_smi_a[0] - used as a sys async reset (GBIN1)
// GPIO5_SA0 | Not connected to FPGA (MixerRst)
//
// In order to perform SMI data bus direction selection (highZ / PushPull)
// signal a[0] was chosen, while the '0' level (default) denotes RPI => FPGA
// direction, and the DATA bus is highZ (recessive mode).
// The signal a[2] selects the RX source (900 MHZ or 2.4GHz)
// The signal a[1] can be used in the future for other purposes
//
// Description | a[2] (SA3)| a[1] (SA2) |
// -------------|------------|---------------|
// | 0 | 0 |
// TX |------------| RPI => FPGA |
// | 1 | Data HighZ |
// -------------|------------|---------------|
// RX09 | 0 | 1 |
// -------------|------------| FPGA => RPI |
// RX24 | 1 | Data PushPull |
// -------------|------------|---------------|
input i_smi_a2,
input i_smi_a3,
input i_smi_soe_se,
input i_smi_swe_srw,
inout [7:0] io_smi_data,
output o_smi_write_req,
output o_smi_read_req,
// SPI
input i_mosi,
input i_sck,
input i_ss,
2023-02-22 08:42:41 +00:00
output o_miso
);
2023-02-14 15:39:24 +00:00
//=========================================================================
// INNER SIGNALS
//=========================================================================
reg r_counter;
wire w_clock_spi;
wire w_clock_sys;
wire [4:0] w_ioc;
wire [7:0] w_rx_data;
reg [7:0] r_tx_data;
wire [3:0] w_cs;
wire w_fetch;
wire w_load;
wire [7:0] w_tx_data_sys;
wire [7:0] w_tx_data_io;
wire [7:0] w_tx_data_smi;
//=========================================================================
// INSTANCES
//=========================================================================
spi_if spi_if_ins
(
.i_rst_b (i_rst_b),
.i_sys_clk (w_clock_sys),
.o_ioc (w_ioc),
.o_data_in (w_rx_data),
.i_data_out (r_tx_data),
.o_cs (w_cs),
.o_fetch_cmd (w_fetch),
.o_load_cmd (w_load),
// SPI Interface
.i_spi_sck (i_sck),
.o_spi_miso (int_miso),
.i_spi_mosi (i_mosi),
.i_spi_cs_b (i_ss)
);
wire int_miso;
assign o_miso = (i_ss)?1'bZ:int_miso;
// SYSTEM CTRL
sys_ctrl sys_ctrl_ins
(
.i_rst_b (i_rst_b),
.i_sys_clk (w_clock_sys),
.i_ioc (w_ioc),
.i_data_in (w_rx_data),
.o_data_out (w_tx_data_sys),
.i_cs (w_cs[0]),
.i_fetch_cmd (w_fetch),
.i_load_cmd (w_load),
.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)
);
wire w_debug_fifo_push;
wire w_debug_fifo_pull;
wire w_debug_smi_test;
// IO CTRL
io_ctrl io_ctrl_ins
(
.i_rst_b (i_rst_b),
.i_sys_clk (w_clock_sys),
.i_ioc (w_ioc),
.i_data_in (w_rx_data),
.o_data_out (w_tx_data_io),
.i_cs (w_cs[1]),
.i_fetch_cmd (w_fetch),
.i_load_cmd (w_load),
// Digital interfaces
.i_button (i_button),
.i_config (i_config),
.o_led0 (o_led0),
.o_led1 (o_led1),
.o_pmod (),
// Analog interfaces
.o_mixer_fm (o_mixer_fm),
.o_rx_h_tx_l (o_rx_h_tx_l),
.o_rx_h_tx_l_b (o_rx_h_tx_l_b),
.o_tr_vc1 (o_tr_vc1),
.o_tr_vc1_b (o_tr_vc1_b),
.o_tr_vc2 (o_tr_vc2),
.o_shdn_tx_lna (o_shdn_tx_lna),
.o_shdn_rx_lna (o_shdn_rx_lna),
.o_mixer_en (o_mixer_en)
);
//=========================================================================
// CLOCK AND DATA-FLOW
//=========================================================================
assign w_clock_sys = r_counter;
2023-02-22 08:42:41 +00:00
//=========================================================================
// CLOCK AND DATA-FLOW
//=========================================================================
2023-02-14 15:39:24 +00:00
always @(posedge i_glob_clock)
begin
if (i_rst_b == 1'b0) begin
r_counter <= 1'b0;
end else begin
r_counter <= !r_counter;
case (w_cs)
4'b0001: r_tx_data <= w_tx_data_sys;
4'b0010: r_tx_data <= w_tx_data_io;
4'b0100: r_tx_data <= w_tx_data_smi;
4'b1000: r_tx_data <= 8'b10100101; // 0xA5: reserved
4'b0000: r_tx_data <= 8'b00000000; // no module selected
endcase
end
end
//=========================================================================
// I/O (SB_IO, SB_GB) DIFFERENTIAL LINES
//=========================================================================
// 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'
assign lvds_clock_buf = lvds_clock;
// Differential 2.4GHz I/Q DDR signal
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
// 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
// Differential 0.9GHz I/Q DDR signal
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),
.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
//=========================================================================
// LVDS RX SIGNAL FROM MODEM
//=========================================================================
wire w_lvds_rx_09_d0; // 0 degree
wire w_lvds_rx_09_d1; // 180 degree
wire w_lvds_rx_24_d0; // 0 degree
wire w_lvds_rx_24_d1; // 180 degree
wire w_rx_09_fifo_write_clk;
wire w_rx_09_fifo_push;
wire [31:0] w_rx_09_fifo_data;
wire w_rx_24_fifo_write_clk;
wire w_rx_24_fifo_push;
wire [31:0] w_rx_24_fifo_data;
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_fifo_full (w_rx_fifo_full),
.o_fifo_write_clk (w_rx_09_fifo_write_clk),
.o_fifo_push (w_rx_09_fifo_push),
.o_fifo_data (w_rx_09_fifo_data),
.i_sync_input (1'b0),
.o_debug_state ()
);
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_fifo_full (w_rx_fifo_full),
.o_fifo_write_clk (w_rx_24_fifo_write_clk),
.o_fifo_push (w_rx_24_fifo_push),
.o_fifo_data (w_rx_24_fifo_data),
.i_sync_input (1'b0),
.o_debug_state ()
);
wire w_rx_fifo_write_clk = (channel == 1'b0)?w_rx_09_fifo_write_clk:w_rx_24_fifo_write_clk;
wire w_rx_fifo_push = (channel == 1'b0)?w_rx_09_fifo_push:w_rx_24_fifo_push;
wire [31:0] w_rx_fifo_data = (channel == 1'b0)?w_rx_09_fifo_data:w_rx_24_fifo_data;
wire w_rx_fifo_pull;
wire [31:0] w_rx_fifo_pulled_data;
wire w_rx_fifo_full;
wire w_rx_fifo_empty;
wire channel;
complex_fifo rx_fifo(
.wr_rst_b_i (i_rst_b),
.wr_clk_i (w_rx_fifo_write_clk),
.wr_en_i (w_rx_fifo_push),
.wr_data_i (w_rx_fifo_data),
.rd_rst_b_i (i_rst_b),
.rd_clk_i (w_clock_sys),
.rd_en_i (w_rx_fifo_pull),
.rd_data_o (w_rx_fifo_pulled_data),
.full_o (w_rx_fifo_full),
.empty_o (w_rx_fifo_empty),
.debug_pull (w_debug_fifo_pull),
.debug_push (w_debug_fifo_push)
);
smi_ctrl smi_ctrl_ins
(
.i_rst_b (i_rst_b),
.i_sys_clk (w_clock_sys),
.i_fast_clk (i_glob_clock),
.i_ioc (w_ioc),
.i_data_in (w_rx_data),
.o_data_out (w_tx_data_smi),
.i_cs (w_cs[2]),
.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),
.i_smi_soe_se (i_smi_soe_se),
.i_smi_swe_srw (i_smi_swe_srw),
.o_smi_data_out (w_smi_data_output),
.i_smi_data_in (w_smi_data_input),
.o_smi_read_req (w_smi_read_req),
.o_smi_write_req (w_smi_write_req),
.o_channel (channel),
.i_smi_test (w_debug_smi_test),
.o_address_error ()
);
wire [7:0] w_smi_data_output;
wire [7:0] w_smi_data_input;
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;
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] = ...;
2021-06-13 11:45:08 +00:00
endmodule // top