1
0
mirror of https://github.com/aolofsson/oh.git synced 2025-01-30 02:32:53 +08:00
oh/mio/hdl/mtx_io.v

144 lines
4.8 KiB
Coq
Raw Normal View History

//#############################################################################
//# Purpose: MIO Transmit IO #
//#############################################################################
//# Author: Andreas Olofsson #
//# License: MIT (see LICENSE file in OH! repository) #
//#############################################################################
2016-02-24 20:29:56 -05:00
module mtx_io #(parameter IOW = 64, // IO width
parameter TARGET = "GENERIC" // target selector
)
(// reset, clk, cfg
input nreset, // async active low reset
input io_clk, // clock from divider
input ddr_mode, // send data as ddr
input [1:0] iowidth, // iowidth *8,16,32,64
// chip IO interface
output [IOW-1:0] tx_packet, // data for IO
output reg tx_access, // access signal for IO
input tx_wait, // IO wait signals
// core side
input [7:0] io_valid, // per byte valid indicator
input [IOW-1:0] io_packet, // packet
output io_wait // pushback to serializer in sdr mode
);
//local wires
reg [63:0] shiftreg;
reg [2:0] tx_state;
reg [IOW-1:0] tx_packet_sdr;
reg [7:0] io_valid_reg;
wire [IOW/2-1:0] tx_packet_ddr;
wire tx_wait_sync;
wire transfer_active;
wire [7:0] io_valid_next;
2016-08-25 17:29:29 -04:00
wire [IOW/2-1:0] ddr_data_even;
wire [IOW/2-1:0] ddr_data_odd;
2016-08-26 00:41:42 -04:00
wire dmode8;
wire dmode16;
wire dmode32;
wire dmode64;
wire io_nreset;
wire reload;
2016-02-24 20:29:56 -05:00
//########################################
//# STATE MACHINE
//########################################
2016-02-24 20:29:56 -05:00
assign dmode8 = (iowidth[1:0]==2'b00);
2016-08-25 17:29:29 -04:00
assign dmode16 = ((iowidth[1:0]==2'b01) & ~ddr_mode) |
(iowidth[1:0]==2'b00) & ddr_mode;
assign dmode32 = ((iowidth[1:0]==2'b10) & ~ddr_mode) |
(iowidth[1:0]==2'b01) & ddr_mode;
assign dmode64 = ((iowidth[1:0]==2'b11) & ~ddr_mode) |
(iowidth[1:0]==2'b10) & ddr_mode;
assign io_valid_next[7:0] = dmode8 ? {1'b0,io_valid_reg[7:1]} :
dmode16 ? {2'b0,io_valid_reg[7:2]} :
dmode32 ? {4'b0,io_valid_reg[7:4]} :
8'b0;
assign reload = ~transfer_active | dmode64 | (io_valid_next[7:0]==8'b0);
always @ (posedge io_clk or negedge io_nreset)
2016-02-24 20:29:56 -05:00
if(!io_nreset)
io_valid_reg[7:0] <= 'b0;
else if(reload)
io_valid_reg[7:0] <= io_valid[7:0];
else
io_valid_reg[7:0] <= io_valid_next[7:0];
assign transfer_active = |io_valid_reg[7:0];
//pipeline access signal
always @ (posedge io_clk or negedge io_nreset)
if(!io_nreset)
tx_access <= 1'b0;
else
tx_access <= transfer_active;
assign io_wait = tx_wait_sync | ~reload;
2016-02-24 20:29:56 -05:00
//########################################
//# SHIFT REGISTER (SHIFT DOWN)
2016-02-24 20:29:56 -05:00
//########################################
always @ (posedge io_clk)
if(reload)
shiftreg[63:0] <= io_packet[IOW-1:0];
else if(dmode8)//8 bit
shiftreg[63:0] <= {8'b0,shiftreg[IOW-1:8]};
else if(dmode16)//16 bit
shiftreg[63:0] <= {16'b0,shiftreg[IOW-1:16]};
else if(dmode32)//32 bit
shiftreg[63:0] <= {32'b0,shiftreg[IOW-1:32]};
//########################################
//# DDR OUTPUT
//########################################
// pipeline sdr to compensate for ddr
always @ (posedge io_clk)
tx_packet_sdr[IOW-1:0] <= shiftreg[IOW-1:0];
// ddr circuit (one stage pipeline delay!)
2016-08-25 17:29:29 -04:00
assign ddr_data_even[IOW/2-1:0] = shiftreg[IOW/2-1:0];
assign ddr_data_odd[IOW/2-1:0] = (iowidth[1:0]==2'b00) ? shiftreg[7:4] : //byte
(iowidth[1:0]==2'b01) ? shiftreg[15:8] : //short
(iowidth[1:0]==2'b10) ? shiftreg[31:16] : //word
shiftreg[63:32]; //double
2016-08-25 17:29:29 -04:00
oh_oddr#(.DW(IOW/2))
data_oddr (.out (tx_packet_ddr[IOW/2-1:0]),
.clk (io_clk),
2016-08-25 17:29:29 -04:00
.din1 (ddr_data_even[IOW/2-1:0]),
.din2 (ddr_data_odd[IOW/2-1:0]));
//select between ddr/sdr
assign tx_packet[IOW-1:0] = ddr_mode ? {{(IOW/2){1'b0}},tx_packet_ddr[IOW/2-1:0]}:
2016-08-25 17:29:29 -04:00
tx_packet_sdr[IOW-1:0];
//########################################
//# Synchronizers
//########################################
// synchronize reset to io clock
oh_rsync sync_reset(.nrst_out (io_nreset),
.clk (io_clk),
.nrst_in (nreset));
//synchronize wait
oh_dsync sync_wait(.nreset (io_nreset),
.clk (io_clk),
.din (tx_wait),
.dout (tx_wait_sync));
2016-02-26 22:51:35 -05:00
endmodule // mtx_io
2016-02-24 20:29:56 -05:00
// Local Variables:
// verilog-library-directories:("." "../../common/hdl")
// End: