mirror of
https://github.com/aolofsson/oh.git
synced 2025-01-17 20:02:53 +08:00
213 lines
7.7 KiB
Verilog
213 lines
7.7 KiB
Verilog
//#############################################################################
|
|
//# Function: MIO Configuration Registers #
|
|
//# (See README.md for complete documentation) #
|
|
//#############################################################################
|
|
//# Author: Andreas Olofsson #
|
|
//# License: MIT (see LICENSE file in this repository) #
|
|
//#############################################################################
|
|
|
|
`include "mio_regmap.vh"
|
|
module mio_regs #(parameter N = 8, // number of I/O pins
|
|
parameter AW = 32, // address width
|
|
parameter PW = 104, // packet width
|
|
parameter DEF_CFG = 18'h1070, // default config
|
|
parameter DEF_CLK = 7 // clock divider
|
|
)
|
|
(
|
|
// clk,reset
|
|
input clk,
|
|
input nreset,
|
|
// register access interface
|
|
input access_in, // incoming access
|
|
input [PW-1:0] packet_in, // incoming packet
|
|
output wait_out,
|
|
output access_out, // outgoing read packet
|
|
output [PW-1:0] packet_out, // outgoing read packet
|
|
input wait_in,
|
|
// config outputs
|
|
output tx_en, // enable tx
|
|
output rx_en, // enable rx
|
|
output ddr_mode, // ddr mode for mio
|
|
output emode, // epiphany packet mode
|
|
output amode, // mio packet mode
|
|
output dmode, // mio packet mode
|
|
output [1:0] datamode, // mio datasize
|
|
output [1:0] iowidth, // mio io width
|
|
output lsbfirst, // lsb shift first
|
|
output framepol, // framepolarity (0=actrive high)
|
|
output [4:0] ctrlmode, // emode ctrlmode
|
|
output [AW-1:0] dstaddr, // destination address for RX dmode
|
|
output clkchange, // indicates a clock change
|
|
output [7:0] clkdiv, // mio clk clock setting
|
|
output [15:0] clkphase0, // [7:0]=rising,[15:8]=falling
|
|
output [15:0] clkphase1, // [7:0]=rising,[15:8]=falling
|
|
// status inputs
|
|
input tx_full, //tx fifo is full (should not happen!)
|
|
input tx_prog_full, //tx fifo is nearing full
|
|
input tx_empty, //tx fifo is empty
|
|
input rx_full, //rx fifo is full (should not happen!)
|
|
input rx_prog_full, //rx fifo is nearing full
|
|
input rx_empty //rx fifo is empty
|
|
);
|
|
|
|
localparam DEF_RISE0 = 0; // 0 degrees
|
|
localparam DEF_FALL0 = ((DEF_CLK+8'd1)>>8'd1); // 180 degrees
|
|
localparam DEF_RISE1 = ((DEF_CLK+8'd1)>>8'd2); // 90 degrees
|
|
localparam DEF_FALL1 = ((DEF_CLK+8'd1)>>8'd2)+
|
|
((DEF_CLK+8'd1)>>8'd1); // 270 degrees
|
|
|
|
//##############
|
|
//# LOCAL WIRES
|
|
//##############
|
|
|
|
reg [20:0] config_reg;
|
|
reg [15:0] status_reg;
|
|
reg [31:0] clkdiv_reg;
|
|
reg [63:0] addr_reg;
|
|
reg [31:0] clkphase_reg;
|
|
wire [7:0] status_in;
|
|
wire reg_write;
|
|
wire config_write;
|
|
wire status_write;
|
|
wire clkdiv_write;
|
|
wire clkphase_write;
|
|
wire idelay_write;
|
|
wire odelay_write;
|
|
wire addr0_write;
|
|
wire addr1_write;
|
|
|
|
/*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
|
|
//#####################################
|
|
|
|
packet2emesh #(.AW(AW),
|
|
.PW(PW))
|
|
p2e (/*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]),
|
|
// Inputs
|
|
.packet_in (packet_in[PW-1:0]));
|
|
|
|
assign reg_write = write_in & access_in;
|
|
assign config_write = reg_write & (dstaddr_in[5:2]==`MIO_CONFIG);
|
|
assign status_write = reg_write & (dstaddr_in[5:2]==`MIO_STATUS);
|
|
assign clkdiv_write = reg_write & (dstaddr_in[5:2]==`MIO_CLKDIV);
|
|
assign clkphase_write = reg_write & (dstaddr_in[5:2]==`MIO_CLKPHASE);
|
|
assign idelay_write = reg_write & (dstaddr_in[5:2]==`MIO_IDELAY);
|
|
assign odelay_write = reg_write & (dstaddr_in[5:2]==`MIO_ODELAY);
|
|
assign addr0_write = reg_write & (dstaddr_in[5:2]==`MIO_ADDR0);
|
|
assign addr1_write = reg_write & (dstaddr_in[5:2]==`MIO_ADDR1);
|
|
|
|
assign clkchange = clkdiv_write | clkphase_write;
|
|
|
|
//################################
|
|
//# CONFIG
|
|
//################################
|
|
|
|
always @ (posedge clk or negedge nreset)
|
|
if(!nreset)
|
|
begin
|
|
config_reg[20:0] <= DEF_CFG;
|
|
end
|
|
else if(config_write)
|
|
config_reg[20:0] <= data_in[20:0];
|
|
|
|
assign tx_en = ~config_reg[0]; // tx disable
|
|
assign rx_en = ~config_reg[1]; // rx disable
|
|
assign emode = config_reg[3:2]==2'b00; // emesh packets
|
|
assign dmode = config_reg[3:2]==2'b01; // data mode (streaming)
|
|
assign amode = config_reg[3:2]==2'b10; // auto address mode
|
|
assign iowidth[1:0] = config_reg[5:4]; // iowidth(or 8,16,32,64 pins)
|
|
assign datamode[1:0] = config_reg[7:6]; // rx datamode(8,16,32,64)
|
|
assign ddr_mode = config_reg[12]; // dual data rate mode
|
|
assign lsbfirst = config_reg[13]; // lsb-first transmit
|
|
assign framepol = config_reg[14]; // frame polarity
|
|
assign ctrlmode[4:0] = config_reg[20:16]; // ctrlmode
|
|
|
|
//###############################
|
|
//# STATUS
|
|
//################################
|
|
assign status_in[7:0] = {2'b0, //7:6
|
|
tx_full, //5
|
|
tx_prog_full,//4
|
|
tx_empty, //3
|
|
rx_full, //2
|
|
rx_prog_full,//1
|
|
rx_empty //0
|
|
};
|
|
|
|
always @ (posedge clk or negedge nreset)
|
|
if(!nreset)
|
|
status_reg[15:0] <= 'b0;
|
|
else if(status_write)
|
|
status_reg[15:0] <= data_in[7:0];
|
|
else
|
|
status_reg[15:0] <= {(status_reg[15:8] | status_in[7:0]), // sticky bits
|
|
status_in[7:0]}; // immediate bits
|
|
|
|
//###############################
|
|
//# CLKDIV
|
|
//################################
|
|
always @ (posedge clk or negedge nreset)
|
|
if(!nreset)
|
|
clkdiv_reg[7:0] <= DEF_CLK;
|
|
else if(clkdiv_write)
|
|
clkdiv_reg[7:0] <= data_in[7:0];
|
|
|
|
assign clkdiv[7:0] = clkdiv_reg[7:0];
|
|
|
|
//###############################
|
|
//# CLKPHASE
|
|
//################################
|
|
always @ (posedge clk or negedge nreset)
|
|
if(!nreset)
|
|
begin
|
|
clkphase_reg[7:0] <= DEF_RISE0;
|
|
clkphase_reg[15:8] <= DEF_FALL0;
|
|
clkphase_reg[23:16] <= DEF_RISE1;
|
|
clkphase_reg[31:24] <= DEF_FALL1;
|
|
end
|
|
else if(clkphase_write)
|
|
clkphase_reg[31:0] <= data_in[31:0];
|
|
|
|
assign clkphase0[15:0] = clkphase_reg[15:0];
|
|
assign clkphase1[15:0] = clkphase_reg[31:16];
|
|
|
|
//###############################
|
|
//# RX DESTINATION ADDR ("AMODE")
|
|
//################################
|
|
always @ (posedge clk)
|
|
if(addr0_write)
|
|
addr_reg[31:0] <= data_in[31:0];
|
|
else if(addr1_write)
|
|
addr_reg[63:32] <= data_in[31:0];
|
|
|
|
assign dstaddr[AW-1:0] = addr_reg[AW-1:0];
|
|
|
|
//###############################
|
|
//# READBACK
|
|
//################################
|
|
assign access_out ='b0;
|
|
assign wait_out ='b0;
|
|
assign packet_out ='b0;
|
|
|
|
endmodule
|
|
// Local Variables:
|
|
// verilog-library-directories:("." "../../emesh/hdl" "../../../oh/common/hdl")
|
|
// End:
|