SV学习笔记(7)

学习目标:

实验2
SV绿皮书第六章:随机化

学习内容:

1.实验012代码整理

测试文件tb1

'timescale  1ns/1ps
module  tb1;
reg		clk;
reg		rstn;
reg		[31:0]ch0_data;
reg		ch0_valid;		//数据有效标志信号
wire	ch0_ready;		//为高可以写入
wire	[4:0]ch0_margin;	//
reg		[31:0]ch1_data;
reg		ch1_valid;
wire	ch1_ready;
wire	[4:0]ch1_margin;
reg		[31:0]ch2_data;
reg		ch2_valid;
wire	ch2_ready;
wire	[4:0]ch2_margin;
wire	[31:0]mcdt_data;
wire	mcdt_val;			//
wire	[1:0]mcdt_id;

mcdt  dut(
	.clk_i(clk)
  ,.rstn_i(rstn)
  ,.ch0_data_i(ch0_data)
  ,.ch0_valid_i(ch0_valid)
  ,.ch0_ready_o(ch0_ready)
  ,.ch0_margin_o(ch0_margin)
  ,.ch1_data_i(ch1_data)
  ,.ch1_valid_i(ch1_valid)
  ,.ch1_ready_o(ch1_ready)
  ,.ch1_margin_o(ch1_margin)
  ,.ch2_data_i(ch2_data)
  ,.ch2_valid_i(ch2_valid)
  ,.ch2_ready_o(ch2_ready)
  ,.ch2_margin_o(ch2_margin)
  ,.mcdt_data_o(mcdt_data)
  ,.mcdt_val_o(mcdt_val)
  ,.mcdt_id_o(mcdt_id)
);

//时钟生成
initial  begin
	clk<=0;
	forever  begin
		#5 clk<=!clk;
	end
end

//复位
initial  begin
	#10 rstn<=0;
	repeat(10)  @(posedge  clk);
	rstn<=1;
end

