数字集成电路设计-18-UVM

引言

UVM(Universal Verification Methodology)可以理解为形而上的东西,可以理解为是基于System verilog的一个库,提供一些API调用。

其实没必要把UVM抬的那么高,上升到形而上的层次。因为在实际的IC验证时,对某个复杂DUT的验证时,一般都会拆分成那几个模块。

要对DUT测试,肯定需要先产生测试用例,就是UVM中的sequencer和sequence概念。

产生测试用例之后,肯定需要把测试用例送到DUT端口上,作为激励,就是UVM中的driver的概念。

既然是验证,就是比较DUT是不是对的,既然要比较对与错,就需要DUT的行为模型,就是UVM中的reference model的概念。

既然要对比,可能对比算法比较复杂,一般需要单独出来,就是UVM中scoreboard的概念。

有了DUT的行为模型,要给行为模型激励啊,怎么给呢?直接采集DUT的端口信息就行了,这个工作也独立出来,就是UVM中monitor的概念。

monitor(软件部分)怎么采集DUT(RTL部分)的端口信息呢?用PLI,VPI,DPI,都可以。UVM将这个内容封装了一下,就是uvm_config_db。

这么多拆开独立的部分,他们之间肯定需要通信啊,怎么办呢?用消息队列,有名管道,socket等进行间通信方式都可以,UVM又封装了一下,美其名曰TLM。

从上面可以看出,UVM带给我们的不是形而上的高达上概念(当然,如果你之前在验证时,没有自觉的将不同功能模块分开的话,可能会感觉UVM很高达上,哈哈),而是实实在在的代码,提供了一组API,使我们在做verification时少敲了几行代码。用UVM也有不好的地方,个人感觉运行效率有点低,仿真时间加长。

总之,UVM是无数验证工程师经验的结晶,仿真工具也都支持,所以在做IC验证时尽量用UVM中的API,也可以自己实现TLM,config机制,实现起来也很简单(我实现过)。

之前我们熟悉了一下SVUNIT(http://blog.csdn.net/rill_zhen/article/details/45342999),本小节我们通过一个实验来熟悉一下UVM。

仔细体会本实验中的代码,领会其背后含义之后,UVM就入门了。

1,DUT

要进行验证,必须要有个靶子,就是DUT。本例DUT很简单:“左耳进,右耳出”,吃什么吐什么。

/*
* uvm test example
* Rill 2015-05-02
*/

 module Mdut
 #
 (
 parameter DATA_L = 8
 )
 (
	input clk,
	input rst_n,

	IFrx.S 			rx_if,
	output 			tx_dv,
	output [DATA_L-1:0]	txd
 );

	logic 			tx_dv_r;
	logic [DATA_L-1:0] 	txd_r;

	always_ff @(posedge clk)
		if(~rst_n)
			begin
				tx_dv_r <= 1‘b0;
				txd_r <= DATA_L‘b0;
			end
		else if(rx_if.vld)
			begin
				tx_dv_r <= rx_if.vld;
				txd_r <= rx_if.data;
			end

	assign tx_dv = tx_dv_r;
	assign txd = txd_r;

 endmodule //Mdut
 

interface:

/*
* uvm test example
* Rill 2015-05-02
*/

 interface IFrx
 #(
 parameter DATA_L=8
 )
 ();

 logic vld;
 logic [DATA_L-1:0] data;

 modport M
 (
	output vld,
	output data
);

 modport S
 (
	input vld,
	input data
);
 endinterface:IFrx

2,UVM部分

有了DUT,用UVM那一套东西怎么对DUT进行测试呢?

根据引言中的分析,UVM中的概念不是凭空产生的,一定要搞明白为什么会出现那个概念,是什么需求促使了那个概念的产生。

此外,下面我将直接将代码清单列出,要仔细体会,每一行代码的作用,为什么那么写,换个写法行不行。要做UVM的主人,千万不要被UVM的那些概念牵着鼻子走,否则会很被动。要理解TLM,config机制对RTL design人员可能会有点难度,可以请教公司的软件人员。UVM用多了之后,会发现那些概念都是水到渠成事。

