最近用SystemC做验证做上瘾了,写一个小文吧。 如何在ModelSim下编译和仿真SystemC的设计? 如何在ModelSim下用SystemC的做验证? SystemC作为一种系统级设计与验证语言,非常适合做复杂IC的验证,而不是用于RTL描述。很多人问我如何将SystemC综合和编译为可以下载的CPLD/FPGA的比特文件或者综合为ASIC网表,我的回答是用SystemC做RTL设计还为时过早。可以想象将来可能将SystemC的行为级的描述综合为网表,即所谓高层次综合,这是一个很美好的未来,但未来不是现在。Verilog/SystemVerilog依然是最好的RTL设计语言。未来的RTL设计属于SystemVerilog。关于SystemC和SystemVerilog在设计中的地位问题,我认为在验证方面,SystemC有明显的优势。如果你设计纯粹的ASIC,那么用SystemVerilog可能就足够了。但是在很多场合,软硬件同时存在,SystemC的代码很多部分可以之间用于设计软件,这个是很明显的优势。大家同时也可以看到,现在在ModelSim等仿真软件中,SystemC使用起来跟Verilog/VHDL一样,非常方便。举一个例子,我们假如想做DVB-S2的LDPC,我们一定会先用C++(M atlab也可以)写仿真程序,验证算法的正确性。然后假设我们已经确定了目标ASIC的架构,打算用Verilog做RTL设计。现在既然C++代码的验证部分可以几乎不加改变的用于基于SystemC的验证模块的设计,我们为什么还要费力的用SystemVerilog重新写一遍验证代码呢? 下面步入正题,讲一讲如何在ModelSim下编译和仿真SystemC的设计。我们设计一个一位移位寄存器模块(Verilog代码): 1.shifter.v `timescale 1ns/100ps module shifter(clk,nrst,din,dout); input clk,nrst; input din; output reg dout; always@(posedge clk or negedge nrst) begin:shifter_with_nreset if(~nrst) dout<=1'b0; else dout<=din; end endmodule
顶层设计为验证模块加shifter模块的例化: 2.tb.v `timescale 1ns/100ps module tb; wire clk,nrst,data,data_fd_bk; shifter_test tester(.clk(clk),.nrst(nrst),.data(data),.data_fd_bk(data_fd_bk)); shifter uut(.clk(clk),.nrst(nrst),.din(data),.dout(data_fd_bk)); endmodule 其中shifter_test用SystemC描述。这个例子实际上不能显示SystemC的好处。 下面是SystemC的代码:
3.Shifter_test.h #ifndef __shifter_test_h #define __shifter_test_h
#include <systemc.h> #include <assert.h> SC_MODULE(shifter_test) { public: // Module ports sc_out<bool> clk,nrst; sc_out<bool> data; sc_in<bool> data_fd_bk; bool data_reg; bool err; sc_clock internal_clk; void st_behaviour() { nrst=0; data=0; wait(5); data=1; wait(2); nrst=1; wait(2); while(1) { data=0; wait(2); data=1; wait(3); data=0; wait(4); if(err) printf("Test failed"); else printf("Test passed\n"); } } void gen_clk(){clk=internal_clk.read();} void disp_data(){ printf("nrst=%d,data input=%d,data output=%d\n",nrst.read(),data_reg,data_fd_bk.read()); if((nrst.read()==1) && (data_reg!=data.read())) { err=1; assert(false); } data_reg=data.read(); } SC_CTOR(shifter_test) :clk("clk"),nrst("nrst"),data("data"),data_fd_bk("data_fd_bk"),internal_clk("internal_clk",1000,0.5,SC_NS) { SC_METHOD(gen_clk); sensitive<<internal_clk; dont_initialize(); SC_CTHREAD(st_behaviour, clk.pos()); SC_METHOD(disp_data); sensitive<<clk.neg(); err=0; } };
#endif |