//a500_8mb, modification of LDV's (LordV) a600_8mb memory from year 2007 //NOTE: READ-MODIFY-WRITE cycles not looked at. (neither by of 68000 nor dram side view) This mode not used on Amiga? or is it? //12.9.2018, v6x board mod //5-june-2017, mod for v42 pcb, do use programmable grounds, but use also preserve unused inputs //apr-18/19-2017: compiler settings: optimise speed, use pin feed back:no, ... jedec id code "1904" //apr-18-2017 take cpu clk and reset direct from io pins, don't use pcb loops to gsr,gck like in v 3003 // make dram adresses driven high(or low) when cpu address strobe negated //MAR-2017 -used to make jedec file for cpld with used id code "3003" -- later note: version 3003 is malfunctioning, don't use //feb-2017 //dec-2016 a600_8mb altera ldv 2007 to other verilog (xilinx) compatible and all dram adress (also dram_ma2..ma9) cpld muxed -mkl // older xilinx webpack 4.2 verilog doesn't understand "always @*" but ISE 14.7 does (Verilog 2001) module a500_8mb( cpu_clk,cpu_nreset, cpu_a21,cpu_a22,cpu_a23, cpu_a1, cpu_a2, cpu_a3, cpu_a4, cpu_a5, cpu_a6, cpu_a7, cpu_a8, cpu_a9, cpu_a10, cpu_a11, cpu_a12, cpu_a13, cpu_a14, cpu_a15, cpu_a16,cpu_a17,cpu_a18,cpu_a19,cpu_a20, cpu_d12,cpu_d13,cpu_d14,cpu_d15, cpu_nas,cpu_nlds,cpu_nuds, dram_nras, //1 ram chip //dram_nras0,dram_nras1,dram_nras2,dram_nras3, //4-chip ram dram_nlcas,dram_nucas, dram_ma0,dram_ma1, dram_ma2,dram_ma3,dram_ma4,dram_ma5,dram_ma6,dram_ma7,dram_ma8,dram_ma9, dram_ma10,dram_ma11, //mux_switch, //internal address multiplexers only, no output nconfigin,nconfigout, // nledout, cpu_rnw, dram_nwr, dram_noe ); output dram_noe; input cpu_rnw; output dram_nwr; input nconfigin; output nconfigout; // output nledout; reg nconfigout; reg nledout; reg dram_nwr; reg dram_noe; always @* begin dram_nwr <= cpu_rnw; end input cpu_a21,cpu_a22,cpu_a23; // cpu high addresses input cpu_a1, cpu_a2, cpu_a3, cpu_a4, cpu_a5, cpu_a6; // cpu low addresses for autoconfig input cpu_a16,cpu_a17,cpu_a18,cpu_a19,cpu_a20; // cpu high addresses for autoconfig input cpu_a7, cpu_a8, cpu_a9, cpu_a10, cpu_a11, cpu_a12, cpu_a13, cpu_a14, cpu_a15; //other cpu addresses //"inout" as "reg" is not supported in verilog generally //As cpu d12..15 is not used to input to cpld, changing "inout" to "output" with tri-state might suffice for compatibility output cpu_d12,cpu_d13,cpu_d14,cpu_d15; // autoconfig data out (with tristate output disable highZ) //inout cpu_d12,cpu_d13,cpu_d14,cpu_d15; // autoconfig data in-out reg cpu_d12,cpu_d13,cpu_d14,cpu_d15; input cpu_nas,cpu_nlds,cpu_nuds; // cpu bus control signals input cpu_clk; // cpu clock input cpu_nreset; // cpu system reset // output dram_nras0,dram_nras1,dram_nras2,dram_nras3; // reg dram_nras0,dram_nras1,dram_nras2,dram_nras3; // /RAS dram signals output dram_nras; //one 4mx16 ram only reg dram_nras; output dram_nlcas,dram_nucas; reg dram_nlcas,dram_nucas; // /CAS dram signals output dram_ma0,dram_ma1; reg dram_ma0,dram_ma1; // DRAM MAx addresses output dram_ma2,dram_ma3,dram_ma4,dram_ma5,dram_ma6,dram_ma7,dram_ma8,dram_ma9; reg dram_ma2,dram_ma3,dram_ma4,dram_ma5,dram_ma6,dram_ma7,dram_ma8,dram_ma9; // more DRAM MAx addresses output dram_ma10,dram_ma11; //for 4mx16 chip reg dram_ma10,dram_ma11; // output mux_switch; no external MUX switching reg mux_switch; // internal MUX switching reg [3:0] datout; // data out wire [7:0] high_addr; wire [5:0] low_addr; //ERROR:Xst:902 - "../a500_8mb.v" line 170: Unexpected which_ras event in always block sensitivity list. // reg which_ras[0:3]; // which /RAS signal to activate (based on a21-a23) // reg [3:0] which_ras; //changed [] position// changed order from 3..0 from 0..3 reg mem_selected; reg rfsh_ras,rfsh_cas; // refresh /RAS, /CAS generators reg access_ras,access_cas; // normal access /RAS, /CAS generators reg read_cycle; // if current cycle is read cycle reg write_cycle; reg autoconf_on; reg cpu_nas_z; // cpu /AS with 1 clock latency //use refresh to 4M16 chip when rfsh_select = 00 reg [1:0] rfsh_select; // for cycling refresh over every of four chips assign high_addr = {cpu_a23,cpu_a22,cpu_a21,cpu_a20,cpu_a19,cpu_a18,cpu_a17,cpu_a16}; assign low_addr = {cpu_a6,cpu_a5,cpu_a4,cpu_a3,cpu_a2,cpu_a1}; // chip selector decoder always @* begin casex( high_addr ) 8'b001xxxxx: // $200000-$3fffff begin // {which_ras[0],which_ras[1],which_ras[2],which_ras[3]} <= 4'b1000; // /RAS0 mem_selected <= 1'b1; end 8'b010xxxxx: // $400000-$5fffff begin // {which_ras[0],which_ras[1],which_ras[2],which_ras[3]} <= 4'b0100; // /RAS1 mem_selected <= 1'b1; end // remove this two CASE sections below for 4Mb only decoding (do not remove "default:"!) 8'b011xxxxx: // $600000-$7fffff begin // {which_ras[0],which_ras[1],which_ras[2],which_ras[3]} <= 4'b0010; // /RAS2 mem_selected <= 1'b1; end 8'b100xxxxx: // $800000-$9fffff begin // {which_ras[0],which_ras[1],which_ras[2],which_ras[3]} <= 4'b0001; // /RAS3 mem_selected <= 1'b1; end default: //mem not selected begin // {which_ras[0],which_ras[1],which_ras[2],which_ras[3]} <= 4'b0000; // nothing mem_selected <= 1'b0; end endcase end // normal cycle generator always @(posedge cpu_clk,posedge cpu_nas) begin // STATE 7 On the falling edge of the clock entering S7, the processor negates AS, LDS, and DS. As the clock rises at the end of S7, the processor places the address and data buses in the high-impedance state, and drives R/W high. The device negates DTACK or BERR at this time. if( cpu_nas==1 ) begin // /AS=1 access_ras <= 0; access_cas <= 0; end else begin // /AS=0, positive clock access_ras <= 1; access_cas <= access_ras; // one clock later end end // refresh cycle generator always @(negedge cpu_clk) begin if( cpu_nas==1 ) // /AS negated begin rfsh_cas <= ~rfsh_cas; end else // /AS asserted begin rfsh_cas <= 0; end if( (rfsh_cas == 1'b0) && (cpu_nas==1) ) begin rfsh_select <= rfsh_select + 2'b01; end end always @* begin rfsh_ras <= rfsh_cas & cpu_clk; end // output signals generator always @* begin dram_nras <= ~( (mem_selected & access_ras) | ((rfsh_select==2'b00)?rfsh_ras:1'b0) ); // dram_nras0 <= ~( ( which_ras[0] & access_ras ) | ((rfsh_select==2'b00)?rfsh_ras:1'b0) ); // dram_nras1 <= ~( ( which_ras[1] & access_ras ) | ((rfsh_select==2'b01)?rfsh_ras:1'b0) ); // dram_nras2 <= ~( ( which_ras[2] & access_ras ) | ((rfsh_select==2'b10)?rfsh_ras:1'b0) ); // dram_nras3 <= ~( ( which_ras[3] & access_ras ) | ((rfsh_select==2'b11)?rfsh_ras:1'b0) ); dram_nlcas <= ~( ( ~cpu_nlds & access_cas & mem_selected ) | rfsh_cas ); dram_nucas <= ~( ( ~cpu_nuds & access_cas & mem_selected ) | rfsh_cas ); end // MUX switcher generator always @(negedge cpu_clk,negedge access_ras) begin if( access_ras==0 ) begin // reset on no access_ras mux_switch <= 0; end else begin // set to 1 on negedge after beginning of access_ras mux_switch <= 1; end end // DRAM MAx multiplexor always @* begin if (cpu_nas==1) //address strobe negated, cpu address bus may be floating { dram_ma0,dram_ma1,dram_ma2,dram_ma3,dram_ma4,dram_ma5,dram_ma6,dram_ma7,dram_ma8,dram_ma9,dram_ma10,dram_ma11} <= {1,1,1,1,1,1,1,1,1,1,1,1}; else begin //when nas asserted and address valid dram_ma10 <= cpu_a21; dram_ma11 <= cpu_a22; if( mux_switch==0 ) { dram_ma0,dram_ma1,dram_ma2,dram_ma3,dram_ma4,dram_ma5,dram_ma6,dram_ma7,dram_ma8,dram_ma9} <= { cpu_a1,cpu_a2,cpu_a3,cpu_a4,cpu_a5,cpu_a6,cpu_a7,cpu_a8,cpu_a9,cpu_a10 }; else // mux_switch==1 { dram_ma0,dram_ma1,dram_ma2,dram_ma3,dram_ma4,dram_ma5,dram_ma6,dram_ma7,dram_ma8,dram_ma9 } <= { cpu_a11,cpu_a12,cpu_a13,cpu_a14,cpu_a15,cpu_a16,cpu_a17,cpu_a18,cpu_a19,cpu_a20 }; end end // make clocked cpu_nas_z always @(posedge cpu_clk) begin cpu_nas_z <= cpu_nas; end // detect if current cycle is read or write cycle always @(posedge cpu_clk, posedge cpu_nas) begin if( cpu_nas==1 ) // async reset on end of /AS strobe begin read_cycle <= 0; // end of cycles write_cycle <= 0; end // STATE 2 On the rising edge of state 2 (S2), the processor asserts AS and UDS, LDS, or DS. //next rising cpu clock enters state 4 else // sync beginning of cycle begin //looking cpu_nas status at state 3 entering state 4 if( cpu_nas==0 && cpu_nas_z==1 ) // beginning of /AS strobe begin if( (cpu_nlds&cpu_nuds)==0 ) //since cpu_rnw is connected, this could be: if( cpu_rnw==1 ) read_cycle <= 1; else write_cycle <= 1; end end end // autoconfig data forming always @* begin case( low_addr ) 6'b000000: // $00 datout <= 4'b1110; 6'b000001: // $02 datout <= 4'b0000; // 0111 for 4mb, 0000 for 8mb 6'b000010: // $04 datout <= 4'hE; 6'b000011: // $06 datout <= 4'hE; 6'b000100: // $08 datout <= 4'h3; 6'b000101: // $0a datout <= 4'hF; 6'b001000: // $10 datout <= 4'hE; 6'b001001: // $12 datout <= 4'hE; 6'b001010: // $14 datout <= 4'hE; 6'b001011: // $16 datout <= 4'hE; 6'b100000: // $40 datout <= 4'b0000; 6'b100001: // $42 datout <= 4'b0000; default: datout <= 4'b1111; endcase end // out autoconfig data always @* begin if( read_cycle==1 && high_addr==8'hE8 && autoconf_on==1 ) {cpu_d15,cpu_d14,cpu_d13,cpu_d12} <= datout; else {cpu_d15,cpu_d14,cpu_d13,cpu_d12} <= 4'bZZZZ; end //autoconfig with autoconfig in and out lines reg autoconfig_done; always @* begin autoconf_on = (autoconfig_done == 0) && (nconfigin == 0); //autoconf on when not done and nconfigin active low end always @(posedge write_cycle,negedge cpu_nreset) begin if (cpu_nreset==0) //reset autoconfig_done <= 0; else begin if( high_addr==8'hE8 && low_addr[5:2]==4'b1001 ) // $E80048..$E8004E autoconfig_done <= 1; end end always @* //other signal lines depending on autoconfig done begin dram_noe <= ~autoconfig_done; //dram _oe normally grounded, but output switched off while config not done nconfigout <= ~autoconfig_done; //nconfigout line low when config done // nledout <= ~autoconfig_done; //led on when autoconf done end endmodule