MCDF实验0:权力的游戏(从verilog到SV的入门lab0)

前言:从MCDF实验来更全面的了解IC验证,将从权力的游戏、列王的纷争、冰雨的风暴、群鸦的盛宴、魔龙的狂舞和凛冬的寒风这六个章节,一步一步讲解实验。

种一棵树最好的时间是十年前,其次是现在。不是吗?

简述MCDF

MC代表多通道,有很多通道让数据传输进来。从Slave输送进来数据,数据存储在fifo,3个fifo再把数据送到Arbiter,Arbiter每次只能从一个fifo接收数据(仲裁)。Arbiter把选择的数据输送到Formater。Formater把多个数据整合在一起。Register是一个功能模块,可以控制哪些模块工作不工作,控制哪个fifo输送数据。

  • 在第0次实验,将mcdf的功能做了简化。简化后的功能已经用verilog完成设计,我们需要完成的是tb部分的工作。

实验0 lab.0

简化后的结构图:
在这里插入图片描述

  • 从框图来看,我们需要给slave传送一些数据,看arbiter能不能选择数据,并输出。
  • 同时输入给slave的数据需要满足时序的要求。
  • 所以只需要在tb中完成时钟的编写、dut的例化,给slave发送符合时序的数据这几个部分。

有没有很简单呢?
选择发送数据的方式是定义task chnl_write,来发送固定的数据。当然还有别的办法,源代码如下:

`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( 			//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)
	);

//clk每5个时间单位翻转一次
	initial begin 
	  clk <= 0;//clk初始值
	  forever begin
 	   #5 clk <= !clk;
	  end
	end

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

// 测试数据
	initial begin  //initial按顺序执行
	  @(posedge rstn); //当复位后开始运行
	  repeat(5) @(posedge clk);
  // 给channel 发送数据,任务channel在下面做了定义
 	chnl_write(0, 'h00C0_0000);
 	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

// channel write task
	task chnl_write(input reg[1:0] id, input reg[31:0] data); //发送数据的时序写在了channel里,具体时序参考说明文档。
  	case(id)
    	0: begin
      		@(posedge clk);
      		ch0_valid <= 1; //当时钟上升沿来临,将valid置为高,写入数据
      		ch0_data <= data;
      		@(posedge clk);
      		ch0_valid <= 0;//数据传输完后置为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

实验0完成了简单的测试数据,时钟,复位和模块的例化,后边的实验大致也是这几个部分,但是使用了更加快捷有效的方式。

  • 12
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值