基于 SystemC 的 Fir Filter 示例。
有两个模块,fir 为算法实现,tb 验证数据的输入输出。
使用 vld 和 rdy 来控制 fir 和 tb 之间的握手机制。
视频链接:https://www.bilibili.com/video/BV1P54y1z77U?p=2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
   |                  SYSTEM     tb0                          fir0 +-----------+                +-----------+ |           |                |           | |           |    sc_clock    |           | |       clk | <------------> | clk       | |           |                |           | |           |    rst_sig     |           | |       rst | <------------> | rst       | |           |                |           | |           |    inp_sig     |           | |       inp | <------------> | inp       | |           | <rdy      vld> |           | |           |    outp_sig    |           | |      outp | <------------> | outp      | |           | <vld      rdy> |           | |    tb     |                |    fir    | +-----------+                +-----------+
   | 
 
main.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   | #include "fir.h" #include "tb.h" #include <systemc.h>
  int sc_main(int argc, char *argv[]) { 	sc_signal<sc_int<16>> inp_sig; 	sc_signal<bool>		  inp_sig_vld;  	sc_signal<bool>		  inp_sig_rdy;  	sc_signal<sc_int<16>> outp_sig; 	sc_signal<bool>		  outp_sig_vld; 	sc_signal<bool>		  outp_sig_rdy;      	sc_signal<bool>		  rst_sig; 	sc_clock clk_sig("clk_sig", 10, SC_NS);
  	tb tb0("tb0"); 	tb0.clk(clk_sig); 	tb0.rst(rst_sig); 	tb0.inp(inp_sig); 	tb0.inp_vld(inp_sig_vld); 	tb0.inp_rdy(inp_sig_rdy); 	tb0.outp(outp_sig); 	tb0.outp_vld(outp_sig_vld); 	tb0.outp_rdy(outp_sig_rdy);
  	fir fir0("fir0"); 	fir0.clk(clk_sig); 	fir0.rst(rst_sig); 	fir0.inp(inp_sig); 	fir0.inp_vld(inp_sig_vld); 	fir0.inp_rdy(inp_sig_rdy); 	fir0.outp(outp_sig); 	fir0.outp_vld(outp_sig_vld); 	fir0.outp_rdy(outp_sig_rdy);
  	sc_start(); 	getchar(); 	return 0; }
   | 
 
tb.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
   | #pragma once #include <systemc.h>
  using JiliType = int;
 
 
 
 
 
  JiliType genExcitation(int clock) { 	if (clock > 23 && clock < 29) 		return clock; 	else 		return 0; }
  SC_MODULE(tb) { 	sc_in<bool>		   clk; 	sc_out<bool>	   rst; 	sc_out<sc_int<16>> inp;		 	sc_out<bool>	   inp_vld;  	sc_in<bool>		   inp_rdy; 	sc_in<sc_int<16>>  outp; 	sc_in<bool>		   outp_vld; 	sc_out<bool>	   outp_rdy;
  	sc_time start_time[64], end_time[64], 		clock_period; 
  	
 
 
  	void source() 	{ 		 		inp.write(0); 		inp_vld.write(0); 		rst.write(1);  		wait(); 		rst.write(0);  		wait();
  		 		sc_int<16> tmp; 		for (int i = 0; i < 64; i++) 		{ 			 			tmp = genExcitation(i);
  			 			 			inp_vld.write(1); 			inp.write(tmp); 			start_time[i] = sc_time_stamp(); 			 			do 			{ 				wait();  			} while (!inp_rdy.read()); 			inp_vld.write(0); 		}
  		 		wait(10000);  		cout << "run too long, stopped force" << endl; 	}
  	
 
 
  	void sink() 	{ 		 		outp_rdy.write(0); 		 		sc_clock *clk_p = 			DCAST<sc_clock *>(clk.get_interface());  		clock_period = clk_p->period();		 		double total_cycles = 0; 
  		 		sc_int<16> indata; 		for (int i = 0; i < 64; i++) 		{ 			outp_rdy.write(1); 			 			do 			{ 				wait();  			} while (!outp_vld.read()); 			indata = outp.read(); 			end_time[i] = sc_time_stamp(); 			total_cycles += (end_time[i] - start_time[i]) / clock_period; 			outp_rdy.write(0);
  			cout << i << " :\t" << indata.to_int() << endl; 		}
  		 		sc_stop();
  		 		double total_throughput = 			(start_time[63] - start_time[0]) / clock_period; 		cout << "Averag latency = " << (double)(total_cycles / 64) << " cycles." 			<< endl; 		cout << "Averag throughput = " << (double)(total_throughput / 63) 			<< " cycles per input." << endl; 	}
  	SC_CTOR(tb) 	{ 		SC_CTHREAD(source, clk.pos()); 		SC_CTHREAD(sink, clk.pos()); 	} };
   | 
 
fir.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
   | #pragma once #include <systemc.h>
  const sc_uint<8> coef[5] = {18, 77, 107, 77, 18}; 
  SC_MODULE(fir) { 	sc_in<bool>		   clk; 	sc_in<bool>		   rst; 	sc_in<sc_int<16>>  inp; 	sc_in<bool>		   inp_vld; 	sc_out<bool>	   inp_rdy; 	sc_out<sc_int<16>> outp; 	sc_out<bool>	   outp_vld; 	sc_in<bool>		   outp_rdy;
  	void fir_main() 	{ 		 		sc_int<16> taps[5] = {0, 0, 0, 0, 0};
  		 		inp_rdy.write(0); 		outp_vld.write(0); 		outp.write(0); 		wait();
  		while (true) 		{ 			 			inp_rdy.write(1); 			do 			{ 				wait();  			} while (!inp_vld.read()); 			sc_int<16> in_val = inp.read(); 			inp_rdy.write(0);
               			 			for (int i = 4; i > 0; --i) 			{ 				taps[i] = taps[i - 1]; 			} 			taps[0] = in_val;
  			 			sc_int<16> out_val; 			for (int i = 0; i < 5; ++i) 			{ 				out_val += coef[i] * taps[i];  				 					  			}
  			 			outp_vld.write(1); 			outp.write(out_val); 			 			do 			{ 				wait();  			} while (!outp_rdy->read()); 			outp_vld.write(0); 		} 	}
  	SC_CTOR(fir) 	{ 		SC_CTHREAD(fir_main, clk.pos()); 		reset_signal_is(rst, true);  	} };
   |