mirror of
https://github.com/aolofsson/oh.git
synced 2025-01-30 02:32:53 +08:00
289024fd89
- Creating an arbitrary 'src' directory really doesn't help much... - Goal is to make each folder self contained - Make meta repos and individual repos have the same directory structure
144 lines
4.8 KiB
Verilog
144 lines
4.8 KiB
Verilog
//#############################################################################
|
|
//# Purpose: MIO Transmit IO #
|
|
//#############################################################################
|
|
//# Author: Andreas Olofsson #
|
|
//# License: MIT (see LICENSE file in OH! repository) #
|
|
//#############################################################################
|
|
|
|
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;
|
|
wire [IOW/2-1:0] ddr_data_even;
|
|
wire [IOW/2-1:0] ddr_data_odd;
|
|
wire dmode8;
|
|
wire dmode16;
|
|
wire dmode32;
|
|
wire dmode64;
|
|
wire io_nreset;
|
|
wire reload;
|
|
|
|
//########################################
|
|
//# STATE MACHINE
|
|
//########################################
|
|
|
|
assign dmode8 = (iowidth[1:0]==2'b00);
|
|
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)
|
|
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;
|
|
|
|
//########################################
|
|
//# SHIFT REGISTER (SHIFT DOWN)
|
|
//########################################
|
|
|
|
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!)
|
|
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
|
|
|
|
oh_oddr#(.DW(IOW/2))
|
|
data_oddr (.out (tx_packet_ddr[IOW/2-1:0]),
|
|
.clk (io_clk),
|
|
.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]}:
|
|
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));
|
|
|
|
endmodule // mtx_io
|
|
// Local Variables:
|
|
// verilog-library-directories:("." "../../common/hdl")
|
|
// End:
|
|
|
|
|
|
|