1
0
mirror of https://github.com/aolofsson/oh.git synced 2025-01-17 20:02:53 +08:00
oh/elink/hdl/etx_cfg.v
Andreas Olofsson 57c44bafb1 Fixing MMU write access
- MMU was being written when it shouldn't
2016-01-12 09:02:00 -05:00

251 lines
8.0 KiB
Verilog

/*
########################################################################
ELINK TX CONFIGURATION REGISTER FILE
########################################################################
*/
`include "elink_regmap.v"
module etx_cfg (/*AUTOARG*/
// Outputs
cfg_mmu_access, etx_cfg_access, etx_cfg_packet, tx_enable,
mmu_enable, gpio_enable, remap_enable, burst_enable, gpio_data,
ctrlmode, ctrlmode_bypass,
// Inputs
nreset, clk, cfg_access, etx_access, etx_packet, etx_wait,
tx_status
);
//##################################################################
//# INTERFACE
//##################################################################
parameter AW = 32;
parameter PW = 2*AW+40;
parameter RFAW = 6;
parameter VERSION = 16'h0000;
parameter ID = 999;
//reset+clk
input nreset; // sync reset
input clk; // slow clock
//packet input
input cfg_access; // register access
input etx_access; // for transaction counter
input [PW-1:0] etx_packet; // for transaction sampler
input etx_wait; // wait signal
output cfg_mmu_access; // mmu access
//packet output (for RX)
output etx_cfg_access; // access for rx (write or rdata forward)
output [PW-1:0] etx_cfg_packet; // packet
//tx (static configs)
output tx_enable; // enable signal for TX
output mmu_enable; // enables MMU on transmit path
output gpio_enable; // forces TX output pins to constants
output remap_enable; // enable address remapping
output burst_enable; // enables bursting
output [8:0] gpio_data; // data for elink outputs (static)
output [3:0] ctrlmode; // value for emesh ctrlmode tag
output ctrlmode_bypass; // selects ctrlmode
input [15:0] tx_status; // tx status signals
//##################################################################
//# BODY
//##################################################################
//registers/wires
reg [15:0] tx_version_reg;
reg [11:0] tx_cfg_reg;
reg [8:0] tx_gpio_reg;
reg [15:0] tx_status_reg;
reg [31:0] tx_monitor_reg;
reg [31:0] tx_packet_reg;
reg [31:0] cfg_dout;
reg ecfg_access;
reg [1:0] datamode_out;
reg [4:0] ctrlmode_out;
reg write_out;
reg [AW-1:0] dstaddr_out;
reg [AW-1:0] srcaddr_out;
reg [AW-1:0] data_out;
reg read_sel;
reg etx_cfg_access;
wire [15:0] tx_status_sync;
wire [31:0] data_mux;
/*AUTOWIRE*/
// Beginning of automatic wires (for undeclared instantiated-module outputs)
wire [4:0] ctrlmode_in; // From p2e of packet2emesh.v
wire [AW-1:0] data_in; // From p2e of packet2emesh.v
wire [1:0] datamode_in; // From p2e of packet2emesh.v
wire [AW-1:0] dstaddr_in; // From p2e of packet2emesh.v
wire [AW-1:0] srcaddr_in; // From p2e of packet2emesh.v
wire write_in; // From p2e of packet2emesh.v
// End of automatics
//###########################
//# DECODE LOGIC
//###########################
packet2emesh #(.AW(AW))
p2e (.packet_in (etx_packet[PW-1:0]),
/*AUTOINST*/
// Outputs
.write_in (write_in),
.datamode_in (datamode_in[1:0]),
.ctrlmode_in (ctrlmode_in[4:0]),
.dstaddr_in (dstaddr_in[AW-1:0]),
.srcaddr_in (srcaddr_in[AW-1:0]),
.data_in (data_in[AW-1:0]));
//read/write decode
assign tx_match = cfg_access &
(dstaddr_in[19:16] ==`EGROUP_MMR) &
(dstaddr_in[10:8] ==`EGROUP_TX);
//MMU access
assign cfg_mmu_access = cfg_access &
(dstaddr_in[19:16] ==`EGROUP_MMU) &
~dstaddr_in[15];
assign ecfg_read = tx_match & ~write_in;
assign ecfg_write = tx_match & write_in;
//Config write enables
assign tx_version_write = ecfg_write & (dstaddr_in[RFAW+1:2]==`E_VERSION);
assign tx_cfg_write = ecfg_write & (dstaddr_in[RFAW+1:2]==`ETX_CFG);
assign tx_status_write = ecfg_write & (dstaddr_in[RFAW+1:2]==`ETX_STATUS);
assign tx_gpio_write = ecfg_write & (dstaddr_in[RFAW+1:2]==`ETX_GPIO);
assign tx_monitor_write = ecfg_write & (dstaddr_in[RFAW+1:2]==`ETX_MONITOR);
//###########################
//# TX CONFIG
//###########################
always @ (posedge clk)
if(!nreset)
tx_cfg_reg[11:0] <= 'b0;
else if (tx_cfg_write)
tx_cfg_reg[11:0] <= data_in[11:0];
assign tx_enable = 1'b1;//TODO: fix! ecfg_tx_config_reg[0];
assign mmu_enable = tx_cfg_reg[1];
assign remap_enable = (tx_cfg_reg[3:2]==2'b01);
assign ctrlmode[3:0] = tx_cfg_reg[7:4];
assign ctrlmode_bypass = tx_cfg_reg[9];
assign burst_enable = tx_cfg_reg[10];
assign gpio_enable = (tx_cfg_reg[11:10]==2'b01);
//###########################
//# STATUS REGISTER
//###########################
//Synchronize to make easy regular
oh_dsync #(.DW(16))
dsync (// Outputs
.dout (tx_status_sync[15:0]),
// Inputs
.clk (clk),
.din (tx_status[15:0])
);
always @ (posedge clk)
if (tx_status_write)
tx_status_reg[15:0] <= data_in[15:0];
else
tx_status_reg[15:0]<= tx_status_reg[15:0] | {tx_status_sync[15:0]};
//###########################
//# GPIO DATA
//###########################
always @ (posedge clk)
if (tx_gpio_write)
tx_gpio_reg[8:0] <= data_in[8:0];
assign gpio_data[8:0] = tx_gpio_reg[8:0];
//###########################
//# VERSION
//###########################
always @ (posedge clk)
if(!nreset)
tx_version_reg[15:0] <= VERSION;
else if (tx_version_write)
tx_version_reg[15:0] <= data_in[15:0];
//###########################
//# MONITOR
//###########################
always @ (posedge clk)
if (tx_monitor_write)
tx_monitor_reg[31:0] <= data_in[31:0];
else
tx_monitor_reg[31:0] <= tx_monitor_reg[31:0] + (etx_access & ~etx_wait);
//###########################
//# PACKET (FOR DEBUG)
//###########################
always @ (posedge clk)
if(etx_access)
tx_packet_reg[31:0] <= etx_packet[39:8];
//###############################
//# DATA READBACK MUX
//###############################
//Pipelineing readback
always @ (posedge clk)
if(ecfg_read)
case(dstaddr_in[RFAW+1:2])
`E_VERSION: cfg_dout[31:0] <= {16'b0, tx_version_reg[15:0]};
`ETX_CFG: cfg_dout[31:0] <= {21'b0, tx_cfg_reg[10:0]};
`ETX_GPIO: cfg_dout[31:0] <= {23'b0, tx_gpio_reg[8:0]};
`ETX_STATUS: cfg_dout[31:0] <= {16'b0, tx_status_reg[15:0]};
`ETX_MONITOR: cfg_dout[31:0] <= {tx_monitor_reg[31:0]};
`ETX_PACKET: cfg_dout[31:0] <= {tx_packet_reg[31:0]};
default: cfg_dout[31:0] <= 32'd0;
endcase // case (dstaddr_in[RFAW+1:2])
else
cfg_dout[31:0] <= 32'd0;
//###########################
//# FORWARD PACKET TO RX
//###########################
//pipeline
always @ (posedge clk)
if(~etx_wait)
begin
etx_cfg_access <= cfg_access;
datamode_out[1:0] <= datamode_in[1:0];
ctrlmode_out[4:0] <= {1'b0,ctrlmode_in[3:0]};
write_out <= ecfg_read | write_in;
dstaddr_out[31:0] <= ecfg_read ? srcaddr_in[31:0] : dstaddr_in[31:0];
data_out[31:0] <= data_in[31:0];
srcaddr_out[31:0] <= srcaddr_in[31:0];
read_sel <= ecfg_read;
end
assign data_mux[31:0] = read_sel ? cfg_dout[31:0] :
data_out[31:0];
//Create packet
emesh2packet #(.AW(AW))
e2p (.packet_out (etx_cfg_packet[PW-1:0]),
.data_out (data_mux[AW-1:0]),
/*AUTOINST*/
// Inputs
.write_out (write_out),
.datamode_out (datamode_out[1:0]),
.ctrlmode_out (ctrlmode_out[4:0]),
.dstaddr_out (dstaddr_out[AW-1:0]),
.srcaddr_out (srcaddr_out[AW-1:0]));
endmodule // ecfg_tx
// Local Variables:
// verilog-library-directories:("." "../../emesh/hdl" "../../common/hdl")
// End: