SFLでのSDRAMコントローラ

  • タグ:
  • タグはありません
/*
	SDRAM Controller 2007/2/14

	IS42S16400
		1M Words x 16 bits x 4 Banks (64Mbit)

	clock 50 MHz
		bank<2> adrs<20> data<16>

	QuartusII 7.2 177LC 125DLR
*/

circuit sdram_ctrl
{
	output CSn, RASn, CASn, WEn;
	output LDM, HDM;
	output DEn; // Write data output enable
	output BA<2>, A<12>;
	input Din<16>;
	output Dout<16>;

	instrin write(adrs, wdata);
	input wdata<16>, adrs<22>;
	instrin read(adrs);
	output rdata<16>, ack;

	output err;
	reg_wr err_reg;

	reg_wr BA_reg<2>;
	reg_ws A_reg<12>;
//	reg_ws LDM_reg, HDM_reg;
	reg_ws RASn_reg, CASn_reg, WEn_reg, DEn_reg;

	reg_ws reset;
	reg_wr init_count<16>; // use <14>
	reg_wr adrs_reg<22>, rdata_reg<16>, wdata_reg<16>;

	instrself com_NOP, com_PRE, com_REF, com_MRS, com_ACT, com_WRITE, com_READ;

	stage_name init { task do(); }
	stage_name refresh { task do(); }
	stage_name refresh_cnt { task do(); }
	stage_name swrite { task do(adrs_reg, wdata_reg); }
	stage_name sread { task do(adrs_reg); }

	par{
		if(reset){
			reset := 0b0;
			generate init.do();
		}

		ack = ^(init.do | sread.do | swrite.do);

		CSn = 0b0;
		LDM = 0b0; // LDM_reg;
		HDM = 0b0; // HDM_reg;
		RASn = RASn_reg;
		CASn = CASn_reg;
		WEn = WEn_reg;
		DEn = DEn_reg;
		BA = BA_reg;
		A = A_reg;

		Dout = wdata_reg;

		rdata = rdata_reg;

		init_count++;
	}

	instruct read par{
		generate sread.do(adrs);
	}

	instruct write par{
		generate swrite.do(adrs, wdata);
	}

	instruct com_NOP par{
		RASn_reg := 0b1;
		CASn_reg := 0b1;
		WEn_reg  := 0b1;
	}

	// Trp 20 ns
	instruct com_PRE par{
		RASn_reg := 0b0;
		CASn_reg := 0b1;
		WEn_reg  := 0b0;
	}

	// Trc 70 ns
	instruct com_REF par{
		RASn_reg := 0b0;
		CASn_reg := 0b0;
		WEn_reg  := 0b1;
	}

	// Trc 10 ns
	instruct com_MRS par{
		RASn_reg := 0b0;
		CASn_reg := 0b0;
		WEn_reg  := 0b0;
	}

	// Trcd 20 ns
	instruct com_ACT par{
		RASn_reg := 0b0;
		CASn_reg := 0b1;
		WEn_reg  := 0b1;
	}

	instruct com_WRITE par{
		RASn_reg := 0b1;
		CASn_reg := 0b0;
		WEn_reg  := 0b0;
	}

	instruct com_READ par{
		RASn_reg := 0b1;
		CASn_reg := 0b0;
		WEn_reg  := 0b1;
	}

	stage init {
		state_name st_PON,st_PALL,st_wPALL1,st_wPALL2,st_REF,st_wREF,st_MRS,st_wMRS;
		first_state st_PON;
		state st_PON par{
			com_NOP();
			if(init_count<14>) goto st_PALL;
		}
		state st_PALL par{
			com_PRE();
			A_reg := 0b010000000000; // All banks
			goto st_wPALL1;
		}
		state st_wPALL1 par{
			com_NOP();
			goto st_wPALL2;
		}
		state st_wPALL2 par{
			com_NOP();
			if(/&init_count<5:0>) goto st_REF;
		}
		state st_REF par{
			if(init_count<2:0>==0b000) com_REF();
			else com_NOP();
			if(/&init_count<5:0>) goto st_wREF;
		}
		state st_wREF par{
			goto st_MRS;
		}
		state st_MRS par{
			com_MRS();
			BA_reg := 0b00;
			A_reg := 0b00000 || 0b010 || 0b0000; // CAS 2 Burst 1
			goto st_wMRS;
		}
		state st_wMRS par{
			com_NOP(); // 4回以上
			if(init_count<3>) relay refresh_cnt.do();
		}
	}

	stage swrite {
		state_name st_ACT, st_WRITEA, st_w1;
		first_state st_ACT;
		state st_ACT if(^refresh.do){
			com_ACT();
			BA_reg := adrs_reg<21:20>;
			A_reg := adrs_reg<19:8>;
			DEn_reg := 0b0;
			goto st_WRITEA;
		}
		state st_WRITEA par{
			com_WRITE();
			A_reg := 0b0100 || adrs_reg<7:0>;
			goto st_w1;
		}
		state st_w1 par{
			com_NOP();
			DEn_reg := 0b1;
			goto st_ACT;
			finish;
		}
	}

	stage sread {
		reg_wr ap;
		state_name st_ACT,st_READA,st_w0,st_w1,st_w2;
		first_state st_ACT;
		state st_ACT if(^refresh.do){
			com_ACT();
			BA_reg := adrs_reg<21:20>;
			A_reg := adrs_reg<19:8>;
			goto st_READA;
		}
		state st_READA par{
			com_READ();
			A_reg := 0b0100 || adrs_reg<7:0>;
			goto st_w0;
		}
		state st_w0 par{
			com_NOP();
			ap := ^ap;
			if(ap) goto st_w2; // オートプリチャージ
		}
		state st_w2 par{ // CL 2
			rdata_reg := Din;
			goto st_ACT;
			finish;
		}
	}

	stage refresh_cnt {
		reg_wr refresh_time<7>;
		reg_wr notused;
		state_name st1,st2;
		first_state st1;
		if(notused) finish;
		state st1 if(^refresh.do){
			refresh_time++;
			if(/&refresh_time) goto st2;
		}
		state st2 if(^(sread.do | swrite.do)){
			generate refresh.do();
			goto st1;
		}
	}

// read と refresh が同時に起動しても refresh を優先
	stage refresh {
		reg_wr refresh_A<14>;
		state_name st_ACT, st_PRE, st_wPRE;
		first_state st_ACT;
		state st_ACT par{
			com_ACT();
			BA_reg := refresh_A<1:0>;
			A_reg := refresh_A<13:2>;
			goto st_PRE;
		}
		state st_PRE par{
			com_PRE();
			A_reg := 0b010000000000;
			refresh_A++;
			goto st_wPRE;
		}
		state st_wPRE par{
			com_NOP();
			goto st_ACT;
			finish;
		}
	}

}