mirror of
https://github.com/aolofsson/oh.git
synced 2025-01-17 20:02:53 +08:00
d7d959da45
- This is DEFINITELY the way to do things, sweep the delays and find the right value. No f'ing way to get these stupid FPGAs to work otherwise with the ridiculuosly over margined PVT nubmers they are running through the STAs. I understand they want to make the design bullet proof, but as a result designers are wasting countless hours overoptimzinng designs and being clever. So much performance is left on the table for expert users. - Lesson: I/O design should be "self syncrhonizing". Only contraints in the design should be create_clk - Made RX clock async, too tricky to guarantee that there clock is there. No way to do this if the clock sources are actually independent for RX/TX!
177 lines
6.1 KiB
Verilog
177 lines
6.1 KiB
Verilog
/*
|
|
########################################################################
|
|
ELINK CONFIGURATION REGISTER FILE
|
|
########################################################################
|
|
|
|
*/
|
|
`include "elink_regmap.v"
|
|
|
|
module erx_cfg (/*AUTOARG*/
|
|
// Outputs
|
|
mi_dout, rx_enable, mmu_enable, remap_mode, remap_base,
|
|
remap_pattern, remap_sel, timer_cfg, idelay_value, load_taps,
|
|
// Inputs
|
|
reset, clk, mi_en, mi_we, mi_addr, mi_din, gpio_datain, rx_status
|
|
);
|
|
|
|
/******************************/
|
|
/*Compile Time Parameters */
|
|
/******************************/
|
|
parameter RFAW = 6; // 32 registers for now
|
|
parameter GROUP = 4'h0;
|
|
|
|
/******************************/
|
|
/*HARDWARE RESET (EXTERNAL) */
|
|
/******************************/
|
|
input reset; // ecfg registers reset only by "hard reset"
|
|
input clk;
|
|
|
|
/*****************************/
|
|
/*SIMPLE MEMORY INTERFACE */
|
|
/*****************************/
|
|
input mi_en;
|
|
input mi_we; // single we, must write 32 bit words
|
|
input [14:0] mi_addr; // complete physical address (no shifting!)
|
|
input [31:0] mi_din;
|
|
output [31:0] mi_dout;
|
|
|
|
/*****************************/
|
|
/*CONFIG SIGNALS */
|
|
/*****************************/
|
|
//rx
|
|
output rx_enable; // enable signal for rx
|
|
output mmu_enable; // enables MMU on rx path (static)
|
|
input [8:0] gpio_datain; // frame and data inputs (static)
|
|
input [15:0] rx_status; // etx status signals
|
|
output [1:0] remap_mode; // remap mode (static)
|
|
output [31:0] remap_base; // base for dynamic remap (static)
|
|
output [11:0] remap_pattern; // patter for static remap (static)
|
|
output [11:0] remap_sel; // selects for static remap (static)
|
|
output [1:0] timer_cfg; // timeout config (00=off) (static)
|
|
output [39:0] idelay_value; // tap values for erx idelay
|
|
output load_taps; // loads the idelay_value into IDELAY prim
|
|
|
|
/*------------------------CODE BODY---------------------------------------*/
|
|
|
|
//registers
|
|
reg [31:0] ecfg_rx_reg;
|
|
reg [31:0] ecfg_offset_reg;
|
|
reg [8:0] ecfg_gpio_reg;
|
|
reg [2:0] ecfg_rx_status_reg;
|
|
reg [63:0] ecfg_idelay_reg;
|
|
reg load_taps;
|
|
reg [31:0] mi_dout;
|
|
|
|
//wires
|
|
wire ecfg_read;
|
|
wire ecfg_write;
|
|
wire ecfg_rx_write;
|
|
wire ecfg_offset_write;
|
|
wire ecfg_remap_write;
|
|
wire ecfg_idelay0_write;
|
|
wire ecfg_idelay1_write;
|
|
|
|
/*****************************/
|
|
/*ADDRESS DECODE LOGIC */
|
|
/*****************************/
|
|
|
|
//read/write decode
|
|
assign ecfg_write = mi_en & mi_we;
|
|
assign ecfg_read = mi_en & ~mi_we;
|
|
|
|
//Config write enables
|
|
assign ecfg_rx_write = ecfg_write & (mi_addr[RFAW+1:2]==`ERX_CFG);
|
|
assign ecfg_offset_write = ecfg_write & (mi_addr[RFAW+1:2]==`ERX_OFFSET);
|
|
assign ecfg_idelay0_write = ecfg_write & (mi_addr[RFAW+1:2]==`ERX_IDELAY0);
|
|
assign ecfg_idelay1_write = ecfg_write & (mi_addr[RFAW+1:2]==`ERX_IDELAY1);
|
|
|
|
//###########################
|
|
//# RXCFG
|
|
//###########################
|
|
always @ (posedge clk or posedge reset)
|
|
if(reset)
|
|
ecfg_rx_reg[31:0] <= 'b0;
|
|
else if (ecfg_rx_write)
|
|
ecfg_rx_reg[31:0] <= mi_din[31:0];
|
|
|
|
assign rx_enable = 1'b1;//is there any good reason turn RX off?
|
|
assign mmu_enable = ecfg_rx_reg[1];
|
|
assign remap_mode[1:0] = ecfg_rx_reg[3:2];
|
|
assign remap_sel[11:0] = ecfg_rx_reg[15:4];
|
|
assign remap_pattern[11:0] = ecfg_rx_reg[27:16];
|
|
assign timer_cfg[1:0] = ecfg_rx_reg[29:28];
|
|
|
|
//###########################
|
|
//# DATAIN
|
|
//###########################
|
|
always @ (posedge clk)
|
|
ecfg_gpio_reg[8:0] <= gpio_datain[8:0];
|
|
|
|
//###########################1
|
|
//# DEBUG
|
|
//###########################
|
|
always @ (posedge clk or posedge reset)
|
|
if(reset)
|
|
ecfg_rx_status_reg[2:0] <= 'b0;
|
|
else
|
|
ecfg_rx_status_reg[2:0] <= ecfg_rx_status_reg[2:0] | rx_status[2:0];
|
|
|
|
//###########################1
|
|
//# DYNAMIC REMAP BASE
|
|
//###########################
|
|
always @ (posedge clk)
|
|
if (ecfg_offset_write)
|
|
ecfg_offset_reg[31:0] <= mi_din[31:0];
|
|
|
|
assign remap_base[31:0] = ecfg_offset_reg[31:0];
|
|
|
|
//###########################1
|
|
//# IDELAY TAP VALUES
|
|
//###########################
|
|
always @ (posedge clk or posedge reset)
|
|
if(reset)
|
|
ecfg_idelay_reg[63:0] <= 'b0;
|
|
else if (ecfg_idelay0_write)
|
|
ecfg_idelay_reg[31:0] <= mi_din[31:0];
|
|
else if(ecfg_idelay1_write)
|
|
ecfg_idelay_reg[63:32] <= mi_din[31:0];
|
|
|
|
assign idelay_value[39:0] = {ecfg_idelay_reg[41:32],ecfg_idelay_reg[29:0]};
|
|
|
|
always @ (posedge clk)
|
|
load_taps <= ecfg_idelay1_write;
|
|
|
|
//###############################
|
|
//# DATA READBACK MUX
|
|
//###############################
|
|
|
|
//Pipelineing readback
|
|
always @ (posedge clk)
|
|
if(ecfg_read)
|
|
case(mi_addr[RFAW+1:2])
|
|
`ERX_CFG: mi_dout[31:0] <= {ecfg_rx_reg[31:0]};
|
|
`ERX_GPIO: mi_dout[31:0] <= {23'b0, ecfg_gpio_reg[8:0]};
|
|
`ERX_STATUS: mi_dout[31:0] <= {16'b0, rx_status[15:3],ecfg_rx_status_reg[2:0]};
|
|
`ERX_OFFSET: mi_dout[31:0] <= {ecfg_offset_reg[31:0]};
|
|
default: mi_dout[31:0] <= 32'd0;
|
|
endcase // case (mi_addr[RFAW+1:2])
|
|
else
|
|
mi_dout[31:0] <= 32'd0;
|
|
|
|
endmodule // ecfg_rx
|
|
|
|
/*
|
|
Copyright (C) 2015 Adapteva, Inc.
|
|
Contributed by Andreas Olofsson <andreas@adapteva.com>
|
|
|
|
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 (see the file
|
|
COPYING). If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|