OpenCores
URL https://opencores.org/ocsvn/next186_soc_pc/next186_soc_pc/trunk

Subversion Repositories next186_soc_pc

[/] [next186_soc_pc/] [trunk/] [HW/] [ddr_186.v] - Rev 2

Compare with Previous | Blame | View Log

//////////////////////////////////////////////////////////////////////////////////
//
// This file is part of the Next186 Soc PC project
// http://opencores.org/project,next186
//
// Filename: ddr_186.v
// Description: Part of the Next186 SoC PC project, main system, ddr interface
// Version 1.0
// Creation date: Apr2012
//
// Author: Nicolae Dumitrache 
// e-mail: ndumitrache@opencores.org
//
/////////////////////////////////////////////////////////////////////////////////
// 
// Copyright (C) 2012 Nicolae Dumitrache
// 
// This source file may be used and distributed without 
// restriction provided that this copyright statement is not 
// removed from the file and that any derivative work contains 
// the original copyright notice and the associated disclaimer.
// 
// This source file is free software; you can redistribute it 
// and/or modify it under the terms of the GNU Lesser General 
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any 
// later version. 
// 
// This source is distributed in the hope that it will be 
// useful, but WITHOUT ANY WARRANTY; without even the implied 
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
// PURPOSE. See the GNU Lesser General Public License for more 
// details. 
// 
// You should have received a copy of the GNU Lesser General 
// Public License along with this source; if not, download it 
// from http://www.opencores.org/lgpl.shtml 
// 
///////////////////////////////////////////////////////////////////////////////////
// Additional Comments: 
//
// 25Apr2012 - added SD card SPI support
// 15May2012 - added PIT 8253 (sound + timer INT8)
// 24May2012 - added PIC 8259  
// 28May2012 - RS232 boot loader does not depend on CPU speed anymore (uses timer0)
//	01Feb2013 - ADD 8042 PS2 Keyboard & Mouse controller
// 27Feb2013 - ADD RTC
// 04Apr2013 - ADD NMI, port 3bc for 8 leds
//
//Route:455 - CLK Net:u_ddr/top_00/dqs_int_delay_in<0> may have excessive skew because 
//   22 CLK pins and 0 NON_CLK pins failed to route using a CLK template.
//////////////////////////////////////////////////////////////////////////////////
 
