:vpi_module "system";


; IMPORTANT NOTE:
;
; This example uses constructs that are no longer supported. It will
; not run with the current vvp implementation!


; Copyright (c) 2001-2008  Stephen Williams (steve@icarus.com)
; Copyright (c) 2001  Stephan Boettcher <stephan@nevis.columbia.edu>
;
;    This source code is free software; you can redistribute it
;    and/or modify it in source code form under the terms of the GNU
;    General Public License as published by the Free Software
;    Foundation; either version 2 of the License, or (at your option)
;    any later version.
;
;    This program is distributed in the hope that it will be useful,
;    but WITHOUT ANY WARRANTY; without even the implied warranty of
;    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;    GNU General Public License for more details.
;
;    You should have received a copy of the GNU General Public License
;    along with this program; if not, write to the Free Software
;    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

; This sample demonstrates memory,  also including index register
; arithmetic.  And a memory write port

main	.scope	"example";

;;; Make a memory.
;
;   reg [8:2] memory[5:27];

memory	.mem	"memory", 8,2, 27,5 ;

;;; The word width is 7 bits [8:2].
;;; The memory size is 23 words, 5..27.
;;; Memory words are always numbered in ascending order.

;;; An address/data port.
;
;   reg [4:0]  a;
;   reg        we;
;   event      wclk;
;   reg [5:0]  di;
;   wire [5:0] d = memory[a][8:3];
;   reg [6:0]  m;

a	.var	"a", 4,0;
we	.var	"we", 0,0;
wclk	.event	"wclk";
di	.var	"di", 5,0;
d	.net	"d", 5,0, mem[0],mem[1],mem[2],mem[3],mem[4],mem[5];
mem	.mem/port memory, 6,1,
		5, a[0],a[1],a[2],a[3],a[4],
		wclk, we, di[0],di[1],di[2],di[3],di[4],di[5];
m	.var	"m", 6,0;

;;; The data port mem[] does not connect to the LSB of the memory.

;;; Initialize some part of the memory.	 Starting at memory bit [20],
;;; which is in the middle of the third memory word, memory[7].	 The
;;; memory words occupy 8 bits each, that is 7 rounded up to the next
;;; multiple of 4.

;;; Four bits per byte.	 Word fill bits are included.  Commas are
;;; optional, there may be a comma after the last byte.

	.mem/init memory[20],
		     0x55
		0x00 0x00
		0x50 0x05
		0x05 0x50
		0x05 0x05
		0x00 0x00
		0x00 0x01
		0x00 0x04
		0x00 0x10
		0x00 0x40
		0x01 0x00
		0x04,0x00,
		0x10,0x00,
		0x40,0x00,
		;

;;; Run through the addresses and display the data output.
;
;   always
;     begin
;	#5 $display("a:%b d:%b", a, d);
;	-> wclk;
;	#5 a <= a+1;
;     end

	.scope main;
always ;
	%delay	5;

	%vpi_call "$display", "a:%b d:%b", a, d;

	%set	wclk, 0;

	%delay	5;

	%load	10, a[0];
	%load	11, a[1];
	%load	12, a[2];
	%load	13, a[3];
	%load	14, a[4];
	%mov	20, 1, 1;
	%mov	21, 0, 4;
	%add	10, 20, 5;
	%assign	a[0], 0, 10;
	%assign a[1], 0, 11;
	%assign a[2], 0, 12;
	%assign a[3], 0, 13;
	%assign a[4], 0, 14;

	%jmp	always;
	.thread	always;

;;; Initialize a[], run some cycles, overwrite a memory word, run a
;;; bit more, read a memory word, finish.
;
;   initial
;     begin
;       we = 0;
;	di = 'b 10zx10;
;	a = 0;
;	#220;
;       $readmemh("memory.hex", memory);
;	#30;
;	we = 1;
;	#5;
;	$display("write to a=%b", a);
;	#5;
;	we = 0;
;	#60;
;	memory[23] <= 'b 1xz01;
;	#320;
;	m = memory[9];
;	$display("memory[9]=%b", m);
;	#1;
;	$finish;
;     end

	.scope	main;
initial ;
	%set	we, 0;
	%set	di[0], 0;
	%set	di[1], 1;
	%set	di[2], 2;
	%set	di[3], 3;
	%set	di[4], 0;
	%set	di[5], 1;
	%set	a[0], 0;
	%set	a[1], 0;
	%set	a[2], 0;
	%set	a[3], 0;
	%set	a[4], 0;

	%delay	220;
	%vpi_call "$readmemh", "memory.hex", memory;
	%delay	30;
	%set	we, 1;
	%delay	5;
	%vpi_call "$display", "write to a=%b", a;
	%delay	5;
	%set	we, 0;
	%delay	60;

;;; Memories are indexed by index register 3.  The index register
;;; points to the bit position in the memory.  Each memory word
;;; occupies a multiple of 4 bits.  Bit position zero is the LSB of
;;; the first memory word, here: memory[5][2].

	%ix/load 3, 23 ;	memory word index
	%ix/sub	 3,  5 ;	minus memory root index
	%ix/mul	 3,  8 ;	times memory word size (rounded up)
	%assign/m memory, 0, 1;
	%ix/add	 3, 1 ;		next bit
	%assign/m memory, 0, 0;
	%ix/add	 3, 1 ;
	%assign/m memory, 0, 3;
	%ix/add	 3, 1 ;
	%assign/m memory, 0, 2;
	%ix/add	 3, 1 ;
	%assign/m memory, 0, 1;
	%ix/add	 3, 1 ;
	%assign/m memory, 0, 0;
	%ix/add	 3, 1 ;
	%assign/m memory, 0, 0;

	%delay	320;

	%ix/load 3,  32 ;	precomputed memory bit index
	%load/m	 10, memory;
	%set	 m[0], 10;
	%ix/add	 3, 1 ;
	%load/m	 10, memory;
	%set	 m[1], 10;
	%ix/add	 3, 1 ;
	%load/m	 10, memory;
	%set	 m[2], 10;
	%ix/add	 3, 1 ;
	%load/m	 10, memory;
	%set	 m[3], 10;
	%ix/add	 3, 1 ;
	%load/m	 10, memory;
	%set	 m[4], 10;
	%ix/add	 3, 1 ;
	%load/m	 10, memory;
	%set	 m[5], 10;
	%ix/add	 3, 1 ;
	%load/m	 10, memory;
	%set	 m[6], 10;
	%vpi_call "$display", "memory[9]=%b", m;

	#1;
	%vpi_call "$finish";

	%end;
	.thread initial;
