1
0
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:
Andreas Olofsson 2015-04-15 11:54:43 -04:00
parent bee90fcacc
commit 69f3df4140
10 changed files with 671 additions and 193 deletions

116
common/hdl/clock_divider.v Normal file
View 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/>.
*/

View File

@ -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")

View File

@ -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
View 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/>.
*/

View File

@ -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
View 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

View File

@ -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

View File

@ -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]));

View File

@ -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
View 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