/* qs5_ql08.tf test fixture for the qs5 in the QuickLogic 8-bit environment =================================================================================== Copyright 1997-1999 by John Rible, Permission is granted for individual non-commercial use, provided this notice is included. Contact the author concerning any other use. =================================================================================== My Verilog name conventions: - combinatorial signals have lower-case names 60 lines per page, 2-up - registers and flipflops have UPPERCASE NAMES 85 characters per line - functions and tasks have Capitalized Names ----------------------------------------------------------------------------------- 03/20/1999 jr: cleaned up 8-bit interface and output file 12/26/1998 jr: modified for 8-bit memory interface 07/13/1998 jr: modified for new 'send' handshake 03/17/1998 jr: included new handshake from shakers and new chip pinout 10/20/1997 jr: more editing 09/22/1997 jr: modified the 'sentinel' changes to work with handshake 06/07/1997 jr: copied from sp1601 file =================================================================================*/ `timescale 1ns/1ns module t(); parameter period = 1000, // ns nClocks = 800, // number of periods to run simulation nMem = 1024, // number of memory cells (must be 2**n) nBoot = 3, // number of bytes to load empty = 16'hffff, // unlikely opcode/unprogrammed eprom perline = 8; // number of cells displayed per line parameter hostout = 64, // max number of characters from host hostin = 1024, // max number of characters to host hostperline = 16; // number of characters displayed per line // chip inputs to provide reg clock; reg boot, reset, req; // chip state // chip outputs to verify wire ack, dir; // i/o port control wire csb, oeb, web; // memory control wire [14:0] ma; // memory address wire [1:0] po; // output port data // chip inouts to do both wire [7:0] md; // memory data wire [7:0] pd; // i/o port data // instantiate the chip qs5 m( .clock(clock), .boot(boot), .reset(reset), .req(req), .pd(pd), .po(po), .ack(ack), .dir(dir), .ma(ma), .md(md), .csb(csb), .oeb(oeb), .web(web) ); // Note: 'boot', 'reset', and 'req' are asynchronous signals from the PC that // are delayed one cycle on-chip to reduce the metastability problem. // All are modeled here with synchronous falling-edge signals. The boot // process is simulated by using input from the already loaded memory, // which is then changed to 'x' so that errors will be noticed. // 16-bit wide memory ------------------------------------------------------------- reg [15:0] MEMORY[0:nMem]; // model nK x 16-bit memory plus error counter reg [15:0] d; reg [15:1] a; // memory cell address reg a0; // memory byte select task fill_memory; integer i; begin for (i=0; i>1; a0 = ma[0]; if (a < nMem) begin // valid 16-bit memory address d = MEMORY[a]; if (web==0 && csb==0) begin // writing to memory case (a0) 0: d[7:0] = md[7:0]; 1: d[15:8] = md[7:0]; endcase MEMORY[a] = d; end end else begin MEMORY[nMem] = MEMORY[nMem] + 1; d = 16'bx; end end // always assign #1 md[7:0] = (oeb==0 && csb==0)? (a0? d[15:8]: d[7:0]): 8'bz; // model host 8-bit send/receive buffers ========================================== // host memory for input/output reg [7:0] HOSTMEM[0:hostin+hostout]; reg [15:0] hostaddrin, hostaddrout; task hostdump; input io; // will display only occupied lines of input/output buffer reg [15:0] i, istart, iend, j, n; // these are byte addresses begin if (io==0) begin // host output buffer istart = 0; iend = hostout; $display ("host output characters"); end else begin // host input buffer istart = hostout; iend = hostin+hostout; $display ("host input characters"); end for (i=istart; iChip communication via the PC parallel port ============================= task GetChar; // PC end of chip's TX routine (called with dir==1,req==?) reg pending; begin pending=req; req=0; // save send request $write("%0d RTS, ", $time); while (ack!=1) @(negedge clock); // wait for ack==1 $write("%0d TX2, ", $time,); repeat (1) @(negedge clock); trisig = 1; // turn host drivers off repeat (1) @(negedge clock); req = 1 ; // turn chip drivers on while (ack!=0) @(negedge clock); // and wait for turn-around $write("%0d TX4: %h, ", $time, q); HOSTMEM[hostaddrin] = q; // read data repeat (1) @(negedge clock); req = 0 ; // turn chip drivers off while (dir!=0) @(negedge clock); // and wait for turn-around $display("%0d TX6.", $time); repeat (1) @(negedge clock); trisig = 0; // turn host drivers on again req=pending; // restore send request end endtask // host GetChar task SendKey; // PC end of chip's RX routine (called with dir==0,req==1) begin $write("%0d RX2, ", $time); while (ack!=1) @(negedge clock); // wait for chip to read it $write("%0d RX3: %h, ", $time, p); req = 0; // acknowledge receipt while (ack!=0) @(negedge clock); // and wait for idle $display("%0d RX6.", $time); end endtask // SendKey task Boot; // PC end of chip's boot process begin if (a0==1) begin p = d[15:8]; MEMORY[a] = {8'bx,d[7:0]}; // send odd byte end else begin p = d[7:0]; MEMORY[a] = {d[15:8],8'bx}; // send even byte end repeat (1) @(negedge clock) req = 1; // signal that data is on bus SendKey; end endtask // Boot initial begin: Host // host side of terminal process boot = 1; reset = 1; // powerup state trisig = 0; req = 0; repeat (4) @(negedge clock); reset = 0; // enter boot state when stable repeat (nBoot) Boot; // only do a few to test it repeat (2) @(negedge clock) reset = 1; // turn reset back on to end booting, repeat (5) @(negedge clock) boot = 0; // then turn boot off, repeat (5) @(negedge clock) reset = 0; // and turn reset off to run while (hostaddrout