//通道012数据
initial  begin
	@(posedge rstn);
	repeat(5)  @(posedge  clk);
	//通道0  数据
	  chn1_write(0,'h00C0_0000);			//chn_write为任务
	  chnl_write(0, 'h00C0_0001);
	  chnl_write(0, 'h00C0_0002);
	  chnl_write(0, 'h00C0_0003);
	  chnl_write(0, 'h00C0_0004);
	  chnl_write(0, 'h00C0_0005);
	  chnl_write(0, 'h00C0_0006);
	  chnl_write(0, 'h00C0_0007);
	  chnl_write(0, 'h00C0_0008);
	  chnl_write(0, 'h00C0_0009);
	  // channel 1 test
	  chnl_write(1, 'h00C1_0000);
	  chnl_write(1, 'h00C1_0001);
	  chnl_write(1, 'h00C1_0002);
	  chnl_write(1, 'h00C1_0003);
	  chnl_write(1, 'h00C1_0004);
	  chnl_write(1, 'h00C1_0005);
	  chnl_write(1, 'h00C1_0006);
	  chnl_write(1, 'h00C1_0007);
	  chnl_write(1, 'h00C1_0008);
	  chnl_write(1, 'h00C1_0009);
	  // channel 2 test
	  chnl_write(2, 'h00C2_0000);
	  chnl_write(2, 'h00C2_0001);
	  chnl_write(2, 'h00C2_0002);
	  chnl_write(2, 'h00C2_0003);
	  chnl_write(2, 'h00C2_0004);
	  chnl_write(2, 'h00C2_0005);
	  chnl_write(2, 'h00C2_0006);
	  chnl_write(2, 'h00C2_0007);
	  chnl_write(2, 'h00C2_0008);
	  chnl_write(2, 'h00C2_0009);
end

task   chn1_write(input   reg[1:0]id,input   reg  [31:0]data);
	case(id)
		0:begin
			@(posedge  clk);
				ch0_valid<=1;
				ch0_data<=data;
			@(posedge  clk);
				ch0_valid<=0;
				ch0_data<=0;
		  end
		 1:begin
			@(posedge  clk);
				ch1_valid<=1;
				ch1_data<=data;
			@(posedge  clk);
				ch1_valid<=0;
				ch1_data<=0;
		    end
		  2:begin
			@(posedge  clk);
				ch2_valid<=1;
				ch2_data<=data;
			@(posedge  clk);
				ch2_valid<=0;
				ch2_data<=0;
		     end
		  default:$error("channel  id  %0d  is  invalid",id);
	endcase
endtask
endmodule

mcdt为顶层文件,连接三个fifo通道和arbiter

实验1TB2:任务与函数

`timescale 1ns/1ps

module tb2;
logic         clk;
logic         rstn;
logic [31:0]  ch0_data;
logic         ch0_valid;
logic         ch0_ready;
logic [ 5:0]  ch0_margin;
logic [31:0]  ch1_data;
logic         ch1_valid;
logic         ch1_ready;
logic [ 5:0]  ch1_margin;
logic [31:0]  ch2_data;
logic         ch2_valid;
logic         ch2_ready;
logic [ 5:0]  ch2_margin;
logic [31:0]  mcdt_data;
logic         mcdt_val;
logic [ 1:0]  mcdt_id;

mcdt dut(
   .clk_i(clk)
  ,.rstn_i(rstn)
  ,.ch0_data_i(ch0_data)
  ,.ch0_valid_i(ch0_valid)
  ,.ch0_ready_o(ch0_ready)
  ,.ch0_margin_o(ch0_margin)
  ,.ch1_data_i(ch1_data)
  ,.ch1_valid_i(ch1_valid)
  ,.ch1_ready_o(ch1_ready)
  ,.ch1_margin_o(ch1_margin)
  ,.ch2_data_i(ch2_data)
  ,.ch2_valid_i(ch2_valid)
  ,.ch2_ready_o(ch2_ready)
  ,.ch2_margin_o(ch2_margin)
  ,.mcdt_data_o(mcdt_data)
  ,.mcdt_val_o(mcdt_val)
  ,.mcdt_id_o(mcdt_id)
);

//创建时钟生成任务,然后调用
task  clk_gen();
	clk<=0;
	forever begin
		#5  clk<=!clk;
	end
endtask

initial  begin
	clk_gen();		//调用
end

//同理的,复位任务创建并调用
task rstn_gen();
  #10 rstn <= 0;
  repeat(10) @(posedge clk);
  rstn <= 1;
endtask
	
initial begin
 	rstn_gen();
end

//后面代码不变

实验1TB3:数组的使用
----data test代码修改

logic [31:0] chnl0_arr[];
logic [31:0] chnl1_arr[];
logic [31:0] chnl2_arr[]; 		//动态数组声明

initial  begin
	chnl0_arr=new[100];
	chnl1_arr=new[100];
	chnl2_arr=new[100];			//创建数组
	//数组赋值
	foreach(chnl0_arr[i])  begin
		chnl0_arr[i]='h00C0_000+i;
		chnl1_arr[i]='h00C1_000+i;
		chnl2_arr[i]='h00C2_000+i;
	end
end

//发送给三个通道
initial begin 
  @(posedge rstn);
  repeat(5) @(posedge clk);
  foreach(chnl0_arr[i]) chnl_write(0, chnl0_arr[i]);
  foreach(chnl1_arr[i]) chnl_write(1, chnl1_arr[i]);
  foreach(chnl2_arr[i]) chnl_write(2, chnl2_arr[i]);
end

实验1TB4:验证结构

//将channel write task封装成chnl_initiator,然后例化
module  chnl_initiator(
	input 			clk,
	input			rstn,
	output   logic [31:0]ch_data,
	output	 logic	ch_valid,
	input			ch_ready,
	input			[5:0]ch_margin
);

string  name;

function  void  set_name(string s);				//chnl0_init.set_name("chnl0_init")  调用
	name=s;
endfunction

task  chnl_write(input logic  [31:0]data);
	  @(posedge clk);
  		ch_valid <= 1;
 		ch_data <= data;
  	  @(negedge clk);					    //验证一下啊
  		wait(ch_ready === 'b1);				//同一拍ready为低,要等待
		$display("%t channel initial [%s] sent data %x", $time, name, data);
		chnl_idle();
endtask

task chnl_idle();
	@(posedge clk);
  		ch_valid <= 0;
  		ch_data <= 0;
endtask

//例化
chnl_initiator chnl0_init(
  .clk      (clk),
  .rstn     (rstn),
  .ch_data  (ch0_data),
  .ch_valid (ch0_valid),
  .ch_ready (ch0_ready),
  .ch_margin(ch0_margin) 
);

chnl_initiator chnl1_init(
  .clk      (clk),
  .rstn     (rstn),
  .ch_data  (ch1_data),
  .ch_valid (ch1_valid),
  .ch_ready (ch1_ready),
  .ch_margin(ch1_margin) 
);

chnl_initiator chnl2_init(
  .clk      (clk),
  .rstn     (rstn),
  .ch_data  (ch2_data),
  .ch_valid (ch2_valid),
  .ch_ready (ch2_ready),
  .ch_margin(ch2_margin) 
);

实验2—TB1:接口的使用

interface  chnl_intf(input clk, input rstn);		//接口
	logic[31:0] ch_data;
	logic  ch_valid;
	logic  ch_ready;
	logic  [5:0]ch_margin;

	clocking drv_ck@(posedge  clk);					//接口时钟块
		default input #1ns  output #1ns;
		output  ch_data,  ch_valid;
		input   ch_ready, ch_margin;
	endclocking
endinterface

module  chnl_initiator(chnl_intf  intf);
	string  name;
	int  idle_cycles=1;
	function automatic  void  set_idle_cycles(int n);		//控制空闲间隔
		idle_cycles=n;
	endfunction
	
	function automatic void set_name(string s);
    	name = s;
  	endfunction

	task automatic chnl_write(input  logic  [31:0]data);		//write任务
		@(posedge intf.clk);
			intf.drv_ck.ch_valid<=1;				//带接口时钟块
			intf.drv_ck.ch_data<=data;
		@(negedge intf.clk);
			wait(intf.ch_ready==='b1);
				$display(%t channel  initiator  [%s]  sent data %x",$time,name,data);
		repeat(idle_cycles) chnl_idle();			//调用方法控制空闲间隔
	endtask

	task automatic chnl_idle();
    	@(posedge intf.clk);
    		intf.drv_ck.ch_valid <= 0;
    		intf.drv_ck.ch_data <= 0;
  	endtask
endmodule

module  chnl_generator;			//id设置,名字设置
	int  chnl_arr[$];
	int  num;
	int  id;
	function automatic void initialize(int n);
		id=n;
		num=0;
	endfunction

	function automatic int  get_data();
		int data;
			data='h00C0_0000+(id<<16)+num;
			num++;
			chnl_arr.push_back(data);
		return  data;
	endfunction
endmodule

module tb1;
  logic         clk;
  logic         rstn;
  logic [31:0]  mcdt_data;
  logic         mcdt_val;
  logic [ 1:0]  mcdt_id;

mcdt dut(
     .clk_i       (clk                )
    ,.rstn_i      (rstn               )
    ,.ch0_data_i  (chnl0_if.ch_data   )
    ,.ch0_valid_i (chnl0_if.ch_valid  )
    ,.ch0_ready_o (chnl0_if.ch_ready  )
    ,.ch0_margin_o(chnl0_if.ch_margin )
    ,.ch1_data_i  (chnl1_if.ch_data   )
    ,.ch1_valid_i (chnl1_if.ch_valid  )
    ,.ch1_ready_o (chnl1_if.ch_ready  )
    ,.ch1_margin_o(chnl1_if.ch_margin )
    ,.ch2_data_i  (chnl2_if.ch_data   )
    ,.ch2_valid_i (chnl2_if.ch_valid  )
    ,.ch2_ready_o (chnl2_if.ch_ready  )
    ,.ch2_margin_o(chnl2_if.ch_margin )
    ,.mcdt_data_o (mcdt_data          )
    ,.mcdt_val_o  (mcdt_val           )
    ,.mcdt_id_o   (mcdt_id            )
  );

// clock generation
  initial begin 
    clk <= 0;
    forever begin
      #5 clk <= !clk;
    end
  end
  
  // reset trigger
  initial begin 
    #10 rstn <= 0;
    repeat(10) @(posedge clk);
    rstn <= 1;
  end

initial  begin
	chnl0_gen.initialize(0);
	chnl1_gen.initialize(1);
	chnl2_gen.initialize(2);
	chnl0_init.set_name("chnl0_init");
	chnl1_init.set_name("chnl1_init");
	chnl2_init.set_name("chnl2_init");
	chnl0_init.set_idle_cycles(0);
	chnl1_init.set_idle_cycles(0);
	chnl2_init.set_idle_cycles(0);
end

initial  begin
	@(posedge rstn);
		repeat(5)  @(posedge clk);
		repeat(100) begin
			chnl0_init.chnl_write(chnl0_gen.get_data());
		end
			chnl0_init.chnl_idle();
end

initial  begin
	@(posedge rstn);
		repeat(5)  @(posedge clk);
		repeat(100) begin
			chnl1_init.chnl_write(chnl1_gen.get_data());
		end
			chnl1_init.chnl_idle();
end

initial  begin
	@(posedge rstn);
		repeat(5)  @(posedge clk);
		repeat(100) begin
			chnl2_init.chnl_write(chnl2_gen.get_data());
		end
			chnl2_init.chnl_idle();
end

  chnl_intf chnl0_if(.*);
  chnl_intf chnl1_if(.*);
  chnl_intf chnl2_if(.*);

  chnl_initiator chnl0_init(chnl0_if);
  chnl_initiator chnl1_init(chnl1_if);
  chnl_initiator chnl2_init(chnl2_if);

  chnl_generator chnl0_gen();
  chnl_generator chnl1_gen();
  chnl_generator chnl2_gen();

endmodule

问题:

学习时间:

早:9-11.30
中:15-17

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值