// Chuck Benz, Hollis, NH Copyright (c)2005 // http://asics.chuckbenz.com // // The information and description contained herein is the // property of Chuck Benz. // // This information may only be used under license from // Chuck Benz Asic & FPGA Design, or it's assignees. Any // other use or modification is prohibited // // $Id: sit_ver_x4.v,v 1.3 2005/07/25 12:54:59 cbenz Exp cbenz $ // /* sit_ver_x4.v - this is the verilog module encapsulating the * simulation interconnection technology - connecting to another * simulation on another system. This verilog module uses Verilog-2001 * file IO with named pipes to communicate with a separate process * running on this system. That process opens a socket to the other * simulation, either directly or through a sit server. * This 27-Jun-05 initial version is simple, assuming that we'll just * sample the data at the bit rate and ship it over. Later versions * will implement a more proper clock recovery and will send over the * timestamp so that the far side can track the clock variation. * An alternative version would send each signal change as a separate * timestamped event, still sending a sync packet every 1/2 link delay * so that the far side can advance it's time clock even when the signal * is not changing. * For x4 module, we'll use a different data type (6), and do all * nibbles from link 0, then all from link 1, then all from link 2... * instead of 20 nibbles of data, we'll have 80, so we'll use 100 byte packets. */ `timescale 1ns / 10ps module sit_ver_x4 (tdata, rdata) ; input [3:0] tdata ; output [3:0] rdata ; reg [3:0] rdata ; parameter bit_period = 0.4 ; parameter half_link_delay = 80 ; // how many bits we'll pack into a packet. // which is also half the link latency... parameter ifile="sit_pipei" ; parameter ofile="sit_pipeo" ; parameter filename_from_param_only = 0 ; integer fd_i, fd_o ; integer len_in ; reg [8*100-1:0] rcvbuf ; reg [8*64:1] filename ; reg [8*65:1] ifilename ; reg [8*65:1] ofilename ; reg tclk, rclk ; reg [half_link_delay-1:0] tx_data, tx_data_sent ; reg [half_link_delay-1:0] tx_dat[0:3] ; reg [half_link_delay-1:0] rx_data ; reg [half_link_delay-1:0] rx_dat[0:3] ; reg [7:0] tx_cntr, rx_cntr ; reg [1:0] rx_ptr, rx_flag, tx_flag ; integer i, i1 ; reg [7:0] tmpdata ; integer rx_block ; reg [31:0] expect ; reg eof_ifile = 0 ; /* Format for data, by bytes: * 1 - header flag (rotates through values of C/B/A/F) * 2 - type: 6 for this data packet * 3 - length in DW of data, / 4 (includes real data only, not time) * 4 - rsvd * 5-8 - rsvd for time info, to be used at later date * 9-28 - link0 data - each byte represents a nibble * of serial data encoded as values 0x30-0x41 - 0x40 being Z, 0x41 as X. * (X and Z get spread to full nibble). * 29-48 - link1 data * 49-68 - link2 data * 69-88 - link3 data * 100 - a \n to finish the packet. * * we're using 80 bits per packet, so it will look like: * * C65 @@?5=4751:3256<5:::::::::::::::::::::::::>0;=4751:3256<5:::::::::::::::::::::::: * B65 ::::::::::::::::::::@@?5=4751:3256<5::::@@?5=4751:3256<5::::@@?5=4751:3256<5:::: * A65 :>0;=4751:3256<5::::.... */ task send_data ; begin case (tx_flag) 0: $fwrite (fd_o, "C6") ; 1: $fwrite (fd_o, "B6") ; 2: $fwrite (fd_o, "A6") ; 3: $fwrite (fd_o, "F6") ; endcase tmpdata = half_link_delay/16 + 8'h30 ; /* in below, there are 4 reserved bytes that will get time info later.*/ $fwrite (fd_o, "%s ", tmpdata) ; tx_flag = tx_flag + 1 ; tmpdata = 0 ; tx_data_sent = tx_dat[0] ; for (i1=0; i1<4 ; i1=i1+1) begin tx_data = tx_dat[i1] ; for (i=0; i 0)) rcvbuf = rcvbuf << ((100 - len_in)*8) ; if (len_in == 0) begin $display ($stime, " EOF on file/pipe %s.", ifilename) ; eof_ifile = 1 ; end else if (rcvbuf[(8*(100-1)-1):(8*(100-2))] == "3") begin $display ($stime, " end record on file/pipe %s.", ifilename) ; eof_ifile = 1 ; end else while (rcvbuf[(8*(100-1)-1):(8*(100-2))] != "6") begin $display ("sit_link non-x4-data record: %s in %s", (rcvbuf[(8*(100-1)-1):(8*(100-2))]), rcvbuf) ; case (rcvbuf[(8*100)-1:8*99]) 8'h43: rx_flag = 1 ; 8'h42: rx_flag = 2 ; 8'h41: rx_flag = 3 ; 8'h46: rx_flag = 0 ; endcase len_in = $fgets (rcvbuf, fd_i) ; if ((len_in < 100) && (len_in > 0)) rcvbuf = rcvbuf << ((100 - len_in)*8) ; end case (rx_flag) 0: expect = "C6 " ; 1: expect = "B6 " ; 2: expect = "A6 " ; 3: expect = "F6 " ; endcase expect[15:8] = half_link_delay/16 + 8'h30 ; if (~eof_ifile && (len_in != 100)) $display ($stime, " error reading from file %s, non-100 char record", ifilename) ; else if (~eof_ifile && (rcvbuf[(8*100)-1:8*96] != expect)) $display ($stime, " surprising rx pkt hdr, %s,\n expected %s", rcvbuf[(8*100)-1:8*96], expect) ; case (rcvbuf[(8*100)-1:8*99]) 8'h43: rx_flag = 1 ; 8'h42: rx_flag = 2 ; 8'h41: rx_flag = 3 ; 8'h46: rx_flag = 0 ; endcase rx_data = 0 ; if (~eof_ifile) for (i1=0;i1<4;i1=i1+1) begin for (i=half_link_delay; i>0; i=i-4) begin /* start at end of data and shift it left so [0] is first on wire. * with 8 prefix bytes, 20 data bytes, 12 unused bytes, * first bits on wire in byte 9, last byte 28. * byte 100 is in bits 7:0 * byte 88 is in bits 13*8-1 to 12*8 (link3 last nibble) * byte 28 is in bits 73*8-1 to 72*8 (link0 last nibble) * byte 9 is in bits 92*8-1 to 91*8 (link0 first nibble) * i will be 80, 76, ..., 4 (never 0), i1 will be 0, 1, 2, 3 */ tmpdata = (rcvbuf >> (8*(92-i1*20-i/4)) & 8'hff) - 8'h30 ; if (tmpdata == 16) rx_data = {rx_data, 4'bxxxx} ; else if (tmpdata == 17) rx_data = {rx_data, 4'bzzzz} ; else rx_data = {rx_data, tmpdata[0], tmpdata[1], tmpdata[2], tmpdata[3]} ; end rx_dat[i1] = rx_data ; end end endtask initial begin tclk = 1 ; rclk = 1 ; tx_cntr = 0 ; rx_cntr = 0 ; rx_ptr = 0 ; tx_flag = 0 ; rx_flag = 0 ; rx_block = 0 ; if (filename_from_param_only || ! $value$plusargs("SIT_FILENAME=%s", filename)) begin $display ("taking file name from parameter"); /* order is important here - open o before i. */ fd_o = $fopen (ofile, "w") ; fd_i = $fopen (ifile, "r") ; ifilename = ifile ; ofilename = ofile ; end else begin $display ("taking file name from command line: %s", filename) ; ifilename = (filename << 8) | "i" ; ofilename = (filename << 8) | "o" ; /* order is important here - open o before i. */ fd_o = $fopen (ofilename, "w") ; fd_i = $fopen (ifilename, "r") ; end end always #bit_period tclk = ~tclk ; always #bit_period rclk = ~ rclk ; always @ (tclk) begin for (i=0; i<4; i=i+1) begin tx_data = tx_dat[i] ; tx_data[tx_cntr] = tdata[i] ; tx_dat[i] = tx_data ; end tx_cntr = tx_cntr + 1 ; if (tx_cntr == half_link_delay) begin tx_cntr = 0 ; send_data ; end end always @ ( rclk) begin for (i=0; i<4; i=i+1) begin rx_data = rx_dat[i] ; rdata[i] = rx_data[rx_cntr] ; end rx_cntr = rx_cntr + 1 ; if (rx_cntr == half_link_delay) begin rx_cntr = 0 ; if ((rx_block > 0) && ~eof_ifile) rcv_data ; rx_block = rx_block + 1 ; end end endmodule /* * $Log: sit_ver_x4.v,v $ * Revision 1.3 2005/07/25 12:54:59 cbenz * 1.2 was broken, compared to 4 instead of "6". some more cleanup as well. * * Revision 1.2 2005/07/22 00:00:32 cbenz * *** empty log message *** * * Revision 1.1 2005/07/12 13:16:39 cbenz * Initial revision * * Revision 1.1 2005/07/07 16:44:04 cbenz * Initial revision */