dbus_mon.v 8.88 KB
// dbus_mon.v v1 Frank Berndt;
// BB dbus monitor;
// turn on with +dbus_mon;
// :set tabstop=4

module dbus_mon (
	sysclk, reset_l,
	cbus_val, cbus_dev,
	dbus_data, ebus_data,
	mi_dma_start, mi_dma_last, mi_dbus_write_enable,
	sp_dma_start, sp_dma_last, sp_dbus_write_enable,
	span_dma_start, span_dma_last, span_dbus_write_enable,
	pi_dma_start, pi_dma_last, pi_dbus_write_enable,
	si_dma_start, si_dma_last, si_dbus_write_enable,
	vi_dma_start, vi_dma_last, vi_dbus_write_enable,
	ai_dma_start, ai_dma_last, ai_dbus_write_enable,
	ui_dma_start, ui_dbus_write_enable,
	ri_dbus_write_enable,
);
	input sysclk;				// system clock;
	input reset_l;				// global reset;

	// input from cbus monitor for issue monitoring;

	input cbus_val;				// a device issued a cbus dma;
	input [3:0] cbus_dev;		// device that issued last cbus dma;
	input [63:0] dbus_data;
	input [7:0] ebus_data;

	// per-device controls;
	// units that don't have dma_stop must wire dma_start;

	input mi_dma_start, mi_dma_last, mi_dbus_write_enable;
	input sp_dma_start, sp_dma_last, sp_dbus_write_enable;
	input span_dma_start, span_dma_last, span_dbus_write_enable;
	input pi_dma_start, pi_dma_last, pi_dbus_write_enable;
	input si_dma_start, si_dma_last, si_dbus_write_enable;
	input vi_dma_start, vi_dma_last, vi_dbus_write_enable;
	input ai_dma_start, ai_dma_last, ai_dbus_write_enable;
	input ui_dma_start, ui_dbus_write_enable;
	input ri_dbus_write_enable;

	wire ui_dma_last = ui_dma_start;

	// +dbus_mon turns on the monitor;

	reg dbus_mon;

	initial
		dbus_mon = $test$plusargs("dbus_mon");

	// print data moving on dbus;

	reg [63:0] dbus_reg;
	reg [7:0] ebus_reg;
	reg dbus_val;

	always @(posedge sysclk)
	begin
		dbus_reg <= dbus_data;
		ebus_reg <= ebus_data;
		dbus_val <= 0; // XXX
		if(dbus_val & dbus_mon)
			$display("%t: %M: XXX 0x%h 0x%h", $time, dbus_reg, ebus_reg);
	end

	// dbus write enable check;
	// only the ri or one other unit is allowed to drive the dbus;

	wire [8:0] dbus_ena;
	reg dbus_ena_ok;

	assign dbus_ena = { mi_dbus_write_enable,
		sp_dbus_write_enable,
		span_dbus_write_enable,
		pi_dbus_write_enable,
		si_dbus_write_enable,
		vi_dbus_write_enable,
		ai_dbus_write_enable,
		ui_dbus_write_enable,
		ri_dbus_write_enable };

	always @(posedge sysclk)
	begin
		dbus_ena_ok = 0;
		if(reset_l == 0) begin
			case(dbus_ena)
				9'b000000000,
				9'b000000001,
				9'b000000010,
				9'b000000100,
				9'b000001000,
				9'b000010000,
				9'b000100000,
				9'b001000000,
				9'b010000000,
				9'b100000000:
					dbus_ena_ok = 1;
				default:
					$display("ERROR: %t: %M: multiple dbus drivers: %b", $time, dbus_ena);
			endcase
		end
	end

	// dma_start and dma_last are only legal after cbus dma issue;

	wire mi_val, sp_val, span_val, pi_val, si_val, vi_val, ai_val, ui_val;
	reg mi_issue, sp_issue, span_issue, pi_issue, si_issue, vi_issue, ai_issue, ui_issue;

	assign mi_val = cbus_val & (cbus_dev == `CBUS_DEV_MI);
	assign sp_val = cbus_val & ((cbus_dev == `CBUS_DEV_CMD) | (cbus_dev == `CBUS_DEV_SP));
	assign span_val = cbus_val & (cbus_dev == `CBUS_DEV_SPAN);
	assign pi_val = cbus_val & (cbus_dev == `CBUS_DEV_PI);
	assign si_val = cbus_val & (cbus_dev == `CBUS_DEV_SI);
	assign vi_val = cbus_val & (cbus_dev == `CBUS_DEV_VI);
	assign ai_val = cbus_val & (cbus_dev == `CBUS_DEV_AI);
	assign ui_val = cbus_val & (cbus_dev == `CBUS_DEV_UI);

	always @(posedge sysclk)
	begin
		if(reset_l == 0) begin
			mi_issue <= 0;
			sp_issue <= 0;
			span_issue <= 0;
			pi_issue <= 0;
			si_issue <= 0;
			vi_issue <= 0;
			ai_issue <= 0;
			ui_issue <= 0;
		end else begin
			mi_issue <= ~mi_dma_start & (mi_issue | mi_val);
			sp_issue <= ~sp_dma_start & (sp_issue | sp_val);
			span_issue <= ~span_dma_start & (span_issue | span_val);
			pi_issue <= ~pi_dma_start & (pi_issue | pi_val);
			si_issue <= ~si_dma_start & (si_issue | si_val);
			vi_issue <= ~vi_dma_start & (vi_issue | vi_val);
			ai_issue <= ~ai_dma_start & (ai_issue | ai_val);
			ui_issue <= ~ui_dma_start & (ui_issue | ui_val);
		end
		if(mi_dma_start & !mi_issue)
			$display("ERROR: %t: %M: mi dma_start without cbus issue", $time);
		if(sp_dma_start & !sp_issue)
			$display("ERROR: %t: %M: sp dma_start without cbus issue", $time);
		if(span_dma_start & !span_issue)
			$display("ERROR: %t: %M: span dma_start without cbus issue", $time);
		if(pi_dma_start & !pi_issue)
			$display("ERROR: %t: %M: pi dma_start without cbus issue", $time);
		if(si_dma_start & !si_issue)
			$display("ERROR: %t: %M: si dma_start without cbus issue", $time);
		if(vi_dma_start & !vi_issue)
			$display("ERROR: %t: %M: vi dma_start without cbus issue", $time);
		if(ai_dma_start & !ai_issue)
			$display("ERROR: %t: %M: ai dma_start without cbus issue", $time);
		if(ui_dma_start & !ui_issue)
			$display("ERROR: %t: %M: ui dma_start without cbus issue", $time);
	end

	// dma_start and dma_last should only be active for one clock;

	reg mi_start, mi_last;
	reg sp_start, sp_last;
	reg span_start, span_last;
	reg pi_start, pi_last;
	reg si_start, si_last;
	reg vi_start, vi_last;
	reg ai_start, ai_last;
	reg ui_start, ui_last;

	always @(posedge sysclk)
	begin
		if(reset_l == 0) begin
			mi_start <= 0;
			mi_last <= 0;
			sp_start <= 0;
			sp_last <= 0;
			span_start <= 0;
			span_last <= 0;
			pi_start <= 0;
			pi_last <= 0;
			si_start <= 0;
			si_last <= 0;
			vi_start <= 0;
			vi_last <= 0;
			ai_start <= 0;
			ai_last <= 0;
			ui_start <= 0;
			ui_last <= 0;
		end else begin
			mi_start <= mi_dma_start;
			mi_last <= mi_dma_last;
			sp_start <= sp_dma_start;
			sp_last <= sp_dma_last;
			span_start <= span_dma_start;
			span_last <= span_dma_last;
			pi_start <= pi_dma_start;
			pi_last <= pi_dma_last;
			si_start <= si_dma_start;
			si_last <= si_dma_last;
			vi_start <= vi_dma_start;
			vi_last <= vi_dma_last;
			ai_start <= ai_dma_start;
			ai_last <= ai_dma_last;
			ui_start <= ui_dma_start;
			ui_last <= ui_dma_last;
		end
		if(mi_start & mi_dma_start)
			$display("ERROR: %t: %M: multi-cycle mi_dma_start", $time);
		if(mi_last & mi_dma_last)
			$display("ERROR: %t: %M: multi-cycle mi_dma_last", $time);
		if(sp_start & sp_dma_start)
			$display("ERROR: %t: %M: multi-cycle sp_dma_start", $time);
		if(sp_last & sp_dma_last)
			$display("ERROR: %t: %M: multi-cycle sp_dma_last", $time);
		if(span_start & span_dma_start)
			$display("ERROR: %t: %M: multi-cycle span_dma_start", $time);
		if(span_last & span_dma_last)
			$display("ERROR: %t: %M: multi-cycle span_dma_last", $time);
		if(pi_start & pi_dma_start)
			$display("ERROR: %t: %M: multi-cycle pi_dma_start", $time);
		if(pi_last & pi_dma_last)
			$display("ERROR: %t: %M: multi-cycle pi_dma_last", $time);
		if(si_start & si_dma_start)
			$display("ERROR: %t: %M: multi-cycle si_dma_start", $time);
		if(si_last & si_dma_last)
			$display("ERROR: %t: %M: multi-cycle si_dma_last", $time);
		if(vi_start & vi_dma_start)
			$display("ERROR: %t: %M: multi-cycle vi_dma_start", $time);
		if(vi_last & vi_dma_last)
			$display("ERROR: %t: %M: multi-cycle vi_dma_last", $time);
		if(ai_start & ai_dma_start)
			$display("ERROR: %t: %M: multi-cycle ai_dma_start", $time);
		if(ai_last & ai_dma_last)
			$display("ERROR: %t: %M: multi-cycle ai_dma_last", $time);
		if(ui_last & ui_dma_last)
			$display("ERROR: %t: %M: multi-cycle ui_dma_last", $time);
	end

	// dma_last should not be active before a dma_start;

	reg mi_act;
	reg sp_act;
	reg span_act;
	reg pi_act;
	reg si_act;
	reg vi_act;
	reg ai_act;
	reg ui_act;

	always @(posedge sysclk)
	begin
		if(reset_l == 0) begin
			mi_act <= 0;
			sp_act <= 0;
			span_act <= 0;
			pi_act <= 0;
			si_act <= 0;
			vi_act <= 0;
			ai_act <= 0;
			ui_act <= 0;
		end else begin
			mi_act <= ~mi_dma_last & (mi_act | mi_dma_start);
			sp_act <= ~sp_dma_last & (sp_act | sp_dma_start);
			span_act <= ~span_dma_last & (span_act | span_dma_start);
			pi_act <= ~pi_dma_last & (pi_act | pi_dma_start);
			si_act <= ~si_dma_last & (si_act | si_dma_start);
			vi_act <= ~vi_dma_last & (vi_act | vi_dma_start);
			ai_act <= ~ai_dma_last & (ai_act | ai_dma_start);
			ui_act <= ~ui_dma_last & (ui_act | ui_dma_start);
		end
		if(mi_dma_last & !mi_dma_start & !mi_act)
			$display("ERROR: %t: %M: mi dma_last before dma_start", $time);
		if(sp_dma_last & !sp_dma_start & !sp_act)
			$display("ERROR: %t: %M: sp dma_last before dma_start", $time);
		if(span_dma_last & !span_dma_start & !span_act)
			$display("ERROR: %t: %M: span dma_last before dma_start", $time);
		if(pi_dma_last & !pi_dma_start & !pi_act)
			$display("ERROR: %t: %M: pi dma_last before dma_start", $time);
		if(si_dma_last & !si_dma_start & !si_act)
			$display("ERROR: %t: %M: si dma_last before dma_start", $time);
		if(vi_dma_last & !vi_dma_start & !vi_act)
			$display("ERROR: %t: %M: vi dma_last before dma_start", $time);
		if(ai_dma_last & !ai_dma_start & !ai_act)
			$display("ERROR: %t: %M: ai dma_last before dma_start", $time);
		if(ui_dma_last & !ui_dma_start & !ui_act)
			$display("ERROR: %t: %M: ui dma_last before dma_start", $time);
	end

	// dma_last should be no more then 64 clocks after dma_start;
	// XXX

endmodule