diff --git a/rtl/apple1_mist.sv b/rtl/apple1_mist.sv index b094f26..587fbb1 100644 --- a/rtl/apple1_mist.sv +++ b/rtl/apple1_mist.sv @@ -117,7 +117,6 @@ wire pll_locked; wire sys_clock; // cpu x 7 x 8 system clock (sdram.v) wire osd_clock; // cpu x 7 x 2 for the OSD menu -wire sdram_clock_ph; // cpu x 7 x 8 phase shifted -2.5 ns pll pll ( @@ -126,7 +125,7 @@ pll pll .c0( osd_clock ), // cpu x 7 x 2 video clock for OSD menu .c2( sys_clock ), // cpu x 7 x 8 system clock (sdram.v) - .c3( sdram_clock_ph ) // cpu x 7 x 8 phase shifted -2.5 ns + .c3( SDRAM_CLK ) // cpu x 7 x 8 phase shifted -2.5 ns ); /******************************************************************************************/ @@ -173,55 +172,21 @@ downloader /******************************************************************************************/ /******************************************************************************************/ -/***************************************** @apple1 ****************************************/ +/***************************************** @ram *******************************************/ /******************************************************************************************/ /******************************************************************************************/ -// RAM -ram ram( +wire [7:0] ram_dout; + +// low system RAM +ram #(.SIZE(16384)) ram( .clk (sys_clock ), - .ena (cpu_clken ), // fake does not work .address(sdram_addr[15:0]), - .w_en (sdram_wr ), + .w_en (sdram_wr & ram_cs), .din (sdram_din ), - .dout (sdram_dout) + .dout (ram_dout ) ); -// SDRAM control signals - -wire [24:0] sdram_addr; -wire [7:0] sdram_din; -wire sdram_wr; -wire sdram_rd; -wire [7:0] sdram_dout; - -assign dummy = is_downloading && download_wr; - -always @(*) begin - if(is_downloading && download_wr) begin - sdram_addr <= download_addr; - sdram_din <= download_data; - sdram_wr <= download_wr; - sdram_rd <= 1'b1; - end - /* - else if(eraser_busy) begin - sdram_addr <= eraser_addr; - sdram_din <= eraser_data; - sdram_wr <= eraser_wr; - sdram_rd <= 1'b1; - end - */ - else begin - sdram_addr <= { 9'b0, cpu_addr[15:0] }; - sdram_din <= cpu_dout; - sdram_wr <= cpu_wr; - sdram_rd <= cpu_rd; - end -end - -assign LED = ~dummy; - // WozMon ROM wire [7:0] rom_dout; rom_wozmon rom_wozmon( @@ -230,6 +195,7 @@ rom_wozmon rom_wozmon( .dout(rom_dout) ); +/* // Basic ROM wire [7:0] basic_dout; rom_basic rom_basic( @@ -237,6 +203,51 @@ rom_basic rom_basic( .address(cpu_addr[11:0]), .dout(basic_dout) ); +*/ + +// Basic RAM +wire [7:0] basic_dout; +ram #(.SIZE(4096)) rom_basic( + .clk(sys_clock), + .address({4'b000, sdram_addr[11:0]}), + .w_en (sdram_wr & basic_cs), + .din (sdram_din ), + .dout (basic_dout) +); + + +/******************************************************************************************/ +/******************************************************************************************/ +/***************************************** @apple1 ****************************************/ +/******************************************************************************************/ +/******************************************************************************************/ + +// SDRAM control signals + +wire [24:0] sdram_addr; +wire [7:0] sdram_din; +wire sdram_wr; +wire sdram_rd; +wire [7:0] sdram_dout; + +always @(*) begin + if(is_downloading && download_wr) begin + sdram_addr <= download_addr; + sdram_din <= download_data; + sdram_wr <= download_wr; + sdram_rd <= 1'b1; + end + else begin + sdram_addr <= { 9'b0, cpu_addr[15:0] }; + sdram_din <= cpu_dout; + sdram_wr <= cpu_wr; + sdram_rd <= 1'b1; + end +end + +wire dummy = is_downloading && download_wr; +assign LED = ~dummy; + // ram interface wire [15:0] cpu_addr; @@ -244,13 +255,15 @@ wire [7:0] cpu_dout; wire cpu_rd; wire cpu_wr; -wire ram_cs = cpu_addr < 16'hc000; // 0x0000 -> 0x1FFF -wire basic_cs = cpu_addr >= 16'hE000 && cpu_addr <= 16'hEFFF; // 0xE000 -> 0xEFFF -wire rom_cs = cpu_addr >= 16'hFF00 && cpu_addr <= 16'hFFFF; // 0xFF00 -> 0xFFFF +wire ram_cs = sdram_addr < 'h4000; // 0x0000 -> 0x3FFF +wire sdram_cs = sdram_addr >= 'h4000 && sdram_addr <= 'hBFFF; // 0x4000 -> 0xBFFF +wire basic_cs = sdram_addr >= 'hE000 && sdram_addr <= 'hEFFF; // 0xE000 -> 0xEFFF +wire rom_cs = sdram_addr >= 'hFF00; // 0xFF00 -> 0xFFFF -wire [7:0] bus_dout = basic_cs ? basic_dout : - rom_cs ? rom_dout : - ram_cs ? sdram_dout : +wire [7:0] bus_dout = rom_cs ? rom_dout : + basic_cs ? basic_dout : + sdram_cs ? sdram_dout : + ram_cs ? ram_dout : 8'b0; apple1 apple1 @@ -324,7 +337,7 @@ mist_video .VGA_G(VGA_G), .VGA_B(VGA_B), .VGA_VS(VGA_VS), - .VGA_HS(VGA_HS), + .VGA_HS(VGA_HS) ); /******************************************************************************************/ @@ -368,7 +381,6 @@ user_io ( // SDRAM control signals assign SDRAM_CKE = 1'b1; -assign SDRAM_CLK = sdram_clock_ph; // same as sys_clock but with -2.5 ns phase /* wire [24:0] sdram_addr; @@ -397,6 +409,7 @@ always @(*) begin sdram_rd <= cpu_rd; end end +*/ sdram sdram ( // interface to the MT48LC16M16 chip @@ -412,8 +425,8 @@ sdram sdram ( // system interface .clk ( sys_clock ), .clkref ( cpu_clock ), - .init ( !pll_locked ), - + .init ( !pll_locked ), + // cpu interface .din ( sdram_din ), .addr ( sdram_addr ), @@ -421,21 +434,22 @@ sdram sdram ( .oe ( sdram_rd ), .dout ( sdram_dout ) ); -*/ /******************************************************************************************/ /******************************************************************************************/ -/***************************************** @clock_ena *************************************/ +/***************************************** @clock *****************************************/ /******************************************************************************************/ /******************************************************************************************/ wire cpu_clken; // provides the cpu clock enable signal derived from main clock wire pixel_clken; // provides the cpu clock enable signal derived from main clock +wire cpu_clock; clock clock( - .sys_clock ( sys_clock ), // input: main clock + .sys_clock ( sys_clock ), // input: main clock .reset ( reset_button ), // input: reset signal - + + .cpu_clock ( cpu_clock ), .cpu_clken ( cpu_clken ), // output: cpu clock enable .pixel_clken( pixel_clken ) // output: pixel clock enable ); diff --git a/rtl/clock.v b/rtl/clock.v index b21347a..4356c20 100644 --- a/rtl/clock.v +++ b/rtl/clock.v @@ -5,7 +5,9 @@ module clock input reset, // reset output cpu_clken, // 1MHz clock enable for the CPU - output pixel_clken // 7MHz clock enable for the display + output pixel_clken, // 7MHz clock enable for the display + + output cpu_clock ); localparam CPU_DIVISOR = 56; // (sys_clock / CPU_DIVISOR) = 1 MHz @@ -27,10 +29,13 @@ localparam PIXEL_DIVISOR = 8; // (sys_clock / PIXEL_DIVISOR) = 7 MHz if (counter_pixel == (PIXEL_DIVISOR-1)) counter_pixel <= 0; else counter_pixel <= counter_pixel + 1; + end end assign cpu_clken = counter_cpu == 0; assign pixel_clken = counter_pixel == 0; - + + assign cpu_clock = counter_pixel < 4 ? 1 : 0; + endmodule diff --git a/rtl/pll.v b/rtl/pll.v index 77902f4..e2e7a6b 100644 --- a/rtl/pll.v +++ b/rtl/pll.v @@ -266,12 +266,12 @@ endmodule // Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000" // Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "0.00000000" // Retrieval info: PRIVATE: PHASE_SHIFT2 STRING "0.00000000" -// Retrieval info: PRIVATE: PHASE_SHIFT3 STRING "-2.50000000" +// Retrieval info: PRIVATE: PHASE_SHIFT3 STRING "-2500.00000000" // Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0" // Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg" // Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "deg" // Retrieval info: PRIVATE: PHASE_SHIFT_UNIT2 STRING "ps" -// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT3 STRING "ns" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT3 STRING "ps" // Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0" // Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "1" // Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1" diff --git a/rtl/sdram.v b/rtl/sdram.v index 5ff686a..348ffc8 100644 --- a/rtl/sdram.v +++ b/rtl/sdram.v @@ -24,10 +24,10 @@ module sdram ( // interface to the MT48LC16M16 chip inout [15:0] sd_data, // 16 bit bidirectional data bus - output [12:0] sd_addr, // 13 bit multiplexed address bus + output [12:0] sd_addr, // 13 bit multiplexed address bus for row/col select output [1:0] sd_dqm, // two byte masks - output [1:0] sd_ba, // two banks - output sd_cs, // a single chip select + output [1:0] sd_ba, // four banks + output sd_cs, // chip select output sd_we, // write enable output sd_ras, // row address select output sd_cas, // columns address select @@ -37,6 +37,8 @@ module sdram ( input clk, // sdram is accessed at up to 128MHz input clkref, // reference clock to sync to + // input [2:0] q, + input [7:0] din, // data input from chipset/cpu output [7:0] dout, // data output to chipset/cpu input [24:0] addr, // 25 bit byte address @@ -44,26 +46,33 @@ module sdram ( input we // cpu/chipset requests write ); -// no burst configured +// --------------------------------------------------------------------- +// ------------------------ sdram configuration ------------------------ +// --------------------------------------------------------------------- +// MODE is sent as address on reset = 2 +// PRECHARGE_ADDR is sent as address on reset = 13 localparam RASCAS_DELAY = 3'd3; // tRCD>=20ns -> 2 cycles@64MHz localparam BURST_LENGTH = 3'b000; // 000=none, 001=2, 010=4, 011=8 localparam ACCESS_TYPE = 1'b0; // 0=sequential, 1=interleaved localparam CAS_LATENCY = 3'd2; // 2/3 allowed localparam OP_MODE = 2'b00; // only 00 (standard operation) allowed localparam NO_WRITE_BURST = 1'b1; // 0= write burst enabled, 1=only single access write - localparam MODE = { 3'b000, NO_WRITE_BURST, OP_MODE, CAS_LATENCY, ACCESS_TYPE, BURST_LENGTH}; +localparam PRECHARGE_ADDR = 13'b0010000000000; // --------------------------------------------------------------------- // ------------------------ cycle state machine ------------------------ // --------------------------------------------------------------------- -localparam STATE_IDLE = 3'd0; // first state in cycle -localparam STATE_CMD_START = 3'd1; // state in which a new command can be started -localparam STATE_CMD_CONT = STATE_CMD_START + RASCAS_DELAY - 3'd1; // 4 command can be continued -localparam STATE_LAST = 3'd7; // last state in cycle +// there are 8 states (0-7) tracked by "q" + +localparam STATE_IDLE = 3'd0; // first state in cycle +localparam STATE_CMD_START = 3'd1; // state in which a new command can be started +localparam STATE_CMD_CONT = STATE_CMD_START+RASCAS_DELAY-3'd1; // 4 command can be continued +localparam STATE_LAST = 3'd7; // last state in cycle reg [2:0] q /* synthesis noprune */; + always @(posedge clk) begin // 32Mhz counter synchronous to 4 Mhz clock // force counter to pass state 5->6 exactly after the rising edge of clkref @@ -74,6 +83,7 @@ always @(posedge clk) begin q <= q + 3'd1; end + // --------------------------------------------------------------------- // --------------------------- startup/reset --------------------------- // --------------------------------------------------------------------- @@ -92,25 +102,25 @@ end // --------------------------------------------------------------------- // all possible commands -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; +localparam CMD_INHIBIT = 4'b1111; // initial state +localparam CMD_NOP = 4'b0111; // (not used here) +localparam CMD_ACTIVE = 4'b0011; // command starts, done at STATE_IDLE +localparam CMD_READ = 4'b0101; // read commanddone, done at STATE_CMD_CONT +localparam CMD_WRITE = 4'b0100; // write command, done at STATE_CMD_CONT +localparam CMD_BURST_TERMINATE = 4'b0110; // (not used here) +localparam CMD_PRECHARGE = 4'b0010; // sends a precharge address, done when reset=13 and STATE_IDLE +localparam CMD_AUTO_REFRESH = 4'b0001; // refresh command, done at STATE_IDLE +localparam CMD_LOAD_MODE = 4'b0000; // sends MODE (sdram config), done when reset=2 and STATE_IDLE reg [3:0] sd_cmd; // current command sent to sd ram // drive control signals according to current command -assign sd_cs = sd_cmd[3]; -assign sd_ras = sd_cmd[2]; -assign sd_cas = sd_cmd[1]; -assign sd_we = sd_cmd[0]; +assign sd_cs = sd_cmd[3]; // in negated logic +assign sd_ras = sd_cmd[2]; // in negated logic +assign sd_cas = sd_cmd[1]; // in negated logic +assign sd_we = sd_cmd[0]; // in negated logic -assign sd_data = we?{din, din}:16'bZZZZZZZZZZZZZZZZ; +assign sd_data = we ? {din, din} : 16'bZZZZZZZZZZZZZZZZ; assign dout = sd_data[7:0]; @@ -118,30 +128,34 @@ always @(posedge clk) begin sd_cmd <= CMD_INHIBIT; if(reset != 0) begin + // SDRAM is resetting, counting from 31 to 0 if(q == STATE_IDLE) begin if(reset == 13) sd_cmd <= CMD_PRECHARGE; if(reset == 2) sd_cmd <= CMD_LOAD_MODE; end end else begin + // normal run if(q == STATE_IDLE) begin if(we || oe) sd_cmd <= CMD_ACTIVE; else sd_cmd <= CMD_AUTO_REFRESH; - end else if(q == STATE_CMD_CONT) begin + end + else if(q == STATE_CMD_CONT) begin if(we) sd_cmd <= CMD_WRITE; else if(oe) sd_cmd <= CMD_READ; end end end - -wire [12:0] reset_addr = (reset == 13)?13'b0010000000000:MODE; - -wire [12:0] run_addr = - (q == STATE_CMD_START)?addr[20:8]:{ 4'b0010, addr[23], addr[7:0]}; -assign sd_addr = (reset != 0)?reset_addr:run_addr; +// address during reset +wire [12:0] reset_addr = (reset == 13) ? PRECHARGE_ADDR : MODE; -assign sd_ba = addr[22:21]; +// address during normal run +wire [12:0] row = addr[20:8]; +wire [12:0] col = { 4'b0010, addr[23], addr[7:0] }; +wire [12:0] run_addr = (q == STATE_CMD_START)? row : col; -assign sd_dqm = 2'b00; +assign sd_addr = (reset != 0) ? reset_addr : run_addr; +assign sd_ba = addr[22:21]; // bank is taken from cpu address high bits +assign sd_dqm = 2'b00; // no mask endmodule