data/full_repos/permissive/422882113/rtl/sdram.sv
1: b'%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:54: Define or directive not defined: \'`SDRAM_ROWBITS\'\n output reg [`SDRAM_ROWBITS-1:0] SDRAM_A,     \n             ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:105: Define or directive not defined: \'`SDRAM_tRC\'\n                                                             : ... Suggested alternative: \'`SDRAM_CL\'\nlocalparam BANK_DELAY = ((`SDRAM_tRC+(SDRAM_tCK-1))/SDRAM_tCK)-2;  \n                          ^~~~~~~~~~\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:106: Define or directive not defined: \'`SDRAM_tRP\'\n                                                             : ... Suggested alternative: \'`SDRAM_CL\'\nlocalparam BANK_WRITE_DELAY = ((`SDRAM_tRP+(SDRAM_tCK-1))/SDRAM_tCK)+`SDRAM_tWR;  \n                                ^~~~~~~~~~\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:106: Define or directive not defined: \'`SDRAM_tWR\'\n                                                             : ... Suggested alternative: \'`SDRAM_CL\'\nlocalparam BANK_WRITE_DELAY = ((`SDRAM_tRP+(SDRAM_tCK-1))/SDRAM_tCK)+`SDRAM_tWR;  \n                                                                     ^~~~~~~~~~\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:106: syntax error, unexpected \';\', expecting TYPE-IDENTIFIER\nlocalparam BANK_WRITE_DELAY = ((`SDRAM_tRP+(SDRAM_tCK-1))/SDRAM_tCK)+`SDRAM_tWR;  \n                                                                               ^\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:107: Define or directive not defined: \'`SDRAM_tRC\'\n                                                             : ... Suggested alternative: \'`SDRAM_CL\'\nlocalparam REFRESH_DELAY = ((`SDRAM_tRC+(SDRAM_tCK-1))/SDRAM_tCK)-1;  \n                             ^~~~~~~~~~\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:109: Define or directive not defined: \'`SDRAM_tCKminCL2\'\ninitial assert(2!=2 || SDRAM_tCK>=`SDRAM_tCKminCL2)\n                                  ^~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:109: syntax error, unexpected \')\', expecting TYPE-IDENTIFIER\ninitial assert(2!=2 || SDRAM_tCK>=`SDRAM_tCKminCL2)\n                                                  ^\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:110: Define or directive not defined: \'`SDRAM_tCKminCL2\'\n else $error("CL2 not allowed at %d MHz (max speed is %d)",1000000/SDRAM_tCK,1000000/`SDRAM_tCKminCL2);\n                                                                                     ^~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:303: Define or directive not defined: \'`SDRAM_COLBITS\'\n                                                             : ... Suggested alternative: \'`SDRAM_CL\'\nlocalparam bank0_rowbits=(22-`SDRAM_COLBITS);  \n                             ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:303: syntax error, unexpected \')\', expecting TYPE-IDENTIFIER\nlocalparam bank0_rowbits=(22-`SDRAM_COLBITS);  \n                                           ^\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:304: Define or directive not defined: \'`SDRAM_COLBITS\'\n                                                             : ... Suggested alternative: \'`SDRAM_CL\'\nlocalparam bank1_rowbits=(16-`SDRAM_COLBITS);\n                             ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:304: syntax error, unexpected \')\', expecting TYPE-IDENTIFIER\nlocalparam bank1_rowbits=(16-`SDRAM_COLBITS);\n                                           ^\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:305: Define or directive not defined: \'`SDRAM_COLBITS\'\n                                                             : ... Suggested alternative: \'`SDRAM_CL\'\nlocalparam bank2_rowbits=(15-`SDRAM_COLBITS);\n                             ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:305: syntax error, unexpected \')\', expecting TYPE-IDENTIFIER\nlocalparam bank2_rowbits=(15-`SDRAM_COLBITS);\n                                           ^\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:306: Define or directive not defined: \'`SDRAM_COLBITS\'\n                                                             : ... Suggested alternative: \'`SDRAM_CL\'\nlocalparam bank3_rowbits=(15-`SDRAM_COLBITS);\n                             ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:306: syntax error, unexpected \')\', expecting TYPE-IDENTIFIER\nlocalparam bank3_rowbits=(15-`SDRAM_COLBITS);\n                                           ^\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:417: Define or directive not defined: \'`SDRAM_COLBITS\'\n                                                             : ... Suggested alternative: \'`SDRAM_CL\'\n  bankaddr[0][`SDRAM_COLBITS:1]<=rom_addr[`SDRAM_COLBITS:1];  \n              ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:417: syntax error, unexpected \':\', expecting TYPE-IDENTIFIER\n  bankaddr[0][`SDRAM_COLBITS:1]<=rom_addr[`SDRAM_COLBITS:1];  \n                            ^\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:417: Define or directive not defined: \'`SDRAM_COLBITS\'\n                                                             : ... Suggested alternative: \'`SDRAM_CL\'\n  bankaddr[0][`SDRAM_COLBITS:1]<=rom_addr[`SDRAM_COLBITS:1];  \n                                          ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:418: Define or directive not defined: \'`SDRAM_COLBITS\'\n                                                             : ... Suggested alternative: \'`SDRAM_CL\'\n  bankaddr[0][23:`SDRAM_COLBITS+1]<={1\'b0,refresh_addr_0}; \n                 ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:443: Define or directive not defined: \'`SDRAM_COLBITS\'\n                                                             : ... Suggested alternative: \'`SDRAM_CL\'\n  bankaddr[1][`SDRAM_COLBITS:1]<=wram_addr[`SDRAM_COLBITS:1];  \n              ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:443: syntax error, unexpected \':\', expecting TYPE-IDENTIFIER\n  bankaddr[1][`SDRAM_COLBITS:1]<=wram_addr[`SDRAM_COLBITS:1];  \n                            ^\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:443: Define or directive not defined: \'`SDRAM_COLBITS\'\n                                                             : ... Suggested alternative: \'`SDRAM_CL\'\n  bankaddr[1][`SDRAM_COLBITS:1]<=wram_addr[`SDRAM_COLBITS:1];  \n                                           ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:444: Define or directive not defined: \'`SDRAM_COLBITS\'\n                                                             : ... Suggested alternative: \'`SDRAM_CL\'\n  bankaddr[1][23:`SDRAM_COLBITS+1]<={7\'b0000001,refresh_addr_1};\n                 ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:470: Define or directive not defined: \'`SDRAM_COLBITS\'\n                                                             : ... Suggested alternative: \'`SDRAM_CL\'\n   bankaddr[2][`SDRAM_COLBITS:1]<=vram0_addr[`SDRAM_COLBITS:1];  \n               ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:470: syntax error, unexpected \':\', expecting TYPE-IDENTIFIER\n   bankaddr[2][`SDRAM_COLBITS:1]<=vram0_addr[`SDRAM_COLBITS:1];  \n                             ^\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:470: Define or directive not defined: \'`SDRAM_COLBITS\'\n                                                             : ... Suggested alternative: \'`SDRAM_CL\'\n   bankaddr[2][`SDRAM_COLBITS:1]<=vram0_addr[`SDRAM_COLBITS:1];  \n                                             ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:471: Define or directive not defined: \'`SDRAM_COLBITS\'\n                                                             : ... Suggested alternative: \'`SDRAM_CL\'\n   bankaddr[2][23:`SDRAM_COLBITS+1]<={8\'h00,refresh_addr_2};\n                  ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:496: Define or directive not defined: \'`SDRAM_COLBITS\'\n                                                             : ... Suggested alternative: \'`SDRAM_CL\'\n   bankaddr[3][`SDRAM_COLBITS:1]<=vram1_addr[`SDRAM_COLBITS:1];  \n               ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:496: syntax error, unexpected \':\', expecting TYPE-IDENTIFIER\n   bankaddr[3][`SDRAM_COLBITS:1]<=vram1_addr[`SDRAM_COLBITS:1];  \n                             ^\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:496: Define or directive not defined: \'`SDRAM_COLBITS\'\n                                                             : ... Suggested alternative: \'`SDRAM_CL\'\n   bankaddr[3][`SDRAM_COLBITS:1]<=vram1_addr[`SDRAM_COLBITS:1];  \n                                             ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:497: Define or directive not defined: \'`SDRAM_COLBITS\'\n                                                             : ... Suggested alternative: \'`SDRAM_CL\'\n   bankaddr[3][23:`SDRAM_COLBITS+1]<={8\'h00,refresh_addr_3};\n                  ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:538: Define or directive not defined: \'`SDRAM_COLBITS\'\n                                                             : ... Suggested alternative: \'`SDRAM_CL\'\nreg [`SDRAM_COLBITS-1:0] ras_casaddr;\n     ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:554: Define or directive not defined: \'`SDRAM_ROWBITS\'\nreg [`SDRAM_ROWBITS-1:0] cas_addr;\n     ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:687: Define or directive not defined: \'`SDRAM_COLBITS\'\n                                                             : ... Suggested alternative: \'`SDRAM_CL\'\n      ras_casaddr<=bankaddr[2][`SDRAM_COLBITS:1];\n                               ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:687: syntax error, unexpected \':\', expecting TYPE-IDENTIFIER\n      ras_casaddr<=bankaddr[2][`SDRAM_COLBITS:1];\n                                             ^\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:695: Define or directive not defined: \'`SDRAM_ROWBITS\'\n      SDRAM_A <= bankaddr[2][`SDRAM_ROWBITS+`SDRAM_COLBITS:`SDRAM_COLBITS+1];\n                             ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:695: Define or directive not defined: \'`SDRAM_COLBITS\'\n                                                             : ... Suggested alternative: \'`SDRAM_CL\'\n      SDRAM_A <= bankaddr[2][`SDRAM_ROWBITS+`SDRAM_COLBITS:`SDRAM_COLBITS+1];\n                                            ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:695: syntax error, unexpected \':\', expecting TYPE-IDENTIFIER\n      SDRAM_A <= bankaddr[2][`SDRAM_ROWBITS+`SDRAM_COLBITS:`SDRAM_COLBITS+1];\n                                                          ^\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:695: Define or directive not defined: \'`SDRAM_COLBITS\'\n                                                             : ... Suggested alternative: \'`SDRAM_CL\'\n      SDRAM_A <= bankaddr[2][`SDRAM_ROWBITS+`SDRAM_COLBITS:`SDRAM_COLBITS+1];\n                                                           ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:702: Define or directive not defined: \'`SDRAM_COLBITS\'\n                                                             : ... Suggested alternative: \'`SDRAM_CL\'\n      ras_casaddr<=bankaddr[3][`SDRAM_COLBITS:1];\n                               ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:702: syntax error, unexpected \':\', expecting TYPE-IDENTIFIER\n      ras_casaddr<=bankaddr[3][`SDRAM_COLBITS:1];\n                                             ^\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:710: Define or directive not defined: \'`SDRAM_ROWBITS\'\n      SDRAM_A <= bankaddr[3][`SDRAM_ROWBITS+`SDRAM_COLBITS:`SDRAM_COLBITS+1];\n                             ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:710: Define or directive not defined: \'`SDRAM_COLBITS\'\n                                                             : ... Suggested alternative: \'`SDRAM_CL\'\n      SDRAM_A <= bankaddr[3][`SDRAM_ROWBITS+`SDRAM_COLBITS:`SDRAM_COLBITS+1];\n                                            ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:710: syntax error, unexpected \':\', expecting TYPE-IDENTIFIER\n      SDRAM_A <= bankaddr[3][`SDRAM_ROWBITS+`SDRAM_COLBITS:`SDRAM_COLBITS+1];\n                                                          ^\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:710: Define or directive not defined: \'`SDRAM_COLBITS\'\n                                                             : ... Suggested alternative: \'`SDRAM_CL\'\n      SDRAM_A <= bankaddr[3][`SDRAM_ROWBITS+`SDRAM_COLBITS:`SDRAM_COLBITS+1];\n                                                           ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:717: Define or directive not defined: \'`SDRAM_COLBITS\'\n                                                             : ... Suggested alternative: \'`SDRAM_CL\'\n      ras_casaddr<=bankaddr[0][`SDRAM_COLBITS:1];\n                               ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:717: syntax error, unexpected \':\', expecting TYPE-IDENTIFIER\n      ras_casaddr<=bankaddr[0][`SDRAM_COLBITS:1];\n                                             ^\n%Error: data/full_repos/permissive/422882113/rtl/sdram.sv:725: Define or directive not defined: \'`SDRAM_ROWBITS\'\n      SDRAM_A <= bankaddr[0][`SDRAM_ROWBITS+`SDRAM_COLBITS:`SDRAM_COLBITS+1];\n                             ^~~~~~~~~~~~~~\n%Error: Exiting due to too many errors encountered; --error-limit=50\n'
module sdram #(parameter SDRAM_tCK=7800 )
(

	inout  [15:0] SDRAM_DQ,
	output reg [`SDRAM_ROWBITS-1:0] SDRAM_A,
	output reg        SDRAM_DQML,
	output reg        SDRAM_DQMH,
	output reg [1:0]  SDRAM_BA,
	output            SDRAM_nCS,
	output            SDRAM_nWE,
	output            SDRAM_nRAS,
	output            SDRAM_nCAS,


	input             init_n,
	input             clk,
	input             clkref,
	input             sync_en,

	input      [15:0] rom_din,
	output reg [15:0] rom_dout,
	input      [21:1] rom_addr,
	input             rom_req,
	output reg        rom_req_ack,
	input             rom_we,
	
	input      [21:0] wram_addr,
	input       [7:0] wram_din,
	output reg [15:0] wram_dout,
	input             wram_req,
	output reg        wram_req_ack,
	input             wram_we,

	input             vram0_req,
	output reg        vram0_ack,
	input      [15:1] vram0_addr,
	input      [15:0] vram0_din,
	output reg [15:0] vram0_dout,
	input             vram0_we,

	input             vram1_req,
	output reg        vram1_ack,
	input      [15:1] vram1_addr,
	input      [15:0] vram1_din,
	output reg [15:0] vram1_dout,
	input             vram1_we,

	input      [16:0] aram_addr,
	input       [7:0] aram_din,
	output reg [15:0] aram_dout,
	input             aram_req,
	output reg        aram_req_ack,
	input             aram_we
);

localparam BANK_DELAY = ((`SDRAM_tRC+(SDRAM_tCK-1))/SDRAM_tCK)-2;
localparam BANK_WRITE_DELAY = ((`SDRAM_tRP+(SDRAM_tCK-1))/SDRAM_tCK)+`SDRAM_tWR;
localparam REFRESH_DELAY = ((`SDRAM_tRC+(SDRAM_tCK-1))/SDRAM_tCK)-1;

initial assert(`SDRAM_CL!=2 || SDRAM_tCK>=`SDRAM_tCKminCL2)
	else $error("CL2 not allowed at %d MHz (max speed is %d)",1000000/SDRAM_tCK,1000000/`SDRAM_tCKminCL2);

`ifdef SDRAM_DQM_SHARED
initial assert(`SDRAM_CL==2)
	else $error("The SDRAM controller can't operate in CL3 mode when DQMs are shared.");
`endif
	


localparam BURST_LENGTH   = 3'b000;
localparam ACCESS_TYPE    = 1'b0;
localparam CAS_LATENCY = 3'd`SDRAM_CL;
localparam OP_MODE        = 2'b00;
localparam NO_WRITE_BURST = 1'b1;

localparam MODE = { 3'b000, NO_WRITE_BURST, OP_MODE, CAS_LATENCY, ACCESS_TYPE, BURST_LENGTH}; 





localparam CMD_INHIBIT         = 4'b1111;
localparam CMD_NOP             = 4'b0111;
localparam CMD_ACTIVE          = 4'b0011;
localparam CMD_READ            = 4'b0101;
localparam CMD_WRITE           = 4'b0100;
localparam CMD_BURST_TERMINATE = 4'b0110;
localparam CMD_PRECHARGE       = 4'b0010;
localparam CMD_AUTO_REFRESH    = 4'b0001;
localparam CMD_LOAD_MODE       = 4'b0000;

reg  [3:0] sd_cmd;
reg  [1:0] sd_dqm;
reg [15:0] sd_din;


assign SDRAM_nCS  = sd_cmd[3];
assign SDRAM_nRAS = sd_cmd[2];
assign SDRAM_nCAS = sd_cmd[1];
assign SDRAM_nWE  = sd_cmd[0];
assign SDRAM_DQMH = sd_dqm[1];
assign SDRAM_DQML = sd_dqm[0];

























































































reg evencycle;
reg clkref_d;
reg [2:0] refreshwindow;

always@(posedge clk) begin
	evencycle<=!evencycle;

	clkref_d<=clkref;
	if(clkref_d && !clkref) begin
			refreshwindow<=3'b001;
			evencycle<=1'b1;
	end
	if(|refreshwindow)
		refreshwindow<=refreshwindow-1'b1;
end

wire allowrefresh_vram = |refreshwindow;





reg [3:0] romsync_ctr;
reg rom_req_d;
reg allowrefresh_rom;

reg [3:0] aramsync_ctr;
reg aram_req_d;
reg allowrefresh_aram;

always @(posedge clk or negedge init_n) begin
	if(!init_n) begin
		allowrefresh_rom<=1'b0;
		allowrefresh_aram<=1'b0;
	end else begin
		rom_req_d<=rom_req;
		if(|romsync_ctr)
			romsync_ctr<=romsync_ctr-1'b1;
		else
			allowrefresh_rom<=1'b0;

		if(rom_req_d!=rom_req) begin
			allowrefresh_rom<=1'b1;
			romsync_ctr<=4'hf;
		end

		aram_req_d<=aram_req;
		if(|aramsync_ctr)
			aramsync_ctr<=aramsync_ctr-1'b1;
		else
			allowrefresh_aram<=1'b0;

		if(aram_req_d!=aram_req) begin
			allowrefresh_aram<=1'b1;
			aramsync_ctr<=4'hf;
		end
	end
end

wire need_refresh[4];
wire force_refresh[4];

localparam bank0_rowbits=(22-`SDRAM_COLBITS);
localparam bank1_rowbits=(16-`SDRAM_COLBITS);
localparam bank2_rowbits=(15-`SDRAM_COLBITS);
localparam bank3_rowbits=(15-`SDRAM_COLBITS);

reg [bank0_rowbits-1:0] refresh_addr_0;
reg [bank1_rowbits-1:0] refresh_addr_1;
reg [bank2_rowbits-1:0] refresh_addr_2;
reg [bank3_rowbits-1:0] refresh_addr_3;

refresh_schedule #(.tCK(SDRAM_tCK),.rowbits(bank0_rowbits)) refresh_bank0
(
	.clk(clk),
	.reset_n(init_n),
	.refreshing(cas2_port==PORT_REFRESH && cas_ba==2'b00 ? 1'b1 : 1'b0),
	.allow(allowrefresh_rom),
	.refresh_req(need_refresh[0]),
	.refresh_force(force_refresh[0]),
	.addr(refresh_addr_0)
);

refresh_schedule #(.tCK(SDRAM_tCK),.rowbits(bank1_rowbits)) refresh_bank1
(
	.clk(clk),
	.reset_n(init_n),
	.refreshing(cas2_port==PORT_REFRESH && cas_ba==2'b01 ? 1'b1 : 1'b0),
	.allow(allowrefresh_aram),
	.refresh_req(need_refresh[1]),
	.refresh_force(force_refresh[1]),
	.addr(refresh_addr_1)
);

refresh_schedule #(.tCK(SDRAM_tCK),.rowbits(bank2_rowbits)) refresh_bank2
(
	.clk(clk),
	.reset_n(init_n),
	.refreshing(cas2_port==PORT_REFRESH && cas_ba==2'b10 ? 1'b1 : 1'b0),
	.allow(allowrefresh_vram),
	.refresh_req(need_refresh[2]),
	.refresh_force(force_refresh[2]),
	.addr(refresh_addr_2)
);

refresh_schedule #(.tCK(SDRAM_tCK),.rowbits(bank3_rowbits)) refresh_bank3
(
	.clk(clk),
	.reset_n(init_n),
	.refreshing(cas2_port==PORT_REFRESH && cas_ba==2'b11 ? 1'b1 : 1'b0),
	.allow(allowrefresh_vram),
	.refresh_req(need_refresh[3]),
	.refresh_force(force_refresh[3]),
	.addr(refresh_addr_3)
);





reg [3:0] bankactive;
reg [4:0] bankbusy [4];
wire [3:0] bankready;

assign bankready[0]=bankbusy[0][4];
assign bankready[1]=bankbusy[1][4];
assign bankready[2]=bankbusy[2][4];
assign bankready[3]=bankbusy[3][4];




localparam PORT_NONE   = 4'd0;
localparam PORT_ROM    = 4'd1;
localparam PORT_WRAM   = 4'd2;
localparam PORT_VRAM0  = 4'd3;
localparam PORT_VRAM1  = 4'd4;
localparam PORT_ARAM   = 4'd5;
localparam PORT_REFRESH = 4'd6;

reg [3:0] bankreq;
reg [3:0] bankstate;
reg [3:0] bankwr;
reg [15:0] bankwrdata[4];
reg [3:0] bankport[4];
reg [23:1] bankaddr[4];
reg [1:0] bankdqm[4];



always @(posedge clk or negedge init_n) begin
	if (!init_n) begin
		bankreq[0]<=1'b0;
		bankstate[0]<=1'b0;
	end else if((!force_refresh[0]) && rom_req ^ port_state[PORT_ROM]) begin
		bankreq[0]<=1'b1;
		bankstate[0]<=rom_req;
		bankport[0]<=PORT_ROM;
		bankdqm[0]<={!rom_we,!rom_we};
		bankwrdata[0]<=rom_din;
		bankaddr[0]<={2'b00,rom_addr[21:1]};
		bankwr[0]<=rom_we;
	end else if ((!force_refresh[0]) && wram_req ^ port_state[PORT_WRAM]) begin
		bankreq[0]<=1'b1;
		bankstate[0]<=wram_req;
		bankport[0]<=PORT_WRAM;
		bankdqm[0]<=wram_we ? { ~wram_addr[0], wram_addr[0] } : 2'b11;
		bankaddr[0]<={2'b01,wram_addr[21:1]};
		bankwr[0]<=wram_we;
		bankwrdata[0]<={wram_din,wram_din};
	end else begin

		bankreq[0]<=need_refresh[0];
		bankwr[0]<=1'b0;
		bankstate[0]<=1'b0;
		bankdqm[0]<=2'b11;
		bankaddr[0][`SDRAM_COLBITS:1]<=rom_addr[`SDRAM_COLBITS:1];
		bankaddr[0][23:`SDRAM_COLBITS+1]<={1'b0,refresh_addr_0};
		bankwr[0]<=1'b0;
		bankwrdata[0]<={wram_din,wram_din};
		bankport[0]<=PORT_REFRESH;
	end
end



always @(posedge clk or negedge init_n) begin
	if (!init_n) begin
		bankreq[1]<=1'b0;
		bankstate[1]<=1'b0;
	end else if ((!force_refresh[1]) && aram_req ^ port_state[PORT_ARAM]) begin
		bankdqm[1]<=aram_we ? { ~aram_addr[0], aram_addr[0] } : 2'b11;
		bankwrdata[1]<={aram_din,aram_din};
		bankreq[1]<=1'b1;
		bankstate[1]<=aram_req;
		bankport[1]<=PORT_ARAM;
		bankaddr[1]<={7'b0000001,aram_addr[16:1]};
		bankwr[1]<=aram_we;
	end else begin

		bankreq[1]<=need_refresh[1];
		bankstate[1]<=1'b0;
		bankaddr[1][`SDRAM_COLBITS:1]<=wram_addr[`SDRAM_COLBITS:1];
		bankaddr[1][23:`SDRAM_COLBITS+1]<={7'b0000001,refresh_addr_1};
		bankdqm[1]<=aram_we ? { ~aram_addr[0], aram_addr[0] } : 2'b11;
		bankwrdata[1]<={aram_din,aram_din};
		bankwr[1]<=1'b0;
		bankport[1]<=PORT_REFRESH;
	end
end


always @(posedge clk or negedge init_n) begin
	if (!init_n) begin
		bankreq[2]<=1'b0;
		bankstate[2]<=1'b0;
	end else begin
		bankwrdata[2]<=vram0_din;
		bankdqm[2]<={!vram0_we,!vram0_we};
		if((!force_refresh[2]) && vram0_req ^ port_state[PORT_VRAM0]) begin
			bankreq[2]<=vram0_req ^ port_state[PORT_VRAM0];
			bankstate[2]<=vram0_req;
			bankport[2]<=PORT_VRAM0;
			bankaddr[2]<={8'h00,vram0_addr};
			bankwr[2]<=vram0_we;
		end else begin

			bankreq[2]<=need_refresh[2];
			bankstate[2]<=1'b0;
			bankaddr[2][`SDRAM_COLBITS:1]<=vram0_addr[`SDRAM_COLBITS:1];
			bankaddr[2][23:`SDRAM_COLBITS+1]<={8'h00,refresh_addr_2};
			bankwr[2]<=1'b0;
			bankport[2]<=PORT_REFRESH;
		end
	end
end


always @(posedge clk or negedge init_n) begin
	if (!init_n) begin
		bankreq[3]<=1'b0;
		bankstate[3]<=1'b0;
	end else begin
		bankwrdata[3]<=vram1_din;
		bankdqm[3]<={!vram1_we,!vram1_we};
		if((!force_refresh[3]) && vram1_req ^ port_state[PORT_VRAM1]) begin
			bankreq[3]<=1'b1;
			bankstate[3]<=vram1_req;
			bankport[3]<=PORT_VRAM1;
			bankaddr[3]<={8'h00,vram1_addr};
			bankwr[3]<=vram1_we;
		end else begin

			bankreq[3]<=need_refresh[3];
			bankstate[3]<=1'b0;
			bankaddr[3][`SDRAM_COLBITS:1]<=vram1_addr[`SDRAM_COLBITS:1];
			bankaddr[3][23:`SDRAM_COLBITS+1]<={8'h00,refresh_addr_3};
			bankwr[3]<=1'b0;
			bankport[3]<=PORT_REFRESH;
		end
	end
end






reg [1:0] readcycles;





wire writepending_c;
reg writepending;
reg writeblocked;
reg reservewrite;

assign writepending_c = !(force_refresh[0]|force_refresh[1]|force_refresh[2]|force_refresh[3]) && ((vram0_we & (vram0_req ^ port_state[PORT_VRAM0]))
			| (vram1_we & (vram1_req ^ port_state[PORT_VRAM1])));

always @(posedge clk) begin
	writepending <= writepending_c;
	writeblocked <= |readcycles;
	reservewrite <= writepending & (|readcycles);
end




reg port_state[10];




reg [1:0] ras_ba;
reg [`SDRAM_COLBITS-1:0] ras_casaddr;
reg ras_wr;
reg [15:0] ras_wrdata;
reg [1:0] ras_dqm;
reg [3:0] ras1_port;
reg ras1_act;
reg [3:0] ras2_port;
reg ras2_act;



reg [3:0] cas1_port;
reg cas1_act;
reg [3:0] cas2_port;

reg [1:0] cas_ba;
reg [`SDRAM_ROWBITS-1:0] cas_addr;
reg cas_wr;
reg [15:0] cas_wrdata;
reg [1:0] cas_dqm;



reg [3:0] mask1_port;
reg [3:0] mask2_port;
reg mask_wr;



reg [3:0] latch1_port;
reg [3:0] latch2_port;

integer loopvar;

reg [15:0] dq_reg;
`ifdef VERILATOR
reg drive_dq;
assign SDRAM_DQ = drive_dq ? dq_reg : 16'bzzzzzzzzzzzzzzzz;
`else
assign SDRAM_DQ = dq_reg;
`endif

reg init = 1'b1;
reg [4:0] reset;


always @(posedge clk,negedge init_n) begin

	if(!init_n) begin
		ras1_port<=PORT_NONE;
		ras2_port<=PORT_NONE;
		cas1_port<=PORT_NONE;
		cas2_port<=PORT_NONE;
		mask1_port<=PORT_NONE;
		mask2_port<=PORT_NONE;
		latch1_port<=PORT_NONE;
		sd_cmd<=CMD_INHIBIT;
		port_state[0]<=1'b0;
		port_state[1]<=1'b0;
		port_state[2]<=1'b0;
		port_state[3]<=1'b0;
		port_state[4]<=1'b0;
		port_state[5]<=1'b0;
		port_state[6]<=1'b0;
		port_state[7]<=1'b0;
		port_state[8]<=1'b0;
		port_state[9]<=1'b0;
		bankbusy[0]<=5'h7;
		bankbusy[1]<=5'h1f;
		bankbusy[2]<=5'h1f;
		bankbusy[3]<=5'h1f;
		init<=1'b1;
		reset<=5'd31;
	end else begin

		for(loopvar=0; loopvar<4; loopvar=loopvar+1) begin
			if(!bankready[loopvar])
				bankbusy[loopvar]<=bankbusy[loopvar]-4'b1;
		end

`ifndef VERILATOR
		dq_reg<=16'bZZZZZZZZZZZZZZZZ;
`endif

		SDRAM_A <= cas_addr;
		sd_dqm<=2'b11;
		
		if(init) begin

			sd_cmd<=CMD_INHIBIT;
			if(bankready[0]) begin
				case(reset)
					16: cas_addr[10]<=1'b1;
					15: sd_cmd <= CMD_PRECHARGE;
					11: sd_cmd <= CMD_AUTO_REFRESH;
					10: sd_cmd <= CMD_AUTO_REFRESH;
					9: sd_cmd <= CMD_AUTO_REFRESH;
					8: sd_cmd <= CMD_AUTO_REFRESH;
					7: sd_cmd <= CMD_AUTO_REFRESH;
					6: sd_cmd <= CMD_AUTO_REFRESH;
					5: sd_cmd <= CMD_AUTO_REFRESH;
					4: sd_cmd <= CMD_AUTO_REFRESH;
					3: cas_addr <= MODE;
					2: begin
						sd_cmd <= CMD_LOAD_MODE;
						SDRAM_BA <= 2'b00;
					end
				endcase

				reset<=reset-1'b1;
				bankbusy[0]<=BANK_DELAY[4:0];
				if(reset==0)
				begin
					init<=1'b0;
					bankbusy[0]<=0;
				end
			end
		end else begin



`ifdef VERILATOR
			drive_dq<=1'b0;
`endif
			sd_cmd<=CMD_INHIBIT;

			ras1_port<=PORT_NONE;
			ras1_act<=1'b0;
			ras2_port<=ras1_port;
			ras2_act<=ras1_act;

			if(!ras1_act && !cas1_act) begin
				readcycles<={1'b0,readcycles[1]};
				ras_wr<=1'b0;
				ras_dqm<=2'b11;
				


				if(!reservewrite) begin

					if(bankreq[2] && bankready[2] && (!writepending || bankwr[2]) && !(writeblocked && bankwr[2])) begin



						readcycles[(`SDRAM_RISKCONTENTION || `SDRAM_CL==2) && BURST_LENGTH==3'b000 ? 0 : 1]<=~bankwr[2];

						port_state[bankport[2]]<=bankstate[2];
						bankbusy[2]<=BANK_DELAY[4:0];
						ras_ba<=2'b10;
						ras_casaddr<=bankaddr[2][`SDRAM_COLBITS:1];
						ras_wr<=bankwr[2];
						ras_wrdata<=bankwrdata[2];
						ras_dqm<=bankdqm[2];
						ras1_port<=bankport[2];
						ras1_act<=1'b1;

						sd_cmd<=CMD_ACTIVE;
						SDRAM_A <= bankaddr[2][`SDRAM_ROWBITS+`SDRAM_COLBITS:`SDRAM_COLBITS+1];
						SDRAM_BA <= 2'b10;
					end else if(bankreq[3] && bankready[3] && (!writepending || bankwr[3]) && !(writeblocked && bankwr[3])) begin
						readcycles[(`SDRAM_RISKCONTENTION || `SDRAM_CL==2) && BURST_LENGTH==3'b000 ? 0 : 1]<=~bankwr[3];
						port_state[bankport[3]]<=bankstate[3];
						bankbusy[3]<=BANK_DELAY[4:0];
						ras_ba<=2'b11;
						ras_casaddr<=bankaddr[3][`SDRAM_COLBITS:1];
						ras_wr<=bankwr[3];
						ras_wrdata<=bankwrdata[3];
						ras_dqm<=bankdqm[3];
						ras1_port<=bankport[3];
						ras1_act<=1'b1;

						sd_cmd<=CMD_ACTIVE;
						SDRAM_A <= bankaddr[3][`SDRAM_ROWBITS+`SDRAM_COLBITS:`SDRAM_COLBITS+1];
						SDRAM_BA <= 2'b11;
					end else if(bankreq[0] && bankready[0] && (!writepending || bankwr[0]) && !(writeblocked && bankwr[0])) begin
						readcycles[(`SDRAM_RISKCONTENTION || `SDRAM_CL==2) && BURST_LENGTH==3'b000 ? 0 : 1]<=~bankwr[0];
						port_state[bankport[0]]<=bankstate[0];
						bankbusy[0]<=BANK_DELAY[4:0];
						ras_ba<=2'b00;
						ras_casaddr<=bankaddr[0][`SDRAM_COLBITS:1];
						ras_wr<=bankwr[0];
						ras_wrdata<=bankwrdata[0];
						ras_dqm<=bankdqm[0];
						ras1_port<=bankport[0];
						ras1_act<=1'b1;

						sd_cmd<=CMD_ACTIVE;
						SDRAM_A <= bankaddr[0][`SDRAM_ROWBITS+`SDRAM_COLBITS:`SDRAM_COLBITS+1];
						SDRAM_BA <= 2'b00;
					end else if(bankreq[1] && bankready[1] && (!writepending || bankwr[1]) && !(writeblocked && bankwr[1])) begin
						readcycles[(`SDRAM_RISKCONTENTION || `SDRAM_CL==2) && BURST_LENGTH==3'b000 ? 0 : 1]<=~bankwr[1];
						port_state[bankport[1]]<=bankstate[1];
						bankbusy[1]<=BANK_DELAY[4:0];
						ras_ba<=2'b01;
						ras_casaddr<=bankaddr[1][`SDRAM_COLBITS:1];
						ras_wr<=bankwr[1];
						ras_wrdata<=bankwrdata[1];
						ras_dqm<=bankdqm[1];
						ras1_port<=bankport[1];
						ras1_act<=1'b1;

						sd_cmd<=CMD_ACTIVE;
						SDRAM_A <= bankaddr[1][`SDRAM_ROWBITS+`SDRAM_COLBITS:`SDRAM_COLBITS+1];
						SDRAM_BA <= 2'b01;
					end
				end
			end

			if(ras2_port != PORT_NONE) begin 
				cas_addr<={`SDRAM_ROWBITS{1'b0}};
				cas_addr[10]<=1'b1;
				cas_addr[`SDRAM_COLBITS-1:0]<=ras_casaddr;
				cas_wr<=ras_wr;
				cas_dqm<=ras_dqm;
				cas_wrdata<=ras_wrdata;
				cas_ba<=ras_ba;
			end
			cas1_port<=ras2_port;
			cas1_act<=ras2_act;



			if(cas1_port != PORT_NONE) begin 

				SDRAM_BA <= cas_ba;
				if(cas_wr) begin
					sd_cmd<=CMD_WRITE;
					bankbusy[cas_ba]<=BANK_WRITE_DELAY[4:0];
`ifdef VERILATOR
					drive_dq<=1'b1;
`endif
					dq_reg <= cas_wrdata;
					sd_dqm<=cas_dqm;
`ifdef SDRAM_DQM_SHARED
					SDRAM_A[`SDRAM_ROWBITS-1:`SDRAM_ROWBITS-2] <= cas_dqm;
`endif
				end else begin
					sd_cmd<=CMD_READ;
					if(`SDRAM_CL==2) begin
						sd_dqm<=2'b00;
`ifdef SDRAM_DQM_SHARED
						SDRAM_A[`SDRAM_ROWBITS-1:`SDRAM_ROWBITS-2] <= 2'b00;
`endif
					end
				end
			end

			cas2_port<=cas1_port;

			if(cas2_port!=PORT_NONE && !cas_wr && `SDRAM_CL==3) begin
				sd_dqm<=2'b00;
`ifdef SDRAM_DQM_SHARED
				SDRAM_A[`SDRAM_ROWBITS-1:`SDRAM_ROWBITS-2] <= 2'b00;
`endif
			end
			


			if(`SDRAM_CL==2) begin
				mask2_port<=mask_wr ? PORT_NONE : cas2_port;
				mask_wr<=cas_wr;
			end else begin
				mask1_port<=cas2_port;
				mask_wr<=cas_wr;

				mask2_port<=mask_wr ? PORT_NONE : mask1_port;
			end


			latch1_port<=mask2_port;
		end
	end
end




reg [15:0] vram0_dout_r;
reg [15:0] vram1_dout_r;
reg [15:0] rom_dout_r;
reg [15:0] aram_dout_r;
reg [15:0] wram_dout_r;

assign vram0_dout=latch2_port == PORT_VRAM0 ? sd_din : vram0_dout_r;
assign vram1_dout=latch2_port == PORT_VRAM1 ? sd_din : vram1_dout_r;
assign rom_dout=latch2_port == PORT_ROM ? sd_din : rom_dout_r;
assign aram_dout=latch2_port == PORT_ARAM ? sd_din : aram_dout_r;
assign wram_dout=latch2_port == PORT_WRAM ? sd_din : wram_dout_r;

always @(posedge clk, negedge init_n) begin

	if(!init_n) begin
		latch2_port<=PORT_NONE;
		rom_req_ack <= 1'b0;
		wram_req_ack <= 1'b0;
		vram0_ack <= 1'b0;
		vram1_ack <= 1'b0;
		aram_req_ack <= 1'b0;
	end else begin

		sd_din<=SDRAM_DQ;




		if(ras_wr) begin
			case (ras2_port)
				PORT_ROM: rom_req_ack <= rom_req;
				PORT_WRAM: wram_req_ack <= wram_req;
				PORT_VRAM0: vram0_ack <= vram0_req;
				PORT_VRAM1: vram1_ack <= vram1_req;
				PORT_ARAM: aram_req_ack <= aram_req;
				default: ;
			endcase
		end















		latch2_port<=latch1_port;

		case (latch1_port)
			PORT_ROM:	rom_req_ack <= rom_req;
			PORT_ARAM:	aram_req_ack <= aram_req;
			PORT_WRAM:	wram_req_ack <= wram_req;
			PORT_VRAM0:	vram0_ack <= vram0_req;
			PORT_VRAM1:	vram1_ack <= vram1_req;
			default: ;
		endcase

		case (latch2_port)
			PORT_ROM:	rom_dout_r <= sd_din;
			PORT_ARAM:	aram_dout_r <= sd_din;
			PORT_WRAM:	wram_dout_r <= sd_din;
			PORT_VRAM0:	vram0_dout_r <= sd_din;
			PORT_VRAM1:	vram1_dout_r <= sd_din;
			default: ;
		endcase
	


		if (aram_we && (aram_req ^ port_state[PORT_ARAM])) begin
			if (aram_addr[0])
				aram_dout_r[15:8] <= aram_din;
			else
				aram_dout_r[7:0] <= aram_din;
		end

		if (wram_we && (wram_req ^ port_state[PORT_WRAM])) begin
			if (wram_addr[0])
				wram_dout_r[15:8] <= wram_din;
			else
				wram_dout_r[7:0] <= wram_din;
		end

		if (vram0_we && (vram0_req ^ port_state[PORT_VRAM0]))
			vram0_dout_r <= vram0_din;

		if (vram1_we && (vram1_req ^ port_state[PORT_VRAM1]))
			vram1_dout_r <= vram1_din;
	
	end
end

endmodule
module sdram #(parameter SDRAM_tCK=7800 )
(

	inout  [15:0] SDRAM_DQ,
	output reg [`SDRAM_ROWBITS-1:0] SDRAM_A,
	output reg        SDRAM_DQML,
	output reg        SDRAM_DQMH,
	output reg [1:0]  SDRAM_BA,
	output            SDRAM_nCS,
	output            SDRAM_nWE,
	output            SDRAM_nRAS,
	output            SDRAM_nCAS,


	input             init_n,
	input             clk,
	input             clkref,
	input             sync_en,

	input      [15:0] rom_din,
	output reg [15:0] rom_dout,
	input      [21:1] rom_addr,
	input             rom_req,
	output reg        rom_req_ack,
	input             rom_we,
	
	input      [21:0] wram_addr,
	input       [7:0] wram_din,
	output reg [15:0] wram_dout,
	input             wram_req,
	output reg        wram_req_ack,
	input             wram_we,

	input             vram0_req,
	output reg        vram0_ack,
	input      [15:1] vram0_addr,
	input      [15:0] vram0_din,
	output reg [15:0] vram0_dout,
	input             vram0_we,

	input             vram1_req,
	output reg        vram1_ack,
	input      [15:1] vram1_addr,
	input      [15:0] vram1_din,
	output reg [15:0] vram1_dout,
	input             vram1_we,

	input      [16:0] aram_addr,
	input       [7:0] aram_din,
	output reg [15:0] aram_dout,
	input             aram_req,
	output reg        aram_req_ack,
	input             aram_we
);


localparam BANK_DELAY = ((`SDRAM_tRC+(SDRAM_tCK-1))/SDRAM_tCK)-2;
localparam BANK_WRITE_DELAY = ((`SDRAM_tRP+(SDRAM_tCK-1))/SDRAM_tCK)+`SDRAM_tWR;
localparam REFRESH_DELAY = ((`SDRAM_tRC+(SDRAM_tCK-1))/SDRAM_tCK)-1;

initial assert(`SDRAM_CL!=2 || SDRAM_tCK>=`SDRAM_tCKminCL2)
	else $error("CL2 not allowed at %d MHz (max speed is %d)",1000000/SDRAM_tCK,1000000/`SDRAM_tCKminCL2);

`ifdef SDRAM_DQM_SHARED
initial assert(`SDRAM_CL==2)
	else $error("The SDRAM controller can't operate in CL3 mode when DQMs are shared.");
`endif
	


localparam BURST_LENGTH   = 3'b000;
localparam ACCESS_TYPE    = 1'b0;
localparam CAS_LATENCY = 3'd`SDRAM_CL;
localparam OP_MODE        = 2'b00;
localparam NO_WRITE_BURST = 1'b1;

localparam MODE = { 3'b000, NO_WRITE_BURST, OP_MODE, CAS_LATENCY, ACCESS_TYPE, BURST_LENGTH}; 





localparam CMD_INHIBIT         = 4'b1111;
localparam CMD_NOP             = 4'b0111;
localparam CMD_ACTIVE          = 4'b0011;
localparam CMD_READ            = 4'b0101;
localparam CMD_WRITE           = 4'b0100;
localparam CMD_BURST_TERMINATE = 4'b0110;
localparam CMD_PRECHARGE       = 4'b0010;
localparam CMD_AUTO_REFRESH    = 4'b0001;
localparam CMD_LOAD_MODE       = 4'b0000;

reg  [3:0] sd_cmd;
reg  [1:0] sd_dqm;
reg [15:0] sd_din;


assign SDRAM_nCS  = sd_cmd[3];
assign SDRAM_nRAS = sd_cmd[2];
assign SDRAM_nCAS = sd_cmd[1];
assign SDRAM_nWE  = sd_cmd[0];
assign SDRAM_DQMH = sd_dqm[1];
assign SDRAM_DQML = sd_dqm[0];

























































































reg evencycle;
reg clkref_d;
reg [2:0] refreshwindow;

always@(posedge clk) begin
	evencycle<=!evencycle;

	clkref_d<=clkref;
	if(clkref_d && !clkref) begin
			refreshwindow<=3'b001;
			evencycle<=1'b1;
	end
	if(|refreshwindow)
		refreshwindow<=refreshwindow-1'b1;
end

wire allowrefresh_vram = |refreshwindow;





reg [3:0] romsync_ctr;
reg rom_req_d;
reg allowrefresh_rom;

reg [3:0] aramsync_ctr;
reg aram_req_d;
reg allowrefresh_aram;

always @(posedge clk or negedge init_n) begin
	if(!init_n) begin
		allowrefresh_rom<=1'b0;
		allowrefresh_aram<=1'b0;
	end else begin
		rom_req_d<=rom_req;
		if(|romsync_ctr)
			romsync_ctr<=romsync_ctr-1'b1;
		else
			allowrefresh_rom<=1'b0;

		if(rom_req_d!=rom_req) begin
			allowrefresh_rom<=1'b1;
			romsync_ctr<=4'hf;
		end

		aram_req_d<=aram_req;
		if(|aramsync_ctr)
			aramsync_ctr<=aramsync_ctr-1'b1;
		else
			allowrefresh_aram<=1'b0;

		if(aram_req_d!=aram_req) begin
			allowrefresh_aram<=1'b1;
			aramsync_ctr<=4'hf;
		end
	end
end

wire need_refresh[4];
wire force_refresh[4];

localparam bank0_rowbits=(22-`SDRAM_COLBITS);
localparam bank1_rowbits=(16-`SDRAM_COLBITS);
localparam bank2_rowbits=(15-`SDRAM_COLBITS);
localparam bank3_rowbits=(15-`SDRAM_COLBITS);

reg [bank0_rowbits-1:0] refresh_addr_0;
reg [bank1_rowbits-1:0] refresh_addr_1;
reg [bank2_rowbits-1:0] refresh_addr_2;
reg [bank3_rowbits-1:0] refresh_addr_3;

refresh_schedule #(.tCK(SDRAM_tCK),.rowbits(bank0_rowbits)) refresh_bank0
(
	.clk(clk),
	.reset_n(init_n),
	.refreshing(cas2_port==PORT_REFRESH && cas_ba==2'b00 ? 1'b1 : 1'b0),
	.allow(allowrefresh_rom),
	.refresh_req(need_refresh[0]),
	.refresh_force(force_refresh[0]),
	.addr(refresh_addr_0)
);

refresh_schedule #(.tCK(SDRAM_tCK),.rowbits(bank1_rowbits)) refresh_bank1
(
	.clk(clk),
	.reset_n(init_n),
	.refreshing(cas2_port==PORT_REFRESH && cas_ba==2'b01 ? 1'b1 : 1'b0),
	.allow(allowrefresh_aram),
	.refresh_req(need_refresh[1]),
	.refresh_force(force_refresh[1]),
	.addr(refresh_addr_1)
);

refresh_schedule #(.tCK(SDRAM_tCK),.rowbits(bank2_rowbits)) refresh_bank2
(
	.clk(clk),
	.reset_n(init_n),
	.refreshing(cas2_port==PORT_REFRESH && cas_ba==2'b10 ? 1'b1 : 1'b0),
	.allow(allowrefresh_vram),
	.refresh_req(need_refresh[2]),
	.refresh_force(force_refresh[2]),
	.addr(refresh_addr_2)
);

refresh_schedule #(.tCK(SDRAM_tCK),.rowbits(bank3_rowbits)) refresh_bank3
(
	.clk(clk),
	.reset_n(init_n),
	.refreshing(cas2_port==PORT_REFRESH && cas_ba==2'b11 ? 1'b1 : 1'b0),
	.allow(allowrefresh_vram),
	.refresh_req(need_refresh[3]),
	.refresh_force(force_refresh[3]),
	.addr(refresh_addr_3)
);





reg [3:0] bankactive;
reg [4:0] bankbusy [4];
wire [3:0] bankready;

assign bankready[0]=bankbusy[0][4];
assign bankready[1]=bankbusy[1][4];
assign bankready[2]=bankbusy[2][4];
assign bankready[3]=bankbusy[3][4];




localparam PORT_NONE   = 4'd0;
localparam PORT_ROM    = 4'd1;
localparam PORT_WRAM   = 4'd2;
localparam PORT_VRAM0  = 4'd3;
localparam PORT_VRAM1  = 4'd4;
localparam PORT_ARAM   = 4'd5;
localparam PORT_REFRESH = 4'd6;

reg [3:0] bankreq;
reg [3:0] bankstate;
reg [3:0] bankwr;
reg [15:0] bankwrdata[4];
reg [3:0] bankport[4];
reg [23:1] bankaddr[4];
reg [1:0] bankdqm[4];



always @(posedge clk or negedge init_n) begin
	if (!init_n) begin
		bankreq[0]<=1'b0;
		bankstate[0]<=1'b0;
	end else if((!force_refresh[0]) && rom_req ^ port_state[PORT_ROM]) begin
		bankreq[0]<=1'b1;
		bankstate[0]<=rom_req;
		bankport[0]<=PORT_ROM;
		bankdqm[0]<={!rom_we,!rom_we};
		bankwrdata[0]<=rom_din;
		bankaddr[0]<={2'b00,rom_addr[21:1]};
		bankwr[0]<=rom_we;
	end else if ((!force_refresh[0]) && wram_req ^ port_state[PORT_WRAM]) begin
		bankreq[0]<=1'b1;
		bankstate[0]<=wram_req;
		bankport[0]<=PORT_WRAM;
		bankdqm[0]<=wram_we ? { ~wram_addr[0], wram_addr[0] } : 2'b11;
		bankaddr[0]<={2'b01,wram_addr[21:1]};
		bankwr[0]<=wram_we;
		bankwrdata[0]<={wram_din,wram_din};
	end else begin

		bankreq[0]<=need_refresh[0];
		bankwr[0]<=1'b0;
		bankstate[0]<=1'b0;
		bankdqm[0]<=2'b11;
		bankaddr[0][`SDRAM_COLBITS:1]<=rom_addr[`SDRAM_COLBITS:1];
		bankaddr[0][23:`SDRAM_COLBITS+1]<={1'b0,refresh_addr_0};
		bankwr[0]<=1'b0;
		bankwrdata[0]<={wram_din,wram_din};
		bankport[0]<=PORT_REFRESH;
	end
end



always @(posedge clk or negedge init_n) begin
	if (!init_n) begin
		bankreq[1]<=1'b0;
		bankstate[1]<=1'b0;
	end else if ((!force_refresh[1]) && aram_req ^ port_state[PORT_ARAM]) begin
		bankdqm[1]<=aram_we ? { ~aram_addr[0], aram_addr[0] } : 2'b11;
		bankwrdata[1]<={aram_din,aram_din};
		bankreq[1]<=1'b1;
		bankstate[1]<=aram_req;
		bankport[1]<=PORT_ARAM;
		bankaddr[1]<={7'b0000001,aram_addr[16:1]};
		bankwr[1]<=aram_we;
	end else begin

		bankreq[1]<=need_refresh[1];
		bankstate[1]<=1'b0;
		bankaddr[1][`SDRAM_COLBITS:1]<=wram_addr[`SDRAM_COLBITS:1];
		bankaddr[1][23:`SDRAM_COLBITS+1]<={7'b0000001,refresh_addr_1};
		bankdqm[1]<=aram_we ? { ~aram_addr[0], aram_addr[0] } : 2'b11;
		bankwrdata[1]<={aram_din,aram_din};
		bankwr[1]<=1'b0;
		bankport[1]<=PORT_REFRESH;
	end
end


always @(posedge clk or negedge init_n) begin
	if (!init_n) begin
		bankreq[2]<=1'b0;
		bankstate[2]<=1'b0;
	end else begin
		bankwrdata[2]<=vram0_din;
		bankdqm[2]<={!vram0_we,!vram0_we};
		if((!force_refresh[2]) && vram0_req ^ port_state[PORT_VRAM0]) begin
			bankreq[2]<=vram0_req ^ port_state[PORT_VRAM0];
			bankstate[2]<=vram0_req;
			bankport[2]<=PORT_VRAM0;
			bankaddr[2]<={8'h00,vram0_addr};
			bankwr[2]<=vram0_we;
		end else begin

			bankreq[2]<=need_refresh[2];
			bankstate[2]<=1'b0;
			bankaddr[2][`SDRAM_COLBITS:1]<=vram0_addr[`SDRAM_COLBITS:1];
			bankaddr[2][23:`SDRAM_COLBITS+1]<={8'h00,refresh_addr_2};
			bankwr[2]<=1'b0;
			bankport[2]<=PORT_REFRESH;
		end
	end
end


always @(posedge clk or negedge init_n) begin
	if (!init_n) begin
		bankreq[3]<=1'b0;
		bankstate[3]<=1'b0;
	end else begin
		bankwrdata[3]<=vram1_din;
		bankdqm[3]<={!vram1_we,!vram1_we};
		if((!force_refresh[3]) && vram1_req ^ port_state[PORT_VRAM1]) begin
			bankreq[3]<=1'b1;
			bankstate[3]<=vram1_req;
			bankport[3]<=PORT_VRAM1;
			bankaddr[3]<={8'h00,vram1_addr};
			bankwr[3]<=vram1_we;
		end else begin

			bankreq[3]<=need_refresh[3];
			bankstate[3]<=1'b0;
			bankaddr[3][`SDRAM_COLBITS:1]<=vram1_addr[`SDRAM_COLBITS:1];
			bankaddr[3][23:`SDRAM_COLBITS+1]<={8'h00,refresh_addr_3};
			bankwr[3]<=1'b0;
			bankport[3]<=PORT_REFRESH;
		end
	end
end






reg [1:0] readcycles;





wire writepending_c;
reg writepending;
reg writeblocked;
reg reservewrite;

assign writepending_c = !(force_refresh[0]|force_refresh[1]|force_refresh[2]|force_refresh[3]) && ((vram0_we & (vram0_req ^ port_state[PORT_VRAM0]))
			| (vram1_we & (vram1_req ^ port_state[PORT_VRAM1])));

always @(posedge clk) begin
	writepending <= writepending_c;
	writeblocked <= |readcycles;
	reservewrite <= writepending & (|readcycles);
end




reg port_state[10];




reg [1:0] ras_ba;
reg [`SDRAM_COLBITS-1:0] ras_casaddr;
reg ras_wr;
reg [15:0] ras_wrdata;
reg [1:0] ras_dqm;
reg [3:0] ras1_port;
reg ras1_act;
reg [3:0] ras2_port;
reg ras2_act;



reg [3:0] cas1_port;
reg cas1_act;
reg [3:0] cas2_port;

reg [1:0] cas_ba;
reg [`SDRAM_ROWBITS-1:0] cas_addr;
reg cas_wr;
reg [15:0] cas_wrdata;
reg [1:0] cas_dqm;



reg [3:0] mask1_port;
reg [3:0] mask2_port;
reg mask_wr;



reg [3:0] latch1_port;
reg [3:0] latch2_port;

integer loopvar;

reg [15:0] dq_reg;
`ifdef VERILATOR
reg drive_dq;
assign SDRAM_DQ = drive_dq ? dq_reg : 16'bzzzzzzzzzzzzzzzz;
`else
assign SDRAM_DQ = dq_reg;
`endif

reg init = 1'b1;
reg [4:0] reset;


always @(posedge clk,negedge init_n) begin

	if(!init_n) begin
		ras1_port<=PORT_NONE;
		ras2_port<=PORT_NONE;
		cas1_port<=PORT_NONE;
		cas2_port<=PORT_NONE;
		mask1_port<=PORT_NONE;
		mask2_port<=PORT_NONE;
		latch1_port<=PORT_NONE;
		sd_cmd<=CMD_INHIBIT;
		port_state[0]<=1'b0;
		port_state[1]<=1'b0;
		port_state[2]<=1'b0;
		port_state[3]<=1'b0;
		port_state[4]<=1'b0;
		port_state[5]<=1'b0;
		port_state[6]<=1'b0;
		port_state[7]<=1'b0;
		port_state[8]<=1'b0;
		port_state[9]<=1'b0;
		bankbusy[0]<=5'h7;
		bankbusy[1]<=5'h1f;
		bankbusy[2]<=5'h1f;
		bankbusy[3]<=5'h1f;
		init<=1'b1;
		reset<=5'd31;
	end else begin

		for(loopvar=0; loopvar<4; loopvar=loopvar+1) begin
			if(!bankready[loopvar])
				bankbusy[loopvar]<=bankbusy[loopvar]-4'b1;
		end

`ifndef VERILATOR
		dq_reg<=16'bZZZZZZZZZZZZZZZZ;
`endif

		SDRAM_A <= cas_addr;
		sd_dqm<=2'b11;
		
		if(init) begin

			sd_cmd<=CMD_INHIBIT;
			if(bankready[0]) begin
				case(reset)
					16: cas_addr[10]<=1'b1;
					15: sd_cmd <= CMD_PRECHARGE;
					11: sd_cmd <= CMD_AUTO_REFRESH;
					10: sd_cmd <= CMD_AUTO_REFRESH;
					9: sd_cmd <= CMD_AUTO_REFRESH;
					8: sd_cmd <= CMD_AUTO_REFRESH;
					7: sd_cmd <= CMD_AUTO_REFRESH;
					6: sd_cmd <= CMD_AUTO_REFRESH;
					5: sd_cmd <= CMD_AUTO_REFRESH;
					4: sd_cmd <= CMD_AUTO_REFRESH;
					3: cas_addr <= MODE;
					2: begin
						sd_cmd <= CMD_LOAD_MODE;
						SDRAM_BA <= 2'b00;
					end
				endcase

				reset<=reset-1'b1;
				bankbusy[0]<=BANK_DELAY[4:0];
				if(reset==0)
				begin
					init<=1'b0;
					bankbusy[0]<=0;
				end
			end
		end else begin



`ifdef VERILATOR
			drive_dq<=1'b0;
`endif
			sd_cmd<=CMD_INHIBIT;

			ras1_port<=PORT_NONE;
			ras1_act<=1'b0;
			ras2_port<=ras1_port;
			ras2_act<=ras1_act;

			if(!ras1_act && !cas1_act) begin
				readcycles<={1'b0,readcycles[1]};
				ras_wr<=1'b0;
				ras_dqm<=2'b11;
				


				if(!reservewrite) begin

					if(bankreq[2] && bankready[2] && (!writepending || bankwr[2]) && !(writeblocked && bankwr[2])) begin



						readcycles[(`SDRAM_RISKCONTENTION || `SDRAM_CL==2) && BURST_LENGTH==3'b000 ? 0 : 1]<=~bankwr[2];

						port_state[bankport[2]]<=bankstate[2];
						bankbusy[2]<=BANK_DELAY[4:0];
						ras_ba<=2'b10;
						ras_casaddr<=bankaddr[2][`SDRAM_COLBITS:1];
						ras_wr<=bankwr[2];
						ras_wrdata<=bankwrdata[2];
						ras_dqm<=bankdqm[2];
						ras1_port<=bankport[2];
						ras1_act<=1'b1;

						sd_cmd<=CMD_ACTIVE;
						SDRAM_A <= bankaddr[2][`SDRAM_ROWBITS+`SDRAM_COLBITS:`SDRAM_COLBITS+1];
						SDRAM_BA <= 2'b10;
					end else if(bankreq[3] && bankready[3] && (!writepending || bankwr[3]) && !(writeblocked && bankwr[3])) begin
						readcycles[(`SDRAM_RISKCONTENTION || `SDRAM_CL==2) && BURST_LENGTH==3'b000 ? 0 : 1]<=~bankwr[3];
						port_state[bankport[3]]<=bankstate[3];
						bankbusy[3]<=BANK_DELAY[4:0];
						ras_ba<=2'b11;
						ras_casaddr<=bankaddr[3][`SDRAM_COLBITS:1];
						ras_wr<=bankwr[3];
						ras_wrdata<=bankwrdata[3];
						ras_dqm<=bankdqm[3];
						ras1_port<=bankport[3];
						ras1_act<=1'b1;

						sd_cmd<=CMD_ACTIVE;
						SDRAM_A <= bankaddr[3][`SDRAM_ROWBITS+`SDRAM_COLBITS:`SDRAM_COLBITS+1];
						SDRAM_BA <= 2'b11;
					end else if(bankreq[0] && bankready[0] && (!writepending || bankwr[0]) && !(writeblocked && bankwr[0])) begin
						readcycles[(`SDRAM_RISKCONTENTION || `SDRAM_CL==2) && BURST_LENGTH==3'b000 ? 0 : 1]<=~bankwr[0];
						port_state[bankport[0]]<=bankstate[0];
						bankbusy[0]<=BANK_DELAY[4:0];
						ras_ba<=2'b00;
						ras_casaddr<=bankaddr[0][`SDRAM_COLBITS:1];
						ras_wr<=bankwr[0];
						ras_wrdata<=bankwrdata[0];
						ras_dqm<=bankdqm[0];
						ras1_port<=bankport[0];
						ras1_act<=1'b1;

						sd_cmd<=CMD_ACTIVE;
						SDRAM_A <= bankaddr[0][`SDRAM_ROWBITS+`SDRAM_COLBITS:`SDRAM_COLBITS+1];
						SDRAM_BA <= 2'b00;
					end else if(bankreq[1] && bankready[1] && (!writepending || bankwr[1]) && !(writeblocked && bankwr[1])) begin
						readcycles[(`SDRAM_RISKCONTENTION || `SDRAM_CL==2) && BURST_LENGTH==3'b000 ? 0 : 1]<=~bankwr[1];
						port_state[bankport[1]]<=bankstate[1];
						bankbusy[1]<=BANK_DELAY[4:0];
						ras_ba<=2'b01;
						ras_casaddr<=bankaddr[1][`SDRAM_COLBITS:1];
						ras_wr<=bankwr[1];
						ras_wrdata<=bankwrdata[1];
						ras_dqm<=bankdqm[1];
						ras1_port<=bankport[1];
						ras1_act<=1'b1;

						sd_cmd<=CMD_ACTIVE;
						SDRAM_A <= bankaddr[1][`SDRAM_ROWBITS+`SDRAM_COLBITS:`SDRAM_COLBITS+1];
						SDRAM_BA <= 2'b01;
					end
				end
			end

			if(ras2_port != PORT_NONE) begin 
				cas_addr<={`SDRAM_ROWBITS{1'b0}};
				cas_addr[10]<=1'b1;
				cas_addr[`SDRAM_COLBITS-1:0]<=ras_casaddr;
				cas_wr<=ras_wr;
				cas_dqm<=ras_dqm;
				cas_wrdata<=ras_wrdata;
				cas_ba<=ras_ba;
			end
			cas1_port<=ras2_port;
			cas1_act<=ras2_act;



			if(cas1_port != PORT_NONE) begin 

				SDRAM_BA <= cas_ba;
				if(cas_wr) begin
					sd_cmd<=CMD_WRITE;
					bankbusy[cas_ba]<=BANK_WRITE_DELAY[4:0];
`ifdef VERILATOR
					drive_dq<=1'b1;
`endif
					dq_reg <= cas_wrdata;
					sd_dqm<=cas_dqm;
`ifdef SDRAM_DQM_SHARED
					SDRAM_A[`SDRAM_ROWBITS-1:`SDRAM_ROWBITS-2] <= cas_dqm;
`endif
				end else begin
					sd_cmd<=CMD_READ;
					if(`SDRAM_CL==2) begin
						sd_dqm<=2'b00;
`ifdef SDRAM_DQM_SHARED
						SDRAM_A[`SDRAM_ROWBITS-1:`SDRAM_ROWBITS-2] <= 2'b00;
`endif
					end
				end
			end

			cas2_port<=cas1_port;

			if(cas2_port!=PORT_NONE && !cas_wr && `SDRAM_CL==3) begin
				sd_dqm<=2'b00;
`ifdef SDRAM_DQM_SHARED
				SDRAM_A[`SDRAM_ROWBITS-1:`SDRAM_ROWBITS-2] <= 2'b00;
`endif
			end
			


			if(`SDRAM_CL==2) begin
				mask2_port<=mask_wr ? PORT_NONE : cas2_port;
				mask_wr<=cas_wr;
			end else begin
				mask1_port<=cas2_port;
				mask_wr<=cas_wr;

				mask2_port<=mask_wr ? PORT_NONE : mask1_port;
			end


			latch1_port<=mask2_port;
		end
	end
end




reg [15:0] vram0_dout_r;
reg [15:0] vram1_dout_r;
reg [15:0] rom_dout_r;
reg [15:0] aram_dout_r;
reg [15:0] wram_dout_r;

assign vram0_dout=latch2_port == PORT_VRAM0 ? sd_din : vram0_dout_r;
assign vram1_dout=latch2_port == PORT_VRAM1 ? sd_din : vram1_dout_r;
assign rom_dout=latch2_port == PORT_ROM ? sd_din : rom_dout_r;
assign aram_dout=latch2_port == PORT_ARAM ? sd_din : aram_dout_r;
assign wram_dout=latch2_port == PORT_WRAM ? sd_din : wram_dout_r;

always @(posedge clk, negedge init_n) begin

	if(!init_n) begin
		latch2_port<=PORT_NONE;
		rom_req_ack <= 1'b0;
		wram_req_ack <= 1'b0;
		vram0_ack <= 1'b0;
		vram1_ack <= 1'b0;
		aram_req_ack <= 1'b0;
	end else begin

		sd_din<=SDRAM_DQ;




		if(ras_wr) begin
			case (ras2_port)
				PORT_ROM: rom_req_ack <= rom_req;
				PORT_WRAM: wram_req_ack <= wram_req;
				PORT_VRAM0: vram0_ack <= vram0_req;
				PORT_VRAM1: vram1_ack <= vram1_req;
				PORT_ARAM: aram_req_ack <= aram_req;
				default: ;
			endcase
		end















		latch2_port<=latch1_port;

		case (latch1_port)
			PORT_ROM:	rom_req_ack <= rom_req;
			PORT_ARAM:	aram_req_ack <= aram_req;
			PORT_WRAM:	wram_req_ack <= wram_req;
			PORT_VRAM0:	vram0_ack <= vram0_req;
			PORT_VRAM1:	vram1_ack <= vram1_req;
			default: ;
		endcase

		case (latch2_port)
			PORT_ROM:	rom_dout_r <= sd_din;
			PORT_ARAM:	aram_dout_r <= sd_din;
			PORT_WRAM:	wram_dout_r <= sd_din;
			PORT_VRAM0:	vram0_dout_r <= sd_din;
			PORT_VRAM1:	vram1_dout_r <= sd_din;
			default: ;
		endcase
	


		if (aram_we && (aram_req ^ port_state[PORT_ARAM])) begin
			if (aram_addr[0])
				aram_dout_r[15:8] <= aram_din;
			else
				aram_dout_r[7:0] <= aram_din;
		end

		if (wram_we && (wram_req ^ port_state[PORT_WRAM])) begin
			if (wram_addr[0])
				wram_dout_r[15:8] <= wram_din;
			else
				wram_dout_r[7:0] <= wram_din;
		end

		if (vram0_we && (vram0_req ^ port_state[PORT_VRAM0]))
			vram0_dout_r <= vram0_din;

		if (vram1_we && (vram1_req ^ port_state[PORT_VRAM1]))
			vram1_dout_r <= vram1_din;
	
	end
end

endmodule