基于 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); } };
|