`timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: DJ Delorie // // Create Date: 19:07:20 04/05/2009 // Design Name: // Module Name: top1 // Project Name: // Target Devices: Spartan 3A // Tool versions: // Description: This is the implementation-specific pinout connecting the SDRAM // driver to the specific MCU and SDRAM pins. It also does fpga-specific // setup, clock generation, etc. // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// module top1(c_data, c_addr, c_wrl, c_wrh, c_rd, c_bclk, c_ale, c_rdy, f_io_0, f_io_1, f_io_2, f_io_3, r_addr, c_bclk2, r_data, r_dqm, r_we, r_cas, r_ras, r_cs, r_ba, r_clk, r_cke, c_rd2, c_rdy2, c_wrl2, c_wrh2, r_clk2, r_clk3 ); inout [15:0] c_data; input [23:0] c_addr; input c_wrl; input c_wrh; input c_rd; input c_bclk; input c_ale; output c_rdy; input f_io_0; input f_io_1; input f_io_2; input f_io_3; output [11:0] r_addr; inout [15:0] r_data; output [1:0] r_dqm; output r_we; output r_cas; output r_ras; output r_cs; output [1:0] r_ba; output r_clk; output r_cke; output c_bclk2; output c_rd2; output c_rdy2; output c_wrl2; output c_wrh2; output r_clk2; output r_clk3; /* Chip reset is active HIGH. */ wire chip_reset = f_io_0; /* Chip select is active LOW. */ //wire chip_select = f_io_1; wire chip_select = 0; reg sdram_select; reg la_select; wire [7:0] wclk_status; wire wclk_stopped = wclk_status[2]; wire wclk_locked; dcm_resetter wclk_resetter (chip_reset, ~wclk_stopped, c_bclk, wclk_reset); wire r_wclk_unbuffered; wire simple_reset = chip_reset | wclk_reset; wire mcu_rdy; wire [4:0] djstate; wire [4:0] djrstate; wire [4:0] djnewstate; /* The M32C's external address space is 0x0010_0000 to 0x00EF_FFFF */ /* We have 8 Mb of SDRAM at 0x0040_0000 - 0x00BF_FFFF */ /* We have 1 Mb for the logic analyzer at 0x0010_0000 - 0x001F_FFFF */ /* Note that A23 is inverted at the chip :-P */ always @(c_addr or chip_select) begin sdram_select = 1; la_select = 1; case ({~c_addr[23], c_addr[22:20]}) 4'h0: /* reserved for on-chip ram, peripherals, data flash */ ; 4'h1: la_select = chip_select; 4'h2: /* available */ ; 4'h3: /* available */ ; 4'h4: sdram_select = chip_select; 4'h5: sdram_select = chip_select; 4'h6: sdram_select = chip_select; 4'h7: sdram_select = chip_select; 4'h8: sdram_select = chip_select; 4'h9: sdram_select = chip_select; 4'ha: sdram_select = chip_select; 4'hb: sdram_select = chip_select; 4'hc: /* available */ ; 4'hd: /* available */ ; 4'he: /* available */ ; 4'hf: /* reserved for on-chip program flash */ ; endcase end OBUF rd2_iob (.I(c_rd), .O(c_rd2)); //OBUF wrl2_iob (.I(c_wrl), .O(c_wrl2)); //OBUF wrh2_iob (.I(c_wrh), .O(c_wrh2)); OBUF rdy2_iob (.I(c_rdy), .O(c_rdy2)); //OBUF wrl2_iob (.I(r_data[0]), .O(c_wrl2)); OBUF wrl2_iob (.I(mcu_rdy), .O(c_wrl2)); OBUF wrh2_iob (.I(la_select), .O(c_wrh2)); //OBUF rdy2_iob (.I(la_select), .O(c_rdy2)); //OBUF bclk2_iob (.I(c_bclk), .O(c_bclk2)); OBUF bclk2_iob (.I(la_select), .O(c_bclk2)); // 20.0MHz * 13/2 = 130 MHz // 2.5MHz * 32/1 = 80 MHz DCM_SP #( // .CLKDV_DIVIDE(2.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 .CLKFX_DIVIDE(2), // Can be any integer from 1 to 32 .CLKFX_MULTIPLY(13), // Can be any integer from 2 to 32 .CLKIN_DIVIDE_BY_2("FALSE"), // TRUE/FALSE to enable CLKIN divide by two feature .CLKIN_PERIOD(50), // Specify period of input clock .CLKOUT_PHASE_SHIFT("NONE"), // Specify phase shift of NONE, FIXED or VARIABLE .CLK_FEEDBACK("NONE"), // Specify clock feedback of NONE, 1X or 2X .DESKEW_ADJUST("SOURCE_SYNCHRONOUS"), // SOURCE_SYNCHRONOUS, SYSTEM_SYNCHRONOUS or // an integer from 0 to 15 .DLL_FREQUENCY_MODE("LOW"), // HIGH or LOW frequency mode for DLL .DUTY_CYCLE_CORRECTION("TRUE"), // Duty cycle correction, TRUE or FALSE .PHASE_SHIFT(0), // Amount of fixed phase shift from -255 to 255 .STARTUP_WAIT("FALSE") // Delay configuration DONE until DCM LOCK, TRUE/FALSE ) ram_wclock ( // .CLK0(wclk_0), // 0 degree DCM CLK output // .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(CLKDV), // Divided DCM CLK out (CLKDV_DIVIDE) .CLKFX(r_wclk_unbuffered), // DCM CLK synthesis out (M/D) // .CLKFX180(CLKFX180), // 180 degree CLK synthesis out // .LOCKED(wclk_locked), // DCM LOCK status output .STATUS(wclk_status), // 8-bit DCM status bits output // .CLKFB(wclk_0b), // DCM clock feedback .CLKIN(c_bclk), // 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 // .PSDONE(PSDONE), // Dynamic phase adjust done output .RST(wclk_reset) // DCM asynchronous reset input ); // In theory, the 3A-5 memory goes to 320 MHz. DCM_SP #( .CLKFX_DIVIDE(1), // Can be any integer from 1 to 32 .CLKFX_MULTIPLY(13), // Can be any integer from 2 to 32 .CLKIN_PERIOD(50), // Specify period of input clock .CLK_FEEDBACK("NONE"), // Specify clock feedback of NONE, 1X or 2X .DESKEW_ADJUST("SOURCE_SYNCHRONOUS"), // SOURCE_SYNCHRONOUS, SYSTEM_SYNCHRONOUS or // an integer from 0 to 15 .DLL_FREQUENCY_MODE("LOW"), // HIGH or LOW frequency mode for DLL .DUTY_CYCLE_CORRECTION("TRUE"), // Duty cycle correction, TRUE or FALSE .CLKOUT_PHASE_SHIFT("FIXED"), // Specify phase shift of NONE, FIXED or VARIABLE .PHASE_SHIFT(64), // Amount of fixed phase shift from -255 to 255 .STARTUP_WAIT("FALSE") // Delay configuration DONE until DCM LOCK, TRUE/FALSE ) la_clock ( // .CLK0(wclk_0), // 0 degree DCM CLK output // .CLK90(CLK90), // 90 degree DCM CLK output // .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 // .CLKDV(CLKDV), // Divided DCM CLK out (CLKDV_DIVIDE) .CLKFX(la_clk0_u), // DCM CLK synthesis out (M/D) .CLKFX180(la_clk1_u), // 180 degree CLK synthesis out // .LOCKED(wclk_locked), // DCM LOCK status output .STATUS(laclk_status), // 8-bit DCM status bits output // .CLKFB(wclk_0b), // DCM clock feedback .CLKIN(c_bclk), // Clock input (from IBUFG, BUFG or DCM) .RST(wclk_reset) // DCM asynchronous reset input ); BUFG la_clk0_buf (.I(la_clk0_u), .O(la_clk0)); BUFG la_clk1_buf (.I(la_clk1_u), .O(la_clk1)); // This ties the r_wclk signal to the global clock grid BUFG r_wclk_buf (.I(r_wclk_unbuffered), .O(r_wclk)); //BUFG r_wclk_buf0 (.I(wclk_0), .O(wclk_0b)); //IBUFG #(.IBUF_DELAY_VALUE(0)) r_rclk_buf (.I //wire [2:0] r_rclk_delay = {f_io_3, f_io_2, f_io_1}; //IBUF_DLY_ADJ #(.DELAY_OFFSET("OFF")) r_rclk_buf (.I(r_clk), .O(r_rclk), .S(r_rclk_delay)); // This ties the r_clk pins OBUF rclk1_iob (.I(r_wclk), .O(r_clk)); OBUF rclk2_iob (.I(r_wclk), .O(r_clk2)); OBUF rclk3_iob (.I(r_wclk), .O(r_clk3)); wire la_rdy; wire la_trigger = 0; wire [35:0] la_samples0; wire [35:0] la_samples1; wire djstate_21 = (djrstate == 21); assign la_samples0[15:0] = r_data; assign la_samples0[27:16] = r_addr; assign la_samples0[29:28] = r_dqm; assign la_samples0[30] = r_ras; assign la_samples0[31] = r_cas; assign la_samples0[32] = r_we; assign la_samples0[33] = r_wclk; assign la_samples0[34] = sdram_select; assign la_samples0[35] = c_bclk; assign la_samples1[15:0] = c_data; //assign la_samples1[25:16] = c_addr; assign la_samples1[20:16] = djnewstate; assign la_samples1[25:21] = djstate; assign la_samples1[30:26] = c_addr[4:0]; assign la_samples1[31] = djstate_21; assign la_samples1[32] = c_rd; assign la_samples1[33] = c_wrl; assign la_samples1[34] = c_wrh; assign la_samples1[35] = c_rdy; logic_analyzer log_anal ( .reset(simple_reset), .clock0(la_clk0), .clock1(la_clk0), .mcu_cs(la_select), .mcu_nwrl(c_wrl), .mcu_nwrh(c_wrh), .mcu_nrd(c_rd), .mcu_ready(la_rdy), .mcu_addr(c_addr[23:0]), .mcu_data(c_data), .samples0(la_samples0), .samples1(la_samples1), .trigger(la_trigger) ); djsdram_simple1 dut ( .reset(simple_reset), .mcu_cs(sdram_select), .mcu_nwrl(c_wrl), .mcu_nwrh(c_wrh), .mcu_nrd(c_rd), .mcu_ready(mcu_rdy), .mcu_addr(c_addr), .mcu_data(c_data), .ram_wclock(r_wclk), .ram_rclock(r_rclk), .ram_bank(r_ba), .ram_clock_enable(r_cke), .ram_ncs(r_cs), .ram_nras(r_ras), .ram_ncas(r_cas), .ram_nwe(r_we), .ram_dqm(r_dqm), .ram_addr(r_addr), .ram_data(r_data), .state(djstate), .newstate(djnewstate), .rstate(djrstate) ); //assign c_rdy = mcu_rdy & ~wclk_stopped; //assign c_rdy = 1; reg c_rdy; always @(mcu_rdy or wclk_stopped or sdram_select or la_select or la_rdy) begin if (wclk_stopped) c_rdy = 0; else if (~sdram_select) c_rdy = mcu_rdy; else if (~la_select) c_rdy = la_rdy; else c_rdy = 1; end endmodule module dcm_resetter (reset_in, locked, clock, reset_out); input reset_in; input locked; input clock; output reset_out; reg [2:0] timer; reg reset_out; reg prev_locked; reg tmp_locked; always @(negedge locked or negedge prev_locked) begin if (~prev_locked) tmp_locked <= 1; else tmp_locked <= 0; end always @(negedge clock) begin prev_locked <= tmp_locked; if (reset_in) begin reset_out <= 1; prev_locked <= 1; timer <= 7; end else if (~prev_locked) begin timer <= 7; reset_out <= 1; end else if (timer) timer <= timer - 1; else reset_out <= 0; end endmodule // dcm_resetter