/* ----------------- implemented ports -------------------
0001 - write RS232 (bit0)
 
0021, 00a1 - interrupt controller data ports. R/W interrupt mask, 1disabled/0enabled (bit0=timer, bit1=keyboard, bit3=RTC, bit4=mouse) 
 
0040-0043 - PIT 8253 ports
 
0x60, 0x64 - 8042 keyboard/mouse data and cfg
 
0061 - bits1:0 speaker on/off (write only)
 
0070 - RTC (16bit write only counter value). RTC is incremented with 1Mhz and at set value sends INT70h, then restart from 0
		 When set, it restarts from 0. If the set value is 0, it will send INT70h only once, if it was not already 0
 
080h-08fh - memory map: bit9:0=64 Kbytes DDRAM segment index (up to 1024 segs = 64MB), mapped over 
								PORT[3:0] 80186 addressable segment
 
03BC - parallel port (out only) LED[7:0]
 
03C0 - VGA mode (index 10h only)
			bit0 = graphic(1)/text(0)
			bit3 = text mode flash enabled(1)
			bit6 = 320x200(1)/640x480(0)
 
03C6 - DAC mask (rw)
03C7 - DAC read index (rw)
03C8 - DAC write index (rw)
03C9 - DAC color (rw)
03CB - font: write WORD = set index (8 bit), r/w BYTE = r/w font data
 
03DA - read VGA status, bit0=1 on vblank or hblank, bit1=RS232in, bit3=1 on vblank, bit7=1 always, bit15:8=SD SPI byte read
		 write bit7=SD SPI MOSI bit, SPI CLK 0->1 (BYTE write only), bit8 = SD card chip select (WORD write only)
		 also reset the 3C0 port index flag
 
03B4, 03D4 - VGA CRT write index:  
										0A(bit 5 only): hide cursor
										0C: HI screen offset
										0D: LO screen offset
										0E: HI cursor pos
										0F: LO cursor pos
03B5, 03D5 - VGA CRT read/write data
*/
 
 
`timescale 1ns / 1ps
 
module system
	(
		 inout	[15:0]cntrl0_ddr2_dq,        
		 output	[12:0]cntrl0_ddr2_a,         
		 output	[1:0]	cntrl0_ddr2_ba,        
		 output			cntrl0_ddr2_cke,       
		 output			cntrl0_ddr2_cs_n,      
		 output			cntrl0_ddr2_ras_n,     
		 output			cntrl0_ddr2_cas_n,     
		 output			cntrl0_ddr2_we_n,      
		 output			cntrl0_ddr2_odt,       
		 output	[1:0]	cntrl0_ddr2_dm,        
		 inout	[1:0]	cntrl0_ddr2_dqs,       
		 inout	[1:0]	cntrl0_ddr2_dqs_n,     
		 output			cntrl0_ddr2_ck,        
		 output			cntrl0_ddr2_ck_n,
		 input			cntrl0_rst_dqs_div_in, 
		 output			cntrl0_rst_dqs_div_out,
 
		 input			sys_clk_in,     // 133Mhz
		 input 			CLK_50MHZ,
 
		 output wire[3:0]	VGA_R,
		 output wire[3:0]	VGA_G,
		 output wire[3:0]	VGA_B,
		 output wire VGA_HSYNC,
		 output wire VGA_VSYNC,
 
		 input BTN_SOUTH,		// Reset
		 input BTN_WEST,		// NMI
//		 output reg [7:0]LED,
		 output FPGA_AWAKE,	// HALT
		 input RS232_DCE_RXD,
		 output reg RS232_DCE_TXD,
 
		 output reg SD_CS = 1,
		 output wire SD_DI,
		 output reg SD_CK = 0,
		 input SD_DO,
 
		 output AUD_L,
		 output AUD_R,
	 	 inout PS2_CLK1,
		 inout PS2_CLK2,
		 inout PS2_DATA1,
		 inout PS2_DATA2
    );
 
	wire [31:0]cntrl0_user_output_data;//o    
	wire [31:0]cntrl0_user_input_data;//i    
	wire [11:0]waddr;
	wire [31:0] DOUT;
	wire [15:0]CPU_DOUT;
	wire [15:0]PORT_ADDR;
	wire [31:0] DRAM_dout;
	wire [31:0] SRAM_dout;
	wire [19:0] ADDR;
	wire IORQ;
	wire WR;
	wire INTA;
	wire WORD;
	wire [3:0] RAM_WMASK;
	wire cntrl0_ar_done;
	wire cntrl0_auto_ref_req;
	wire cntrl0_user_cmd_ack;
	wire cntrl0_user_data_valid;
	wire cntrl0_sys_rst180_tb;
	wire cntrl0_init_done;
	wire hblnk;
	wire vblnk;
	wire [9:0]hcount;
	wire [9:0]vcount;
	wire displ_on = !(hblnk | vblnk);
	wire [15:0]fifo_dout;
	wire [11:0]DAC_COLOR;
	wire fifo_empty;	// fifo empty
	wire full;
	wire prog_full;
	wire prog_empty;
	wire clk_25;
	wire clk_cpu;
	wire CPU_CE;	// CPU clock enable
	wire CE;
	wire ddr_rd; 
	wire ddr_wr;
	wire TIMER_OE;
	wire VGA_DAC_OE;
	wire LED_PORT = PORT_ADDR[15:0] == 16'h03bc;
	wire SPEAKER_PORT = PORT_ADDR[15:0] == 16'h0061;
	wire MEMORY_MAP = PORT_ADDR[15:4] == 12'h008;
	wire VGA_FONT_OE = PORT_ADDR[15:0] == 16'h03cb;
	wire RS232_OE = PORT_ADDR[15:0] == 16'h0001;
	wire INPUT_STATUS_OE = PORT_ADDR[15:0] == 16'h03da;
	wire VGA_CRT_OE = (PORT_ADDR[15:1] == 15'b000000111011010) || (PORT_ADDR[15:1] == 15'b000000111101010); // 3b4, 3b5, 3d4, 3d5
	wire RTC_SELECT = PORT_ADDR[15:0] == 16'h0070;
	wire [7:0]VGA_DAC_DATA;
	wire [7:0]VGA_CRT_DATA;
	wire [15:0]PORT_IN;
	wire [7:0]TIMER_DOUT;
	wire [7:0]KB_DOUT;
	wire [7:0]PIC_DOUT;
	wire PIC_OE; 
	wire KB_OE;
 
	reg [3:0]STATE = 0;
	reg [1:0]cntrl0_user_command_register = 0;
	reg cntrl0_burst_done = 0;
	reg [15:0]vga_ddr_row_col = 0;// = 16'h4000; // video buffer at 0xa0000
	reg [4:0]cache_counter = 0;
	reg [5:0]lowaddr = 0; //cache mem address
	reg s_prog_full;
	reg s_prog_empty;
	reg s_ddr_rd;
	reg s_ddr_wr;
	reg cache_op = 0;
	reg [1:0]cww = 0; // cache write window
	reg [3:0]crw = 0;	// cache read window
	reg crw_start = 0;
	reg rfsh = 0;
	wire ccd = cache_counter == 5'b11111;
	reg s_RS232_DCE_RXD;
	reg [4:0]rstcount = 0;
	reg [1:0]s_displ_on = 0;	// clk_25 delayed displ_on
	reg [2:0]vga400 = 0; 	// 1 for 400 lines, 0 for 480 lines
	reg [2:0]vgatext = 0;  // 1 for text mode
	wire vgaflash;
	reg flashbit = 0;
	reg [5:0]flashcount = 0;
	reg s_ddr_endburst = 0;
	wire [11:0]charcount = {vcount[8:4], 4'b0000} + {vcount[8:4], 6'b000000} + hcount[9:3];
 
	reg [8:0]vga_ddr_row_count = 0; 
	reg [3:0]vga_repln_count = 0; // repeat line counter
	reg [6:0]vga_lnbytecount = 0; // line byte count (multiple of 8)
	reg [11:0]vga_font_counter = 0;
	reg [7:0]vga_attr;
	reg [4:0]RTCDIV25 = 0;
	reg [1:0]RTCSYNC = 0;
	reg [15:0]RTC = 0;
	reg [15:0]RTCSET = 0;
	wire RTCEND = RTC == RTCSET;
	wire RTCDIVEND = RTCDIV25 == 24;
	wire [11:0]cache_hi_addr = |cww ? waddr : ADDR[19:8];
	wire [9:0]memmap;
	wire [9:0]memmap_mux;
	wire [3:0]vga_repln = vgatext[0] ? 15 : vga400[0] ? 1 : 0;
	wire [6:0]vga_lnend = vgatext[0] ? 19 : vga400[0] ? 39 : 79; // multiple of 8(DDRAM resolution = 8)
	wire vga_end_line = vga_lnbytecount == vga_lnend;
	wire vga_repeat_line = vga_repln_count != vga_repln;
	wire vga_end_frame = vga_ddr_row_count == (vgatext[0] | vga400[0] ? 399 : 479);
	wire [7:0]font_dout;
	wire [7:0]VGA_FONT_DATA;
	wire [2:0]pxindex = -hcount[2:0];
	wire vgatextreq;
	wire vga400req;
	wire oncursor;
	wire [11:0]cursorpos;
	wire [15:0]scraddr;
	reg flash_on;
	reg speaker_on = 0;
	reg [9:0]rNMI = 0;
	wire [3:0]VGA_MUX = (font_dout[pxindex] ^ flash_on) ? vga_attr[3:0] : {vga_attr[7] & ~vgaflash, vga_attr[6:4]};
 
	wire [3:0]sdon = {4{s_displ_on[vgatext[1]]}};
	assign VGA_R[3:0] = DAC_COLOR[3:0] & sdon;
	assign VGA_G[3:0] = DAC_COLOR[7:4] & sdon;
	assign VGA_B[3:0] = DAC_COLOR[11:8] & sdon;
 
// SD interface
	reg [7:0]SDI;
	assign SD_DI = CPU_DOUT[7];
 
	assign PORT_IN[15:8] = { ({8{MEMORY_MAP}} & {6'b000000, memmap[9:8]}) |
									 ({8{INPUT_STATUS_OE}} & SDI)
								  };
 
	assign PORT_IN[7:0] = {  ({8{VGA_DAC_OE}} & VGA_DAC_DATA) |
									 ({8{VGA_FONT_OE}}& VGA_FONT_DATA) |
									 ({8{KB_OE}} & KB_DOUT) |
									 ({8{INPUT_STATUS_OE}} & {4'b1xxx, vblnk, 1'bx, s_RS232_DCE_RXD, hblnk | vblnk}) | 
									 ({8{VGA_CRT_OE}} & VGA_CRT_DATA) | 
									 ({8{MEMORY_MAP}} & {memmap[7:0]}) |
									 ({8{TIMER_OE}} & TIMER_DOUT) |
									 ({8{PIC_OE}} & PIC_DOUT)
								 };
 
	dcm_vga dcm133_25 
	(
    .CLKIN_IN(sys_clk_in), 
    .CLKFX_OUT(clk_25), 
    .CLKIN_IBUFG_OUT(CLKIN_IBUFG_OUT), 
    .CLK0_OUT(CLK0_OUT), 
    .CLK90_OUT(CLK90_OUT), 
    .LOCKED_OUT(LOCKED_OUT)
//	 .CLKDV_OUT(clk_cpu)
    );
 
	 dcm_cpu dcm50_cpu 
	 (
	  .CLKIN_IN(CLK_50MHZ), 
     .CLKFX_OUT(clk_cpu)
//	  .CLKDV_OUT(clk_25)
 //   .CLKIN_IBUFG_OUT(CLKIN_IBUFG_OUT), 
 //   .CLK0_OUT(CLK0_OUT)
    );
 
// ddr_cal_ctl.v, line 194, I made <tapfordqs> always fixed <default_tap> instead of variable <tapfordqs1> 
// ddr_s3_dqs_iob.v, line 115, added delay property .IBUF_DELAY_VALUE("4") to IBUFDS (works ok for values < 8)
	ddr u_ddr 
	( 
      .cntrl0_ddr2_dq            (cntrl0_ddr2_dq),
      .cntrl0_ddr2_a             (cntrl0_ddr2_a),
      .cntrl0_ddr2_ba            (cntrl0_ddr2_ba),
      .cntrl0_ddr2_cke           (cntrl0_ddr2_cke),
      .cntrl0_ddr2_cs_n          (cntrl0_ddr2_cs_n),
      .cntrl0_ddr2_ras_n         (cntrl0_ddr2_ras_n),
      .cntrl0_ddr2_cas_n         (cntrl0_ddr2_cas_n),
      .cntrl0_ddr2_we_n          (cntrl0_ddr2_we_n),
      .cntrl0_ddr2_odt           (cntrl0_ddr2_odt),
      .cntrl0_ddr2_dm            (cntrl0_ddr2_dm),
      .cntrl0_ddr2_dqs           (cntrl0_ddr2_dqs),
      .cntrl0_ddr2_dqs_n         (cntrl0_ddr2_dqs_n),
      .cntrl0_ddr2_ck            (cntrl0_ddr2_ck),
      .cntrl0_ddr2_ck_n          (cntrl0_ddr2_ck_n),
      .cntrl0_rst_dqs_div_in     (cntrl0_rst_dqs_div_in),
      .cntrl0_rst_dqs_div_out    (cntrl0_rst_dqs_div_out),
 
      .clk_int                   (CLK0_OUT),
      .clk90_int                 (CLK90_OUT),
      .dcm_lock                  (LOCKED_OUT),
 
      .reset_in_n                (1'b1),
      .cntrl0_burst_done         (cntrl0_burst_done),
      .cntrl0_init_done          (cntrl0_init_done),
      .cntrl0_ar_done            (cntrl0_ar_done),
      .cntrl0_user_data_valid    (cntrl0_user_data_valid),
      .cntrl0_auto_ref_req       (cntrl0_auto_ref_req),
      .cntrl0_user_cmd_ack       (cntrl0_user_cmd_ack),
      .cntrl0_user_command_register  ({cntrl0_user_command_register, 1'b0}),
      .cntrl0_clk_tb             (cntrl0_clk_tb),
      .cntrl0_clk90_tb           (cntrl0_clk90_tb),
  //    .cntrl0_sys_rst_tb         (cntrl0_sys_rst_tb),
  //    .cntrl0_sys_rst90_tb       (cntrl0_sys_rst90_tb),
      .cntrl0_sys_rst180_tb      (cntrl0_sys_rst180_tb),
      .cntrl0_user_output_data   (cntrl0_user_output_data),
      .cntrl0_user_input_data    (cntrl0_user_input_data),
      .cntrl0_user_data_mask     (4'b0000),
      .cntrl0_user_input_address  (cache_op ? {memmap_mux[9:6], memmap_mux[3:0], cache_hi_addr[7:0], cache_counter, 2'b00, memmap_mux[5:4]}: {5'b00001, vga_ddr_row_col, 2'b00, 2'b00})
	);
 
	fifo ddr_vga_fifo 
	(
	  .rst(cntrl0_sys_rst180_tb), // input rst
	  .wr_clk(cntrl0_clk90_tb), // input wr_clk
	  .rd_clk(clk_25), // input rd_clk
	  .din({cntrl0_user_output_data[7:0], cntrl0_user_output_data[15:8], cntrl0_user_output_data[23:16], cntrl0_user_output_data[31:24]}), // input [31 : 0] din
	  .wr_en(~crw[3] && cntrl0_user_data_valid),
	  .rd_en(!fifo_empty && displ_on && (vgatext[1] ? &hcount[2:0] : vga400[1] ? &hcount[1:0] : hcount[0])), // input rd_en
	  .dout(fifo_dout), // output [15 : 0] dout
	  .full(full), // output full
	  .empty(fifo_empty), // output empty
	  .prog_full(prog_full), // output prog_full
	  .prog_empty(prog_empty) // output prog_empty
	);
 
	VGA_SG VGA 
	(
		.tc_hsblnk(10'd639), 
		.tc_hssync(10'd655), 
		.tc_hesync(10'd751), 
		.tc_heblnk(10'd799), 
		.hcount(hcount), 
		.hsync(VGA_HSYNC), 
		.hblnk(hblnk), 
		.tc_vsblnk(vga400[2] | vgatext[2] ? 10'd399 : 10'd479), 
		.tc_vssync(vga400[2] | vgatext[2] ? 10'd411 : 10'd489), 
		.tc_vesync(vga400[2] | vgatext[2] ? 10'd413 : 10'd491), 
		.tc_veblnk(vga400[2] | vgatext[2] ? 10'd446 : 10'd520), 
		.vcount(vcount), 
		.vsync(VGA_VSYNC), 
		.vblnk(vblnk), 
		.clk(clk_25),
		.ce(!fifo_empty)
	);
 
	VGA_DAC dac 
	(
		 .CE(IORQ && CPU_CE && (PORT_ADDR[15:4] == 12'h03c)), 
		 .WR(WR), 
		 .addr(PORT_ADDR[3:0]), 
		 .din(CPU_DOUT[7:0]), 
		 .OE(VGA_DAC_OE), 
		 .dout(VGA_DAC_DATA), 
		 .CLK(clk_cpu), 
		 .VGA_CLK(clk_25), 
		 .vga_addr(vgatext[1] ? {4'b0000, VGA_MUX} : (vga400[1] ? hcount[1] : hcount[0]) ? fifo_dout[7:0] : fifo_dout[15:8]), 
		 .color(DAC_COLOR),
		 .vgatext(vgatextreq),
		 .vga400(vga400req),
		 .vgaflash(vgaflash),
		 .setindex(INPUT_STATUS_OE && IORQ && CPU_CE)
    );
 
	 VGA_CRT crt
	 (
		.CE(IORQ && CPU_CE && VGA_CRT_OE),
		.WR(WR),
		.din(CPU_DOUT[7:0]),
		.addr(PORT_ADDR[0]),
		.dout(VGA_CRT_DATA),
		.CLK(clk_cpu),
		.oncursor(oncursor),
		.cursorpos(cursorpos),
		.scraddr(scraddr)
	);
 
	sr_font VGA_FONT 
	(
	  .clka(clk_25), // input clka
	  .wea(1'b0), // input [0 : 0] wea
	  .addra({fifo_dout[15:8], vcount[3:0]}), // input [11 : 0] addra
	  .dina(8'hxx), // input [7 : 0] dina
	  .douta(font_dout), // output [7 : 0] douta
	  .clkb(clk_cpu), // input clkb
	  .web(CPU_CE & WR & IORQ & VGA_FONT_OE & ~WORD), // input [0 : 0] web
	  .addrb(vga_font_counter), // input [11 : 0] addrb
	  .dinb(CPU_DOUT[7:0]), // input [7 : 0] dinb
	  .doutb(VGA_FONT_DATA) // output [7 : 0] doutb
	);
 
	cache_controller cache_ctl 
	(
		 .addr(ADDR), 
		 .dout(DRAM_dout), 
		 .din(DOUT), 
		 .clk(clk_cpu), 
		 .mreq(MREQ), 
		 .wr(WR),
		 .wmask(RAM_WMASK),	 
		 .ce(CE), 
		 .ddr_din(cntrl0_user_output_data), 
		 .ddr_dout(cntrl0_user_input_data), 
		 .ddr_clk(cntrl0_clk90_tb), 
		 .ddr_rd(ddr_rd), 
		 .ddr_wr(ddr_wr),
		 .lowaddr(lowaddr),
		 .waddr(waddr),
		 .cache_write_data(crw[3] && cntrl0_user_data_valid) // read DDR, write to cache
	);
 
	wire I_KB;
	wire I_MOUSE;
	wire KB_RST;
	KB_Mouse_8042 KB_Mouse 
	(
		 .CS(IORQ && CPU_CE && PORT_ADDR[15:4] == 12'h006 && {PORT_ADDR[3], PORT_ADDR[1:0]} == 3'b000), // 60h, 64h
		 .WR(WR), 
		 .cmd(PORT_ADDR[2]), // 64h
		 .din(CPU_DOUT[7:0]), 
		 .OE(KB_OE), 
		 .dout(KB_DOUT), 
		 .clk(clk_cpu), 
		 .I_KB(I_KB), 
		 .I_MOUSE(I_MOUSE), 
		 .CPU_RST(KB_RST), 
		 .PS2_CLK1(PS2_CLK1), 
		 .PS2_CLK2(PS2_CLK2), 
		 .PS2_DATA1(PS2_DATA1), 
		 .PS2_DATA2(PS2_DATA2)
	);
 
	wire [7:0]PIC_IVECT;
	wire INT;
	wire timer_int;
	PIC_8259 PIC 
	(
		 .CS((PORT_ADDR[15:8] == 8'h00) && (PORT_ADDR[6:0] == 7'b0100001) && IORQ && CPU_CE), // 21h, a1h
		 .WR(WR), 
		 .din(CPU_DOUT[7:0]), 
		 .OE(PIC_OE), 
		 .dout(PIC_DOUT), 
		 .ivect(PIC_IVECT), 
		 .clk(clk_cpu), 
		 .INT(INT), 
		 .IACK(INTA & CPU_CE), 
		 .I({I_MOUSE, RTCEND, I_KB, timer_int})
//		 .I({hblnk, 1'b0, vblnk, timer_int})
    );
 
	unit186 CPUUnit
	(
		 .INPORT(INTA ? PIC_IVECT : PORT_IN), 
		 .DIN(DRAM_dout), 
		 .CPU_DOUT(CPU_DOUT),
		 .PORT_ADDR(PORT_ADDR),
		 .DOUT(DOUT), 
		 .ADDR(ADDR), 
		 .WMASK(RAM_WMASK), 
		 .CLK(clk_cpu), 
		 .CE(CE), 
		 .CPU_CE(CPU_CE),
		 .INTR(INT), 
		 .NMI(rNMI[9]), 
		 .RST(BTN_SOUTH || !rstcount[4]), 
		 .INTA(INTA), 
//		 .LOCK(LOCK), 
		 .HALT(FPGA_AWAKE), 
		 .MREQ(MREQ),
		 .IORQ(IORQ),
		 .WR(WR),
		 .WORD(WORD)
	);
 
	seg_map seg_mapper 
	(
		 .CLK(clk_cpu), 
		 .addr(PORT_ADDR[3:0]), 
		 .rdata(memmap), 
		 .wdata(CPU_DOUT[9:0]), 
		 .addr1(cache_hi_addr[11:8]), 
		 .data1(memmap_mux), 
		 .WE(MEMORY_MAP & WR & WORD & IORQ & CPU_CE)
    );
 
	 wire timer_spk;
	 timer_8253 timer 
	 (
		 .CS(PORT_ADDR[15:2] == 14'b00000000010000 && IORQ && CPU_CE), 
		 .WR(WR), 
		 .addr(PORT_ADDR[1:0]), 
		 .din(CPU_DOUT[7:0]), 
		 .OE(TIMER_OE), 
		 .dout(TIMER_DOUT), 
		 .CLK_25(clk_25), 
		 .clk(clk_cpu), 
		 .out0(timer_int), 
		 .out2(timer_spk)
    );
	 assign AUD_L = speaker_on & timer_spk;
	 assign AUD_R = speaker_on & timer_spk; 
 
	always @ (negedge cntrl0_clk_tb) begin
		cntrl0_user_command_register <= 2'b00;
		cntrl0_burst_done <= 1'b0;
		s_prog_full <= prog_full; // sychronized because prog_full is asserted on a different clock
		s_prog_empty <= prog_empty;
		s_ddr_rd <= ddr_rd;
		s_ddr_wr <= ddr_wr;
		s_ddr_endburst <= s_prog_full || cntrl0_auto_ref_req || (~s_prog_empty && (s_ddr_rd || s_ddr_wr));
		crw_start <= 1'b0;
		cww[1] <= cww[0];
		if(cntrl0_auto_ref_req) rfsh <= 1'b1;
		else if(cntrl0_ar_done) rfsh <= 1'b0;
 
		if(cntrl0_sys_rst180_tb) begin
			STATE <= 4'b0000;
			vga_ddr_row_col <= 0;
			vga_ddr_row_count <= 0;
			cache_counter <= 0;
			vga_repln_count <= 0;
			vga_lnbytecount <= 0;
		end else case(STATE)
			4'b0000: begin
				cntrl0_user_command_register <= 2'b01;	// initialize DDR
				STATE <= 4'b0001;	// reset
			end
 
// wait for completion
			4'b0001: begin
				if(~cntrl0_user_cmd_ack && cntrl0_init_done && ~rfsh && ~cntrl0_auto_ref_req) begin
					if(s_prog_empty) begin
						cntrl0_user_command_register <= 2'b11;
						STATE <= 4'b0010;
					end else if(s_ddr_wr) begin
						cntrl0_user_command_register <= 2'b10;
						cache_op <= 1'b1;
						cww[0] <= 1'b1;
						STATE <= 4'b0110;
					end else if(s_ddr_rd) begin
						cntrl0_user_command_register <= 2'b11;
						cache_op <= 1'b1;
						STATE <= 4'b1010;
					end else if(~s_prog_full) begin
						cntrl0_user_command_register <= 2'b11;
						STATE <= 4'b0010;
					end
				end
			end
 
// VGA read
			4'b0010: begin	// assert READ command, wait for ACK
				cntrl0_user_command_register <= 2'b11; // read
				if(cntrl0_user_cmd_ack) STATE <= 4'b0011;
			end
			4'b0011: begin // keep READ for 2nd T after ACK
				cntrl0_user_command_register <= 2'b11; // read
				STATE <= 4'b0100;
			end
			4'b0100: begin	// keep READ for 3rd T after ACK
				cntrl0_user_command_register <= 2'b11; // read
 
				if(vga_end_line) begin
					vga_lnbytecount <= 0;
					vga_ddr_row_count <= vga_ddr_row_count + 1;
					if(vga_repeat_line) begin
						vga_repln_count <= vga_repln_count + 1;
						vga_ddr_row_col <= vga_ddr_row_col - vga_lnend;
					end else begin
						vga_repln_count <= 0;
						if(vga_end_frame) begin
							vga400[0] <= vga400req;
							vgatext[0] <= vgatextreq;
							vga_ddr_row_col <= scraddr + {vgatext[0] ? 4'b0111 : 4'b0100, 12'h000};
							vga_ddr_row_count <= 0;
						end else vga_ddr_row_col <= vga_ddr_row_col + 1;
					end
				end else begin
					vga_lnbytecount <= vga_lnbytecount + 1;
					vga_ddr_row_col <= vga_ddr_row_col + 1;
				end
 
//				vga_ddr_row_col <= vga_ddr_row_col == vga_ddr_row_col_end ? vga_ddr_row_col_start : vga_ddr_row_col + 1; 
				if(s_ddr_endburst || &vga_ddr_row_col[7:0] || ((vga_end_frame || vga_repeat_line) && vga_end_line)) begin // end burst if (FIFO full or DDR refresh or end column address)
					cntrl0_burst_done <= 1'b1;
					STATE <= 4'b0101;	// end burst
				end else STATE <= 4'b0011;	// continue read burst
			end
			4'b0101: begin	// keep burst_done
				cntrl0_burst_done <= 1'b1;
				cache_op <= 1'b0;
				STATE <= 4'b0001;
			end
 
// cache write to DDR
			4'b0110: begin // assert WRITE command, wait for ACK
				cntrl0_user_command_register <= 2'b10; // write
				if(cntrl0_user_cmd_ack) STATE <= 4'b0111;
			end
			4'b0111: begin // keep WRITE for 2nd T after ACK
				cntrl0_user_command_register <= 2'b10; // write
				if(cntrl0_auto_ref_req || ccd) cww[0] <= 1'b0;
				STATE <= 4'b1000;
			end
			4'b1000: begin // keep WRITE for 3rd T after ACK
				cntrl0_user_command_register <= 2'b10; // write
				cache_counter <= cache_counter + 1;
				if(~cww[0]) begin
					cntrl0_burst_done <= 1'b1;
					STATE <= ccd ? 4'b0101 : 4'b1001;
				end else STATE <= 4'b0111;
			end
			4'b1001: begin
				cntrl0_burst_done <= 1'b1;
				STATE <= 4'b1110;
			end
			4'b1110: begin
				if(~cntrl0_user_cmd_ack) begin
					cntrl0_user_command_register <= 2'b10; // write
					cww[0] <= 1'b1;
					STATE <= 4'b0110;
				end
			end
 
// cache read from DDR
			4'b1010: begin // assert READ command, wait for ACK
				cntrl0_user_command_register <= 2'b11; // read
				if(cntrl0_user_cmd_ack) STATE <= 4'b1011;
			end
			4'b1011: begin // keep READ for 2nd T after ACK
				crw_start <= 1'b1;
				cntrl0_user_command_register <= 2'b11; // read
				STATE <= 4'b1100;
			end
			4'b1100: begin	// keep READ for 3rd T after ACK
				cntrl0_user_command_register <= 2'b11; // read
				cache_counter <= cache_counter + 1;
				if(cntrl0_auto_ref_req || ccd) begin
					cntrl0_burst_done <= 1'b1;
					STATE <= ccd ? 4'b0101 : 4'b1101;
				end else STATE <= 4'b1011;
			end
			4'b1101: begin	// keep burst_done
				cntrl0_burst_done <= 1'b1;
				STATE <= 4'b1111;
			end
			4'b1111: begin
				if(~cntrl0_user_cmd_ack) begin
					cntrl0_user_command_register <= 2'b11; // read
					STATE <= 4'b1010;
				end
			end
 
		endcase
	end
 
 
	always @ (posedge cntrl0_clk90_tb) begin
		if(cntrl0_sys_rst180_tb) begin
			crw <= 0;
			lowaddr <= 0;
		end else begin
			if((crw[3] && cntrl0_user_data_valid) || (cww[0] && cntrl0_user_cmd_ack)) lowaddr <= lowaddr + 1;
			if(~crw[3]) begin
				if(crw_start || |crw[2:0]) crw <= crw + 1;
			end else if(&lowaddr) crw <= 0;
		end
	end
 
	always @ (posedge clk_cpu) begin
		s_RS232_DCE_RXD <= RS232_DCE_RXD;
		if(IORQ & CPU_CE) begin
			if(WR & RS232_OE) RS232_DCE_TXD <= CPU_DOUT[0];
			if(VGA_FONT_OE) vga_font_counter <= WR && WORD ? {CPU_DOUT[7:0], 4'b0000} : vga_font_counter + 1; 
			if(WR & SPEAKER_PORT) speaker_on <= &CPU_DOUT[1:0];
//			if(WR & LED_PORT) LED <= CPU_DOUT[7:0];
		end
// SD
		if(CPU_CE) begin
			SD_CK <= IORQ & INPUT_STATUS_OE & WR & ~WORD;
			if(IORQ & INPUT_STATUS_OE & WR) begin
				if(WORD) SD_CS <= ~CPU_DOUT[8]; // SD chip select
				else SDI <= {SDI[6:0], SD_DO};
			end
		end
 
		if(KB_RST) rstcount <= 0;
		else if(CPU_CE && ~rstcount[4]) rstcount <= rstcount + 1;
 
// RTC		
		RTCSYNC <= {RTCSYNC[0], RTCDIVEND};
		if(IORQ && CPU_CE && WR && WORD && RTC_SELECT) begin
			RTC <= 0;
			RTCSET <= CPU_DOUT;
		end else if(RTCSYNC == 2'b01) begin
			if(RTCEND) RTC <= 0;
			else RTC <= RTC + 1;
		end
 
	end
 
	always @ (posedge clk_25) begin
		s_displ_on[1:0] <= {s_displ_on[0], displ_on};
		vga_attr <= fifo_dout[7:0];
 
		flash_on <= (vgaflash & fifo_dout[7] & flashcount[5]) | (~oncursor && flashcount[4] && (charcount == cursorpos) && ((vcount[3:0] == 13) || vcount[3:0] == 14));		
 
		if(!vblnk) begin
			flashbit <= 1;
			vga400[2] <= vga400[1];
			vgatext[2] <= vgatext[1];
		end else if(flashbit) begin
			flashcount <= flashcount + 1;
			flashbit <= 0;
			vga400[1] <= vga400[0];
			vgatext[1] <= vgatext[0];
		end
 
		if(RTCDIVEND) RTCDIV25 <= 0;	// real time clock
		else RTCDIV25 <= RTCDIV25 + 1;
 
		if(!BTN_WEST) rNMI <= 0;		// NMI
		else if(!rNMI[9] && RTCDIVEND) rNMI <= rNMI + 1;	// 1Mhz increment
 
	end
 
endmodule
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.