flashmm.v 3.15 KB
// flashmm.v v1 Frank Berndt
// flash memory module;
// :set tabstop=4

module flashmm (
	fl_md, fl_db, fl_ce, fl_cle, fl_ale, fl_we, fl_re, fl_wp, fl_ryby
);
	output fl_md;			// module detect;
	inout [7:0] fl_db;		// data bus;
	input [3:0] fl_ce;		// chip enables;
	input fl_ale;			// address latch enable;
	input fl_cle;			// command latch enable;
	input fl_re;			// read eanble;
	input fl_we;			// write eanble;
	input fl_wp;			// write protect;
	output fl_ryby;			// ready/busy;

	// flash memory module detect;
	// instantiate flash memory module;
	// pulled up on chip side, grounded on module side;
	// overwrite this to simulate module presence;

	reg fl_md;				// 0 means present;

	initial
		fl_md = $test$plusargs("no_module");

	// comilation flag;

	reg [3:0] fl_comp;		// compiled-in flash components;

	initial
	begin
		fl_comp = 4'h0;
`ifdef	FLASH0
		fl_comp[0] = 1;
`endif	// FLASH0
`ifdef	FLASH1
		fl_comp[1] = 1;
`endif	// FLASH1
`ifdef	FLASH2
		fl_comp[2] = 1;
`endif	// FLASH2
`ifdef	FLASH3
		fl_comp[3] = 1;
`endif	// FLASH3
	end

	// instantiate four NAND flash models;
	// use different sizes;
	// turn off ce if module detect is 1;

	wand fl_ryby;

`ifdef	FLASH0
	`FLASH0 flash0 (
		.io(fl_db),
		.cle(fl_cle),
		.ale(fl_ale),
		.ceb(fl_ce[0] | fl_md),
		.reb(fl_re),
		.web(fl_we),
		.rbb(fl_ryby),
		.wpb(fl_wp),
		.seb(1'b0)
	);
`endif	// FLASH0

`ifdef	FLASH1
	`FLASH1 flash1 (
		.io(fl_db),
		.cle(fl_cle),
		.ale(fl_ale),
		.ceb(fl_ce[1] | fl_md),
		.reb(fl_re),
		.web(fl_we),
		.rbb(fl_ryby),
		.wpb(fl_wp),
		.seb(1'b0)
	);
`endif	// FLASH1_PRESENT

`ifdef	FLASH2
	`FLASH2 flash2 (
		.io(fl_db),
		.cle(fl_cle),
		.ale(fl_ale),
		.ceb(fl_ce[2] | fl_md),
		.reb(fl_re),
		.web(fl_we),
		.rbb(fl_ryby),
		.wpb(fl_wp),
		.seb(1'b0)
	);
`endif	// FLASH2

`ifdef	FLASH3
	`FLASH3 flash3 (
		.io(fl_db),
		.cle(fl_cle),
		.ale(fl_ale),
		.ceb(fl_ce[3] | fl_md),
		.reb(fl_re),
		.web(fl_we),
		.rbb(fl_ryby),
		.wpb(fl_wp)
	);
`endif	// FLASH3

`ifdef	NFLASH3
	nflash nflash3 (
		.dev(2'd3),
		.db(fl_db),
		.ce(fl_ce[3] | fl_md),
		.cle(fl_cle),
		.ale(fl_ale),
		.we(fl_we),
		.re(fl_re),
		.wp(fl_wp),
		.ryby(fl_ryby)
	);
`endif	// NFLASH3

	// flash module insertion/removal logic;
	// timing parameter list, 0 marks end of list;
	// bit[14:0] delay in sysclk;
	// bit[15] 0=insert, 1=remove module;
	// set md_busy to 1 to start events;
	// md_busy clears itself when done;

	reg [15:0] md_iolist [0:1023];	// parameter list;
	reg [7:0] md_ioptr;				// ptr to current entry;
	reg md_busy;					// trigger list processing;
	reg [15:0] md_val;				// current value;
	reg md_valx;					// value has Xs in it;
	reg md_new;						// new md state;

	initial
	begin
		md_busy = 0;
		md_iolist[0] = 0;
		$readmemh("tests/mdio.dat", md_iolist);
	end

	always @(posedge md_busy)
	begin
		md_ioptr = 0;
		md_val = md_iolist[md_ioptr];
		while(md_busy & (md_val != 0)) begin
			md_valx = ^md_val;
			if(md_valx === 1'bx)
				$display("ERROR: %t: %M: md_iolist[%0d] 0x%h", $time, md_ioptr, md_val);
			md_new = md_val[15];
			md_val[15] = 0;
			repeat(md_val) @(posedge vsim.bb.sysclk);
			fl_md = md_new;
			md_ioptr = md_ioptr + 1;
			md_val = md_iolist[md_ioptr];
		end
		md_busy = 0;
	end

endmodule