Hi all,
this is a sample case for "Different Clock domain data transition" in SystemC cycle accurate mode, we use the basic way such as "Ask and wait for response", that we call "Request and Grant", "Request" means asking the server to get the property, "Response" means waiting for the server to get the property. and then we add lock function in our design to avoid the dead lock read/write at same time. but in this case only single transition, you can remodel it to burst mode supported like AHB/APB format.
waveform view @ gtkwave
below is our target design, if you want to run it, you should prepare our testbench in
it.
ififo.h
#include <systemc.h>
#define BUFDEP 6
enum iFIFO_ST {
RD_IDLE =0,
RD_GANT =1,
RD_READ =2,
WT_IDLE =3,
WT_REQ =4,
WT_WRITE=5,
};
SC_MODULE(ififo) {
sc_in<bool> Rst;
sc_in<bool> Read_En;
sc_in<int> Read_Dt;
sc_in<bool> Read_Clk;
sc_in<bool> Read_Req;
sc_out<bool> Read_Gnt;
sc_out<bool> Write_En;
sc_out<int> Write_Dt;
sc_in<bool> Write_Clk;
sc_out<bool> Write_Req;
sc_in<bool> Write_Gnt;
sc_signal<int> iBuff[BUFDEP];
sc_signal<bool> iBuff_Full;
sc_signal<int> iBuff_Inx;
sc_signal<bool> iBuff_Emty;
sc_signal<int> iBuff_RD_TMP;
sc_signal<int> iBuff_WT_TMP;
sc_signal<bool> iBuff_WT_En;
sc_signal<int> Cur_RD_ST;
sc_signal<int> Nxt_RD_ST;
sc_signal<int> Cur_WT_ST;
sc_signal<int> Nxt_WT_ST;
sc_signal<bool> Read_Lock;
sc_signal<bool> Write_Lock;
SC_CTOR(ififo)
{
SC_METHOD(PRO_RD_ST);
dont_initialize();
sensitive << Rst;
sensitive << Read_Clk.pos();
SC_METHOD(PRO_RD_ST_DO);
dont_initialize();
sensitive << Cur_RD_ST;
sensitive << Read_Req;
sensitive << iBuff_Full;
sensitive << Read_En;
sensitive << Write_Lock;
SC_METHOD(PRO_RD_ST_OT);
dont_initialize();
sensitive << Cur_RD_ST;
sensitive << iBuff_Full;
sensitive << Read_En;
SC_METHOD(PRO_iBuff);
dont_initialize();
sensitive << iBuff_Inx;
sensitive << Rst;
SC_METHOD(PRO_RW_TRS);
dont_initialize();
sensitive << Rst;
sensitive << Cur_RD_ST;
sensitive << Read_En;
sensitive << Cur_WT_ST;
sensitive << iBuff_WT_En;
SC_METHOD(PRO_WT_ST);
dont_initialize();
sensitive << Rst;
sensitive << Write_Clk.pos();
SC_METHOD(PRO_WT_ST_DO);
dont_initialize();
sensitive << Cur_WT_ST;
sensitive << iBuff_Emty;
sensitive << Write_Gnt;
sensitive << Read_Lock;
SC_METHOD(PRO_WT_ST_OT);
dont_initialize();
sensitive << Cur_WT_ST;
SC_METHOD(PRO_RW_LOCK);
dont_initialize();
sensitive << Cur_RD_ST;
sensitive << Cur_WT_ST;
VCD_DUMP();
};
void PRO_RD_ST();
void PRO_RD_ST_DO();
void PRO_RD_ST_OT();
void PRO_iBuff();
void PRO_RW_TRS();
void PRO_WT_ST();
void PRO_WT_ST_DO();
void PRO_WT_ST_OT();
void PRO_RW_LOCK();
void VCD_DUMP();
};
ififo.cpp
#include "ififo.h"
//========================================
// Read Part Start
//========================================
void ififo::PRO_RD_ST(){
sc_int<32> Tmp_Cur_ST = Cur_RD_ST.read();
sc_int<32> Tmp_Nxt_ST = Nxt_RD_ST.read();
Tmp_Cur_ST = ( Rst.read() == true )? RD_IDLE : Tmp_Nxt_ST;
Cur_RD_ST.write(Tmp_Cur_ST);
}
void ififo::PRO_RD_ST_DO(){
sc_int<32> Tmp_Cur_ST = Cur_RD_ST.read();
sc_int<32> Tmp_Nxt_ST = Nxt_RD_ST.read();
switch (Tmp_Cur_ST) {
case RD_IDLE : Tmp_Nxt_ST = ( Read_Req.read() == true && Write_Lock.read() == false )? RD_GANT : RD_IDLE; break;
case RD_GANT : Tmp_Nxt_ST = ( iBuff_Full.read() == true )? RD_IDLE : RD_READ; break;
case RD_READ : Tmp_Nxt_ST = ( Read_En.read() == true )? RD_IDLE : RD_READ; break;
// default : Tmp_Nxt_ST = RD_IDLE; break;
}
Nxt_RD_ST.write(Tmp_Nxt_ST);
}
void ififo::PRO_RD_ST_OT(){
sc_int<32> Tmp_Cur_ST = Cur_RD_ST.read();
sc_int<32> Tmp_Nxt_ST = Nxt_RD_ST.read();
sc_int<32> Tmp_iBuff_RD;
switch(Tmp_Cur_ST) {
case RD_IDLE : Read_Gnt.write(false); break;
case RD_GANT : ( iBuff_Full.read()== true )? Read_Gnt.write(false): Read_Gnt.write(true); break;
case RD_READ : Read_Gnt.write(false); break;
}
}
void ififo::PRO_iBuff(){
sc_int<32> Tmp_iBuff_Inx = iBuff_Inx.read();
(Tmp_iBuff_Inx == BUFDEP )? iBuff_Full.write(true) : iBuff_Full.write(false) ;
(Tmp_iBuff_Inx == 0 )? iBuff_Emty.write(true) : iBuff_Emty.write(false) ;
}
//=====================================
//Read Part end
//=====================================
void ififo::PRO_RW_LOCK(){
Read_Lock.write(false);
Write_Lock.write(false);
sc_int<32> Tmp_RD_Cur_ST = Cur_RD_ST.read();
sc_int<32> Tmp_WT_Cur_ST = Cur_WT_ST.read();
if( Cur_WT_ST == WT_REQ || Cur_WT_ST == WT_WRITE ){ Write_Lock.write(true); }
else if( Cur_RD_ST == RD_GANT || Cur_RD_ST == RD_READ ){ Read_Lock.write(true); }
}
void ififo::PRO_RW_TRS(){
sc_int<32> Tmp_iBuff_Inx = iBuff_Inx.read();
sc_int<32> Tmp_iBuff_RD = Read_Dt.read();
sc_int<32> Tmp_iBuff_WT = iBuff_WT_TMP.read();
sc_int<32> Tmp_RD_Cur_ST = Cur_RD_ST.read();
sc_int<32> Tmp_WT_Cur_ST = Cur_WT_ST.read();
sc_int<32> Tmp_iBuff;
int i;
if( Rst.read()==true ){
iBuff_Inx.write(0);
} else {
if( Read_En.read()== true && Tmp_RD_Cur_ST == RD_READ ){
iBuff[Tmp_iBuff_Inx].write(Tmp_iBuff_RD);
Tmp_iBuff_Inx++;
iBuff_Inx.write(Tmp_iBuff_Inx);
}
if( iBuff_WT_En.read()== true && Tmp_WT_Cur_ST == WT_WRITE ){
Tmp_iBuff_WT = iBuff[0].read();
iBuff_WT_TMP.write(Tmp_iBuff_WT);
for(i=0; i<BUFDEP-1; i++ ){
Tmp_iBuff = iBuff[i+1].read();
iBuff[i].write(Tmp_iBuff);
}
Tmp_iBuff_Inx--;
iBuff_Inx.write(Tmp_iBuff_Inx);
}
}
}
//===================================
// Write Part end
//===================================
void ififo::PRO_WT_ST(){
sc_int<32> Tmp_Cur_ST = Cur_WT_ST.read();
sc_int<32> Tmp_Nxt_ST = Nxt_WT_ST.read();
Tmp_Cur_ST = ( Rst.read() == true )? WT_IDLE : Tmp_Nxt_ST;
Cur_WT_ST.write(Tmp_Cur_ST);
}
void ififo::PRO_WT_ST_DO(){
sc_int<32> Tmp_Cur_ST = Cur_WT_ST.read();
sc_int<32> Tmp_Nxt_ST = Nxt_WT_ST.read();
switch (Tmp_Cur_ST) {
case WT_IDLE : Tmp_Nxt_ST = ( iBuff_Emty.read() == true || Read_Lock.read()== true )? WT_IDLE : WT_REQ; break;
case WT_REQ : Tmp_Nxt_ST = ( Write_Gnt.read() == true )? WT_WRITE: WT_REQ; break;
case WT_WRITE: Tmp_Nxt_ST = WT_IDLE; break;
// default : Tmp_Nxt_ST = WT_IDLE; break;
}
Nxt_WT_ST.write(Tmp_Nxt_ST);
}
void ififo::PRO_WT_ST_OT(){
sc_int<32> Tmp_Cur_ST = Cur_WT_ST.read();
sc_int<32> Tmp_Nxt_ST = Nxt_WT_ST.read();
sc_int<32> Tmp_iBuff_WT = iBuff_WT_TMP.read();
switch (Tmp_Cur_ST) {
case WT_IDLE : Write_En.write(false); iBuff_WT_En.write(false); Write_Dt.write(0); Write_Req.write(false); break;
case WT_REQ : Write_En.write(false); iBuff_WT_En.write(false); Write_Dt.write(0); Write_Req.write(true); break;
case WT_WRITE: Write_En.write(true); iBuff_WT_En.write(true); Write_Dt.write(Tmp_iBuff_WT); Write_Req.write(false); break;
}
}
void ififo::VCD_DUMP(){
sc_trace_file *fp = sc_create_vcd_trace_file("ififo_file");
((vcd_trace_file*)fp)->sc_set_vcd_time_unit(-9);
sc_trace(fp, Rst,"Rst");
sc_trace(fp, Read_En,"Read_En");
sc_trace(fp, Read_Dt,"Read_Dt");
sc_trace(fp, Read_Clk,"Read_Clk");
sc_trace(fp, Read_Req,"Read_Req");
sc_trace(fp, Read_Gnt,"Read_Gnt");
sc_trace(fp, iBuff_Full,"iBuff_Full");
sc_trace(fp, iBuff_Inx,"iBuff_Inx");
sc_trace(fp, iBuff_Emty,"iBuff_Emty");
sc_trace(fp, Cur_RD_ST,"Cur_RD_ST");
sc_trace(fp, Nxt_RD_ST,"Nxt_RD_ST");
sc_trace(fp, iBuff_RD_TMP,"iBuff_RD_TMP");
sc_trace(fp, Write_En,"Write_En");
sc_trace(fp, Write_Dt,"Write_Dt");
sc_trace(fp, Write_Clk,"Write_Clk");
sc_trace(fp, Write_Req,"Write_Req");
sc_trace(fp, Write_Gnt,"Write_Gnt");
sc_trace(fp, iBuff_Emty,"iBuff_Emty");
sc_trace(fp, iBuff_WT_En,"iBuff_WT_En");
sc_trace(fp, iBuff_WT_TMP,"iBuff_WT_TMP");
sc_trace(fp, Cur_WT_ST,"Cur_WT_ST");
sc_trace(fp, Nxt_WT_ST,"Nxt_WT_ST");
sc_trace(fp, Read_Lock,"Read_Lock");
sc_trace(fp, Write_Lock,"Write_Lock");
sc_trace(fp, iBuff[0],"iBuff_0");
sc_trace(fp, iBuff[1],"iBuff_1");
sc_trace(fp, iBuff[2],"iBuff_2");
}
沒有留言:
張貼留言