路科v0,第九周,事件、旗语、信箱、多态-虚方法,练习代码

文章展示了Verilog语言中模块的设计,包括并发任务执行、线程控制(fork/join,join_none,disable)、事件处理、内存访问控制(semaphore)以及邮箱通信机制。同时提及了多态和虚方法在继承中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



module tb1;
	task automatic exe(int id, int t);
		$display("@%t exe[%d] entered",$time,id);
		#(t*1ns);
		$display("@%t exe[%d] exited",$time,id);
	endtask

	initial begin//initial 触发一个线程
		fork
			exe(1,10);
			exe(2,20);
		join_none
		fork
			exe(3,30);
			exe(4,60);
		join
		wait fork;//等待这个线程内所有的fork结束
		$display("all fork exited");
	end
endmodule



module tb2;
	task automatic exe(int id, int t);
		$display("@%t exe[%d] entered",$time,id);
		#(t*1ns);
		$display("@%t exe[%d] exited",$time,id);
	endtask

	initial begin//initial 触发一个线程
		fork
			exe(1,10);
			exe(2,20);
		join_none
		fork
			exe(3,30);
			exe(4,60);
		join_none
		#40 disable fork;//等待四十个时间单位,关闭这个线程中所有的fork
		$display("all fork exited");
	end
endmodule



module tb3;
	task automatic exe(int id, int t);
		$display("@%t exe[%d] entered",$time,id);
		#(t*1ns);
		$display("@%t exe[%d] exited",$time,id);
	endtask

	initial begin//initial 触发一个线程
		fork:a_fork
			exe(1,10);
			exe(2,20);
		join_any
		disable a_fork;//上面有任何一个线程结束,就关闭fork,结束所有的线程
		$display("fork exited");
	end
endmodule



module tb4;
	//bit e1,e2,e3;
	event e1,e2,e3;

	//task wait_event(bit e,string name);
	task wait_event(event e,string name);
	//注意这里的参数问题
	//如果是事件的话,这里的参数传递的是句柄,因此该任务根据句柄的指向,仍然能捕捉到事件
	//但如参数是个bit 或者logic的话,该任务线程触发时,进传递了触发时刻logic的值,因此线程就不能捕捉它的变化了
		$display("@%t start wait event %s",$time,name);
		@e;
		$display("@%t after wait event %s",$time,name);
	endtask

	initial begin
		fork
			wait_event(e1,"e1");
			wait_event(e2,"e2");
			wait_event(e3,"e3");
		join
	end

	initial begin
		fork
			begin #10 -> e1; end
			begin #20 -> e2; end
			begin #30 -> e3; end
//			begin #10 e1 = !e1; end
//			begin #20 e2 = !e2; end
//			begin #30 e3 = !e3; end
		join
	end
endmodule



module tb5;
	semaphore mem_acc_key;

	int unsigned mem[int unsigned];


	task automatic write(int unsigned addr, int unsigned data);
		mem_acc_key.get();
		#1ns
		mem[addr] = data;
		mem_acc_key.put();
	endtask



	task automatic read(int unsigned addr, int unsigned data);
		mem_acc_key.get();
		if(mem.exists(addr)) begin
			data = mem[addr];
		end
		else begin
			data = 'x;
		end
		mem_acc_key.put();
	endtask


	initial begin
		int unsigned data1 = 100;
		int unsigned data2 = 100;
		mem_acc_key = new(1);
		forever begin
			fork
				begin
					#10ns;
					write('h10,data1+100);
					$display("write data = %d",data1);
				end
				begin
					#10ns;
					read('h10,data2);
					$display("read data = %d",data2);
				end
			join
		end
	end
endmodule


module tb6
	mailbox #(int) mb;//定义一个信箱,#(int)表示只存放int型

	initial begin
		int data_in,data_out;
		mb = new(8);
		forever begin
			case($urandom()%2)
				0:begin
						#10ns
						data_in = $urandom_range(0,15);
						mb.try_put(data_in);
						$display("put data: %d",data_in);
					end
				1:begin
						#10ns
						if(mb.num()>0)begin 
							mb.get(data_out); 
						end
						$display("get data: %d",data_out);
					end
			endcase
		end
	end
endmodule




//关于多态(虚方法)
//子类与父类有同名方法,将子类的句柄赋值给父类后,此时父类句柄指向子类
//一般情况下父类句柄是检索不到子类中的变量或者方法的,因此调用父类和子类的同名方法时,仍然是调用的父类的方法
//但如果子类的方法(这里讨论的是同名方法)加了virtual,则使得父类能够调用子类的方法(以及该方法涉及的变量,但是子类父类中尽量不要定义同名变量)
//简而言之 子类加virtual 能够使父类能检索到子类域里的方法
//virtual只能给方法添加,变量不行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值