2.1 测试用例,transaction.sv

/*
* uvm test example
* Rill 2015-05-02
*/
 `ifndef MY_TRANSACTION_SV
 `define MY_TRANSACTION_SV

 import uvm_pkg::*;
 `define DATA_MAX 255

 typedef struct packed
 {
	logic vld;
	logic [7:0] data;
 }trans_t;

 class my_transaction extends uvm_sequence_item;

	`uvm_object_utils(my_transaction)
	rand bit vld;
	rand bit [7:0] data;

	constraint c_trans0
	{
		vld dist
		{
			0 :/ 50,
			1 :/ 50
		};

		data dist
		{
			0 				:/ 0,
			[1:100] 		:/ 50,
			[101:`DATA_MAX]	:/ 50
		};
	}

	constraint c_trans1
	{
		data >= 5;
	}

	extern function new(string name = "my_transaction");
	extern function trans_t gen_tr;

 endclass

 function my_transaction::new(string name = "my_transaction");
	super.new();
 endfunction

 function trans_t my_transaction::gen_tr;
	trans_t tr;
	tr.vld = vld;
	tr.data = data;

	return tr;
 endfunction

 `endif //MY_TRANSACTION_SV

2.2 将测试用例送给DUT,driver.sv

/*
* uvm test example
* Rill 2015-05-02
*/

 `ifndef MY_DRIVER_SV
 `define MY_DRIVER_SV
 `include "my_transaction.sv"

 class my_driver extends uvm_driver;
	`uvm_component_utils(my_driver)

	virtual IFrx.M rxif;

	extern function new(string name = "my_driver",uvm_component parent);
	extern virtual function void build_phase(uvm_phase phase);
	extern virtual task main_phase(uvm_phase phase);
	extern task send_pkg(trans_t pkg);
 endclass

 function my_driver::new(string name = "my_driver",uvm_component parent);
	super.new(nam,parent);
 endfunction

 function void my_driver::build_phase(uvm_phase phase);
	super.build_phase(phase);
	uvm_config_db #(virtual IFrx.M)::get(this,"","abcdefg",rxif);
 endfunction

 task my_driver::main_phase(uvm_phase phase);
	int i = 0;
	my_transaction tr;
	trans_t trans;

	phase.raise_objection(this);

	tr = new("tr");

	rxif.vld = 1‘b0;
	rxif.data = 8‘b0;

	while(!Ttb.rst_n)
		@(posedge Ttb.clk);

	repeat(10) @(posedge Ttb.clk);

	for(i=0;i<10;i++)
		begin
			assert(tr.randomize());
			trans = tr.gen_tr();
			send_pkg(trans);

			#0.1
			if(rxif.vld)
				begin
					`uvm_info("my_driver",$psprintf("%t,data[%d]:0x%h is drived",$time,i,rxif.data),UVM_LOW);
				end
		end

	repeat(10) @(posedge Ttb.clk);
	rxif.vld = 1‘b0;
	repeat(10) @(posedge Ttb.clk);

	phase.drop_objection(this);
 endtask

 task my_driver::send_pkg(trans_t pkg);
	@(posedge Ttb.clk);
	rxif.vld <= pkg.vld;
	rxif.data <= pkg.data;
 endtask

 `endif //MY_DRIVER_SV
 

2.3 将DUT的输入信息采集下来,送给DUT的行为模型,monitor_i.sv

/*
* uvm test example
* Rill 2015-05-02
*/

 `ifndef MY_MONITOR_I_SV
 `define MY_MONITOR_I_SV

 class my_monitor_i extends uvm_monitor;
	`uvm_component_utils(my_monitor_i)

	virtual IFrx.S rxif;
	uvm_analysis_port #(trans_t) port_to_rm;//port to reference model

	extern function new(string name = "my_monitor_i",uvm_component parent);
	extern virtual function void build_phase(uvm_phase phase);
	extern task main_phase(uvm_phase phase);
	extern task collect_pkg(ref trans_t pkg);
 endclass

 function my_monitor_i::new(string name = "my_monitor_i",uvm_component parent);
	super.new(name,parent);
 endfunction

 function void my_monitor_i::build_phase(uvm_phase phase);
	super.build_phase(phase);
	uvm_config_db #(virtual IFrx.S)::get(this,"","1234567",rxif);
	port_to_rm = new("port_to_rm",this);
 endfunction

 task my_monitor_i::main_phase(uvm_phase phase);
	trans_t pkg;

	while(1)
		begin
			collect_pkg(pkg);
			if(pkg.vld)
				begin
					port_to_rm.write(pkg);
				end
		end
 endtask

 task my_monitor_i::collect_pkg(ref trans_t pkg);
	@(posedge Ttb.clk);
	#0.1
	if(rxif.vld)
		begin
			pkg.vld = 1;
			pkg.data = rxif.data;
			`uvm_info("my_monitor_i",$psprintf("mon_i::0x%h",pkg.data),UVM_LOW);
		end
 endtask

 `endif //MY_MONITOR_I_SV
 

2.4 将driver和monitor_i封装一下,agent_i.sv

/*
* uvm test example
* Rill 2015-05-02
*/

`ifndef MY_AGENT_I_SV
`define MY_AGENT_I_SV
	`include "driver.sv"
	`include "monitor_i.sv"

	class my_agent_i extends uvm_agent;
		`uvm_component_utils(my_agent_i)

		my_driver drv;
		my_monitor_i mon;
		uvm_analysis_port #(trans_t) port_from_mon;

		extern function new(string name = "my_agent_i",uvm_component parent);
		extern virtual function void build_phase(uvm_phase phase);
		extern virtual function void connect_phase(uvm_phase phase);
	endclass

	function my_agent_i::new(string name = "my_agent_i",uvm_component parent);
		super.new(name,parent);
	endfunction

	function void my_agent_i::build_phase(uvm_phase phase);
		super.build_phase(phase);
		drv = my_driver::type_id::create("drv0",this);
		mon = my_monitor_i::type_id::create("mon_i",this);
	endfunction

	function void my_agent_i::connect_phase(uvm_phase phase);
		super.connect_phase(phase);
		port_from_mon = mon.port_to_rm;
	endfunction
`endif //MY_AGENT_I_SV

2.5 同样的道理,采集DUT的输出信息,并送给scoreboard,monitor_o.sv

/*
* uvm test example
* Rill 2015-05-02
*/

 `ifndef MY_MONITOR_O_SV
 `define MY_MONITOR_O_SV

 class my_monitor_o extends uvm_monitor;
	`uvm_component_utils(my_monitor_o)

	virtual IFrx.M txif;
	uvm_analysis_port #(trans_t) port_to_sb;//port to scoreboard

	extern function new(string name = "my_monitor_o",uvm_component parent);
	extern virtual function void build_phase(uvm_phase phase);
	extern task main_phase(uvm_phase phase);
	extern task collect_pkg(ref trans_t pkg);
 endclass

 function my_monitor_o::new(string name = "my_monitor_o",uvm_component parent);
	super.new(name,parent);
 endfunction

 function void my_monitor_o::build_phase(uvm_phase phase);
	super.build_phase(phase);
	uvm_config_db #(virtual IFrx.M)::get(this,"","7654321",txif);
	port_to_sb = new("port_to_sb",this);
 endfunction

 task my_monitor_o::main_phase(uvm_phase phase);
	trans_t pkg;

	while(1)
		begin
			collect_pkg(pkg);
			if(pkg.vld)
				begin
					port_to_sb.write(pkg);
				end
		end
 endtask

 task my_monitor_o::collect_pkg(ref trans_t pkg);
	@(posedge Ttb.clk);
	#0.1
	if(txif.vld)
		begin
			pkg.vld = 1;
			pkg.data = txif.data;
			`uvm_info("my_monitor_o",$psprintf("mon_o::0x%h",pkg.data),UVM_LOW);
		end

 endtask

 `endif //MY_MONITOR_O_SV

2.6 将monitor_o也封装一下,agent_o.sv

/*
* uvm test example
* Rill 2015-05-02
*/

`ifndef MY_AGENT_O_SV
`define MY_AGENT_O_SV
	`include "driver.sv"
	`include "monitor_o.sv"

	class my_agent_o extends uvm_agent;
		`uvm_component_utils(my_agent_o)

		my_monitor_o mon;
		uvm_analysis_port #(trans_t) port_from_mon;

		extern function new(string name = "my_agent_o",uvm_component parent);
		extern virtual function void build_phase(uvm_phase phase);
		extern virtual function void connect_phase(uvm_phase phase);
	endclass

	function my_agent_o::new(string name = "my_agent_o",uvm_component parent);
		super.new(name,parent);
	endfunction

	function void my_agent_i::build_phase(uvm_phase phase);
		super.build_phase(phase);
		mon = my_monitor_o::type_id::create("mon_o",this);
	endfunction

	function void my_agent_o::connect_phase(uvm_phase phase);
		super.connect_phase(phase);
		port_from_mon = mon.port_to_sb;
	endfunction
`endif //MY_AGENT_O_SV

2,.7 DUT的行为模型,ref_model.sv

/*
* uvm test example
* Rill 2015-05-02
*/

 `ifndef MY_REF_MODEL_SV
 `define MY_REF_MODEL_SV

 class my_ref_model extends uvm_component;
	`uvm_component_utils(my_ref_model)

	uvm_blocking_get_port #(trans_t) port_in; //from monitor_i
	uvm_analysiss_port #(trans_t) port_out; //to monitor_o

	extern function new(string name = "my_ref_model",uvm_component parent);
	extern function void build_phase(uvm_phase phase);
	extern task main_phase(uvm_phase phase);

 endclass

 function my_ref_model::new(string name = "my_ref_model",uvm_component parent);
	super.new(name,parent);
 endfunction

 function void my_ref_model::build_phase(uvm_phase phase);
	super.build_phase(phase);
	port_in = new("port_in",this);
	port_out = new("port_out",this);
 endfunction

 task my_ref_model::main_phase(uvm_phase phase);
	trans_t tr;

	port_in.get(tr);

	`uvm_info("ref_model",$psprintf("rm_from_mon_i:0x%h",tr.data),UVM_LOW);

	port_out.write(tr);
 endtask

 `endif //MY_REF_MODEL_SV
 

2.8 对DUT的输出和参考模型的输出进行对比,scoreboard.sv

/*
* uvm test example
* Rill 2015-05-02
*/

`ifndef MY_SCOREBOARD_SV
`define MY_SCOREBOARD_SV

class my_scoreboard extends uvm_scoreboard;
	`uvm_component_utils(my_scoreboard)

	uvm_blocking_get_port #(trans_t) port_dut;//from dut port
	uvm_blocking_get_port #(trans_t) port_rm;//from reference model port

	extern function new(string name = "my_scoreboard",uvm_component parent);
	extern function void build_phase(uvm_phase phase);
	extern task main_phase(uvm_phase phase);

endclass

function my_scoreboard::new(string name = "my_scoreboard",uvm_component parent);
	super.new(name,parent);
 endfunction

 function void my_scoreboard::build_phase(uvm_phase phase);
	super.build_phase(phase);
	port_dut = new("port_dut",this);
	port_rm = new("port_rm",this);
 endfunction

 task my_ref_model::main_phase(uvm_phase phase);
	trans_t pkg_dut;
	trans_t pkg_rm;

	fork
		while(1)
			begin
				port_rm.get(pkg_rm);
				`uvm_info("sb",%psprintf(sb from rm:0x%h",pkg_rm.data),UVM_LOW);
			end
		//==================//
		while(1)
			begin
				port_dut.get(pkg_dut);
				`uvm_info("sb",%psprintf(sb from dut:0x%h",pkg_dut.data),UVM_LOW);
			end
	join

 endtask

`endif //MY_SCOREBOARD_SV

2.9 将以上所有模块都封装一下,env.sv

/*
* uvm test example
* Rill 2015-05-02
*/

 `ifndef MY_ENV_SV
 `define MY_ENV_SV

`include "agent_i.sv"
`include "agent_o.sv"
`include "ref_model.sv"
`include "scoreboard.sv"

import uvm_pkg::*;

 class my_env extends uvm_env;
	`uvm_component_utils(my_env)

	my_agent_i agent_i;
	my_agent_o agent_o;
	my_ref_model ref_model;
	my_scoreboard scoreboard;

	uvm_tlm_analysis_fifo #(trans_t) agent_i_to_ref_model_fifo;
	uvm_tlm_analysis_fifo #(trans_t) ref_model_to_scoreboard_fifo;
	uvm_tlm_analysis_fifo #(trans_t) agent_o_to_scoreboard_fifo;

	extern function new(string name = "my_env",uvm_component parent);
	extern function void build_phase(uvm_phase phase);
	extern function void connect_phase(uvm_phase phase);
 endclass

 function my_env::new(string name = "my_env",uvm_component parent);
	super.new(name,parent);
 endfunction

 function void my_env::build_phase(uvm_phase phase);
	super.build_phase(phase);
	agent_i = my_agent_i::type_id::create("agent_i0",this);
	agent_o = my_agent_o::type_id::create("agent_o0",this);
	scoreboard = my_scoreboard::type_id::create("scoreboard0",this);
	ref_model = my_ref_model::type_id::create("ref_model",this);

	agent_i.is_active = UVM_ACTIVE;
	agent_o.is_active = UVM_PASSIVE;

	agent_i_to_ref_model_fifo = new("agent_i_to_ref_model_fifo",this);
	ref_model_to_scoreboard_fifo = new("ref_model_to_scoreboard_fifo",this);
	agent_o_to_scoreboard_fifo = new("agent_o_to_scoreboard_fifo",this);
 endfunction

 function void my_env::connect_phase(uvm_phase phase);
	super.connect_phase(phase);

	agent_i.port_from_mon.connect(agent_i_to_ref_model_fifo.analysis_export);
	ref_model.port_in.connect(agent_i_to_ref_model_fifo.blocking_get_export);

	ref_model.port_out.connext(ref_model_to_scoreboard_fifo.analysis_export);
	scoreboard.port_rm.connect(ref_model_to_scoreboard_fifo.blocking_get_export);

	agent_o.port_from_mon.connect(agent_o_to_scoreboard_fifo.analysis_export);
	scoreboard.port_dut.connect(agent_o_to_scoreboard_fifo.blocking_get_export);
 endfunction

 `endif

2.10 当然也少不了顶层tb,tb.sv

/*
* uvm test example
* Rill 2015-05-02
*/

 `include "uvm_macros.svh"
 import uvm_pkg::*;

 module Ttb;

	logic clk;
	logic rst_n;

	logic tx_dv;
	logic [7:0] txd;

	IFrx #(.DATA_L(8)) rxif();
	IFrx #(.DATA_L(8)) txif();

	Mdut dut0
	(
		.clk (clk),
		.rst_n (rst_n),
		.rx_if (rxif.S),
		.tx_dv (txif.M.vld),
		.txd (txif.M.data)
	);

	initial
		begin
			clk = 0;
			rst_n = 0;

			fork
			forver #5 clk = ~clk;
			join_none

			repeat(10) @(posedge clk);
			rst_n = 1‘b1;

			uvm_config_da #(virtual IFrx.M)::set(null,"uvm_test_top.agent_i0.drv0","abcdefg",rxif.M);
			uvm_config_da #(virtual IFrx.S)::set(null,"uvm_test_top.agent_i0.mon_i","1234567",rxif.S);
			uvm_config_da #(virtual IFrx.M)::set(null,"uvm_test_top.agent_o0.mon_o","7654321",txif.M);

			run_test("my_env");
	end
 endmodule

2.11 其它

Makefile:

/*
* uvm test example
* Rill 2015-05-02
*/

UVM_VERBOSITY = UVM_LOW

all:run

 export UVM_HOME=/tools/home/INC13.10.001/tools/uvm/uvm_lib/uvm_sv

 IUS = irun -cdslib ./cds.lib -hdlvar ./hdl.var -access rwc -uvm -uvmhome ${UVM_HOME} -f vflist -l irun.log -input run.tcl +UVM_NO_RELNOTES -timascale 1ns/10ps -quiet

run:
	$(IUS)

clean:
	rm -rf INCA* simv* *.log ucli.key

run.tcl:

database -open waves -into waves.shm -default;
probe -create -shm -all -variable -depth all;
run
exit

cds.lib:

define myuvm_lib /home/openrisc/my_uvm

hdl.var:

 define work myuvm_lib

vflist:

-incdir ./src

./src/env.sv
./src/dut.sv
./src/tb.sv
./src/driver.sv
./src/transaction.sv
./src/interface.sv
./src/agent_i.sv
./sec/agent_o.sv
./src/monitor_i.sv
./src/monitor_o.sv
./src/ref_model.sv
./src/scoreboard.sv

3,验证

一切准备就绪,执行make run,即可看到仿真结果,也可以看到仿真波形(simvision waves.shm/waves.trn &)。

4,小结

本小节,我们熟悉了UVM的基本使用方法,在以后的使用中可能会逐渐有新的疑问,比如,怎么向driver发送不同类型的transaction?由于DUT行为太复杂(乱序执行),reference model难道也要搞成乱序吗?也要做成周期精确的吗?如果不是乱序的,monitor怎么收集DUT的信息呢?既然是乱序的,scoreboard怎么比较呢?有没有必要用sequencer呢?怎么产生覆盖率高的transaction呢?UVM的不同DUT之间怎么复用呢?怎么让不同transaction自动运行呢?等等这些问题都需要实际解决,那时你会发现,UVM做的工作有点少,还可能再需要增强一点。

时间: 2024-11-09 04:57:53

数字集成电路设计-18-UVM的相关文章

数字集成电路设计-12-状态机的四种写法

引言 在实际的数字电路设计中,状态机是最常用的逻辑,而且往往是全部逻辑的核心部分,所以状态机的质量,会在比较大的程度上影响整个电路的质量. 本小节我们通过一个简单的例子(三进制脉动计数器)来说明一下状态机的4中写法. 1,模块功能 由于我们的目的在于说明状态机的写作方式,所以其逻辑越简单有利于理解.就是一个简单的脉动计数器,每个三个使能信号输出一个标示信号. 2,一段式 状态机的写法,一般有四种,即一段式,两段式,三段式,四段式.对于一段式的写法,整个状态机的状态转移.转移条件.对应状态的输出都

数字集成电路设计-16-关于AXI协议

引言 AXI协议有可能是我们平时电路设计时经常遇到的一个协议,也是一个不错的协议,本小节我们就来熟悉一下. 乍一看,AXI协议的信号众多,眼花缭乱,容易发蒙.但其实其基本思想很简单.只要掌握以下几点: 1,valid/ready协议 axi协议是典型的基于valid/ready协议的总线协议.valid/ready协议的优势就是master和slave的相对独立性比较好.对于一次传输,作为master的发起方不用检查salve是否准备好,就可以将传输内容放到总线上:同样对于接收方的slave来说

数字集成电路设计经验技巧分享

废话不多说,直接贴出电路及电路设计经验技巧大合集84个资料的文件列表,太多了,只显示一部分吧,有需要的朋友可以到闯客网技术论坛下载,同时可以加入我们的技术交流裙:613377058,无偿共享,在线解答各种技术问题.资料链接:https://bbs.usoftchina.com/thread-206874-1-1.html 文件列表:BUCKBOOST电路原理分析.docxCAN总线接口电路设计注意事项.docxDC-DC升压电路.docxFPGACPLD数字电路设计经验分享.docxMIC电路工

数字集成电路设计-20-multi-cycle

引言 前面我们介绍了流水线的写法(http://blog.csdn.net/rill_zhen/article/details/45980039),流水线是数字设计中很常用的一种设计方法,可以提高运行频率,提高吞吐量. 如果组合逻辑延迟较大,一个时钟周期完成不了时,除了插入寄存器将组合逻辑拆分成流水线外,还可以采用multi-cycle的方式. multi-cycle的工作机制很简单,从给定输入之后,等待多个周期之后,再去采样输出结果. 本小节我们将通过一个小实验来说明multi-cycle的具

数字集成电路设计-19-pipeline的写法

引言 之前,我们介绍了数字设计中一些基本组合逻辑的写法(http://blog.csdn.net/rill_zhen/article/details/39586191)以及状态机的写法(http://blog.csdn.net/rill_zhen/article/details/39585367),本小节我们通过一个小实验来熟悉一下pipeline的写法. 在多数的资料和教课书中提到pipeline时,大多只是解释概念,很少介绍其具体RTL实现的,给人一种高达上的感觉.有的资料中会提到具体写法,

数字集成电路设计-13-常用模块集锦

引言 C语言,C++语言等软件编程语言吸引我们的一个很重要的原因是他们都能提供非常丰富的函数库供我们使用,大大提高coding的效率. 但是像verilogHDL等HDL语言这方面做的比较弱,尤其是可综合的语法,基本没有通用的模块库供我们使用,所以编码效率会比较低.如果我们把平时经常使用的一些模块积累起来,慢慢的标准化,这样以后我们再设计新的电路时,就会方便很多,今天就是开始. 1,判断两个信号是否相等 function Fcompare; input valid_a,valid_b; inpu

国家明确规划重点软件和集成电路设计领域

关于印发国家规划布局内重点软件和集成电路设计领域的通知 发改高技[2016]1056号 各省.自治区.直辖市及计划单列市发展改革委.工业和信息化主管部门.财政厅(局).国家税务局.地方税务局: 为贯彻落实<国务院关于印发进一步鼓励软件产业和集成电路产业发展若干政策的通知>(国发[2011]4号),按照财政部.国家税务总局.发展改革委.工业和信息化部<关于软件和集成电路产业企业所得税优惠政策有关问题的通知>(财税[2016] 49号)要求,现就国家规划布局内重点软件和集成电路设计领域

集成电路设计流程分工

推荐一下本人的原创博客专栏:SoC嵌入式软件架构设计 谢谢! 正规的集成电路设计公司在进行片上系统(SoC)设计时都有明确的岗位分工,甚至会以部门的形式来区分各部分的职责,而且很多时候集成电路设计公司还会提供整体解决方案,包括芯片.软件和硬件,生产商直接按这个方案买其他的电阻电容等元器件即可生产.测试和销售.整体解决方案分工如下: 1.  市场:负责产品规格调研.产品规划.产品经理负责项目立项. 2.  System design系统设计:制定产品规格,系统设计,模块级的FPGA验证. 3.  

Tanner Tools v16 Win64 1CD集成电路设计环境

Tanner Tools Pro是一套以布局为主的软体(L-Edit, L-Edit/DRC, L-Edit/Extract),配合电路图的绘图输入软体(S-Edit) 与电路层次的模拟软体(T-Spice ),构成了一套IC设计系统. Tanner Tools Pro工具,它可提供完整的集成电路设计环境,帮助初学者进入VLSI设计领域.  Tanner Tools Pro工具非常 适合初学者学习,它从电路图设计.电路分析仿真到电路布局环境一应俱全.本书针对VLSI设计实习课程设计多个实验,读