ide_dev.v 4.54 KB
// ide_dev.v v1 Frank Berndt
// ide bus devices that support dv;
// :set tabstop=4

module ide_dev (
	sysclk, reset_l,
	io_rst, io_ad, io_ale, io_cs, io_ior, io_iow, io_intr, gpio,
);
	input sysclk;		// system clock;
	input reset_l;		// system reset;

	// io bus;

	input io_rst;			// io reset;
	inout [15:0] io_ad;		// io ad bus;
	input io_ale;			// address latch enable;
	input [3:0] io_cs;		// chip selects;
	input io_ior;			// read pulse;
	input io_iow;			// write pulse;
	input io_intr;			// io interrupt;
	inout [3:0] gpio;		// gpio bus;

	// latch io bus address;

	reg [15:0] io_addr;		// latched io address;

	always @(negedge io_ale)
		io_addr <= io_ad;

	// io bus debug printf;
	// io_cs[3] (debug port) and address `PI_PRINTF;
	// io_ad[7:0] contains the character;
	// write chars into line buffer, dump on \n;
	// flush printf buffer on io reset;

	reg [7:0] prf_buf [0:127];	// printf buffer;
	integer prf_nc;				// # of chars in printf buffer;
	reg [7:0] prf_char;			// current char;

	always @(io_rst)
	begin
		if(io_rst !== 1'b1)
			prf_nc = 0;
	end

	task printf;
		reg [7:0] c;
		integer n;
		begin
			$write("%t: %M: ", $time);
			for(n = 0; n < prf_nc; n = n + 1)
				$write("%0s", prf_buf[n]);
			$display("");
		end
	endtask

	// decode accesses to simulator debug space;

	wire dbg_spc;

	assign dbg_spc = (io_rst === 1'b1) & (io_cs[3] === 1'b0);

	always @(posedge io_iow)
	begin
		if(dbg_spc & (io_addr === 16'hfff0)) begin
			prf_char = io_ad[7:0];
			if(prf_char === 8'h0a) begin
				printf;
				prf_nc = 0;
			end else if(prf_nc < 127) begin
				prf_buf[prf_nc] = prf_char;
				prf_nc = prf_nc + 1;
			end
		end
	end

	// io bus dump control;
	// io_cs[3] (debug port) and address `PI_DUMP;
	// io_ad[0] turns dump on or off;

	always @(posedge io_iow)
	begin
		if(dbg_spc & (io_addr === 16'hfff1))
			vsim.dump.dump = io_ad[0];
	end

	// flash module presence
	// io_cs[3] (debug port) and address `PI_MODULE;
	// io_ad[0] controls module presence

	always @(posedge io_iow)
	begin
		if(dbg_spc & (io_addr === 16'hfff2))
			vsim.mm.fl_md = io_ad[0];
	end

	// flash module insertion/removal sequencer;
	// io_cs[3] (debug port) and address;
	// PI_MD_PTR sets list pointer to 0;
	// PI_MD_VAL writes write data to list;
	// PI_MD_TRIG triggers md sequence;

	wire [2:0] md_addr;
	wire md_rd;

	assign md_addr[0] = (io_addr === 16'hfff4);
	assign md_addr[1] = (io_addr === 16'hfff3);
	assign md_addr[2] = (io_addr === 16'hfff5);

	always @(posedge io_iow)
	begin
		if(dbg_spc & md_addr[0]) begin
			vsim.mm.md_ioptr = 0;
			vsim.mm.md_iolist[0] = 0;
		end
		if(dbg_spc & md_addr[1]) begin
			vsim.mm.md_iolist[vsim.mm.md_ioptr] = io_ad[15:0];
			vsim.mm.md_ioptr = vsim.mm.md_ioptr + 1;
		end
		if(dbg_spc & md_addr[2])
			vsim.mm.md_busy = 1;
	end

	assign md_rd = dbg_spc & ~io_ior & |md_addr;
	assign io_ad = md_rd? { 15'd0, vsim.mm.md_busy } : 16'bz;

	// set board_id;

	always @(posedge io_iow)
	begin
		if(dbg_spc & (io_addr === 16'hfff6))
			vsim.board_id = io_ad[15:6];
	end

	// pin reset backdoor;
	// io_cs[3] (debug port) and address `PI_PINRST;
	// do full pin reset;

	always @(posedge io_iow)
	begin
		if(dbg_spc & (io_addr === 16'hffff)) begin
			vsim.rst_l = 0;
			repeat(16) @(posedge sysclk);
			vsim.rst_l = 1;
		end
	end

	// pwr_gd button backdoor
	// io_cs[3] (debug port) and address `PI_PINBTN

	always @(posedge io_iow)
	   begin
		if (dbg_spc & (io_addr == 16'hfffe))
	 	   begin
			repeat (20)
			   @(posedge sysclk)
			   ;
			vsim.button = 1'b1 ;
			repeat (20)
			   @(posedge sysclk)
			   ;
			vsim.button = 1'b0 ;
		   end
	   end

	// backdoor to halt simulator
	// io_cs[3] (debug port) and address `PI_SIMHLT

	always @(posedge io_iow)
	   begin
		if (dbg_spc & (io_addr == 16'hfffd))
			begin
				$display("%t: %M: simulator termination", $time);
				repeat(32) @(posedge sysclk);
				$finish;
			end
	   end

	// gpio backdoor;
	// same as PI_GPIO;

	wire gpio_spc;			// gpio debug space;
	wire gpio_rd;			// read gpio bits;
	reg [3:0] gpio_oe;		// ide side output enables;
	reg [3:0] gpio_out;		// ide side gpio outputs;

	assign gpio_spc = dbg_spc & (io_addr === 16'hfffc);

	always @(posedge sysclk or io_rst)
	begin
		if(io_rst !== 1'b1)
			{ gpio_oe, gpio_out } <= 8'd0;
	end

	always @(posedge io_iow)
	begin
		if(gpio_spc)
			{ gpio_oe, gpio_out } <= io_ad[7:0];
	end

	assign gpio_rd = gpio_spc & ~io_ior;
	assign io_ad = gpio_rd? { 8'd0, gpio_oe, gpio } : 16'bz;
	assign gpio[3] = gpio_oe[3]? gpio_out[3] : 'bz;
	assign gpio[2] = gpio_oe[2]? gpio_out[2] : 'bz;
	assign gpio[1] = gpio_oe[1]? gpio_out[1] : 'bz;
	assign gpio[0] = gpio_oe[0]? gpio_out[0] : 'bz;

endmodule