mirror of
https://github.com/aolofsson/oh.git
synced 2025-01-17 20:02:53 +08:00
Continued work to create clean design:
-pll bypass for clocks (customer request) -adding dividers on all clocks (tx/cclk) -adding reset block (clearer) -using commong clock_divider block -need to clean up divider block later today, slightly broken:-)
This commit is contained in:
parent
bee90fcacc
commit
69f3df4140
116
common/hdl/clock_divider.v
Normal file
116
common/hdl/clock_divider.v
Normal file
@ -0,0 +1,116 @@
|
||||
// ###############################################################
|
||||
// # FUNCTION: Synchronous clock divider that divides by integer
|
||||
// ###############################################################
|
||||
|
||||
module clock_divider(/*AUTOARG*/
|
||||
// Outputs
|
||||
clkout, clkout90,
|
||||
// Inputs
|
||||
clkin, divcfg, reset
|
||||
);
|
||||
|
||||
input clkin; // Input clock
|
||||
input [3:0] divcfg; // Divide factor
|
||||
input reset; // Counter init
|
||||
|
||||
output clkout; // Divided clock phase aligned with clkin
|
||||
output clkout90; // Divided clock with 90deg phase shift with clkout
|
||||
|
||||
|
||||
reg clkout_reg;
|
||||
reg [7:0] counter;
|
||||
reg [7:0] divcfg_dec;
|
||||
|
||||
wire div2_sel;
|
||||
wire div1_sel;
|
||||
wire posedge_match;
|
||||
wire negedge_match;
|
||||
wire posedge90_match;
|
||||
wire negedge90_match;
|
||||
|
||||
wire clkout90_div2_in;
|
||||
wire clkout90_div4_in;
|
||||
|
||||
reg clkout90_div4;
|
||||
reg clkout90_div2;
|
||||
|
||||
// ###################
|
||||
// # Decode divcfg
|
||||
// ###################
|
||||
|
||||
always @ (divcfg[3:0])
|
||||
casez (divcfg[3:0])
|
||||
4'b0111 : divcfg_dec[7:0] = 8'b00000010; // Divide by 2
|
||||
4'b0110 : divcfg_dec[7:0] = 8'b00000100; // Divide by 4
|
||||
4'b0101 : divcfg_dec[7:0] = 8'b00001000; // Divide by 8
|
||||
4'b0100 : divcfg_dec[7:0] = 8'b00010000; // Divide by 16
|
||||
4'b0011 : divcfg_dec[7:0] = 8'b00100000; // Divide by 32
|
||||
4'b0010 : divcfg_dec[7:0] = 8'b01000000; // Divide by 64
|
||||
4'b0001 : divcfg_dec[7:0] = 8'b10000000; // Divide by 128
|
||||
default : divcfg_dec[7:0] = 8'b0000000; // others
|
||||
endcase
|
||||
|
||||
//Divide by two special case
|
||||
assign div2_sel = divcfg[3:0]==4'b0111;
|
||||
assign div1_sel = divcfg[3:0]==4'b1000;//TODO: may change
|
||||
|
||||
always @ (posedge clkin or posedge reset)
|
||||
if(reset)
|
||||
counter[7:0] <= 8'b000001;
|
||||
else
|
||||
if(posedge_match)
|
||||
counter[7:0] <= 8'b000001;// Self resetting
|
||||
else
|
||||
counter[7:0] <= (counter[7:0] + 8'b000001);
|
||||
|
||||
assign posedge_match = (counter[7:0]==divcfg_dec[7:0]);
|
||||
assign negedge_match = (counter[7:0]=={1'b0,divcfg_dec[7:1]});
|
||||
assign posedge90_match = (counter[7:0]==({2'b00,divcfg_dec[7:2]}));
|
||||
assign negedge90_match = (counter[7:0]==({2'b00,divcfg_dec[7:2]} +
|
||||
{1'b0,divcfg_dec[7:1]}));
|
||||
|
||||
always @ (posedge clkin)
|
||||
if(posedge_match)
|
||||
clkout_reg <= 1'b1;
|
||||
else if(negedge_match)
|
||||
clkout_reg <= 1'b0;
|
||||
|
||||
assign clkout = div1_sel ? clkin : clkout_reg;
|
||||
|
||||
assign clkout90_div4_in = posedge90_match ? 1'b1 :
|
||||
negedge90_match ? 1'b0 :
|
||||
clkout90_div4;
|
||||
|
||||
assign clkout90_div2_in = negedge_match ? 1'b1 :
|
||||
posedge_match ? 1'b0 :
|
||||
clkout90_div2;
|
||||
|
||||
|
||||
always @ (posedge clkin)
|
||||
clkout90_div4 <= clkout90_div4_in;
|
||||
|
||||
always @ (negedge clkin)
|
||||
clkout90_div2 <= clkout90_div2_in;
|
||||
|
||||
assign clkout90 = div2_sel ? clkout90_div2 : clkout90_div4;
|
||||
|
||||
endmodule // clock_divider
|
||||
|
||||
/*
|
||||
Copyright (C) 2013 Adapteva, Inc.
|
||||
Contributed by Andreas Olofsson <support@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/>.
|
||||
*/
|
@ -40,7 +40,6 @@ module dv_elink(/*AUTOARG*/
|
||||
/*AUTOINPUT*/
|
||||
/*AUTOOUTPUT*/
|
||||
|
||||
|
||||
/*AUTOWIRE*/
|
||||
// Beginning of automatic wires (for undeclared instantiated-module outputs)
|
||||
wire [7:0] data_n; // From elink of elink.v
|
||||
@ -154,7 +153,7 @@ module dv_elink(/*AUTOARG*/
|
||||
wire embox_full;
|
||||
wire embox_not_empty;
|
||||
wire cclk_p, cclk_n;
|
||||
wire resetb;
|
||||
wire chip_resetb;
|
||||
|
||||
|
||||
|
||||
@ -347,21 +346,20 @@ module dv_elink(/*AUTOARG*/
|
||||
);
|
||||
*/
|
||||
|
||||
elink elink (.reset_in (reset),
|
||||
.clkin (clk),
|
||||
.flag (1'b0),
|
||||
elink elink (.hard_reset (reset),
|
||||
.embox_not_empty (embox_full),
|
||||
.embox_full (embox_not_empty),
|
||||
.cclk_p (cclk_p),
|
||||
.cclk_n (cclk_n),
|
||||
.resetb_out (resetb),
|
||||
.chip_resetb (chip_resetb),
|
||||
.colid (colid[3:0]),
|
||||
.rowid (rowid[3:0]),
|
||||
.s_axi_aresetn (~reset),
|
||||
.m_axi_aresetn (~reset),
|
||||
.s_axi_aclk (clk),
|
||||
.m_axi_aclk (clk),
|
||||
|
||||
.cclk_p (cclk_p),
|
||||
.cclk_n (cclk_n),
|
||||
.clkin (clk),
|
||||
.bypass_clocks ({clk,clk,clk}),
|
||||
/*AUTOINST*/
|
||||
// Outputs
|
||||
.rxo_wr_wait_p (wr_wait_p), // Templated
|
||||
@ -448,7 +446,6 @@ module dv_elink(/*AUTOARG*/
|
||||
.s_axi_wstrb (dv_axi_wstrb[3:0]), // Templated
|
||||
.s_axi_wvalid (dv_axi_wvalid)); // Templated
|
||||
|
||||
|
||||
endmodule // dv_elink
|
||||
// Local Variables:
|
||||
// verilog-library-directories:("." "../hdl")
|
||||
|
166
elink/hdl/ecfg.v
166
elink/hdl/ecfg.v
@ -17,9 +17,8 @@
|
||||
10 - reserved
|
||||
11 - reserved
|
||||
[7:4] Transmit control mode for eMesh
|
||||
[11:8] 0000 - No division, full speed
|
||||
0001 - Divide by 2
|
||||
[12] Bypass mode (clkin used for tx_lclk)
|
||||
[11:8] Reserved
|
||||
[12] Reserved
|
||||
[13] AXI slave read timeout enable
|
||||
-------------------------------------------------------------
|
||||
ESYSRX ***Elink receiver configuration***
|
||||
@ -34,7 +33,7 @@
|
||||
-------------------------------------------------------------
|
||||
ESYSCLK ***Epiphany clock frequency setting***
|
||||
[3:0] Output divider
|
||||
0000 - Clock turned off
|
||||
0000 - CLKIN/128
|
||||
0001 - CLKIN/64
|
||||
0010 - CLKIN/32
|
||||
0011 - CLKIN/16
|
||||
@ -43,8 +42,19 @@
|
||||
0110 - CLKIN/2
|
||||
0111 - CLKIN/1 (full speed)
|
||||
1XXX - RESERVED
|
||||
[7:4] PLL settings (TBD)
|
||||
[8] PLL bypass mode (cclk is set to clkin)
|
||||
[7:4] Elink Transmit Clock
|
||||
0000 - CLKIN/128
|
||||
0001 - CLKIN/64
|
||||
0010 - CLKIN/32
|
||||
0011 - CLKIN/16
|
||||
0100 - CLKIN/8
|
||||
0101 - CLKIN/4
|
||||
0110 - CLKIN/2
|
||||
0111 - CLKIN/1 (full speed)
|
||||
1XXX - RESERVED
|
||||
[11:8] PLL settings (TBD)
|
||||
[12] CCLK PLL bypass mode (cclk is set to clkin)
|
||||
[13] LCLK PLL bypass mode (lclk is set to clkin)
|
||||
-------------------------------------------------------------
|
||||
ESYSCOREID ***CORE ID***
|
||||
[5:0] Column ID-->default at powerup/reset
|
||||
@ -92,7 +102,7 @@
|
||||
[10] emwr_rd_en
|
||||
[9] esaxi_emwr_prog_full
|
||||
[8] esaxi_emwr_wr_en
|
||||
//Sticky signals
|
||||
##########Sticky signals below#############
|
||||
[7] reserved
|
||||
[6] emrr_full (rx)
|
||||
[5] emrq_full (rx)
|
||||
@ -106,87 +116,81 @@
|
||||
|
||||
module ecfg (/*AUTOARG*/
|
||||
// Outputs
|
||||
mi_dout, ecfg_reset, ecfg_resetb, ecfg_tx_enable,
|
||||
ecfg_tx_mmu_enable, ecfg_tx_gpio_enable, ecfg_tx_ctrlmode,
|
||||
ecfg_tx_clkdiv, ecfg_tx_clkbypass, ecfg_timeout_enable,
|
||||
soft_reset, mi_dout, ecfg_tx_enable, ecfg_tx_mmu_enable,
|
||||
ecfg_tx_gpio_enable, ecfg_tx_ctrlmode, ecfg_timeout_enable,
|
||||
ecfg_rx_enable, ecfg_rx_mmu_enable, ecfg_rx_gpio_enable,
|
||||
ecfg_cclk_en, ecfg_cclk_div, ecfg_cclk_pllcfg, ecfg_cclk_bypass,
|
||||
ecfg_coreid, ecfg_dataout, embox_not_empty, embox_full,
|
||||
ecfg_clk_settings, ecfg_coreid, ecfg_dataout, embox_not_empty,
|
||||
embox_full,
|
||||
// Inputs
|
||||
hw_reset, clk, mi_en, mi_we, mi_addr, mi_din, ecfg_rx_datain,
|
||||
hard_reset, mi_clk, mi_en, mi_we, mi_addr, mi_din, ecfg_rx_datain,
|
||||
ecfg_tx_datain, ecfg_tx_debug, ecfg_rx_debug
|
||||
);
|
||||
|
||||
/******************************/
|
||||
/*Compile Time Parameters */
|
||||
/******************************/
|
||||
parameter RFAW = 5; //32 registers for now
|
||||
parameter DEFAULT_COREID = 12'h808; //reset value for ecfg_coreid
|
||||
parameter DEFAULT_VERSION = 16'h0000; //reset value for version
|
||||
parameter RFAW = 5; // 32 registers for now
|
||||
parameter DEFAULT_COREID = 12'h808; // reset value for ecfg_coreid
|
||||
parameter DEFAULT_VERSION = 16'h0000; // reset value for version
|
||||
|
||||
/******************************/
|
||||
/*HARDWARE RESET (POR/BUTTON) */
|
||||
/*HARDWARE RESET (EXTERNAL) */
|
||||
/******************************/
|
||||
input hw_reset;
|
||||
input hard_reset; // ecfg registers reset only by "hard reset"
|
||||
output soft_reset; // soft reset output driven by register
|
||||
|
||||
/*****************************/
|
||||
/*SIMPLE MEMORY INTERFACE */
|
||||
/*****************************/
|
||||
input clk;
|
||||
input mi_en;
|
||||
input mi_we; //single we, must write 32 bit words
|
||||
input [19:0] mi_addr; //complete physical address (no shifting!)
|
||||
input [31:0] mi_din;
|
||||
output [31:0] mi_dout;
|
||||
/*****************************/
|
||||
input mi_clk;
|
||||
input mi_en;
|
||||
input mi_we; // single we, must write 32 bit words
|
||||
input [19:0] mi_addr; // complete physical address (no shifting!)
|
||||
input [31:0] mi_din;
|
||||
output [31:0] mi_dout;
|
||||
|
||||
/*****************************/
|
||||
/*ELINK CONTROL SIGNALS */
|
||||
/*****************************/
|
||||
//reset
|
||||
output ecfg_reset; //reset for all elink logic
|
||||
output ecfg_resetb; //reset for epiphany (active low)
|
||||
|
||||
|
||||
//tx
|
||||
output ecfg_tx_enable; //enable signal for TX
|
||||
output ecfg_tx_mmu_enable; //enables MMU on transmit path
|
||||
output ecfg_tx_gpio_enable; //forces TX output pins to constants
|
||||
output [3:0] ecfg_tx_ctrlmode; //value for emesh ctrlmode tag
|
||||
output [3:0] ecfg_tx_clkdiv; //transmit clock divider
|
||||
output ecfg_tx_clkbypass; //transmit clock bypass
|
||||
output ecfg_timeout_enable; //enables axi-slave timeout circuit
|
||||
output ecfg_tx_enable; // enable signal for TX
|
||||
output ecfg_tx_mmu_enable; // enables MMU on transmit path
|
||||
output ecfg_tx_gpio_enable; // forces TX output pins to constants
|
||||
output [3:0] ecfg_tx_ctrlmode; // value for emesh ctrlmode tag
|
||||
output ecfg_timeout_enable; // enables axi slave timeout circuit
|
||||
|
||||
//rx
|
||||
output ecfg_rx_enable; //enable signal for rx
|
||||
output ecfg_rx_mmu_enable; //enables MMU on rx path
|
||||
output ecfg_rx_gpio_enable; //forces rx wait pins to constants
|
||||
|
||||
//cclk
|
||||
output ecfg_cclk_en; //cclk enable
|
||||
output [3:0] ecfg_cclk_div; //cclk divider setting
|
||||
output [3:0] ecfg_cclk_pllcfg; //pll configuration
|
||||
output ecfg_cclk_bypass; //pll bypass
|
||||
output ecfg_rx_enable; // enable signal for rx
|
||||
output ecfg_rx_mmu_enable; // enables MMU on rx path
|
||||
output ecfg_rx_gpio_enable; // forces rx wait pins to constants
|
||||
|
||||
//clocks
|
||||
output [15:0] ecfg_clk_settings; // clock settings
|
||||
|
||||
//coreid
|
||||
output [11:0] ecfg_coreid; //core-id of fpga elink
|
||||
output [11:0] ecfg_coreid; // core-id of fpga elink
|
||||
|
||||
//gpio
|
||||
input [8:0] ecfg_rx_datain; //frame and data
|
||||
input [1:0] ecfg_tx_datain; //wait signals
|
||||
output [10:0] ecfg_dataout; //data for elink outputs
|
||||
input [8:0] ecfg_rx_datain; // frame and data
|
||||
input [1:0] ecfg_tx_datain; // wait signals
|
||||
output [10:0] ecfg_dataout; // data for elink outputs
|
||||
|
||||
//debug
|
||||
output embox_not_empty; //not-empty
|
||||
output embox_full; //full
|
||||
input [15:0] ecfg_tx_debug; //etx debug signals
|
||||
input [15:0] ecfg_rx_debug; //etx debug signals
|
||||
output embox_not_empty; // not-empty interrupt
|
||||
output embox_full; // full debug signal
|
||||
input [15:0] ecfg_tx_debug; // etx debug signals
|
||||
input [15:0] ecfg_rx_debug; // etx debug signals
|
||||
|
||||
/*------------------------BODY CODE---------------------------------------*/
|
||||
/*------------------------CODE BODY---------------------------------------*/
|
||||
|
||||
//registers
|
||||
reg ecfg_reset_reg;
|
||||
reg [13:0] ecfg_cfgtx_reg;
|
||||
reg [4:0] ecfg_cfgrx_reg;
|
||||
reg [8:0] ecfg_cfgclk_reg;
|
||||
reg [15:0] ecfg_cfgclk_reg;
|
||||
reg [11:0] ecfg_coreid_reg;
|
||||
reg [15:0] ecfg_version_reg;
|
||||
reg [10:0] ecfg_datain_reg;
|
||||
@ -228,20 +232,19 @@ module ecfg (/*AUTOARG*/
|
||||
//###########################
|
||||
//# ESYSRESET
|
||||
//###########################
|
||||
always @ (posedge clk)
|
||||
if(hw_reset)
|
||||
always @ (posedge mi_clk)
|
||||
if(hard_reset)
|
||||
ecfg_reset_reg <= 1'b0;
|
||||
else if (ecfg_reset_write)
|
||||
ecfg_reset_reg <= mi_din[0];
|
||||
|
||||
assign ecfg_reset = ecfg_reset_reg | hw_reset;
|
||||
assign ecfg_resetb = ~ecfg_reset;
|
||||
assign soft_reset = ecfg_reset_reg;
|
||||
|
||||
//###########################
|
||||
//# ESYSTX
|
||||
//###########################
|
||||
always @ (posedge clk)
|
||||
if(hw_reset)
|
||||
always @ (posedge mi_clk)
|
||||
if(hard_reset)
|
||||
ecfg_cfgtx_reg[13:0] <= 14'b0;
|
||||
else if (ecfg_cfgtx_write)
|
||||
ecfg_cfgtx_reg[13:0] <= mi_din[13:0];
|
||||
@ -250,15 +253,13 @@ module ecfg (/*AUTOARG*/
|
||||
assign ecfg_tx_mmu_enable = ecfg_cfgtx_reg[1];
|
||||
assign ecfg_tx_gpio_enable = (ecfg_cfgtx_reg[3:2]==2'b01);
|
||||
assign ecfg_tx_ctrlmode[3:0] = ecfg_cfgtx_reg[7:4];
|
||||
assign ecfg_tx_clkdiv[3:0] = ecfg_cfgtx_reg[11:8];
|
||||
assign ecfg_tx_clkbypass = ecfg_cfgtx_reg[12];
|
||||
assign ecfg_timeout_enable = ecfg_cfgtx_reg[13];
|
||||
|
||||
//###########################
|
||||
//# ESYSRX
|
||||
//###########################
|
||||
always @ (posedge clk)
|
||||
if(hw_reset)
|
||||
always @ (posedge mi_clk)
|
||||
if(hard_reset)
|
||||
ecfg_cfgrx_reg[4:0] <= 5'b0;
|
||||
else if (ecfg_cfgrx_write)
|
||||
ecfg_cfgrx_reg[4:0] <= mi_din[4:0];
|
||||
@ -270,22 +271,25 @@ module ecfg (/*AUTOARG*/
|
||||
//###########################
|
||||
//# ESYSCLK
|
||||
//###########################
|
||||
always @ (posedge clk)
|
||||
if(hw_reset)
|
||||
ecfg_cfgclk_reg[8:0] <= 9'b0;
|
||||
always @ (posedge mi_clk)
|
||||
if(hard_reset)
|
||||
ecfg_cfgclk_reg[15:0] <= 16'b0;
|
||||
else if (ecfg_cfgclk_write)
|
||||
ecfg_cfgclk_reg[8:0] <= mi_din[8:0];
|
||||
ecfg_cfgclk_reg[15:0] <= mi_din[15:0];
|
||||
|
||||
assign ecfg_cclk_en = ~(ecfg_cfgclk_reg[3:0]==4'b0000);
|
||||
assign ecfg_cclk_div[3:0] = ecfg_cfgclk_reg[3:0];
|
||||
assign ecfg_cclk_pllcfg[3:0] = ecfg_cfgclk_reg[7:4];
|
||||
assign ecfg_cclk_bypass = ecfg_cfgclk_reg[8];
|
||||
assign ecfg_clk_settings[15:0] = ecfg_cfgclk_reg[15:0];
|
||||
|
||||
|
||||
//assign ecfg_cclk_en = ~(ecfg_cfgclk_reg[3:0]==4'b0000);
|
||||
//assign ecfg_cclk_div[3:0] = ecfg_cfgclk_reg[3:0];
|
||||
//assign ecfg_cclk_pllcfg[3:0] = ecfg_cfgclk_reg[7:4];
|
||||
//assign ecfg_cclk_bypass = ecfg_cfgclk_reg[8];
|
||||
|
||||
//###########################
|
||||
//# ESYSCOREID
|
||||
//###########################
|
||||
always @ (posedge clk)
|
||||
if(hw_reset)
|
||||
always @ (posedge mi_clk)
|
||||
if(hard_reset)
|
||||
ecfg_coreid_reg[11:0] <= DEFAULT_COREID;
|
||||
else if (ecfg_coreid_write)
|
||||
ecfg_coreid_reg[11:0] <= mi_din[11:0];
|
||||
@ -295,8 +299,8 @@ module ecfg (/*AUTOARG*/
|
||||
//###########################
|
||||
//# ESYSVERSION
|
||||
//###########################
|
||||
always @ (posedge clk)
|
||||
if(hw_reset)
|
||||
always @ (posedge mi_clk)
|
||||
if(hard_reset)
|
||||
ecfg_version_reg[15:0] <= DEFAULT_VERSION;
|
||||
else if (ecfg_version_write)
|
||||
ecfg_version_reg[15:0] <= mi_din[15:0];
|
||||
@ -304,14 +308,14 @@ module ecfg (/*AUTOARG*/
|
||||
//###########################
|
||||
//# ESYSDATAIN
|
||||
//###########################
|
||||
always @ (posedge clk)
|
||||
always @ (posedge mi_clk)
|
||||
ecfg_datain_reg[10:0] <= {ecfg_rx_datain[1:0], ecfg_rx_datain[8:0]};
|
||||
|
||||
//###########################
|
||||
//# ESYSDATAOUT
|
||||
//###########################
|
||||
always @ (posedge clk)
|
||||
if(hw_reset)
|
||||
always @ (posedge mi_clk)
|
||||
if(hard_reset)
|
||||
ecfg_dataout_reg[10:0] <= 11'd0;
|
||||
else if (ecfg_dataout_write)
|
||||
ecfg_dataout_reg[10:0] <= mi_din[10:0];
|
||||
@ -329,8 +333,8 @@ module ecfg (/*AUTOARG*/
|
||||
embox_full
|
||||
};
|
||||
|
||||
always @ (posedge clk)
|
||||
if(hw_reset)
|
||||
always @ (posedge mi_clk)
|
||||
if(hard_reset)
|
||||
ecfg_debug_reg[7:0] <= 8'd0;
|
||||
else
|
||||
ecfg_debug_reg[7:0] <=ecfg_debug_reg[7:0] | ecfg_debug_vector[7:0];
|
||||
@ -340,7 +344,7 @@ module ecfg (/*AUTOARG*/
|
||||
//###############################
|
||||
|
||||
//Pipelineing readback
|
||||
always @ (posedge clk)
|
||||
always @ (posedge mi_clk)
|
||||
if(ecfg_read)
|
||||
case(mi_addr[RFAW+1:2])
|
||||
`ESYSRESET: mi_dout[31:0] <= {31'b0, ecfg_reset_reg};
|
||||
|
281
elink/hdl/eclocks.v
Normal file
281
elink/hdl/eclocks.v
Normal file
@ -0,0 +1,281 @@
|
||||
/*###########################################################################
|
||||
# Function: High speed clock generator elink module
|
||||
#
|
||||
# cclk_p/n - Epiphany Core Clock, Differential, must be connected
|
||||
# directly to IO pins.
|
||||
#
|
||||
# tx_lclk_par - Parallel data clock, at bit rate / 8 for etx
|
||||
#
|
||||
# tx_lclk - Serial DDR data clock, at bit rate / 2 for etx
|
||||
#
|
||||
# tx_lclk_out - DDR "Clock" clock, to generate tx_lclk_p/n output
|
||||
# At bit rate / 2, 90deg shifted from tx_lclk
|
||||
#
|
||||
# Notes: Uses Xilinx macros throughout
|
||||
#
|
||||
############################################################################
|
||||
*/
|
||||
|
||||
`timescale 1ns/1ps
|
||||
|
||||
module eclocks (/*AUTOARG*/
|
||||
// Outputs
|
||||
cclk_p, cclk_n, tx_lclk, tx_lclk_out, tx_lclk_par,
|
||||
// Inputs
|
||||
clkin, hard_reset, ecfg_clk_settings, bypass_clocks
|
||||
);
|
||||
|
||||
// Parameters must be set as follows:
|
||||
// PFD input frequency = 1/CLKIN1_PERIOD / DIVCLK_DIVIDE (10-450MHz)
|
||||
// VCO frequency = PFD input frequency * CLKFBOUT_MULT (800-1600MHz)
|
||||
// Output frequency = VCO frequency / CLKOUTn_DIVIDE
|
||||
|
||||
parameter CLKIN_PERIOD = 10.000; // ns -> 100MHz
|
||||
parameter CLKIN_DIVIDE = 1;
|
||||
parameter VCO_MULT = 12; // VCO = 1200MHz
|
||||
parameter CCLK_DIVIDE = 2; // CCLK = 600MHz
|
||||
parameter LCLK_DIVIDE = 4; // LCLK = 300MHz (600MB/s eLink)
|
||||
parameter FEATURE_CCLK_DIV = 1'b1;
|
||||
parameter IOSTD_ELINK = "LVDS_25";
|
||||
parameter INC_PLL = 1;
|
||||
|
||||
//Input clock, reset, config interface
|
||||
input clkin; // primary input clock
|
||||
input hard_reset; //
|
||||
input [15:0] ecfg_clk_settings; // clock settings
|
||||
input [2:0] bypass_clocks; // for bypassing PLL
|
||||
|
||||
|
||||
//Output Clocks
|
||||
output cclk_p, cclk_n; // high speed Epiphany clock (up to 1GHz)
|
||||
output tx_lclk; // elink tx serdes clock
|
||||
output tx_lclk_out; // center aligned output clock for elink tx
|
||||
output tx_lclk_par; // lclk/8 slow clock for tx parallel logic
|
||||
|
||||
// Wires
|
||||
|
||||
|
||||
`ifdef TARGET_XILINX
|
||||
wire clkfb;
|
||||
wire pll_cclk; //full speed cclk
|
||||
wire pll_lclk; //full speed lclk etx
|
||||
wire pll_lclk_out; //full speed lclk for pin for etx
|
||||
wire pll_lclk_par; //low speed lclk for etx
|
||||
wire pll_cclk_div; //low speed cclk
|
||||
wire pll_cclk_standby; //standby clock
|
||||
wire cclk;
|
||||
wire cclk_base;
|
||||
wire cclk_div;
|
||||
|
||||
// PLL Primitive
|
||||
generate
|
||||
for (i=0; i< INC_PLL; i=i+1) begin : PLL
|
||||
PLLE2_BASE
|
||||
#(
|
||||
.BANDWIDTH("OPTIMIZED"), // OPTIMIZED, HIGH, LOW
|
||||
.CLKFBOUT_MULT(VCO_MULT), // Multiply value for all CLKOUT, (2-64)
|
||||
.CLKFBOUT_PHASE(0.0), // Phase offset in degrees of CLKFB, (-360.000-360.000).
|
||||
.CLKIN1_PERIOD(CLKIN_PERIOD),// Input clock period in ns to ps resolution (i.e. 33.333 is 30 MHz).
|
||||
// CLKOUT0_DIVIDE - CLKOUT5_DIVIDE: Divide amount for each CLKOUT (1-128)
|
||||
.CLKOUT0_DIVIDE(CCLK_DIVIDE), //full speed
|
||||
.CLKOUT1_DIVIDE(LCLK_DIVIDE), //full speed
|
||||
.CLKOUT2_DIVIDE(LCLK_DIVIDE), //full speed
|
||||
.CLKOUT3_DIVIDE(LCLK_DIVIDE * 4), //low speed
|
||||
.CLKOUT4_DIVIDE(CCLK_DIVIDE * 4), //low speed
|
||||
.CLKOUT5_DIVIDE(128), //veeery low speed
|
||||
// CLKOUT0_DUTY_CYCLE - CLKOUT5_DUTY_CYCLE: Duty cycle for each CLKOUT (0.001-0.999).
|
||||
.CLKOUT0_DUTY_CYCLE(0.5),
|
||||
.CLKOUT1_DUTY_CYCLE(0.5),
|
||||
.CLKOUT2_DUTY_CYCLE(0.5),
|
||||
.CLKOUT3_DUTY_CYCLE(0.5),
|
||||
.CLKOUT4_DUTY_CYCLE(0.5),
|
||||
.CLKOUT5_DUTY_CYCLE(0.5),
|
||||
// CLKOUT0_PHASE - CLKOUT5_PHASE: Phase offset for each CLKOUT (-360.000-360.000).
|
||||
.CLKOUT0_PHASE(0.0),
|
||||
.CLKOUT1_PHASE(0.0),
|
||||
.CLKOUT2_PHASE(90.0),
|
||||
.CLKOUT3_PHASE(0.0),
|
||||
.CLKOUT4_PHASE(0.0),
|
||||
.CLKOUT5_PHASE(0.0),
|
||||
.DIVCLK_DIVIDE(CLKIN_DIVIDE),// Master division value, (1-56)
|
||||
.REF_JITTER1(0.01), // Reference input jitter (0.000-0.999).
|
||||
.STARTUP_WAIT("FALSE") // Delay DONE until PLL Locks, ("TRUE"/"FALSE")
|
||||
) eclk_pll
|
||||
(
|
||||
// Clock Outputs: 1-bit (each) output: User configurable clock outputs
|
||||
.CLKOUT0(pll_cclk), //full speed cclk
|
||||
.CLKOUT1(pll_lclk), //full speed lclk etx
|
||||
.CLKOUT2(pll_lclk_out), //full speed lclk for pin for etx
|
||||
.CLKOUT3(pll_lclk_par), //low speed lclk for etx
|
||||
.CLKOUT4(pll_cclk_div), //low speed cclk
|
||||
.CLKOUT5(pll_cclk_standby), //standby clock
|
||||
.CLKFBOUT(clkfb), //feedback clock output
|
||||
.LOCKED(), //lock signal
|
||||
.CLKIN1(clkin), //main input clock
|
||||
.PWRDWN(1'b0), //pll power down
|
||||
.RST(1'b0), //reset
|
||||
.CLKFBIN(clkfb) //feedback clock input
|
||||
);
|
||||
|
||||
|
||||
// Output buffering
|
||||
BUFG cclk_buf (.O (cclk_base), .I (pll_cclk));
|
||||
BUFG cclk_div_buf (.O (cclk_div), .I (pll_cclk_div));
|
||||
BUFG lclk_buf (.O (tx_lclk), .I (pll_lclk));
|
||||
BUFG lclk_out_buf (.O (tx_lclk_out), .I (pll_lclk_out));
|
||||
BUFG lclk_par_buf (.O (tx_lclk_par), .I (pll_lclk_par));
|
||||
|
||||
generate
|
||||
if( FEATURE_CCLK_DIV ) begin : gen_cclk_div
|
||||
|
||||
// Create adjustable (but fast) CCLK
|
||||
wire rxi_cclk_out;
|
||||
reg [8:1] cclk_pattern;
|
||||
reg [3:0] clk_div_sync;
|
||||
reg enb_sync;
|
||||
|
||||
always @ (posedge cclk_div) begin // Might need x-clock TIG here
|
||||
|
||||
clk_div_sync <= ecfg_clk_settings[3:0];
|
||||
enb_sync <= ~(|ecfg_clk_settings[3:0]);
|
||||
|
||||
if(enb_sync)
|
||||
case(clk_div_sync)
|
||||
4'h0: cclk_pattern <= 8'd0; // Clock OFF
|
||||
4'h7: cclk_pattern <= 8'b10101010; // Divide by 1
|
||||
4'h6: cclk_pattern <= 8'b11001100; // Divide by 2
|
||||
4'h5: cclk_pattern <= 8'b11110000; // Divide by 4
|
||||
default: cclk_pattern <= {8{~cclk_pattern[1]}}; // /8
|
||||
endcase
|
||||
else
|
||||
cclk_pattern <= 8'b00000000;
|
||||
end // always @ (posedge cclk_div)
|
||||
|
||||
|
||||
//CCLK CLOCK DIVIDER
|
||||
OSERDESE2
|
||||
#(
|
||||
.DATA_RATE_OQ("DDR"), // DDR, SDR
|
||||
.DATA_RATE_TQ("SDR"), // DDR, BUF, SDR
|
||||
.DATA_WIDTH(8), // Parallel data width (2-8,10,14)
|
||||
.INIT_OQ(1'b0), // Initial value of OQ output (1'b0,1'b1)
|
||||
.INIT_TQ(1'b0), // Initial value of TQ output (1'b0,1'b1)
|
||||
.SERDES_MODE("MASTER"), // MASTER, SLAVE
|
||||
.SRVAL_OQ(1'b0), // OQ output value when SR is used (1'b0,1'b1)
|
||||
.SRVAL_TQ(1'b0), // TQ output value when SR is used (1'b0,1'b1)
|
||||
.TBYTE_CTL("FALSE"), // Enable tristate byte operation (FALSE, TRUE)
|
||||
.TBYTE_SRC("FALSE"), // Tristate byte source (FALSE, TRUE)
|
||||
.TRISTATE_WIDTH(1) // 3-state converter width (1,4)
|
||||
) OSERDESE2_inst
|
||||
(
|
||||
.OFB(), // Feedback path for data
|
||||
.OQ(cclk), // Data path output
|
||||
.SHIFTOUT1(),
|
||||
.SHIFTOUT2(),
|
||||
.TBYTEOUT(), // Byte group tristate
|
||||
.TFB(), // 1-bit output: 3-state control
|
||||
.TQ(), // 3-state control
|
||||
.CLK(cclk_base), // High speed clock
|
||||
.CLKDIV(cclk_div), // Divided clock
|
||||
.D1(cclk_pattern[1]), // Parallel data inputs
|
||||
.D2(cclk_pattern[2]),
|
||||
.D3(cclk_pattern[3]),
|
||||
.D4(cclk_pattern[4]),
|
||||
.D5(cclk_pattern[5]),
|
||||
.D6(cclk_pattern[6]),
|
||||
.D7(cclk_pattern[7]),
|
||||
.D8(cclk_pattern[8]),
|
||||
.OCE(1'b1), // Output data clock enable TODO: gating?
|
||||
.RST(hard_reset), // Reset
|
||||
.SHIFTIN1(1'b0), // Data input expansion (1-bit each)
|
||||
.SHIFTIN2(1'b0),
|
||||
.T1(1'b0), // Parallel 3-state inputs
|
||||
.T2(1'b0),
|
||||
.T3(1'b0),
|
||||
.T4(1'b0),
|
||||
.TBYTEIN(1'b0), // Byte group tristate
|
||||
.TCE(1'b0) // 3-state clock enable
|
||||
);
|
||||
|
||||
end else
|
||||
begin : gen_fixed_cclk // Non-dividable CCLK
|
||||
reg enb_sync;
|
||||
|
||||
always @ (posedge cclk_div)
|
||||
enb_sync <= ~(ecfg_clk_settings[3:0]==4'b0000);
|
||||
|
||||
// The following does not result in timing failures,
|
||||
// but doesn't seem glitch-safe
|
||||
assign cclk = cclk_base & enb_sync;
|
||||
end
|
||||
endgenerate
|
||||
|
||||
//Clock output
|
||||
OBUFDS #(.IOSTANDARD (IOSTD_ELINK)) obufds_cclk_inst (.O (cclk_p), .OB (cclk_n), .I (cclk));
|
||||
|
||||
end // block: PLL
|
||||
endgenerate
|
||||
|
||||
`elsif TARGET_CLEAN
|
||||
wire cclk;
|
||||
|
||||
|
||||
clock_divider cclk_divider(
|
||||
// Outputs
|
||||
.clkout (cclk),
|
||||
.clkout90 (),
|
||||
// Inputs
|
||||
.clkin (clkin),
|
||||
.reset (hard_reset),
|
||||
.divcfg (ecfg_clk_settings[3:0])
|
||||
);
|
||||
|
||||
|
||||
assign cclk_p = cclk;
|
||||
assign cclk_n = ~cclk;
|
||||
|
||||
clock_divider lclk_divider(
|
||||
// Outputs
|
||||
.clkout (tx_lclk),
|
||||
.clkout90 (tx_lclk_out),
|
||||
// Inputs
|
||||
.clkin (clkin),
|
||||
.reset (hard_reset),
|
||||
.divcfg (ecfg_clk_settings[7:4])
|
||||
);
|
||||
|
||||
clock_divider lclk_par_divider(
|
||||
// Outputs
|
||||
.clkout (tx_lclk),
|
||||
.clkout90 (tx_lclk_out),
|
||||
// Inputs
|
||||
.clkin (clkin),
|
||||
.reset (hard_reset),
|
||||
.divcfg (ecfg_clk_settings[7:4]+4'd3)
|
||||
);
|
||||
|
||||
|
||||
`endif
|
||||
|
||||
|
||||
|
||||
endmodule // eclocks
|
||||
// Local Variables:
|
||||
// verilog-library-directories:("." "../../common/hdl")
|
||||
// End:
|
||||
|
||||
|
||||
/*
|
||||
Copyright (C) 2014 Adapteva, Inc.
|
||||
Contributed by Fred Huettig <fred@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/>.
|
||||
*/
|
@ -1,6 +1,6 @@
|
||||
module elink(/*AUTOARG*/
|
||||
// Outputs
|
||||
colid, rowid, resetb_out, cclk_p, cclk_n, rxo_wr_wait_p,
|
||||
colid, rowid, chip_resetb, cclk_p, cclk_n, rxo_wr_wait_p,
|
||||
rxo_wr_wait_n, rxo_rd_wait_p, rxo_rd_wait_n, txo_lclk_p,
|
||||
txo_lclk_n, txo_frame_p, txo_frame_n, txo_data_p, txo_data_n,
|
||||
m_axi_araddr, m_axi_arburst, m_axi_arcache, m_axi_arlen,
|
||||
@ -12,43 +12,45 @@ module elink(/*AUTOARG*/
|
||||
s_axi_bvalid, s_axi_rdata, s_axi_rlast, s_axi_rresp, s_axi_rvalid,
|
||||
s_axi_wready, embox_not_empty, embox_full,
|
||||
// Inputs
|
||||
reset_in, clkin, flag, rxi_lclk_p, rxi_lclk_n, rxi_frame_p,
|
||||
rxi_frame_n, rxi_data_p, rxi_data_n, txi_wr_wait_p, txi_wr_wait_n,
|
||||
txi_rd_wait_p, txi_rd_wait_n, m_axi_aclk, m_axi_aresetn,
|
||||
m_axi_arready, m_axi_awready, m_axi_bresp, m_axi_bvalid,
|
||||
m_axi_rdata, m_axi_rlast, m_axi_rresp, m_axi_rvalid, m_axi_wready,
|
||||
s_axi_aclk, s_axi_aresetn, s_axi_araddr, s_axi_arburst,
|
||||
s_axi_arcache, s_axi_arlen, s_axi_arprot, s_axi_arqos,
|
||||
s_axi_arsize, s_axi_arvalid, s_axi_awaddr, s_axi_awburst,
|
||||
s_axi_awcache, s_axi_awlen, s_axi_awprot, s_axi_awqos,
|
||||
s_axi_awsize, s_axi_awvalid, s_axi_bready, s_axi_rready,
|
||||
s_axi_wdata, s_axi_wlast, s_axi_wstrb, s_axi_wvalid
|
||||
hard_reset, clkin, bypass_clocks, rxi_lclk_p, rxi_lclk_n,
|
||||
rxi_frame_p, rxi_frame_n, rxi_data_p, rxi_data_n, txi_wr_wait_p,
|
||||
txi_wr_wait_n, txi_rd_wait_p, txi_rd_wait_n, m_axi_aclk,
|
||||
m_axi_aresetn, m_axi_arready, m_axi_awready, m_axi_bresp,
|
||||
m_axi_bvalid, m_axi_rdata, m_axi_rlast, m_axi_rresp, m_axi_rvalid,
|
||||
m_axi_wready, s_axi_aclk, s_axi_aresetn, s_axi_araddr,
|
||||
s_axi_arburst, s_axi_arcache, s_axi_arlen, s_axi_arprot,
|
||||
s_axi_arqos, s_axi_arsize, s_axi_arvalid, s_axi_awaddr,
|
||||
s_axi_awburst, s_axi_awcache, s_axi_awlen, s_axi_awprot,
|
||||
s_axi_awqos, s_axi_awsize, s_axi_awvalid, s_axi_bready,
|
||||
s_axi_rready, s_axi_wdata, s_axi_wlast, s_axi_wstrb, s_axi_wvalid
|
||||
);
|
||||
|
||||
parameter DEF_COREID = 12'h810;
|
||||
parameter AW = 32;
|
||||
parameter DW = 32;
|
||||
parameter IDW = 32;
|
||||
parameter RFAW = 13;
|
||||
parameter MW = 44;
|
||||
parameter FW = 1;
|
||||
parameter USE_PLL = 1;
|
||||
parameter INC_PLL = 1; //include pll
|
||||
parameter INC_SPI = 1; //include spi block
|
||||
|
||||
/****************************/
|
||||
/*BASIC INPUTS */
|
||||
/*CLK AND RESET */
|
||||
/****************************/
|
||||
input reset_in; //active high synhcronous hardware reset
|
||||
input clkin; //primary clock input
|
||||
|
||||
input hard_reset; // active high synhcronous hardware reset
|
||||
input clkin; // clock for pll
|
||||
input [2:0] bypass_clocks; // bypass clocks for elinks w/o pll
|
||||
// "advanced", tie to zero if not used
|
||||
|
||||
/********************************/
|
||||
/*EPIPHANY INTERFACE (I/O PINS) */
|
||||
/********************************/
|
||||
|
||||
//Basic
|
||||
input [FW-1:0] flag; //epiphany flag (interrupt?)
|
||||
output [3:0] colid; //epiphany colid
|
||||
output [3:0] rowid; //epiphany rowid
|
||||
output resetb_out; //chip reset for Epiphany (active low)
|
||||
output cclk_p, cclk_n; //high speed clock (1GHz) to Epiphany
|
||||
output [3:0] colid; //epiphany colid
|
||||
output [3:0] rowid; //epiphany rowid
|
||||
output chip_resetb; //chip reset for Epiphany (active low)
|
||||
output cclk_p, cclk_n; //high speed clock (1GHz) to Epiphany
|
||||
|
||||
//Receiver
|
||||
input rxi_lclk_p, rxi_lclk_n; //link rx clock input
|
||||
@ -160,7 +162,6 @@ module elink(/*AUTOARG*/
|
||||
input [3:0] s_axi_wstrb;
|
||||
input s_axi_wvalid;
|
||||
|
||||
|
||||
/*****************************/
|
||||
/*MAILBOX (interrupts) */
|
||||
/*****************************/
|
||||
@ -174,17 +175,14 @@ module elink(/*AUTOARG*/
|
||||
/*AUTOINPUT*/
|
||||
/*AUTOOUTPUT*/
|
||||
|
||||
|
||||
//wires
|
||||
wire [31:0] mi_rd_data;
|
||||
wire [31:0] mi_dout_ecfg;
|
||||
wire [31:0] mi_dout_embox;
|
||||
|
||||
/*AUTOWIRE*/
|
||||
// Beginning of automatic wires (for undeclared instantiated-module outputs)
|
||||
wire ecfg_cclk_bypass; // From ecfg of ecfg.v
|
||||
wire [3:0] ecfg_cclk_div; // From ecfg of ecfg.v
|
||||
wire ecfg_cclk_en; // From ecfg of ecfg.v
|
||||
wire [3:0] ecfg_cclk_pllcfg; // From ecfg of ecfg.v
|
||||
wire [15:0] ecfg_clk_settings; // From ecfg of ecfg.v
|
||||
wire [11:0] ecfg_coreid; // From ecfg of ecfg.v
|
||||
wire [10:0] ecfg_dataout; // From ecfg of ecfg.v
|
||||
wire [8:0] ecfg_rx_datain; // From erx of erx.v
|
||||
@ -193,8 +191,6 @@ module elink(/*AUTOARG*/
|
||||
wire ecfg_rx_gpio_enable; // From ecfg of ecfg.v
|
||||
wire ecfg_rx_mmu_enable; // From ecfg of ecfg.v
|
||||
wire ecfg_timeout_enable; // From ecfg of ecfg.v
|
||||
wire ecfg_tx_clkbypass; // From ecfg of ecfg.v
|
||||
wire [3:0] ecfg_tx_clkdiv; // From ecfg of ecfg.v
|
||||
wire [3:0] ecfg_tx_ctrlmode; // From ecfg of ecfg.v
|
||||
wire [1:0] ecfg_tx_datain; // From etx of etx.v
|
||||
wire [15:0] ecfg_tx_debug; // From etx of etx.v
|
||||
@ -256,10 +252,11 @@ module elink(/*AUTOARG*/
|
||||
wire [31:0] mi_tx_emmu_dout; // From etx of etx.v
|
||||
wire mi_tx_emmu_sel; // From esaxi of esaxi.v
|
||||
wire mi_we; // From esaxi of esaxi.v
|
||||
wire reset; // From ecfg of ecfg.v
|
||||
wire tx_lclk; // From eclock of eclock.v
|
||||
wire tx_lclk_out; // From eclock of eclock.v
|
||||
wire tx_lclk_par; // From eclock of eclock.v
|
||||
wire reset; // From ereset of ereset.v
|
||||
wire soft_reset; // From ecfg of ecfg.v
|
||||
wire tx_lclk; // From eclocks of eclocks.v
|
||||
wire tx_lclk_out; // From eclocks of eclocks.v
|
||||
wire tx_lclk_par; // From eclocks of eclocks.v
|
||||
// End of automatics
|
||||
|
||||
|
||||
@ -419,27 +416,6 @@ module elink(/*AUTOARG*/
|
||||
.s_axi_wstrb (s_axi_wstrb[3:0]),
|
||||
.s_axi_wvalid (s_axi_wvalid));
|
||||
|
||||
/***********************************************************/
|
||||
/*ELINK CLOCK GENERATOR */
|
||||
/***********************************************************/
|
||||
|
||||
eclock eclock(
|
||||
/*AUTOINST*/
|
||||
// Outputs
|
||||
.cclk_p (cclk_p),
|
||||
.cclk_n (cclk_n),
|
||||
.tx_lclk (tx_lclk),
|
||||
.tx_lclk_out (tx_lclk_out),
|
||||
.tx_lclk_par (tx_lclk_par),
|
||||
// Inputs
|
||||
.clkin (clkin),
|
||||
.reset (reset),
|
||||
.ecfg_cclk_en (ecfg_cclk_en),
|
||||
.ecfg_cclk_div (ecfg_cclk_div[3:0]),
|
||||
.ecfg_cclk_pllcfg (ecfg_cclk_pllcfg[3:0]),
|
||||
.ecfg_cclk_bypass (ecfg_cclk_bypass),
|
||||
.ecfg_tx_clkbypass (ecfg_tx_clkbypass));
|
||||
|
||||
/***********************************************************/
|
||||
/*RECEIVER */
|
||||
/***********************************************************/
|
||||
@ -536,7 +512,6 @@ module elink(/*AUTOARG*/
|
||||
.tx_lclk_par (tx_lclk_par),
|
||||
.s_axi_aclk (s_axi_aclk),
|
||||
.m_axi_aclk (m_axi_aclk),
|
||||
.ecfg_tx_clkdiv (ecfg_tx_clkdiv[3:0]),
|
||||
.ecfg_tx_enable (ecfg_tx_enable),
|
||||
.ecfg_tx_gpio_enable (ecfg_tx_gpio_enable),
|
||||
.ecfg_tx_mmu_enable (ecfg_tx_mmu_enable),
|
||||
@ -586,32 +561,26 @@ module elink(/*AUTOARG*/
|
||||
|
||||
|
||||
ecfg ecfg(
|
||||
.ecfg_resetb (resetb_out),
|
||||
.hw_reset (reset_in),
|
||||
/*AUTOINST*/
|
||||
// Outputs
|
||||
.soft_reset (soft_reset),
|
||||
.mi_dout (mi_ecfg_dout[31:0]), // Templated
|
||||
.ecfg_reset (reset), // Templated
|
||||
.ecfg_tx_enable (ecfg_tx_enable),
|
||||
.ecfg_tx_mmu_enable (ecfg_tx_mmu_enable),
|
||||
.ecfg_tx_gpio_enable (ecfg_tx_gpio_enable),
|
||||
.ecfg_tx_ctrlmode (ecfg_tx_ctrlmode[3:0]),
|
||||
.ecfg_tx_clkdiv (ecfg_tx_clkdiv[3:0]),
|
||||
.ecfg_tx_clkbypass (ecfg_tx_clkbypass),
|
||||
.ecfg_timeout_enable (ecfg_timeout_enable),
|
||||
.ecfg_rx_enable (ecfg_rx_enable),
|
||||
.ecfg_rx_mmu_enable (ecfg_rx_mmu_enable),
|
||||
.ecfg_rx_gpio_enable (ecfg_rx_gpio_enable),
|
||||
.ecfg_cclk_en (ecfg_cclk_en),
|
||||
.ecfg_cclk_div (ecfg_cclk_div[3:0]),
|
||||
.ecfg_cclk_pllcfg (ecfg_cclk_pllcfg[3:0]),
|
||||
.ecfg_cclk_bypass (ecfg_cclk_bypass),
|
||||
.ecfg_clk_settings (ecfg_clk_settings[15:0]),
|
||||
.ecfg_coreid (ecfg_coreid[11:0]),
|
||||
.ecfg_dataout (ecfg_dataout[10:0]),
|
||||
.embox_not_empty (embox_not_empty),
|
||||
.embox_full (embox_full),
|
||||
// Inputs
|
||||
.clk (mi_clk), // Templated
|
||||
.hard_reset (hard_reset),
|
||||
.mi_clk (mi_clk),
|
||||
.mi_en (mi_ecfg_sel), // Templated
|
||||
.mi_we (mi_we),
|
||||
.mi_addr (mi_addr[19:0]),
|
||||
@ -644,6 +613,34 @@ module elink(/*AUTOARG*/
|
||||
.mi_addr (mi_addr[19:0]),
|
||||
.mi_din (mi_din[DW-1:0]));
|
||||
|
||||
/***********************************************************/
|
||||
/*RESET CIRCUITRY */
|
||||
/***********************************************************/
|
||||
ereset ereset (/*AUTOINST*/
|
||||
// Outputs
|
||||
.reset (reset),
|
||||
.chip_resetb (chip_resetb),
|
||||
// Inputs
|
||||
.hard_reset (hard_reset),
|
||||
.soft_reset (soft_reset));
|
||||
|
||||
/***********************************************************/
|
||||
/*CLOCKS */
|
||||
/***********************************************************/
|
||||
eclocks eclocks (
|
||||
/*AUTOINST*/
|
||||
// Outputs
|
||||
.cclk_p (cclk_p),
|
||||
.cclk_n (cclk_n),
|
||||
.tx_lclk (tx_lclk),
|
||||
.tx_lclk_out (tx_lclk_out),
|
||||
.tx_lclk_par (tx_lclk_par),
|
||||
// Inputs
|
||||
.clkin (clkin),
|
||||
.hard_reset (hard_reset),
|
||||
.ecfg_clk_settings (ecfg_clk_settings[15:0]),
|
||||
.bypass_clocks (bypass_clocks[2:0]));
|
||||
|
||||
endmodule // elink
|
||||
// Local Variables:
|
||||
// verilog-library-directories:("." "../../embox/hdl" "../../erx/hdl" "../../etx/hdl" "../../axi/hdl" "../../ecfg/hdl" "../../eclock/hdl")
|
||||
|
29
elink/hdl/ereset.v
Normal file
29
elink/hdl/ereset.v
Normal file
@ -0,0 +1,29 @@
|
||||
module ereset (/*AUTOARG*/
|
||||
// Outputs
|
||||
reset, chip_resetb,
|
||||
// Inputs
|
||||
hard_reset, soft_reset
|
||||
);
|
||||
|
||||
//inputs
|
||||
input hard_reset; // hardware reset from external block
|
||||
input soft_reset; // soft reset drive by register (level)
|
||||
|
||||
//outputs
|
||||
output reset; //reset for elink
|
||||
output chip_resetb; //reset for epiphany
|
||||
|
||||
//Reset for link logic
|
||||
assign reset = hard_reset | soft_reset;
|
||||
|
||||
//May become more sophisticated later..
|
||||
//(for example, for epiphany reset, you might want to include some
|
||||
//some hard coded logic to avoid reset edge errata)
|
||||
//also, for multi chip boards, since the coordinates are sampled on
|
||||
//the rising edge of chip_resetb it may be beneficial to have one
|
||||
//reset per chip and to stagger the
|
||||
|
||||
assign chip_resetb = ~(hard_reset | soft_reset);
|
||||
|
||||
endmodule // ereset
|
||||
|
@ -403,29 +403,26 @@ module esaxi (/*autoarg*/
|
||||
emwr_ctrlmode_reg[3:0] <= ecfg_tx_ctrlmode[3:0];//static
|
||||
emwr_datamode_reg[1:0] <= axi_awsize[1:0];
|
||||
emwr_dstaddr_reg[31:2] <= axi_awaddr[31:2]; //set lsbs of address based on write strobes
|
||||
|
||||
casez(s_axi_wstrb[3:0])
|
||||
4'b???1://aligned
|
||||
begin
|
||||
emwr_data_reg[31:0] <= s_axi_wdata[31:0];
|
||||
emwr_dstaddr_reg[1:0] <= 2'd0;
|
||||
end
|
||||
4'b??10 : //shift by byte
|
||||
begin
|
||||
emwr_data_reg[31:0] <= {8'd0, s_axi_wdata[31:8]};
|
||||
emwr_dstaddr_reg[1:0] <= 2'd1;
|
||||
end
|
||||
4'b?100 : //shift by two bytes
|
||||
begin
|
||||
emwr_data_reg[31:0] <= {16'd0, s_axi_wdata[31:16]};
|
||||
emwr_dstaddr_reg[1:0] <= 2'd2;
|
||||
end
|
||||
default: //shift by three bytes
|
||||
begin
|
||||
emwr_data_reg[31:0] <= {24'd0, s_axi_wdata[31:24]};
|
||||
emwr_dstaddr_reg[1:0] <= 2'd3;
|
||||
end
|
||||
endcase // casez (s_axi_wstrb[3:0])
|
||||
if(s_axi_wstrb[0])
|
||||
begin
|
||||
emwr_data_reg[31:0] <= s_axi_wdata[31:0];
|
||||
emwr_dstaddr_reg[1:0] <= 2'd0;
|
||||
end
|
||||
else if(s_axi_wstrb[1])
|
||||
begin
|
||||
emwr_data_reg[31:0] <= {8'd0, s_axi_wdata[31:8]};
|
||||
emwr_dstaddr_reg[1:0] <= 2'd1;
|
||||
end
|
||||
else if(s_axi_wstrb[2])
|
||||
begin
|
||||
emwr_data_reg[31:0] <= {16'd0, s_axi_wdata[31:16]};
|
||||
emwr_dstaddr_reg[1:0] <= 2'd2;
|
||||
end
|
||||
else
|
||||
begin
|
||||
emwr_data_reg[31:0] <= {24'd0, s_axi_wdata[31:24]};
|
||||
emwr_dstaddr_reg[1:0] <= 2'd3;
|
||||
end
|
||||
end // else: !if(~s_axi_aresetn)
|
||||
|
||||
//Pipeline stage
|
||||
|
@ -5,14 +5,14 @@ module etx(/*AUTOARG*/
|
||||
txo_data_p, txo_data_n, mi_dout,
|
||||
// Inputs
|
||||
reset, tx_lclk, tx_lclk_out, tx_lclk_par, s_axi_aclk, m_axi_aclk,
|
||||
ecfg_tx_clkdiv, ecfg_tx_enable, ecfg_tx_gpio_enable,
|
||||
ecfg_tx_mmu_enable, ecfg_dataout, emrq_access, emrq_write,
|
||||
emrq_datamode, emrq_ctrlmode, emrq_dstaddr, emrq_data,
|
||||
emrq_srcaddr, emwr_access, emwr_write, emwr_datamode,
|
||||
emwr_ctrlmode, emwr_dstaddr, emwr_data, emwr_srcaddr, emrr_access,
|
||||
emrr_write, emrr_datamode, emrr_ctrlmode, emrr_dstaddr, emrr_data,
|
||||
emrr_srcaddr, txi_wr_wait_p, txi_wr_wait_n, txi_rd_wait_p,
|
||||
txi_rd_wait_n, mi_clk, mi_en, mi_we, mi_addr, mi_din
|
||||
ecfg_tx_enable, ecfg_tx_gpio_enable, ecfg_tx_mmu_enable,
|
||||
ecfg_dataout, emrq_access, emrq_write, emrq_datamode,
|
||||
emrq_ctrlmode, emrq_dstaddr, emrq_data, emrq_srcaddr, emwr_access,
|
||||
emwr_write, emwr_datamode, emwr_ctrlmode, emwr_dstaddr, emwr_data,
|
||||
emwr_srcaddr, emrr_access, emrr_write, emrr_datamode,
|
||||
emrr_ctrlmode, emrr_dstaddr, emrr_data, emrr_srcaddr,
|
||||
txi_wr_wait_p, txi_wr_wait_n, txi_rd_wait_p, txi_rd_wait_n, mi_clk,
|
||||
mi_en, mi_we, mi_addr, mi_din
|
||||
);
|
||||
parameter AW = 32;
|
||||
parameter DW = 32;
|
||||
@ -27,7 +27,6 @@ module etx(/*AUTOARG*/
|
||||
input m_axi_aclk; //clock for read response fifo
|
||||
|
||||
//Configuration signals
|
||||
input [3:0] ecfg_tx_clkdiv; //transmit clock divider
|
||||
input ecfg_tx_enable; //transmit output buffer enable
|
||||
|
||||
|
||||
@ -342,7 +341,6 @@ module etx(/*AUTOARG*/
|
||||
.tx_data_par (tx_data_par[63:0]),
|
||||
.ecfg_tx_enable (ecfg_tx_enable),
|
||||
.ecfg_tx_gpio_enable (ecfg_tx_gpio_enable),
|
||||
.ecfg_tx_clkdiv (ecfg_tx_clkdiv[3:0]),
|
||||
.ecfg_dataout (ecfg_dataout[8:0]));
|
||||
|
||||
|
||||
|
@ -5,7 +5,7 @@ module etx_io (/*AUTOARG*/
|
||||
// Inputs
|
||||
reset, txi_wr_wait_p, txi_wr_wait_n, txi_rd_wait_p, txi_rd_wait_n,
|
||||
tx_lclk_par, tx_lclk, tx_lclk_out, tx_frame_par, tx_data_par,
|
||||
ecfg_tx_enable, ecfg_tx_gpio_enable, ecfg_tx_clkdiv, ecfg_dataout
|
||||
ecfg_tx_enable, ecfg_tx_gpio_enable, ecfg_dataout
|
||||
);
|
||||
|
||||
parameter IOSTD_ELINK = "LVDS_25";
|
||||
@ -40,7 +40,6 @@ module etx_io (/*AUTOARG*/
|
||||
//#############
|
||||
input ecfg_tx_enable; //enable signal for tx
|
||||
input ecfg_tx_gpio_enable;//forces tx wait pins to constants
|
||||
input [3:0] ecfg_tx_clkdiv; // TODO: Implement this
|
||||
input [8:0] ecfg_dataout; // frame & data for GPIO mode
|
||||
|
||||
//############
|
||||
|
60
memory/hdl/fifo_mem.v
Normal file
60
memory/hdl/fifo_mem.v
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
Copyright (C) 2013 Adapteva, Inc.
|
||||
Contributed by Roman Trogan <support@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/>.
|
||||
*/
|
||||
module fifo_mem (/*AUTOARG*/
|
||||
// Outputs
|
||||
rd_data,
|
||||
// Inputs
|
||||
wr_clk, wr_write, wr_data, wr_addr, rd_addr
|
||||
);
|
||||
|
||||
parameter DW = 104;
|
||||
parameter AW = 2;
|
||||
localparam MD = 1<<AW;
|
||||
|
||||
//#########
|
||||
//# INPUTS
|
||||
//#########
|
||||
input wr_clk; //write clock
|
||||
input wr_write;
|
||||
input [DW-1:0] wr_data;
|
||||
input [AW-1:0] wr_addr;
|
||||
input [AW-1:0] rd_addr;
|
||||
|
||||
//##########
|
||||
//# OUTPUTS
|
||||
//##########
|
||||
output [DW-1:0] rd_data;
|
||||
|
||||
//########
|
||||
//# REGS
|
||||
//########
|
||||
reg [DW-1:0] mem[MD-1:0];
|
||||
|
||||
//Write
|
||||
always @(posedge wr_clk)
|
||||
if(wr_write)
|
||||
mem[wr_addr[AW-1:0]] <= wr_data[DW-1:0];
|
||||
|
||||
//Read
|
||||
assign rd_data[DW-1:0] = mem[rd_addr[AW-1:0]];
|
||||
|
||||
endmodule // fifo_mem
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user