`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer:
// 
// Create Date:    09:58:21 02/12/2008 
// Design Name: 
// Module Name:    sramcontrol 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////



module sram_block( amem, dmem_in, dmem_out, en, wen, 
								addr_sr,
								data_io_0, data_io_1, 
								ce_0, ce_1, 
								oe, 
								we, 
								ub_0, lb_0, 
								ub_1, lb_1,
									clk_cpu, clk_sram, 
									rst);


input[19:0] amem;

input[31:0] dmem_in;
output[31:0] dmem_out;

reg[31:0] dmem_out;

input[3:0] en;
input[3:0] wen;

output[17:0] addr_sr;
reg[17:0] addr_sr;

inout[15:0] data_io_0;
inout[15:0] data_io_1;

//wire[15:0] datawrite_0;
//wire[15:0] datawrite_1;




output ce_0;
output ce_1;

reg ce_0, ce_1;

output oe;

reg oe;

output we;

reg we;

output ub_0;
output lb_0;

reg ub_0, lb_0;

output ub_1;
output lb_1;

reg ub_1, lb_1;

output clk_cpu; 
//reg clk_cpu;

input clk_sram;
input rst;

/*

always @(posedge clk_sram)
	begin
		we <= 1;
		oe <= 1;
		ce_0 <= 1;
		ce_1 <= 1;
		ub_0 <= 1;
		lb_0 <= 1;
		ub_1 <= 1;
		lb_1 <= 1;
		locked <= 1;
	end

*/

// prelude

reg ub_0_A;
reg lb_0_A;
reg ub_1_A;
reg lb_1_A;
reg ce_0_A;
reg ce_1_A;
reg oe_A;
reg we_A;
reg[17:0] addr_sr_A;
reg[31:0] dmem_out1_A;


// a special reset logic for the clk_sram domain

reg r1;

reg rst_sram;


always @(posedge clk_sram or posedge rst)
	begin
		if (rst)
			r1 <= 1'b1;
		else
			r1 <= 1'b0;
	end
	
always @(posedge clk_sram or posedge rst)
	begin
		if (rst)
			rst_sram <= 1'b1;
		else
			rst_sram <= r1;
	end



// the state machine for reading and writing to the SRAM

reg[3:0] state, next_st;

// infer tri-states

parameter	wait_sync_state = 0,
				normal_first = 1,
				first_after_read = 2,
				first_after_write = 3,
				second_state = 4,
				third_state = 5,
				fourth_state = 6,
				read_state_1 = 7,
				read_state_2 = 8,
				write_state_1 = 9,
				write_state_2 = 10,
				fifth_state = 11,
				sixth_state = 12;

reg[15:0] datawrite_0_Mem;
reg[15:0] datawrite_1_Mem;


assign data_io_0 = ((state == write_state_2) || (state == first_after_write)) ? datawrite_0_Mem : 16'bz;
assign data_io_1 = ((state == write_state_2) || (state == first_after_write)) ? datawrite_1_Mem : 16'bz;


	
wire[17:0] addr_sr_in;


assign addr_sr_in = amem[19:2];

//assign datawrite_0 = dmem_in[15:0];
//assign datawrite_1 = dmem_in[31:16];

always @(posedge clk_sram or posedge rst_sram)
	begin
		if (rst_sram)
			begin
				state <= normal_first;
				datawrite_0_Mem <= 16'b0;
				datawrite_0_Mem <= 16'b0;
			end
		else
			begin
				if (state == fourth_state)
					begin
						addr_sr_A <= addr_sr_in;
						state <= next_st;
					end
				else if (state == write_state_1)
					begin
						datawrite_0_Mem <= dmem_in[15:0];
						datawrite_1_Mem <= dmem_in[31:16];
						state <= next_st;
					end				
				else if (state == read_state_2)
					begin
						dmem_out <= dmem_out1_A;
						state <= next_st;
					end
				else
					begin
						state <= next_st;
					end
			end
	end

// next state combinatorial block:

always @(state or en or wen)
	begin
		case (state)
			normal_first:		begin
										next_st = second_state;
									end
			first_after_read:	begin
										next_st = second_state;
									end
			first_after_write:begin
										next_st = second_state;
									end
			second_state:		begin
										next_st = third_state;
									end
			third_state:		begin
										next_st = fourth_state;
									end
			fourth_state:		begin
										if ((|en) & (|wen))
											next_st = write_state_1;
										else if ((|en) & (~(|wen)))
											next_st = read_state_1;
										else
											next_st = fifth_state;
									end
			read_state_1:		begin
										next_st = read_state_2;
									end
			write_state_1:		begin
										next_st = write_state_2;
									end
			read_state_2:		begin
										next_st = first_after_read;
									end
			write_state_2:		begin
										next_st = first_after_write;
									end
			fifth_state:		begin
										next_st = sixth_state;
									end
			sixth_state:		begin
										next_st = normal_first;
									end
			default:				begin
										next_st = normal_first;
									end
		endcase
	end


// output combinatorial block


reg clk_cpu_A;

reg clk_cpu_i;

always @(posedge clk_sram or posedge rst_sram)
	begin
		if (rst_sram)
			clk_cpu_i <= 0;
		else
			clk_cpu_i <= clk_cpu_A;
	end

always @(state)
	begin
		case (state)
			normal_first, first_after_read, first_after_write,
			second_state, sixth_state, read_state_2, write_state_2:
			begin
				clk_cpu_A = 1'b1;
			end
			third_state, fourth_state, fifth_state,
			read_state_1, write_state_1:
			begin
				clk_cpu_A = 1'b0;
			end
			default:
			begin
				clk_cpu_A = 1'b0;
			end
		endcase
	end

BUFG bufg_clk (.I(clk_cpu_i), .O(clk_cpu));


//addr control

reg addrout_allow;
reg addrout_allow_A;

always @(addrout_allow)
	addr_sr = addrout_allow ? addr_sr_A : 18'bz;



always @(posedge clk_sram or posedge rst_sram)
	begin
		if (rst_sram)
			begin
				ub_0 <= 1;
				lb_0 <= 1;
				ub_1 <= 1;
				lb_1 <= 1;
				ce_0 <= 1;
				ce_1 <= 1;
				oe <= 1;
				we <= 1;
				addrout_allow <= 1'b0;
//				addr_sr <= 18'bz;
			end
		else
			begin
				ub_0 <= ub_0_A;
				lb_0 <= lb_0_A;
				ub_1 <= ub_1_A;
				lb_1 <= lb_1_A;
				ce_0 <= ce_0_A;
				ce_1 <= ce_1_A;
				oe <= oe_A;
				we <= we_A;
				addrout_allow <= addrout_allow_A;
//				addr_sr <= addr_sr_A;
			end
	end

always @(state, data_io_1, data_io_0)
	begin
		case (state)
			normal_first, first_after_write,
			second_state, third_state, fourth_state, fifth_state, sixth_state,
			write_state_1, write_state_2:
			begin
				dmem_out1_A = 32'b0;
			end
			read_state_1, read_state_2, first_after_read:
			begin
				dmem_out1_A = {data_io_1,data_io_0};
			end
			default:
			begin
				dmem_out1_A = 32'b0;
			end
		endcase
	end


always @(state or en or wen or addr_sr_in)
	begin
		case (state)
			normal_first,
			first_after_read,
			first_after_write,
			second_state,
			third_state,
			fifth_state, sixth_state
			:		begin
										ub_0_A = 1;
										lb_0_A = 1;
										ub_1_A = 1;
										lb_1_A = 1;
										ce_0_A = 1;
										ce_1_A = 1;
										oe_A = 1;
										we_A = 1;
										addrout_allow_A = 0;
										//addr_sr_A = 18'bz;
									end
			fourth_state:		begin
										if ((|en) & (~(|wen)))
											begin
												oe_A = 0;
												we_A = 1;
												addrout_allow_A = 1;
												//addr_sr_A = addr_sr_in;
												lb_0_A = ~en[0];
												ub_0_A = ~en[1];
												lb_1_A = ~en[2];
												ub_1_A = ~en[3];
												ce_0_A = ~|{en[1:0]};
												ce_1_A = ~|{en[3:2]};
											end
										else if ((|en) & (|wen))
											begin
												oe_A = 1;
												we_A = 1;
												addrout_allow_A = 1;
												//addr_sr_A = addr_sr_in;
												lb_0_A = ~wen[0];
												ub_0_A = ~wen[1];
												lb_1_A = ~wen[2];
												ub_1_A = ~wen[3];
												ce_0_A = ~|{en[1:0]};
												ce_1_A = ~|{en[3:2]};
											end 
										else
											begin
												ub_0_A = 1;
												lb_0_A = 1;
												ub_1_A = 1;
												lb_1_A = 1;
												ce_0_A = 1;
												ce_1_A = 1;
												oe_A = 1;
												we_A = 1;
												addrout_allow_A = 0;
												//addr_sr_A = 18'bz;
											end
									end
			read_state_1:		begin
										oe_A = 0;
										we_A = 1;
										addrout_allow_A = 1;
										//addr_sr_A = addr_sr_in;
										lb_0_A = ~en[0];
										ub_0_A = ~en[1];
										lb_1_A = ~en[2];
										ub_1_A = ~en[3];
										ce_0_A = ~|{en[1:0]};
										ce_1_A = ~|{en[3:2]};
									end
			read_state_2:		begin
										oe_A = 0;
										we_A = 1;
										addrout_allow_A = 1;
										//addr_sr_A = addr_sr_in;
										lb_0_A = ~en[0];
										ub_0_A = ~en[1];
										lb_1_A = ~en[2];
										ub_1_A = ~en[3];
										ce_0_A = ~|{en[1:0]};
										ce_1_A = ~|{en[3:2]};
									end
			write_state_1:		begin
										oe_A = 1;
										we_A = 0;
										addrout_allow_A = 1;
										//addr_sr_A = addr_sr_in;
										lb_0_A = ~wen[0];
										ub_0_A = ~wen[1];
										lb_1_A = ~wen[2];
										ub_1_A = ~wen[3];
										ce_0_A = ~|{en[1:0]};
										ce_1_A = ~|{en[3:2]};
									end
			write_state_2:		begin
										oe_A = 1;
										we_A = 1;
										addrout_allow_A = 1;
										//addr_sr_A = addr_sr_in;
										lb_0_A = ~wen[0];
										ub_0_A = ~wen[1];
										lb_1_A = ~wen[2];
										ub_1_A = ~wen[3];
										ce_0_A = ~|{en[1:0]};
										ce_1_A = ~|{en[3:2]};
									end
			default:				begin
										ub_0_A = 1;
										lb_0_A = 1;
										ub_1_A = 1;
										lb_1_A = 1;
										ce_0_A = 1;
										ce_1_A = 1;
										oe_A = 1;
										we_A = 1;
										addrout_allow_A = 0;
										//addr_sr_A = 18'bz;
									end
		endcase
	end


endmodule


module takt (clk, clk1, clk_cpu, clk_sram, locked, rst );

input clk;

input rst;

output locked;

output clk1;

output clk_cpu;

output clk_sram;



// DCM : In order to incorporate this function into the design,
// Verilog : the following instance declaration needs to be placed
// instance : in the body of the design code. The instance name
// declaration : (DCM_inst) and/or the port declarations within the
// code : parenthesis maybe changed to properly reference and
// : connect this function to the design. Unused inputs
// : and outputs may be removed or commented out.
// <-----Cut code below this line---->
// DCM: Digital Clock Manager Circuit for Virtex-II/II-Pro and Spartan-3
// The current version of the Xilinx HDL Libraries Guide




wire CLKIN = clk;

wire clkfx;
wire clkdv;
wire clk0;

wire CLKFB = clk0;

assign clk_cpu = clkdv;
assign clk_sram = clkfx;

wire[7:0] STATUS;

DCM DCM_inst (
.CLK0(CLK01), // 0 degree DCM CLK ouptput
.CLK180(CLK180), // 180 degree DCM CLK output
.CLK270(CLK270), // 270 degree DCM CLK output
.CLK2X(CLK2X), // 2X DCM CLK output
.CLK2X180(CLK2X180), // 2X, 180 degree DCM CLK out
.CLK90(CLK90), // 90 degree DCM CLK output
.CLKDV(CLKDV1), // Divided DCM CLK out (CLKDV_DIVIDE)
.CLKFX(CLKFX1), // DCM CLK synthesis out (M/D)
.CLKFX180(CLKFX180), // 180 degree CLK synthesis out
.LOCKED(LOCKED1), // DCM LOCK status output
.PSDONE(PSDONE), // Dynamic phase adjust done output
.STATUS(STATUS), // 8-bit DCM status bits output
.CLKFB(CLKFB), // DCM clock feedback
.CLKIN(CLKIN), // Clock input (from IBUFG, BUFG or DCM)
.PSCLK(PSCLK), // Dynamic phase adjust clock input
.PSEN(PSEN), // Dynamic phase adjust enable input
.PSINCDEC(PSINCDEC), // Dynamic phase adjust increment/decrement
.RST(rst) // DCM asynchronous reset input
);

BUFG bufg_1 (.I(CLKFX1), .O(clkfx));
BUFG bufg_2 (.I(CLKDV1), .O(clkdv));

BUFG bufg_3 (.I(CLK01), .O(clk0));

assign locked = LOCKED1;
assign clk1 = clk0;

// The following defparam declarations are only necessary if you
// wish to change the default behavior
// of the DCM. If the instance name is changed, these defparams need
// to be updated accordingly.
defparam DCM_inst.CLKDV_DIVIDE = 4.0; 
// Divide by:
//1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0,5.5,6.0,6.5
//7.0,7.5,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0 or 16.0
defparam DCM_inst.CLKFX_DIVIDE = 2;
// Can be any integer from 1 to 32
defparam DCM_inst.CLKFX_MULTIPLY = 3; 
// Can be any integer from 2 to 32
defparam DCM_inst.CLKIN_DIVIDE_BY_2 = "FALSE"; 
// TRUE/FALSE to enable CLKIN divide by two feature
defparam DCM_inst.CLKIN_PERIOD = 20.0; 
// Specify period of input clock
defparam DCM_inst.CLKOUT_PHASE_SHIFT = "NONE"; 
// Specify phase shift of NONE, FIXED or VARIABLE
defparam DCM_inst.CLK_FEEDBACK = "1X"; // Specify clock feedback of NONE, 1X or 2X

defparam DCM_inst.DESKEW_ADJUST = "SYSTEM_SYNCHRONOUS"; 
//SOURCE_SYNCHRONOUS, SYSTEM_SYNCHRONOUS or
// an integer from 0 to 15
defparam DCM_inst.DFS_FREQUENCY_MODE = "LOW"; 
// HIGH or LOW frequency mode for frequency synthesis
defparam DCM_inst.DLL_FREQUENCY_MODE = "LOW"; 
// HIGH or LOW frequency mode for DLL
defparam DCM_inst.DUTY_CYCLE_CORRECTION = "TRUE"; 
// Duty cycle correction, TRUE or FALSE
defparam DCM_inst.FACTORY_JF = 16'hC080; 
// FACTORY JF Values
defparam DCM_inst.PHASE_SHIFT = 0; 
// Amount of fixed phase shift from -255 to 255
defparam DCM_inst.STARTUP_WAIT = "FALSE"; 
// Delay configuration DONE until DCM LOCK, TRUE/FALSE

// End of DCM_inst instantiation




endmodule




