Synopsys培训 lab3

在这里插入图片描述

route_io.sv

在lab3中的router_io.sv中进行的接口的声明,指明了信号的输入和输出的方向,以及一些延时的时序信息。

interface router_io(input bit clock);
  //声明信号
  logic		reset_n;
  logic [15:0]	din;
  logic [15:0]	frame_n;
  logic [15:0]	valid_n;
  logic [15:0]	dout;
  logic [15:0]	valido_n;
  logic [15:0]	busy_n;
  logic [15:0]	frameo_n;
  //在时钟块中,声明仿真延迟的时序信息,以及信号的方向
  //即是输入还是输出
  clocking cb @(posedge clock);
    default input #1 output #1;
    output reset_n;
    output din;
    output frame_n;
    output valid_n;
    input dout;
    input valido_n;
    input busy_n;
    input frameo_n;
  endclocking

  modport TB(clocking cb, output reset_n);
endinterface

test.sv

代码里有详细的注释

program automatic test(router_io.TB rtr_io);

    int             run_for_n_packets   ;   //测试n个数据包
    bit     [3:0]   sa                  ;   //源地址
    bit     [3:0]   da                  ;   //目标地址
    logic   [7:0]   payload[$]          ;   //预期的数据包数据数组

    //任务1:声明一个队列来存储采样的数据
    logic   [7:0]   pkt2cmp_payload[$]  ;   //实际数据包数据数组

    initial begin
        $vcdpluson;
        //任务2:发送2000个数据包,需要在任务中执行
        run_for_n_packets = 2000;
        reset();                            //全局复位任务
        repeat(run_for_n_packets) begin
            gen();                          //产生数据包
            //任务3:同时执行发送和接收数据包线程
            fork
                send();                     //发送数据包
                recv();                     //接收数据包
            join

            check();                        //检查
        end
    end

//reset的任务
task reset();
    rtr_io.reset_n = 1'b0;
    rtr_io.frame_n <= '1;
    rtr_io.valid_n <= '1;
    ##2 rtr_io.cb.reset_n <= 1'b1;
endtask:reset

//gen的任务
task gen();
    //任务4:随机产生sa and da
    sa = $urandom;
    da = $urandom;
    payload.delete();                       //删除过去的数据
    repeat($urandom_range(4,2))
        payload.push_back($urandom);
endtask:gen

//send任务
task send();
    send_addrs();                           //发送数据
    send_pad();                                
    send_payload();
endtask: gen
//发送地址
task send_addrs;
    rtr_io.cb.frame_n[sa] <= 1'b0;             //一个数据包的开始
    for(int i = 0; i < 4; i++) begin
        rtr_io.cb.din[sa] <= da[i];         //da的每一位
        @(rtr_io.cb);                       //等待时钟的上升沿
    end
endtask
//发送pad
task send_pad();
    rtr_io.cb.frame_n[sa] <= 1'b0;
	rtr_io.cb.din[sa] <= 1'b1;
	rtr_io.cb.valid_n[sa] <= 1'b1;
	repeat(5) @(rtr_io.cb);
endtask

//发送payload
task send_payload();

    foreach(payload[index])
        for(int i=0; i<8; i++) begin
            rtr_io.cb.din[sa] <= payload[index][i]; //发送每一位
            rtr_io.cb.valid_n[sa] <= 1'b0;          //驱动一个有效位
            //下面语句当整个传输完成时,拉高frame_n[sa]
            rtr_io.cb.frame_n[sa] <= ((i == 7) && (index == (payload.size()-1)));
            @(rtr_io.cb);
        end   

endtask

//任务4:声明接收任务
task recv();

    //调用任务get_payload来检索有效负载
    get_payload();

endtask

task get_payload();
    //删除pkt2cmp_payload的内容
    pkt2cmp_payload.delete();
    fork
      begin: wd_timer_fork
      fork: frameo_wd_timer
        @(negedge rtr_io.cb.frameo_n[da]); //一个线程:等待下降沿
        begin                              //另一个线程:检测超时
          repeat(1000) @(rtr_io.cb);
      	$display("\n%m\n[ERROR]%t Frame signal timed out!\n", $realtime);
          $finish;
        end
      join_any: frameo_wd_timer
      disable fork;                         
      end: wd_timer_fork
    join

    //任务继续,采样router的输出
    //直到frame的被检测到,循环结束
    forever begin
        logic [7:0] datam;
        for(int i = 0; i<8; i++) begin
            if(!rtr_io.cb.valido_n[da])         //数据有效
                datum[i++] = rtr_io.cb.dout[da];
            if(rtr_io.cb.frameo_n[da])          //一个字节传输完成
                if(i==8) begin //byte alligned
      	            pkt2cmp_payload.push_back(datum);//加入队列
      	                return;      //done with payload
      	        end
      	else begin
      	  $display("\n%m\n[ERROR]%t Packet payload not byte aligned!\n", $realtime);
      	  $finish;
      	end
        @(rtr_io.cb);  
        end
        pkt2cmp_payload.push_back(datum);
    end
endtask

//compare function 比较payload[$]和pkt2cmp_payload[$]
//如果大小不匹配
//数据不匹配 使用==
  function bit compare(ref string message);

    if(payload.size() != pkt2cmp_payload.size()) begin
      message = "Payload size Mismatch:\n";
      message = {
    
     message, $sformatf("payload.size() = %0d, pkt2cmp_payload.size() = %0d\n", payload.size(), pkt2cmp_payload.size()) };
      return (0);
    end
    if(payload == pkt2cmp_payload) ;
    else begin
      message = "Payload Content Mismatch:\n";
      message = {
    
     message, $sformatf("Packet Sent:   %p\nPkt Received:   %p", payload, pkt2cmp_payload) };
      return (0);
    end
    message = "Successfully Compared";
    return(1);
  endfunction: compare
 task check();
    string message;
    static int pkts_checked = 0;

    if (!compare(message)) begin
      $display("\n%m\n[ERROR]%t Packet #%0d %s\n", $realtime, pkts_checked, message);
      $finish;
    end
    $display("[NOTE]%t Packet #%0d %s", $realtime, pkts_checked++, message);
  endtask: check
endprogram

猜你喜欢

转载自blog.csdn.net/weixin_45614076/article/details/126618801